Compare commits
47 Commits
0.4.dev-20
...
0.4.dev-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc00cdeb2c | ||
|
|
3e6e35f383 | ||
|
|
b9e8e20c9c | ||
|
|
932988af46 | ||
|
|
69bc9224db | ||
|
|
a17efe6e8f | ||
|
|
e8b0722137 | ||
|
|
ed128fff26 | ||
|
|
a465fd5b99 | ||
|
|
9af0142a36 | ||
|
|
34fd47887e | ||
|
|
2dc9a0c724 | ||
|
|
c357985135 | ||
|
|
ae2b7f9523 | ||
|
|
5344dec760 | ||
|
|
89bc306632 | ||
|
|
dc05b106f2 | ||
|
|
a416cf7c45 | ||
|
|
09010410cf | ||
|
|
f8bbecebf5 | ||
|
|
9d67037570 | ||
|
|
e4daa4c065 | ||
|
|
08a10b8a6a | ||
|
|
af32240545 | ||
|
|
ee0d3bacbc | ||
|
|
9dcfa882b1 | ||
|
|
cb589b1f99 | ||
|
|
e6e3eef0ef | ||
|
|
0e113a4c81 | ||
|
|
1da3a8e24b | ||
|
|
3509714951 | ||
|
|
146be1f0b6 | ||
|
|
223a4f4741 | ||
|
|
1f1c1790f5 | ||
|
|
2ca00fa585 | ||
|
|
1901158b3e | ||
|
|
63d3403a20 | ||
|
|
7f7fe444d3 | ||
|
|
f4272ccf8f | ||
|
|
4196b0d341 | ||
|
|
ebc7a36a83 | ||
|
|
aab50cd2cc | ||
|
|
96c30452f9 | ||
|
|
4d0f227c70 | ||
|
|
50b87c3791 | ||
|
|
b6539399f4 | ||
|
|
8b8ef8acc0 |
@@ -10,7 +10,7 @@ project(minetest)
|
||||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH dev-20111201-0)
|
||||
set(VERSION_PATCH dev-20111202-1)
|
||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
MESSAGE(STATUS "*** Will build version ${VERSION_STRING} ***")
|
||||
|
||||
11
README.txt
11
README.txt
@@ -195,16 +195,17 @@ cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DR
|
||||
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
|
||||
popd
|
||||
|
||||
License of Minetest-c55 textures
|
||||
--------------------------------
|
||||
License of Minetest-c55 textures and sounds
|
||||
-------------------------------------------
|
||||
|
||||
This does not apply to texture packs made by others.
|
||||
This applies to textures and sounds contained in the main Minetest
|
||||
distribution.
|
||||
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
License of Minetest-c55
|
||||
-----------------------
|
||||
License of Minetest-c55 source code
|
||||
-----------------------------------
|
||||
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
@@ -156,9 +156,9 @@ minetest.register_node("ignore", {
|
||||
|
||||
--
|
||||
-- stackstring manipulation functions
|
||||
-- example stackstring: 'CraftItem "apple" 4'
|
||||
-- example item: {type="CraftItem", name="apple"}
|
||||
-- example item: {type="ToolItem", name="SteelPick", wear="23272"}
|
||||
-- example stackstring: 'craft "apple" 4'
|
||||
-- example item: {type="craft", name="apple"}
|
||||
-- example item: {type="tool", name="SteelPick", wear="23272"}
|
||||
--
|
||||
|
||||
function stackstring_take_item(stackstring)
|
||||
@@ -167,13 +167,13 @@ function stackstring_take_item(stackstring)
|
||||
end
|
||||
local stacktype = nil
|
||||
stacktype = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*)')
|
||||
if stacktype == "NodeItem" or stacktype == "CraftItem" then
|
||||
'([%a%d]+)')
|
||||
if stacktype == "node" or stacktype == "craft" then
|
||||
local itemtype = nil
|
||||
local itemname = nil
|
||||
local itemcount = nil
|
||||
itemtype, itemname, itemcount = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemcount = tonumber(itemcount)
|
||||
if itemcount == 0 then
|
||||
return '', nil
|
||||
@@ -183,12 +183,12 @@ function stackstring_take_item(stackstring)
|
||||
return itemtype.." \""..itemname.."\" "..(itemcount-1),
|
||||
{type=itemtype, name=itemname}
|
||||
end
|
||||
elseif stacktype == "ToolItem" then
|
||||
elseif stacktype == "tool" then
|
||||
local itemtype = nil
|
||||
local itemname = nil
|
||||
local itemwear = nil
|
||||
itemtype, itemname, itemwear = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemwear = tonumber(itemwear)
|
||||
return '', {type=itemtype, name=itemname, wear=itemwear}
|
||||
end
|
||||
@@ -201,17 +201,17 @@ function stackstring_put_item(stackstring, item)
|
||||
stackstring = stackstring or ''
|
||||
local stacktype = nil
|
||||
stacktype = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*)')
|
||||
'([%a%d]+)')
|
||||
stacktype = stacktype or ''
|
||||
if stacktype ~= '' and stacktype ~= item.type then
|
||||
return stackstring, false
|
||||
end
|
||||
if item.type == "NodeItem" or item.type == "CraftItem" then
|
||||
if item.type == "node" or item.type == "craft" then
|
||||
local itemtype = nil
|
||||
local itemname = nil
|
||||
local itemcount = nil
|
||||
itemtype, itemname, itemcount = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemtype = itemtype or item.type
|
||||
itemname = itemname or item.name
|
||||
if itemcount == nil then
|
||||
@@ -219,7 +219,7 @@ function stackstring_put_item(stackstring, item)
|
||||
end
|
||||
itemcount = itemcount + 1
|
||||
return itemtype.." \""..itemname.."\" "..itemcount, true
|
||||
elseif item.type == "ToolItem" then
|
||||
elseif item.type == "tool" then
|
||||
if stacktype ~= nil then
|
||||
return stackstring, false
|
||||
end
|
||||
@@ -227,7 +227,7 @@ function stackstring_put_item(stackstring, item)
|
||||
local itemname = nil
|
||||
local itemwear = nil
|
||||
itemtype, itemname, itemwear = string.match(stackstring,
|
||||
'([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemwear = tonumber(itemwear)
|
||||
return itemtype.." \""..itemname.."\" "..itemwear, true
|
||||
end
|
||||
@@ -253,53 +253,53 @@ function test_stackstring()
|
||||
local item
|
||||
local success
|
||||
|
||||
stack, item = stackstring_take_item('NodeItem "TNT" 3')
|
||||
assert(stack == 'NodeItem "TNT" 2')
|
||||
assert(item.type == 'NodeItem')
|
||||
stack, item = stackstring_take_item('node "TNT" 3')
|
||||
assert(stack == 'node "TNT" 2')
|
||||
assert(item.type == 'node')
|
||||
assert(item.name == 'TNT')
|
||||
|
||||
stack, item = stackstring_take_item('CraftItem "with spaces" 2')
|
||||
assert(stack == 'CraftItem "with spaces" 1')
|
||||
assert(item.type == 'CraftItem')
|
||||
stack, item = stackstring_take_item('craft "with spaces" 2')
|
||||
assert(stack == 'craft "with spaces" 1')
|
||||
assert(item.type == 'craft')
|
||||
assert(item.name == 'with spaces')
|
||||
|
||||
stack, item = stackstring_take_item('CraftItem "with spaces" 1')
|
||||
stack, item = stackstring_take_item('craft "with spaces" 1')
|
||||
assert(stack == '')
|
||||
assert(item.type == 'CraftItem')
|
||||
assert(item.type == 'craft')
|
||||
assert(item.name == 'with spaces')
|
||||
|
||||
stack, item = stackstring_take_item('CraftItem "s8df2kj3" 0')
|
||||
stack, item = stackstring_take_item('craft "s8df2kj3" 0')
|
||||
assert(stack == '')
|
||||
assert(item == nil)
|
||||
|
||||
stack, item = stackstring_take_item('ToolItem "With Spaces" 32487')
|
||||
stack, item = stackstring_take_item('tool "With Spaces" 32487')
|
||||
assert(stack == '')
|
||||
assert(item.type == 'ToolItem')
|
||||
assert(item.type == 'tool')
|
||||
assert(item.name == 'With Spaces')
|
||||
assert(item.wear == 32487)
|
||||
|
||||
stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
|
||||
{type='NodeItem', name='With Spaces'})
|
||||
assert(stack == 'NodeItem "With Spaces" 41')
|
||||
stack, success = stackstring_put_item('node "With Spaces" 40',
|
||||
{type='node', name='With Spaces'})
|
||||
assert(stack == 'node "With Spaces" 41')
|
||||
assert(success == true)
|
||||
|
||||
stack, success = stackstring_put_item('CraftItem "With Spaces" 40',
|
||||
{type='CraftItem', name='With Spaces'})
|
||||
assert(stack == 'CraftItem "With Spaces" 41')
|
||||
stack, success = stackstring_put_item('craft "With Spaces" 40',
|
||||
{type='craft', name='With Spaces'})
|
||||
assert(stack == 'craft "With Spaces" 41')
|
||||
assert(success == true)
|
||||
|
||||
stack, success = stackstring_put_item('ToolItem "With Spaces" 32487',
|
||||
{type='ToolItem', name='With Spaces'})
|
||||
assert(stack == 'ToolItem "With Spaces" 32487')
|
||||
stack, success = stackstring_put_item('tool "With Spaces" 32487',
|
||||
{type='tool', name='With Spaces'})
|
||||
assert(stack == 'tool "With Spaces" 32487')
|
||||
assert(success == false)
|
||||
|
||||
stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
|
||||
{type='ToolItem', name='With Spaces'})
|
||||
assert(stack == 'NodeItem "With Spaces" 40')
|
||||
stack, success = stackstring_put_item('node "With Spaces" 40',
|
||||
{type='tool', name='With Spaces'})
|
||||
assert(stack == 'node "With Spaces" 40')
|
||||
assert(success == false)
|
||||
|
||||
assert(stackstring_put_stackstring('NodeItem "With Spaces" 2',
|
||||
'NodeItem "With Spaces" 1') == 'NodeItem "With Spaces" 3')
|
||||
assert(stackstring_put_stackstring('node "With Spaces" 2',
|
||||
'node "With Spaces" 1') == 'node "With Spaces" 3')
|
||||
end
|
||||
test_stackstring()
|
||||
|
||||
@@ -312,7 +312,7 @@ minetest.craftitem_place_item = function(item, placer, pos)
|
||||
--print("item: " .. dump(item))
|
||||
--print("placer: " .. dump(placer))
|
||||
--print("pos: " .. dump(pos))
|
||||
minetest.env:add_item(pos, 'CraftItem "' .. item .. '" 1')
|
||||
minetest.env:add_item(pos, 'craft "' .. item .. '" 1')
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -327,6 +327,16 @@ minetest.craftitem_eat = function(hp_change)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Creative inventory
|
||||
--
|
||||
|
||||
minetest.creative_inventory = {}
|
||||
|
||||
minetest.add_to_creative_inventory = function(itemstring)
|
||||
table.insert(minetest.creative_inventory, itemstring)
|
||||
end
|
||||
|
||||
--
|
||||
-- Callback registration
|
||||
--
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "bucket" 1',
|
||||
output = 'craft "bucket" 1',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
|
||||
{'', 'CraftItem "steel_ingot"', ''},
|
||||
{'craft "steel_ingot"', '', 'craft "steel_ingot"'},
|
||||
{'', 'craft "steel_ingot"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -16,11 +16,11 @@ minetest.register_craftitem("bucket", {
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
if n.name == "water_source" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="air"})
|
||||
player:add_to_inventory_later('CraftItem "bucket_water" 1')
|
||||
player:add_to_inventory_later('craft "bucket_water" 1')
|
||||
return true
|
||||
elseif n.name == "lava_source" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="air"})
|
||||
player:add_to_inventory_later('CraftItem "bucket_lava" 1')
|
||||
player:add_to_inventory_later('craft "bucket_lava" 1')
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -43,7 +43,7 @@ minetest.register_craftitem("bucket_water", {
|
||||
else
|
||||
minetest.env:add_node(pointed_thing.above, {name="water_source"})
|
||||
end
|
||||
player:add_to_inventory_later('CraftItem "bucket" 1')
|
||||
player:add_to_inventory_later('craft "bucket" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
@@ -65,7 +65,7 @@ minetest.register_craftitem("bucket_lava", {
|
||||
else
|
||||
minetest.env:add_node(pointed_thing.above, {name="lava_source"})
|
||||
end
|
||||
player:add_to_inventory_later('CraftItem "bucket" 1')
|
||||
player:add_to_inventory_later('craft "bucket" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
||||
@@ -7,13 +7,32 @@
|
||||
-- name "foomod", a texture could be called "foomod_superfurnace.png"
|
||||
-- Due to historical reasons, the default mod does not follow this rule.
|
||||
--
|
||||
-- MapNode representation:
|
||||
-- {name="name", param1=num, param2=num}
|
||||
--
|
||||
-- Position representation:
|
||||
-- {x=num, y=num, z=num}
|
||||
--
|
||||
-- stackstring/itemstring: A stack of items in serialized format.
|
||||
-- eg. 'node "dirt" 5'
|
||||
-- eg. 'tool "WPick" 21323'
|
||||
-- eg. 'craft "apple" 2'
|
||||
--
|
||||
-- item: A single item in Lua table format.
|
||||
-- eg. {type="node", name="dirt"}
|
||||
-- ^ a single dirt node
|
||||
-- eg. {type="tool", name="WPick", wear=21323}
|
||||
-- ^ a wooden pick about 1/3 weared out
|
||||
-- eg. {type="craft", name="apple"}
|
||||
-- ^ an apple.
|
||||
--
|
||||
-- Global functions:
|
||||
-- minetest.register_entity(name, prototype_table)
|
||||
-- minetest.register_tool(name, {lots of stuff})
|
||||
-- minetest.register_node(name, {lots of stuff})
|
||||
-- minetest.register_craftitem(name, {lots of stuff})
|
||||
-- minetest.register_craft({output=item, recipe={...})
|
||||
-- minetest.register_globalstep(func)
|
||||
-- minetest.register_entity(name, prototype table)
|
||||
-- minetest.register_tool(name, tool definition)
|
||||
-- minetest.register_node(name, node definition)
|
||||
-- minetest.register_craftitem(name, craftitem definition)
|
||||
-- minetest.register_craft(recipe)
|
||||
-- minetest.register_globalstep(func(dtime))
|
||||
-- minetest.register_on_placenode(func(pos, newnode, placer))
|
||||
-- minetest.register_on_dignode(func(pos, oldnode, digger))
|
||||
-- minetest.register_on_punchnode(func(pos, node, puncher))
|
||||
@@ -22,11 +41,15 @@
|
||||
-- minetest.register_on_respawnplayer(func(ObjectRef))
|
||||
-- ^ return true in func to disable regular player placement
|
||||
-- minetest.register_on_chat_message(func(name, message))
|
||||
-- minetest.setting_get(name)
|
||||
-- minetest.setting_getbool(name)
|
||||
-- minetest.add_to_creative_inventory(itemstring)
|
||||
-- minetest.setting_get(name) -> string or nil
|
||||
-- minetest.setting_getbool(name) -> boolean value or nil
|
||||
-- minetest.chat_send_all(text)
|
||||
-- minetest.chat_send_player(name, text)
|
||||
-- minetest.get_player_privs(name)
|
||||
-- minetest.get_player_privs(name) -> set of privs
|
||||
-- stackstring_take_item(stackstring) -> stackstring, item
|
||||
-- stackstring_put_item(stackstring, item) -> stackstring, success
|
||||
-- stackstring_put_stackstring(stackstring, stackstring) -> stackstring, success
|
||||
--
|
||||
-- Global objects:
|
||||
-- minetest.env - environment reference
|
||||
@@ -61,6 +84,7 @@
|
||||
-- - set_text(text) -- eg. set the text of a sign
|
||||
-- - get_text()
|
||||
-- - get_owner()
|
||||
-- Generic node metadata specific:
|
||||
-- - set_infotext(infotext)
|
||||
-- - inventory_set_list(name, {item1, item2, ...})
|
||||
-- - inventory_get_list(name)
|
||||
@@ -78,29 +102,30 @@
|
||||
-- ObjectRef is basically ServerActiveObject.
|
||||
-- ObjectRef methods:
|
||||
-- - remove(): remove object (after returning from Lua)
|
||||
-- - getpos(): returns {x=num, y=num, z=num}
|
||||
-- - getpos() -> {x=num, y=num, z=num}
|
||||
-- - setpos(pos); pos={x=num, y=num, z=num}
|
||||
-- - moveto(pos, continuous=false): interpolated move
|
||||
-- - punch(puncher); puncher = an another ObjectRef
|
||||
-- - punch(puncher, time_from_last_punch)
|
||||
-- ^ puncher = an another ObjectRef,
|
||||
-- ^ time_from_last_punch = time since last punch action of the puncher
|
||||
-- - right_click(clicker); clicker = an another ObjectRef
|
||||
-- - get_wielded_itemstring()
|
||||
-- - get_wielded_item()
|
||||
-- - damage_wielded_item(num) (item damage/wear range is 0-65535)
|
||||
-- - add_to_inventory(itemstring): add an item to object inventory
|
||||
-- - get_wield_digging_properties() -> digging property table
|
||||
-- - add_to_inventory_later(itemstring): like above, but after callback returns (only allowed for craftitem callbacks)
|
||||
-- - get_hp(): returns number of hitpoints (2 * number of hearts)
|
||||
-- - set_hp(hp): set number of hitpoints (2 * number of hearts)
|
||||
-- LuaEntitySAO-only:
|
||||
-- - setvelocity({x=num, y=num, z=num})
|
||||
-- - setacceleration({x=num, y=num, z=num})
|
||||
-- - getacceleration()
|
||||
-- - getacceleration() -> {x=num, y=num, z=num}
|
||||
-- - settexturemod(mod)
|
||||
-- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
|
||||
-- - select_horiz_by_yawpitch=false)
|
||||
-- Player-only:
|
||||
-- - get_player_name(): will return nil if is not a player
|
||||
-- - inventory_set_list(name, {item1, item2, ...})
|
||||
-- - inventory_get_list(name)
|
||||
-- - inventory_get_list(name) -> {item1, item2, ...}
|
||||
-- - damage_wielded_item(num) (item damage/wear range is 0-65535)
|
||||
-- - add_to_inventory(itemstring): add an item to object inventory
|
||||
--
|
||||
-- Registered entities:
|
||||
-- - Functions receive a "luaentity" as self:
|
||||
@@ -111,13 +136,113 @@
|
||||
-- - on_step(self, dtime)
|
||||
-- - on_punch(self, hitter)
|
||||
-- - on_rightclick(self, clicker)
|
||||
-- - get_staticdata(self): return string
|
||||
-- - get_staticdata(self)
|
||||
-- ^ return string that will be passed to on_activate when the object
|
||||
-- is created next time
|
||||
--
|
||||
-- MapNode representation:
|
||||
-- {name="name", param1=num, param2=num}
|
||||
-- Entity prototype table:
|
||||
-- {
|
||||
-- physical = true,
|
||||
-- collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||
-- visual = "cube",
|
||||
-- textures = {texture,texture,texture,texture,texture,texture},
|
||||
-- on_activate = function(self, staticdata),
|
||||
-- on_step = function(self, dtime),
|
||||
-- on_punch = function(self, hitter),
|
||||
-- on_rightclick = function(self, clicker),
|
||||
-- get_staticdata = function(self),
|
||||
-- # Also you can define arbitrary member variables here
|
||||
-- myvariable = whatever,
|
||||
-- }
|
||||
--
|
||||
-- Position representation:
|
||||
-- {x=num, y=num, z=num}
|
||||
-- Tool definition:
|
||||
-- {
|
||||
-- image = "tool_steelaxe.png",
|
||||
-- full_punch_interval = 1.0,
|
||||
-- basetime = 1.0,
|
||||
-- dt_weight = 0.5,
|
||||
-- dt_crackiness = -0.2,
|
||||
-- dt_crumbliness = 1,
|
||||
-- dt_cuttability = -0.5,
|
||||
-- basedurability = 330,
|
||||
-- dd_weight = 0,
|
||||
-- dd_crackiness = 0,
|
||||
-- dd_crumbliness = 0,
|
||||
-- dd_cuttability = 0,
|
||||
-- }
|
||||
--
|
||||
-- Node definition options:
|
||||
-- {
|
||||
-- name = "somenode",
|
||||
-- drawtype = "normal",
|
||||
-- visual_scale = 1.0,
|
||||
-- tile_images = {"unknown_block.png"},
|
||||
-- inventory_image = "unknown_block.png",
|
||||
-- special_materials = {
|
||||
-- {image="", backface_culling=true},
|
||||
-- {image="", backface_culling=true},
|
||||
-- },
|
||||
-- alpha = 255,
|
||||
-- post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
-- paramtype = "none",
|
||||
-- is_ground_content = false,
|
||||
-- light_propagates = false,
|
||||
-- sunlight_propagates = false,
|
||||
-- walkable = true,
|
||||
-- pointable = true,
|
||||
-- diggable = true,
|
||||
-- climbable = false,
|
||||
-- buildable_to = false,
|
||||
-- wall_mounted = false,
|
||||
-- often_contains_mineral = false,
|
||||
-- dug_item = "",
|
||||
-- extra_dug_item = "",
|
||||
-- extra_dug_item_rarity = 2,
|
||||
-- metadata_name = "",
|
||||
-- liquidtype = "none",
|
||||
-- liquid_alternative_flowing = "",
|
||||
-- liquid_alternative_source = "",
|
||||
-- liquid_viscosity = 0,
|
||||
-- light_source = 0,
|
||||
-- damage_per_second = 0,
|
||||
-- selection_box = {type="regular"},
|
||||
-- material = {
|
||||
-- diggablity = "normal",
|
||||
-- weight = 0,
|
||||
-- crackiness = 0,
|
||||
-- crumbliness = 0,
|
||||
-- cuttability = 0,
|
||||
-- flammability = 0,
|
||||
-- },
|
||||
-- cookresult_item = "", -- Cannot be cooked
|
||||
-- furnace_cooktime = 3.0,
|
||||
-- furnace_burntime = -1, -- Cannot be used as fuel
|
||||
-- }
|
||||
--
|
||||
-- Craftitem definition options:
|
||||
-- minetest.register_craftitem("name", {
|
||||
-- image = "image.png",
|
||||
-- stack_max = <maximum number of items in stack>,
|
||||
-- cookresult_item = itemstring (result of cooking),
|
||||
-- furnace_cooktime = <cooking time>,
|
||||
-- furnace_burntime = <time to burn as fuel in furnace>,
|
||||
-- usable = <uh... some boolean value>,
|
||||
-- dropcount = <amount of items to drop using drop action>
|
||||
-- liquids_pointable = <whether can point liquids>,
|
||||
-- on_drop = func(item, dropper, pos),
|
||||
-- on_place_on_ground = func(item, placer, pos),
|
||||
-- on_use = func(item, player, pointed_thing),
|
||||
-- })
|
||||
--
|
||||
-- Recipe:
|
||||
-- {
|
||||
-- output = 'tool "STPick"',
|
||||
-- recipe = {
|
||||
-- {'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
-- {'', 'craft "Stick"', ''},
|
||||
-- {'', 'craft "Stick"', ''},
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
|
||||
-- print("minetest dump: "..dump(minetest))
|
||||
@@ -320,270 +445,270 @@ minetest.register_tool("", {
|
||||
--
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "wood" 4',
|
||||
output = 'node "wood" 4',
|
||||
recipe = {
|
||||
{'NodeItem "tree"'},
|
||||
{'node "tree"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "Stick" 4',
|
||||
output = 'craft "Stick" 4',
|
||||
recipe = {
|
||||
{'NodeItem "wood"'},
|
||||
{'node "wood"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "wooden_fence" 2',
|
||||
output = 'node "wooden_fence" 2',
|
||||
recipe = {
|
||||
{'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
|
||||
{'craft "Stick"', 'craft "Stick"', 'craft "Stick"'},
|
||||
{'craft "Stick"', 'craft "Stick"', 'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "sign_wall" 1',
|
||||
output = 'node "sign_wall" 1',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'', 'craft "Stick"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "torch" 4',
|
||||
output = 'node "torch" 4',
|
||||
recipe = {
|
||||
{'CraftItem "lump_of_coal"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'craft "lump_of_coal"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "WPick"',
|
||||
output = 'tool "WPick"',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'', 'craft "Stick"', ''},
|
||||
{'', 'craft "Stick"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "STPick"',
|
||||
output = 'tool "STPick"',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
{'', 'craft "Stick"', ''},
|
||||
{'', 'craft "Stick"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "SteelPick"',
|
||||
output = 'tool "SteelPick"',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'craft "steel_ingot"', 'craft "steel_ingot"', 'craft "steel_ingot"'},
|
||||
{'', 'craft "Stick"', ''},
|
||||
{'', 'craft "Stick"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "MesePick"',
|
||||
output = 'tool "MesePick"',
|
||||
recipe = {
|
||||
{'NodeItem "mese"', 'NodeItem "mese"', 'NodeItem "mese"'},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'', 'CraftItem "Stick"', ''},
|
||||
{'node "mese"', 'node "mese"', 'node "mese"'},
|
||||
{'', 'craft "Stick"', ''},
|
||||
{'', 'craft "Stick"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "WShovel"',
|
||||
output = 'tool "WShovel"',
|
||||
recipe = {
|
||||
{'NodeItem "wood"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'node "wood"'},
|
||||
{'craft "Stick"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "STShovel"',
|
||||
output = 'tool "STShovel"',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'node "cobble"'},
|
||||
{'craft "Stick"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "SteelShovel"',
|
||||
output = 'tool "SteelShovel"',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'craft "steel_ingot"'},
|
||||
{'craft "Stick"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "WAxe"',
|
||||
output = 'tool "WAxe"',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', 'CraftItem "Stick"'},
|
||||
{'', 'CraftItem "Stick"'},
|
||||
{'node "wood"', 'node "wood"'},
|
||||
{'node "wood"', 'craft "Stick"'},
|
||||
{'', 'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "STAxe"',
|
||||
output = 'tool "STAxe"',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"', 'CraftItem "Stick"'},
|
||||
{'', 'CraftItem "Stick"'},
|
||||
{'node "cobble"', 'node "cobble"'},
|
||||
{'node "cobble"', 'craft "Stick"'},
|
||||
{'', 'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "SteelAxe"',
|
||||
output = 'tool "SteelAxe"',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "Stick"'},
|
||||
{'', 'CraftItem "Stick"'},
|
||||
{'craft "steel_ingot"', 'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"', 'craft "Stick"'},
|
||||
{'', 'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "WSword"',
|
||||
output = 'tool "WSword"',
|
||||
recipe = {
|
||||
{'NodeItem "wood"'},
|
||||
{'NodeItem "wood"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'node "wood"'},
|
||||
{'node "wood"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "STSword"',
|
||||
output = 'tool "STSword"',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'node "cobble"'},
|
||||
{'node "cobble"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'ToolItem "SteelSword"',
|
||||
output = 'tool "SteelSword"',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "Stick"'},
|
||||
{'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"'},
|
||||
{'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "rail" 15',
|
||||
output = 'node "rail" 15',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "Stick"', 'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
|
||||
{'craft "steel_ingot"', '', 'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"', 'craft "Stick"', 'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"', '', 'craft "steel_ingot"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "chest" 1',
|
||||
output = 'node "chest" 1',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', '', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'node "wood"', '', 'node "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "locked_chest" 1',
|
||||
output = 'node "locked_chest" 1',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', 'CraftItem "steel_ingot"', 'NodeItem "wood"'},
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'node "wood"', 'craft "steel_ingot"', 'node "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "furnace" 1',
|
||||
output = 'node "furnace" 1',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"', '', 'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
{'node "cobble"', '', 'node "cobble"'},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "steelblock" 1',
|
||||
output = 'node "steelblock" 1',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
|
||||
{'craft "steel_ingot"', 'craft "steel_ingot"', 'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"', 'craft "steel_ingot"', 'craft "steel_ingot"'},
|
||||
{'craft "steel_ingot"', 'craft "steel_ingot"', 'craft "steel_ingot"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "sandstone" 1',
|
||||
output = 'node "sandstone" 1',
|
||||
recipe = {
|
||||
{'NodeItem "sand"', 'NodeItem "sand"'},
|
||||
{'NodeItem "sand"', 'NodeItem "sand"'},
|
||||
{'node "sand"', 'node "sand"'},
|
||||
{'node "sand"', 'node "sand"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "clay" 1',
|
||||
output = 'node "clay" 1',
|
||||
recipe = {
|
||||
{'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
|
||||
{'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
|
||||
{'craft "lump_of_clay"', 'craft "lump_of_clay"'},
|
||||
{'craft "lump_of_clay"', 'craft "lump_of_clay"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "brick" 1',
|
||||
output = 'node "brick" 1',
|
||||
recipe = {
|
||||
{'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
|
||||
{'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
|
||||
{'craft "clay_brick"', 'craft "clay_brick"'},
|
||||
{'craft "clay_brick"', 'craft "clay_brick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "paper" 1',
|
||||
output = 'craft "paper" 1',
|
||||
recipe = {
|
||||
{'NodeItem "papyrus"', 'NodeItem "papyrus"', 'NodeItem "papyrus"'},
|
||||
{'node "papyrus"', 'node "papyrus"', 'node "papyrus"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "book" 1',
|
||||
output = 'craft "book" 1',
|
||||
recipe = {
|
||||
{'CraftItem "paper"'},
|
||||
{'CraftItem "paper"'},
|
||||
{'CraftItem "paper"'},
|
||||
{'craft "paper"'},
|
||||
{'craft "paper"'},
|
||||
{'craft "paper"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "bookshelf" 1',
|
||||
output = 'node "bookshelf" 1',
|
||||
recipe = {
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'CraftItem "book"', 'CraftItem "book"', 'CraftItem "book"'},
|
||||
{'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
{'craft "book"', 'craft "book"', 'craft "book"'},
|
||||
{'node "wood"', 'node "wood"', 'node "wood"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "ladder" 1',
|
||||
output = 'node "ladder" 1',
|
||||
recipe = {
|
||||
{'CraftItem "Stick"', '', 'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
|
||||
{'CraftItem "Stick"', '', 'CraftItem "Stick"'},
|
||||
{'craft "Stick"', '', 'craft "Stick"'},
|
||||
{'craft "Stick"', 'craft "Stick"', 'craft "Stick"'},
|
||||
{'craft "Stick"', '', 'craft "Stick"'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "apple_iron" 1',
|
||||
output = 'craft "apple_iron" 1',
|
||||
recipe = {
|
||||
{'', 'CraftItem "steel_ingot"', ''},
|
||||
{'CraftItem "steel_ingot"', 'CraftItem "apple"', 'CraftItem "steel_ingot"'},
|
||||
{'', 'CraftItem "steel_ingot"', ''},
|
||||
{'', 'craft "steel_ingot"', ''},
|
||||
{'craft "steel_ingot"', 'craft "apple"', 'craft "steel_ingot"'},
|
||||
{'', 'craft "steel_ingot"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -676,7 +801,7 @@ minetest.register_node("stone", {
|
||||
is_ground_content = true,
|
||||
often_contains_mineral = true, -- Texture atlas hint
|
||||
material = digprop_stonelike(1.0),
|
||||
dug_item = 'NodeItem "cobble" 1',
|
||||
dug_item = 'node "cobble" 1',
|
||||
})
|
||||
|
||||
minetest.register_node("dirt_with_grass", {
|
||||
@@ -684,7 +809,7 @@ minetest.register_node("dirt_with_grass", {
|
||||
inventory_image = inventorycube("mud.png^grass_side.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_dirtlike(1.0),
|
||||
dug_item = 'NodeItem "dirt" 1',
|
||||
dug_item = 'node "dirt" 1',
|
||||
})
|
||||
|
||||
minetest.register_node("dirt_with_grass_footsteps", {
|
||||
@@ -692,7 +817,7 @@ minetest.register_node("dirt_with_grass_footsteps", {
|
||||
inventory_image = "grass_footsteps.png",
|
||||
is_ground_content = true,
|
||||
material = digprop_dirtlike(1.0),
|
||||
dug_item = 'NodeItem "dirt" 1',
|
||||
dug_item = 'node "dirt" 1',
|
||||
})
|
||||
|
||||
minetest.register_node("dirt", {
|
||||
@@ -707,6 +832,7 @@ minetest.register_node("sand", {
|
||||
inventory_image = inventorycube("sand.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_dirtlike(1.0),
|
||||
cookresult_item = 'node "glass" 1',
|
||||
})
|
||||
|
||||
minetest.register_node("gravel", {
|
||||
@@ -721,7 +847,7 @@ minetest.register_node("sandstone", {
|
||||
inventory_image = inventorycube("sandstone.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_dirtlike(1.0), -- FIXME should this be stonelike?
|
||||
dug_item = 'NodeItem "sand" 1', -- FIXME is this intentional?
|
||||
dug_item = 'node "sand" 1', -- FIXME is this intentional?
|
||||
})
|
||||
|
||||
minetest.register_node("clay", {
|
||||
@@ -729,7 +855,7 @@ minetest.register_node("clay", {
|
||||
inventory_image = inventorycube("clay.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_dirtlike(1.0),
|
||||
dug_item = 'CraftItem "lump_of_clay" 4',
|
||||
dug_item = 'craft "lump_of_clay" 4',
|
||||
})
|
||||
|
||||
minetest.register_node("brick", {
|
||||
@@ -737,7 +863,7 @@ minetest.register_node("brick", {
|
||||
inventory_image = inventorycube("brick.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_stonelike(1.0),
|
||||
dug_item = 'CraftItem "clay_brick" 4',
|
||||
dug_item = 'craft "clay_brick" 4',
|
||||
})
|
||||
|
||||
minetest.register_node("tree", {
|
||||
@@ -745,7 +871,7 @@ minetest.register_node("tree", {
|
||||
inventory_image = inventorycube("tree_top.png", "tree.png", "tree.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_woodlike(1.0),
|
||||
cookresult_item = 'CraftItem "lump_of_coal" 1',
|
||||
cookresult_item = 'craft "lump_of_coal" 1',
|
||||
furnace_burntime = 30,
|
||||
})
|
||||
|
||||
@@ -754,7 +880,7 @@ minetest.register_node("jungletree", {
|
||||
inventory_image = inventorycube("jungletree_top.png", "jungletree.png", "jungletree.png"),
|
||||
is_ground_content = true,
|
||||
material = digprop_woodlike(1.0),
|
||||
cookresult_item = 'CraftItem "lump_of_coal" 1',
|
||||
cookresult_item = 'craft "lump_of_coal" 1',
|
||||
furnace_burntime = 30,
|
||||
})
|
||||
|
||||
@@ -778,7 +904,7 @@ minetest.register_node("leaves", {
|
||||
light_propagates = true,
|
||||
paramtype = "light",
|
||||
material = digprop_leaveslike(1.0),
|
||||
extra_dug_item = 'NodeItem "sapling" 1',
|
||||
extra_dug_item = 'node "sapling" 1',
|
||||
extra_dug_item_rarity = 20,
|
||||
furnace_burntime = 1,
|
||||
})
|
||||
@@ -1068,7 +1194,7 @@ minetest.register_node("cobble", {
|
||||
tile_images = {"cobble.png"},
|
||||
inventory_image = inventorycube("cobble.png"),
|
||||
is_ground_content = true,
|
||||
cookresult_item = 'NodeItem "stone" 1',
|
||||
cookresult_item = 'node "stone" 1',
|
||||
material = digprop_stonelike(0.9),
|
||||
})
|
||||
|
||||
@@ -1123,7 +1249,7 @@ minetest.register_node("apple", {
|
||||
light_propagates = true,
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
dug_item = 'CraftItem "apple" 1',
|
||||
dug_item = 'craft "apple" 1',
|
||||
material = digprop_constanttime(0.0),
|
||||
furnace_burntime = 3,
|
||||
})
|
||||
@@ -1156,13 +1282,13 @@ minetest.register_craftitem("lump_of_coal", {
|
||||
|
||||
minetest.register_craftitem("lump_of_iron", {
|
||||
image = "lump_of_iron.png",
|
||||
cookresult_item = 'CraftItem "steel_ingot" 1',
|
||||
cookresult_item = 'craft "steel_ingot" 1',
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("lump_of_clay", {
|
||||
image = "lump_of_clay.png",
|
||||
cookresult_item = 'CraftItem "clay_brick" 1',
|
||||
cookresult_item = 'craft "clay_brick" 1',
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
})
|
||||
|
||||
@@ -1178,7 +1304,7 @@ minetest.register_craftitem("clay_brick", {
|
||||
|
||||
minetest.register_craftitem("rat", {
|
||||
image = "rat.png",
|
||||
cookresult_item = 'CraftItem "cooked_rat" 1',
|
||||
cookresult_item = 'craft "cooked_rat" 1',
|
||||
on_drop = function(item, dropper, pos)
|
||||
minetest.env:add_rat(pos)
|
||||
return true
|
||||
@@ -1187,7 +1313,7 @@ minetest.register_craftitem("rat", {
|
||||
|
||||
minetest.register_craftitem("cooked_rat", {
|
||||
image = "cooked_rat.png",
|
||||
cookresult_item = 'CraftItem "scorched_stuff" 1',
|
||||
cookresult_item = 'craft "scorched_stuff" 1',
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
on_use = minetest.craftitem_eat(6),
|
||||
})
|
||||
@@ -1219,6 +1345,38 @@ minetest.register_craftitem("apple_iron", {
|
||||
|
||||
print(dump(minetest.registered_craftitems))
|
||||
|
||||
--
|
||||
-- Creative inventory
|
||||
--
|
||||
|
||||
minetest.add_to_creative_inventory('tool MesePick 0')
|
||||
minetest.add_to_creative_inventory('tool SteelPick 0')
|
||||
minetest.add_to_creative_inventory('tool SteelAxe 0')
|
||||
minetest.add_to_creative_inventory('tool SteelShovel 0')
|
||||
|
||||
minetest.add_to_creative_inventory('node torch 0')
|
||||
minetest.add_to_creative_inventory('node cobble 0')
|
||||
minetest.add_to_creative_inventory('node dirt 0')
|
||||
minetest.add_to_creative_inventory('node stone 0')
|
||||
minetest.add_to_creative_inventory('node sand 0')
|
||||
minetest.add_to_creative_inventory('node sandstone 0')
|
||||
minetest.add_to_creative_inventory('node clay 0')
|
||||
minetest.add_to_creative_inventory('node brick 0')
|
||||
minetest.add_to_creative_inventory('node tree 0')
|
||||
minetest.add_to_creative_inventory('node leaves 0')
|
||||
minetest.add_to_creative_inventory('node cactus 0')
|
||||
minetest.add_to_creative_inventory('node papyrus 0')
|
||||
minetest.add_to_creative_inventory('node bookshelf 0')
|
||||
minetest.add_to_creative_inventory('node glass 0')
|
||||
minetest.add_to_creative_inventory('node fence 0')
|
||||
minetest.add_to_creative_inventory('node rail 0')
|
||||
minetest.add_to_creative_inventory('node mese 0')
|
||||
minetest.add_to_creative_inventory('node chest 0')
|
||||
minetest.add_to_creative_inventory('node furnace 0')
|
||||
minetest.add_to_creative_inventory('node sign_wall 0')
|
||||
minetest.add_to_creative_inventory('node water_source 0')
|
||||
minetest.add_to_creative_inventory('node lava_source 0')
|
||||
minetest.add_to_creative_inventory('node ladder 0')
|
||||
|
||||
--
|
||||
-- Some common functions
|
||||
@@ -1325,14 +1483,18 @@ minetest.register_on_chat_message(function(name, message)
|
||||
minetest.chat_send_player(name, "you don't have permission to give")
|
||||
return true -- Handled chat message
|
||||
end
|
||||
stackstring = string.match(message, cmd.." (.*)")
|
||||
local stackstring = string.match(message, cmd.." (.*)")
|
||||
if stackstring == nil then
|
||||
minetest.chat_send_player(name, 'usage: '..cmd..' stackstring')
|
||||
return true -- Handled chat message
|
||||
end
|
||||
print(cmd..' invoked, stackstring="'..stackstring..'"')
|
||||
player = minetest.env:get_player_by_name(name)
|
||||
added, error_msg = player:add_to_inventory(stackstring)
|
||||
local player = minetest.env:get_player_by_name(name)
|
||||
if player == nil then
|
||||
minetest.chat_send_player(name, name2..' is not a known player')
|
||||
return true -- Handled chat message
|
||||
end
|
||||
local added, error_msg = player:add_to_inventory(stackstring)
|
||||
if added then
|
||||
minetest.chat_send_player(name, '"'..stackstring
|
||||
..'" added to inventory.');
|
||||
@@ -1350,19 +1512,19 @@ minetest.register_on_chat_message(function(name, message)
|
||||
minetest.chat_send_player(name, "you don't have permission to give")
|
||||
return true -- Handled chat message
|
||||
end
|
||||
name2, stackstring = string.match(message, cmd.." ([%a%d_-]+) (.*)")
|
||||
local name2, stackstring = string.match(message, cmd.." ([%a%d_-]+) (.*)")
|
||||
if name == nil or stackstring == nil then
|
||||
minetest.chat_send_player(name, 'usage: '..cmd..' name stackstring')
|
||||
return true -- Handled chat message
|
||||
end
|
||||
print(cmd..' invoked, name2="'..name2
|
||||
..'" stackstring="'..stackstring..'"')
|
||||
player = minetest.env:get_player_by_name(name2)
|
||||
local player = minetest.env:get_player_by_name(name2)
|
||||
if player == nil then
|
||||
minetest.chat_send_player(name, name2..' is not a known player')
|
||||
return true -- Handled chat message
|
||||
end
|
||||
added, error_msg = player:add_to_inventory(stackstring)
|
||||
local added, error_msg = player:add_to_inventory(stackstring)
|
||||
if added then
|
||||
minetest.chat_send_player(name, '"'..stackstring
|
||||
..'" added to '..name2..'\'s inventory.');
|
||||
|
||||
@@ -56,7 +56,7 @@ minetest.register_abm({
|
||||
_, srcitem = stackstring_take_item(srclist[1])
|
||||
_, fuelitem = stackstring_take_item(fuellist[1])
|
||||
if not srcitem or not fuelitem then return end
|
||||
if fuelitem.type == "NodeItem" then
|
||||
if fuelitem.type == "node" then
|
||||
local prop = minetest.registered_nodes[fuelitem.name]
|
||||
if prop == nil then return end
|
||||
if prop.furnace_burntime < 0 then return end
|
||||
@@ -64,7 +64,7 @@ minetest.register_abm({
|
||||
return
|
||||
end
|
||||
local resultstack = nil
|
||||
if srcitem.type == "NodeItem" then
|
||||
if srcitem.type == "node" then
|
||||
local prop = minetest.registered_nodes[srcitem.name]
|
||||
if prop == nil then return end
|
||||
if prop.cookresult_item == "" then return end
|
||||
@@ -97,11 +97,11 @@ minetest.register_abm({
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "luafurnace" 1',
|
||||
output = 'node "luafurnace" 1',
|
||||
recipe = {
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
{'node "cobble"', 'node "cobble"', 'node "cobble"'},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -126,9 +126,9 @@ minetest.register_tool("horribletool", {
|
||||
--]]
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "somenode" 4',
|
||||
output = 'node "somenode" 4',
|
||||
recipe = {
|
||||
{'CraftItem "Stick" 1'},
|
||||
{'craft "Stick" 1'},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -151,11 +151,11 @@ minetest.register_node("somenode", {
|
||||
--
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "TNT" 4',
|
||||
output = 'node "TNT" 4',
|
||||
recipe = {
|
||||
{'NodeItem "wood" 1'},
|
||||
{'CraftItem "lump_of_coal" 1'},
|
||||
{'NodeItem "wood" 1'}
|
||||
{'node "wood" 1'},
|
||||
{'craft "lump_of_coal" 1'},
|
||||
{'node "wood" 1'}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -213,7 +213,7 @@ function TNT:on_punch(hitter)
|
||||
self.health = self.health - 1
|
||||
if self.health <= 0 then
|
||||
self.object:remove()
|
||||
hitter:add_to_inventory("NodeItem TNT 1")
|
||||
hitter:add_to_inventory("node TNT 1")
|
||||
hitter:set_hp(hitter:get_hp() - 1)
|
||||
end
|
||||
end
|
||||
@@ -259,7 +259,7 @@ minetest.register_entity("testentity", {
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
self.object:remove()
|
||||
hitter:add_to_inventory('CraftItem testobject1 1')
|
||||
hitter:add_to_inventory('craft testobject1 1')
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ minetest.register_on_newplayer(function(player)
|
||||
print("on_newplayer")
|
||||
if minetest.setting_getbool("give_initial_stuff") then
|
||||
print("giving give_initial_stuff to player")
|
||||
player:add_to_inventory('ToolItem "SteelPick" 0')
|
||||
player:add_to_inventory('NodeItem "torch" 99')
|
||||
player:add_to_inventory('ToolItem "SteelAxe" 0')
|
||||
player:add_to_inventory('ToolItem "SteelShovel" 0')
|
||||
player:add_to_inventory('NodeItem "cobble" 99')
|
||||
player:add_to_inventory('tool "SteelPick" 0')
|
||||
player:add_to_inventory('node "torch" 99')
|
||||
player:add_to_inventory('tool "SteelAxe" 0')
|
||||
player:add_to_inventory('tool "SteelShovel" 0')
|
||||
player:add_to_inventory('node "cobble" 99')
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
@@ -131,12 +131,14 @@
|
||||
#default_password =
|
||||
# Available privileges: build, teleport, settime, privs, shout
|
||||
#default_privs = build, shout
|
||||
# Whether players are transferred to client without any range limit
|
||||
#unlimited_player_transfer_distance = true
|
||||
# Whether to enable players killing each other
|
||||
#enable_pvp = true
|
||||
|
||||
# Profiler data print interval. #0 = disable.
|
||||
#profiler_print_interval = 0
|
||||
#enable_mapgen_debug_info = false
|
||||
# Player and object positions are sent at intervals specified by this
|
||||
#objectdata_interval = 0.2
|
||||
#active_object_send_range_blocks = 3
|
||||
#active_block_range = 2
|
||||
#max_simultaneous_block_sends_per_client = 2
|
||||
@@ -146,8 +148,8 @@
|
||||
#time_send_interval = 20
|
||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour
|
||||
#time_speed = 72
|
||||
#server_unload_unused_data_timeout = 60
|
||||
#server_map_save_interval = 60
|
||||
#server_unload_unused_data_timeout = 29
|
||||
#server_map_save_interval = 5.3
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
# Set to true to enable experimental features or stuff that is tested
|
||||
# (varies from version to version, usually not useful at all)
|
||||
|
||||
6393
misc/map.cpp
6393
misc/map.cpp
File diff suppressed because it is too large
Load Diff
11
misc/minetest.desktop
Normal file
11
misc/minetest.desktop
Normal file
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Name=Minetest
|
||||
GenericName=Minetest
|
||||
Comment=Multiplayer infinite-world block sandbox
|
||||
Exec=minetest
|
||||
Icon=minetest-icon
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Game;
|
||||
StartupNotify=false
|
||||
|
||||
410
misc/noise.cpp
410
misc/noise.cpp
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "noise.h"
|
||||
#include <iostream>
|
||||
#include "debug.h"
|
||||
|
||||
#define NOISE_MAGIC_X 1619
|
||||
#define NOISE_MAGIC_Y 31337
|
||||
#define NOISE_MAGIC_Z 52591
|
||||
#define NOISE_MAGIC_SEED 1013
|
||||
|
||||
double cos_lookup[16] = {
|
||||
1.0,0.9238,0.7071,0.3826,0,-0.3826,-0.7071,-0.9238,
|
||||
1.0,-0.9238,-0.7071,-0.3826,0,0.3826,0.7071,0.9238
|
||||
};
|
||||
|
||||
double dotProduct(double vx, double vy, double wx, double wy){
|
||||
return vx*wx+vy*wy;
|
||||
}
|
||||
|
||||
double easeCurve(double t){
|
||||
return 6*pow(t,5)-15*pow(t,4)+10*pow(t,3);
|
||||
}
|
||||
|
||||
double linearInterpolation(double x0, double x1, double t){
|
||||
return x0+(x1-x0)*t;
|
||||
}
|
||||
|
||||
double biLinearInterpolation(double x0y0, double x1y0, double x0y1, double x1y1, double x, double y){
|
||||
double tx = easeCurve(x);
|
||||
double ty = easeCurve(y);
|
||||
/*double tx = x;
|
||||
double ty = y;*/
|
||||
double u = linearInterpolation(x0y0,x1y0,tx);
|
||||
double v = linearInterpolation(x0y1,x1y1,tx);
|
||||
return linearInterpolation(u,v,ty);
|
||||
}
|
||||
|
||||
double triLinearInterpolation(
|
||||
double v000, double v100, double v010, double v110,
|
||||
double v001, double v101, double v011, double v111,
|
||||
double x, double y, double z)
|
||||
{
|
||||
/*double tx = easeCurve(x);
|
||||
double ty = easeCurve(y);
|
||||
double tz = easeCurve(z);*/
|
||||
double tx = x;
|
||||
double ty = y;
|
||||
double tz = z;
|
||||
return(
|
||||
v000*(1-tx)*(1-ty)*(1-tz) +
|
||||
v100*tx*(1-ty)*(1-tz) +
|
||||
v010*(1-tx)*ty*(1-tz) +
|
||||
v110*tx*ty*(1-tz) +
|
||||
v001*(1-tx)*(1-ty)*tz +
|
||||
v101*tx*(1-ty)*tz +
|
||||
v011*(1-tx)*ty*tz +
|
||||
v111*tx*ty*tz
|
||||
);
|
||||
}
|
||||
|
||||
double noise2d(int x, int y, int seed)
|
||||
{
|
||||
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
|
||||
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
|
||||
n = (n>>13)^n;
|
||||
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
|
||||
return 1.0 - (double)n/1073741824;
|
||||
}
|
||||
|
||||
double noise3d(int x, int y, int z, int seed)
|
||||
{
|
||||
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
|
||||
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
|
||||
n = (n>>13)^n;
|
||||
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
|
||||
return 1.0 - (double)n/1073741824;
|
||||
}
|
||||
|
||||
#if 0
|
||||
double noise2d_gradient(double x, double y, int seed)
|
||||
{
|
||||
// Calculate the integer coordinates
|
||||
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
|
||||
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
|
||||
// Calculate the remaining part of the coordinates
|
||||
double xl = x - (double)x0;
|
||||
double yl = y - (double)y0;
|
||||
// Calculate random cosine lookup table indices for the integer corners.
|
||||
// They are looked up as unit vector gradients from the lookup table.
|
||||
int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
|
||||
int n10 = (int)((noise2d(x0+1, y0, seed)+1)*8);
|
||||
int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
|
||||
int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
|
||||
// Make a dot product for the gradients and the positions, to get the values
|
||||
double s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
|
||||
double u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
|
||||
double v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
|
||||
double w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
|
||||
// Interpolate between the values
|
||||
return biLinearInterpolation(s,u,v,w,xl,yl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
double noise2d_gradient(double x, double y, int seed)
|
||||
{
|
||||
// Calculate the integer coordinates
|
||||
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
|
||||
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
|
||||
// Calculate the remaining part of the coordinates
|
||||
double xl = x - (double)x0;
|
||||
double yl = y - (double)y0;
|
||||
// Get values for corners of cube
|
||||
double v00 = noise2d(x0, y0, seed);
|
||||
double v10 = noise2d(x0+1, y0, seed);
|
||||
double v01 = noise2d(x0, y0+1, seed);
|
||||
double v11 = noise2d(x0+1, y0+1, seed);
|
||||
// Interpolate
|
||||
return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
|
||||
}
|
||||
#endif
|
||||
|
||||
double noise3d_gradient(double x, double y, double z, int seed)
|
||||
{
|
||||
// Calculate the integer coordinates
|
||||
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
|
||||
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
|
||||
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
|
||||
// Calculate the remaining part of the coordinates
|
||||
double xl = x - (double)x0;
|
||||
double yl = y - (double)y0;
|
||||
double zl = z - (double)z0;
|
||||
// Get values for corners of cube
|
||||
double v000 = noise3d(x0, y0, z0, seed);
|
||||
double v100 = noise3d(x0+1, y0, z0, seed);
|
||||
double v010 = noise3d(x0, y0+1, z0, seed);
|
||||
double v110 = noise3d(x0+1, y0+1, z0, seed);
|
||||
double v001 = noise3d(x0, y0, z0+1, seed);
|
||||
double v101 = noise3d(x0+1, y0, z0+1, seed);
|
||||
double v011 = noise3d(x0, y0+1, z0+1, seed);
|
||||
double v111 = noise3d(x0+1, y0+1, z0+1, seed);
|
||||
// Interpolate
|
||||
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
|
||||
}
|
||||
|
||||
double noise2d_perlin(double x, double y, int seed,
|
||||
int octaves, double persistence)
|
||||
{
|
||||
double a = 0;
|
||||
double f = 1.0;
|
||||
double g = 1.0;
|
||||
for(int i=0; i<octaves; i++)
|
||||
{
|
||||
a += g * noise2d_gradient(x*f, y*f, seed+i);
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
double noise2d_perlin_abs(double x, double y, int seed,
|
||||
int octaves, double persistence)
|
||||
{
|
||||
double a = 0;
|
||||
double f = 1.0;
|
||||
double g = 1.0;
|
||||
for(int i=0; i<octaves; i++)
|
||||
{
|
||||
a += g * fabs(noise2d_gradient(x*f, y*f, seed+i));
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
double noise3d_perlin(double x, double y, double z, int seed,
|
||||
int octaves, double persistence)
|
||||
{
|
||||
double a = 0;
|
||||
double f = 1.0;
|
||||
double g = 1.0;
|
||||
for(int i=0; i<octaves; i++)
|
||||
{
|
||||
a += g * noise3d_gradient(x*f, y*f, z*f, seed+i);
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
double noise3d_perlin_abs(double x, double y, double z, int seed,
|
||||
int octaves, double persistence)
|
||||
{
|
||||
double a = 0;
|
||||
double f = 1.0;
|
||||
double g = 1.0;
|
||||
for(int i=0; i<octaves; i++)
|
||||
{
|
||||
a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i));
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// -1->0, 0->1, 1->0
|
||||
double contour(double v)
|
||||
{
|
||||
v = fabs(v);
|
||||
if(v >= 1.0)
|
||||
return 0.0;
|
||||
return (1.0-v);
|
||||
}
|
||||
|
||||
double noise3d_param(const NoiseParams ¶m, double x, double y, double z)
|
||||
{
|
||||
double s = param.pos_scale;
|
||||
x /= s;
|
||||
y /= s;
|
||||
z /= s;
|
||||
|
||||
if(param.type == NOISE_PERLIN)
|
||||
{
|
||||
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
|
||||
param.octaves,
|
||||
param.persistence);
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_ABS)
|
||||
{
|
||||
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
|
||||
param.octaves,
|
||||
param.persistence);
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_CONTOUR)
|
||||
{
|
||||
return contour(param.noise_scale*noise3d_perlin(x,y,z,
|
||||
param.seed, param.octaves,
|
||||
param.persistence));
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
|
||||
{
|
||||
return contour(param.noise_scale*noise3d_perlin(x,z,y,
|
||||
param.seed, param.octaves,
|
||||
param.persistence));
|
||||
}
|
||||
else assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
NoiseBuffer
|
||||
*/
|
||||
|
||||
NoiseBuffer::NoiseBuffer():
|
||||
m_data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
NoiseBuffer::~NoiseBuffer()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void NoiseBuffer::clear()
|
||||
{
|
||||
if(m_data)
|
||||
delete[] m_data;
|
||||
m_data = NULL;
|
||||
m_size_x = 0;
|
||||
m_size_y = 0;
|
||||
m_size_z = 0;
|
||||
}
|
||||
|
||||
void NoiseBuffer::create(const NoiseParams ¶m,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||
{
|
||||
clear();
|
||||
|
||||
m_start_x = first_x - samplelength_x;
|
||||
m_start_y = first_y - samplelength_y;
|
||||
m_start_z = first_z - samplelength_z;
|
||||
m_samplelength_x = samplelength_x;
|
||||
m_samplelength_y = samplelength_y;
|
||||
m_samplelength_z = samplelength_z;
|
||||
|
||||
m_size_x = (last_x - m_start_x)/samplelength_x + 2;
|
||||
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
|
||||
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
|
||||
|
||||
m_data = new double[m_size_x*m_size_y*m_size_z];
|
||||
|
||||
for(int x=0; x<m_size_x; x++)
|
||||
for(int y=0; y<m_size_y; y++)
|
||||
for(int z=0; z<m_size_z; z++)
|
||||
{
|
||||
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||
double a = noise3d_param(param, xd,yd,zd);
|
||||
intSet(x,y,z, a);
|
||||
}
|
||||
}
|
||||
|
||||
void NoiseBuffer::multiply(const NoiseParams ¶m)
|
||||
{
|
||||
assert(m_data != NULL);
|
||||
|
||||
for(int x=0; x<m_size_x; x++)
|
||||
for(int y=0; y<m_size_y; y++)
|
||||
for(int z=0; z<m_size_z; z++)
|
||||
{
|
||||
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||
double a = noise3d_param(param, xd,yd,zd);
|
||||
intMultiply(x,y,z, a);
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
void NoiseBuffer::create(int seed, int octaves, double persistence,
|
||||
bool abs,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||
{
|
||||
NoiseParams param;
|
||||
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
|
||||
param.seed = seed;
|
||||
param.octaves = octaves;
|
||||
param.persistence = persistence;
|
||||
|
||||
create(param, first_x, first_y, first_z,
|
||||
last_x, last_y, last_z,
|
||||
samplelength_x, samplelength_y, samplelength_z);
|
||||
}
|
||||
|
||||
void NoiseBuffer::intSet(int x, int y, int z, double d)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
assert(i >= 0);
|
||||
assert(i < m_size_x*m_size_y*m_size_z);
|
||||
m_data[i] = d;
|
||||
}
|
||||
|
||||
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
assert(i >= 0);
|
||||
assert(i < m_size_x*m_size_y*m_size_z);
|
||||
m_data[i] = m_data[i] * d;
|
||||
}
|
||||
|
||||
double NoiseBuffer::intGet(int x, int y, int z)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
assert(i >= 0);
|
||||
assert(i < m_size_x*m_size_y*m_size_z);
|
||||
return m_data[i];
|
||||
}
|
||||
|
||||
double NoiseBuffer::get(double x, double y, double z)
|
||||
{
|
||||
x -= m_start_x;
|
||||
y -= m_start_y;
|
||||
z -= m_start_z;
|
||||
x /= m_samplelength_x;
|
||||
y /= m_samplelength_y;
|
||||
z /= m_samplelength_z;
|
||||
// Calculate the integer coordinates
|
||||
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
|
||||
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
|
||||
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
|
||||
// Calculate the remaining part of the coordinates
|
||||
double xl = x - (double)x0;
|
||||
double yl = y - (double)y0;
|
||||
double zl = z - (double)z0;
|
||||
// Get values for corners of cube
|
||||
double v000 = intGet(x0, y0, z0);
|
||||
double v100 = intGet(x0+1, y0, z0);
|
||||
double v010 = intGet(x0, y0+1, z0);
|
||||
double v110 = intGet(x0+1, y0+1, z0);
|
||||
double v001 = intGet(x0, y0, z0+1);
|
||||
double v101 = intGet(x0+1, y0, z0+1);
|
||||
double v011 = intGet(x0, y0+1, z0+1);
|
||||
double v111 = intGet(x0+1, y0+1, z0+1);
|
||||
// Interpolate
|
||||
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
|
||||
}
|
||||
|
||||
108
misc/noise.h
108
misc/noise.h
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef NOISE_HEADER
|
||||
#define NOISE_HEADER
|
||||
|
||||
double easeCurve(double t);
|
||||
|
||||
// Return value: -1 ... 1
|
||||
double noise2d(int x, int y, int seed);
|
||||
double noise3d(int x, int y, int z, int seed);
|
||||
|
||||
double noise2d_gradient(double x, double y, int seed);
|
||||
double noise3d_gradient(double x, double y, double z, int seed);
|
||||
|
||||
double noise2d_perlin(double x, double y, int seed,
|
||||
int octaves, double persistence);
|
||||
|
||||
double noise2d_perlin_abs(double x, double y, int seed,
|
||||
int octaves, double persistence);
|
||||
|
||||
double noise3d_perlin(double x, double y, double z, int seed,
|
||||
int octaves, double persistence);
|
||||
|
||||
double noise3d_perlin_abs(double x, double y, double z, int seed,
|
||||
int octaves, double persistence);
|
||||
|
||||
enum NoiseType
|
||||
{
|
||||
NOISE_PERLIN,
|
||||
NOISE_PERLIN_ABS,
|
||||
NOISE_PERLIN_CONTOUR,
|
||||
NOISE_PERLIN_CONTOUR_FLIP_YZ
|
||||
};
|
||||
|
||||
struct NoiseParams
|
||||
{
|
||||
NoiseType type;
|
||||
int seed;
|
||||
int octaves;
|
||||
double persistence;
|
||||
double pos_scale;
|
||||
double noise_scale; // Useful for contour noises
|
||||
|
||||
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
|
||||
int octaves_=3, double persistence_=0.5,
|
||||
double pos_scale_=100.0, double noise_scale_=1.0):
|
||||
type(type_),
|
||||
seed(seed_),
|
||||
octaves(octaves_),
|
||||
persistence(persistence_),
|
||||
pos_scale(pos_scale_),
|
||||
noise_scale(noise_scale_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
double noise3d_param(const NoiseParams ¶m, double x, double y, double z);
|
||||
|
||||
class NoiseBuffer
|
||||
{
|
||||
public:
|
||||
NoiseBuffer();
|
||||
~NoiseBuffer();
|
||||
|
||||
void clear();
|
||||
void create(const NoiseParams ¶m,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||
void multiply(const NoiseParams ¶m);
|
||||
// Deprecated
|
||||
void create(int seed, int octaves, double persistence,
|
||||
bool abs,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||
|
||||
void intSet(int x, int y, int z, double d);
|
||||
void intMultiply(int x, int y, int z, double d);
|
||||
double intGet(int x, int y, int z);
|
||||
double get(double x, double y, double z);
|
||||
|
||||
private:
|
||||
double *m_data;
|
||||
double m_start_x, m_start_y, m_start_z;
|
||||
double m_samplelength_x, m_samplelength_y, m_samplelength_z;
|
||||
int m_size_x, m_size_y, m_size_z;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,6 +94,7 @@ configure_file(
|
||||
)
|
||||
|
||||
set(common_SRCS
|
||||
serverremoteplayer.cpp
|
||||
content_abm.cpp
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
@@ -107,7 +108,6 @@ set(common_SRCS
|
||||
content_sao.cpp
|
||||
mapgen.cpp
|
||||
content_nodemeta.cpp
|
||||
content_craft.cpp
|
||||
content_mapnode.cpp
|
||||
auth.cpp
|
||||
collision.cpp
|
||||
|
||||
18
src/auth.cpp
18
src/auth.cpp
@@ -28,8 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
std::set<std::string> privsToSet(u64 privs)
|
||||
{
|
||||
std::set<std::string> s;
|
||||
if(privs & PRIV_BUILD)
|
||||
s.insert("build");
|
||||
if(privs & PRIV_INTERACT)
|
||||
s.insert("interact");
|
||||
if(privs & PRIV_TELEPORT)
|
||||
s.insert("teleport");
|
||||
if(privs & PRIV_SETTIME)
|
||||
@@ -42,6 +42,8 @@ std::set<std::string> privsToSet(u64 privs)
|
||||
s.insert("ban");
|
||||
if(privs & PRIV_GIVE)
|
||||
s.insert("give");
|
||||
if(privs & PRIV_PASSWORD)
|
||||
s.insert("password");
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -50,8 +52,8 @@ std::set<std::string> privsToSet(u64 privs)
|
||||
std::string privsToString(u64 privs)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
if(privs & PRIV_BUILD)
|
||||
os<<"build,";
|
||||
if(privs & PRIV_INTERACT)
|
||||
os<<"interact,";
|
||||
if(privs & PRIV_TELEPORT)
|
||||
os<<"teleport,";
|
||||
if(privs & PRIV_SETTIME)
|
||||
@@ -64,6 +66,8 @@ std::string privsToString(u64 privs)
|
||||
os<<"ban,";
|
||||
if(privs & PRIV_GIVE)
|
||||
os<<"give,";
|
||||
if(privs & PRIV_PASSWORD)
|
||||
os<<"password,";
|
||||
if(os.tellp())
|
||||
{
|
||||
// Drop the trailing comma. (Why on earth can't
|
||||
@@ -85,7 +89,9 @@ u64 stringToPrivs(std::string str)
|
||||
{
|
||||
std::string s = trim(f.next(","));
|
||||
if(s == "build")
|
||||
privs |= PRIV_BUILD;
|
||||
privs |= PRIV_INTERACT;
|
||||
else if(s == "interact")
|
||||
privs |= PRIV_INTERACT;
|
||||
else if(s == "teleport")
|
||||
privs |= PRIV_TELEPORT;
|
||||
else if(s == "settime")
|
||||
@@ -98,6 +104,8 @@ u64 stringToPrivs(std::string str)
|
||||
privs |= PRIV_BAN;
|
||||
else if(s == "give")
|
||||
privs |= PRIV_GIVE;
|
||||
else if(s == "password")
|
||||
privs |= PRIV_PASSWORD;
|
||||
else
|
||||
return PRIV_INVALID;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// of the player, and define things they're allowed to do. See also
|
||||
// the static methods Player::privsToString and stringToPrivs that
|
||||
// convert these to human-readable form.
|
||||
const u64 PRIV_BUILD = 1; // Can build - i.e. modify the world
|
||||
const u64 PRIV_INTERACT = 1; // Can interact
|
||||
const u64 PRIV_TELEPORT = 2; // Can teleport
|
||||
const u64 PRIV_SETTIME = 4; // Can set the time
|
||||
const u64 PRIV_PRIVS = 8; // Can grant and revoke privileges
|
||||
@@ -41,11 +41,12 @@ const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all
|
||||
// players
|
||||
const u64 PRIV_BAN = 64; // Can ban players
|
||||
const u64 PRIV_GIVE = 128; // Can give stuff
|
||||
const u64 PRIV_PASSWORD = 256; // Can set other players' passwords
|
||||
|
||||
// Default privileges - these can be overriden for new players using the
|
||||
// config option "default_privs" - however, this value still applies for
|
||||
// players that existed before the privileges system was added.
|
||||
const u64 PRIV_DEFAULT = PRIV_BUILD|PRIV_SHOUT;
|
||||
const u64 PRIV_DEFAULT = PRIV_INTERACT|PRIV_SHOUT;
|
||||
const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL;
|
||||
const u64 PRIV_INVALID = 0x8000000000000000ULL;
|
||||
|
||||
|
||||
@@ -29,6 +29,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "nodedef.h" // For wield visualization
|
||||
|
||||
// In Irrlicht 1.8 the signature of ITexture::lock was changed from
|
||||
// (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
|
||||
#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
|
||||
#define MY_ETLM_READ_ONLY true
|
||||
#else
|
||||
#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
|
||||
#endif
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
m_smgr(smgr),
|
||||
m_playernode(NULL),
|
||||
@@ -832,7 +840,7 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
|
||||
{
|
||||
// Texture is in the correct color format, we can pass it
|
||||
// to extrudeARGB right away.
|
||||
void* data = texture->lock(true);
|
||||
void* data = texture->lock(MY_ETLM_READ_ONLY);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
|
||||
@@ -842,7 +850,7 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(true));
|
||||
video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(MY_ETLM_READ_ONLY));
|
||||
if (img1 == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IAnimatedMesh.h>
|
||||
|
||||
class LocalPlayer;
|
||||
class MapDrawControl;
|
||||
struct MapDrawControl;
|
||||
class ExtrudedSpriteSceneNode;
|
||||
class IGameDef;
|
||||
|
||||
|
||||
311
src/client.cpp
311
src/client.cpp
@@ -205,7 +205,7 @@ Client::Client(
|
||||
device->getSceneManager()->getRootSceneNode(),
|
||||
device->getSceneManager(), 666),
|
||||
device->getSceneManager(),
|
||||
tsrc, this
|
||||
tsrc, this, device
|
||||
),
|
||||
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
||||
m_device(device),
|
||||
@@ -566,7 +566,9 @@ void Client::step(float dtime)
|
||||
if(m_ignore_damage_timer <= 0)
|
||||
{
|
||||
u8 damage = event.player_damage.amount;
|
||||
sendDamage(damage);
|
||||
|
||||
if(event.player_damage.send_to_server)
|
||||
sendDamage(damage);
|
||||
|
||||
// Add to ClientEvent queue
|
||||
ClientEvent event;
|
||||
@@ -940,219 +942,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
//infostream<<"Adding mesh update task for received block"<<std::endl;
|
||||
addUpdateMeshTaskWithEdge(p, true);
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYERPOS)
|
||||
{
|
||||
infostream<<"Received deprecated TOCLIENT_PLAYERPOS"
|
||||
<<std::endl;
|
||||
/*u16 our_peer_id;
|
||||
{
|
||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||
our_peer_id = m_con.GetPeerID();
|
||||
}
|
||||
// Cancel if we don't have a peer id
|
||||
if(our_peer_id == PEER_ID_INEXISTENT){
|
||||
infostream<<"TOCLIENT_PLAYERPOS cancelled: "
|
||||
"we have no peer id"
|
||||
<<std::endl;
|
||||
return;
|
||||
}*/
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
u32 player_size = 2+12+12+4+4;
|
||||
|
||||
u32 player_count = (datasize-2) / player_size;
|
||||
u32 start = 2;
|
||||
for(u32 i=0; i<player_count; i++)
|
||||
{
|
||||
u16 peer_id = readU16(&data[start]);
|
||||
|
||||
Player *player = m_env.getPlayer(peer_id);
|
||||
|
||||
// Skip if player doesn't exist
|
||||
if(player == NULL)
|
||||
{
|
||||
start += player_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if player is local player
|
||||
if(player->isLocal())
|
||||
{
|
||||
start += player_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
v3s32 ps = readV3S32(&data[start+2]);
|
||||
v3s32 ss = readV3S32(&data[start+2+12]);
|
||||
s32 pitch_i = readS32(&data[start+2+12+12]);
|
||||
s32 yaw_i = readS32(&data[start+2+12+12+4]);
|
||||
/*infostream<<"Client: got "
|
||||
<<"pitch_i="<<pitch_i
|
||||
<<" yaw_i="<<yaw_i<<std::endl;*/
|
||||
f32 pitch = (f32)pitch_i / 100.0;
|
||||
f32 yaw = (f32)yaw_i / 100.0;
|
||||
v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
|
||||
v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
|
||||
player->setPosition(position);
|
||||
player->setSpeed(speed);
|
||||
player->setPitch(pitch);
|
||||
player->setYaw(yaw);
|
||||
|
||||
/*infostream<<"Client: player "<<peer_id
|
||||
<<" pitch="<<pitch
|
||||
<<" yaw="<<yaw<<std::endl;*/
|
||||
|
||||
start += player_size;
|
||||
}
|
||||
} //envlock
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYERINFO)
|
||||
{
|
||||
u16 our_peer_id;
|
||||
{
|
||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||
our_peer_id = m_con.GetPeerID();
|
||||
}
|
||||
// Cancel if we don't have a peer id
|
||||
if(our_peer_id == PEER_ID_INEXISTENT){
|
||||
infostream<<"TOCLIENT_PLAYERINFO cancelled: "
|
||||
"we have no peer id"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//infostream<<"Client: Server reports players:"<<std::endl;
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
u32 item_size = 2+PLAYERNAME_SIZE;
|
||||
u32 player_count = (datasize-2) / item_size;
|
||||
u32 start = 2;
|
||||
// peer_ids
|
||||
core::list<u16> players_alive;
|
||||
for(u32 i=0; i<player_count; i++)
|
||||
{
|
||||
// Make sure the name ends in '\0'
|
||||
data[start+2+20-1] = 0;
|
||||
|
||||
u16 peer_id = readU16(&data[start]);
|
||||
|
||||
players_alive.push_back(peer_id);
|
||||
|
||||
/*infostream<<"peer_id="<<peer_id
|
||||
<<" name="<<((char*)&data[start+2])<<std::endl;*/
|
||||
|
||||
// Don't update the info of the local player
|
||||
if(peer_id == our_peer_id)
|
||||
{
|
||||
start += item_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
Player *player = m_env.getPlayer(peer_id);
|
||||
|
||||
// Create a player if it doesn't exist
|
||||
if(player == NULL)
|
||||
{
|
||||
player = new RemotePlayer(this,
|
||||
m_device->getSceneManager()->getRootSceneNode(),
|
||||
m_device,
|
||||
-1);
|
||||
player->peer_id = peer_id;
|
||||
m_env.addPlayer(player);
|
||||
infostream<<"Client: Adding new player "
|
||||
<<peer_id<<std::endl;
|
||||
}
|
||||
|
||||
player->updateName((char*)&data[start+2]);
|
||||
|
||||
start += item_size;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove those players from the environment that
|
||||
weren't listed by the server.
|
||||
*/
|
||||
//infostream<<"Removing dead players"<<std::endl;
|
||||
core::list<Player*> players = m_env.getPlayers();
|
||||
core::list<Player*>::Iterator ip;
|
||||
for(ip=players.begin(); ip!=players.end(); ip++)
|
||||
{
|
||||
// Ingore local player
|
||||
if((*ip)->isLocal())
|
||||
continue;
|
||||
|
||||
// Warn about a special case
|
||||
if((*ip)->peer_id == 0)
|
||||
{
|
||||
infostream<<"Client: Removing "
|
||||
"dead player with id=0"<<std::endl;
|
||||
}
|
||||
|
||||
bool is_alive = false;
|
||||
core::list<u16>::Iterator i;
|
||||
for(i=players_alive.begin(); i!=players_alive.end(); i++)
|
||||
{
|
||||
if((*ip)->peer_id == *i)
|
||||
{
|
||||
is_alive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*infostream<<"peer_id="<<((*ip)->peer_id)
|
||||
<<" is_alive="<<is_alive<<std::endl;*/
|
||||
if(is_alive)
|
||||
continue;
|
||||
infostream<<"Removing dead player "<<(*ip)->peer_id
|
||||
<<std::endl;
|
||||
m_env.removePlayer((*ip)->peer_id);
|
||||
}
|
||||
} //envlock
|
||||
}
|
||||
else if(command == TOCLIENT_SECTORMETA)
|
||||
{
|
||||
infostream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl;
|
||||
#if 0
|
||||
/*
|
||||
[0] u16 command
|
||||
[2] u8 sector count
|
||||
[3...] v2s16 pos + sector metadata
|
||||
*/
|
||||
if(datasize < 3)
|
||||
return;
|
||||
|
||||
//infostream<<"Client received TOCLIENT_SECTORMETA"<<std::endl;
|
||||
|
||||
{ //envlock
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u8 buf[4];
|
||||
|
||||
is.read((char*)buf, 1);
|
||||
u16 sector_count = readU8(buf);
|
||||
|
||||
//infostream<<"sector_count="<<sector_count<<std::endl;
|
||||
|
||||
for(u16 i=0; i<sector_count; i++)
|
||||
{
|
||||
// Read position
|
||||
is.read((char*)buf, 4);
|
||||
v2s16 pos = readV2S16(buf);
|
||||
/*infostream<<"Client: deserializing sector at "
|
||||
<<"("<<pos.X<<","<<pos.Y<<")"<<std::endl;*/
|
||||
// Create sector
|
||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
||||
((ClientMap&)m_env.getMap()).deSerializeSector(pos, is);
|
||||
}
|
||||
} //envlock
|
||||
#endif
|
||||
}
|
||||
else if(command == TOCLIENT_INVENTORY)
|
||||
{
|
||||
if(datasize < 3)
|
||||
@@ -1187,73 +976,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
//player->inventory.print(infostream);
|
||||
}
|
||||
}
|
||||
//DEBUG
|
||||
else if(command == TOCLIENT_OBJECTDATA)
|
||||
{
|
||||
// Strip command word and create a stringstream
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u8 buf[12];
|
||||
|
||||
/*
|
||||
Read players
|
||||
*/
|
||||
|
||||
is.read((char*)buf, 2);
|
||||
u16 playercount = readU16(buf);
|
||||
|
||||
for(u16 i=0; i<playercount; i++)
|
||||
{
|
||||
is.read((char*)buf, 2);
|
||||
u16 peer_id = readU16(buf);
|
||||
is.read((char*)buf, 12);
|
||||
v3s32 p_i = readV3S32(buf);
|
||||
is.read((char*)buf, 12);
|
||||
v3s32 s_i = readV3S32(buf);
|
||||
is.read((char*)buf, 4);
|
||||
s32 pitch_i = readS32(buf);
|
||||
is.read((char*)buf, 4);
|
||||
s32 yaw_i = readS32(buf);
|
||||
|
||||
Player *player = m_env.getPlayer(peer_id);
|
||||
|
||||
// Skip if player doesn't exist
|
||||
if(player == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if player is local player
|
||||
if(player->isLocal())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
f32 pitch = (f32)pitch_i / 100.0;
|
||||
f32 yaw = (f32)yaw_i / 100.0;
|
||||
v3f position((f32)p_i.X/100., (f32)p_i.Y/100., (f32)p_i.Z/100.);
|
||||
v3f speed((f32)s_i.X/100., (f32)s_i.Y/100., (f32)s_i.Z/100.);
|
||||
|
||||
player->setPosition(position);
|
||||
player->setSpeed(speed);
|
||||
player->setPitch(pitch);
|
||||
player->setYaw(yaw);
|
||||
}
|
||||
|
||||
/*
|
||||
Read block objects
|
||||
NOTE: Deprecated stuff
|
||||
*/
|
||||
|
||||
// Read active block count
|
||||
u16 blockcount = readU16(is);
|
||||
if(blockcount != 0){
|
||||
infostream<<"TOCLIENT_OBJECTDATA: blockcount != 0 "
|
||||
"not supported"<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(command == TOCLIENT_TIME_OF_DAY)
|
||||
{
|
||||
if(datasize < 4)
|
||||
@@ -1519,7 +1241,12 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
m_mesh_update_thread.setRun(false);
|
||||
// Process the remaining TextureSource queue to let MeshUpdateThread
|
||||
// get it's remaining textures and thus let it stop
|
||||
while(m_mesh_update_thread.IsRunning()){
|
||||
m_tsrc->processQueue();
|
||||
}
|
||||
|
||||
/*
|
||||
u16 command
|
||||
@@ -1595,8 +1322,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
m_tooldef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
m_mesh_update_thread.setRun(false);
|
||||
// Process the remaining TextureSource queue to let MeshUpdateThread
|
||||
// get it's remaining textures and thus let it stop
|
||||
while(m_mesh_update_thread.IsRunning()){
|
||||
m_tsrc->processQueue();
|
||||
}
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_tooldef->deSerialize(tmp_is);
|
||||
|
||||
@@ -1644,8 +1376,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
m_craftitemdef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
m_mesh_update_thread.setRun(false);
|
||||
// Process the remaining TextureSource queue to let MeshUpdateThread
|
||||
// get it's remaining textures and thus let it stop
|
||||
while(m_mesh_update_thread.IsRunning()){
|
||||
m_tsrc->processQueue();
|
||||
}
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_craftitemdef->deSerialize(tmp_is);
|
||||
|
||||
|
||||
@@ -26,9 +26,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
ClientActiveObject
|
||||
*/
|
||||
|
||||
ClientActiveObject::ClientActiveObject(u16 id, IGameDef *gamedef):
|
||||
ClientActiveObject::ClientActiveObject(u16 id, IGameDef *gamedef,
|
||||
ClientEnvironment *env):
|
||||
ActiveObject(id),
|
||||
m_gamedef(gamedef)
|
||||
m_gamedef(gamedef),
|
||||
m_env(env)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -37,7 +39,8 @@ ClientActiveObject::~ClientActiveObject()
|
||||
removeFromScene();
|
||||
}
|
||||
|
||||
ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef)
|
||||
ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
||||
ClientEnvironment *env)
|
||||
{
|
||||
// Find factory function
|
||||
core::map<u16, Factory>::Node *n;
|
||||
@@ -51,7 +54,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef)
|
||||
}
|
||||
|
||||
Factory f = n->getValue();
|
||||
ClientActiveObject *object = (*f)(gamedef);
|
||||
ClientActiveObject *object = (*f)(gamedef, env);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,10 +42,11 @@ class IGameDef;
|
||||
class ClientActiveObject : public ActiveObject
|
||||
{
|
||||
public:
|
||||
ClientActiveObject(u16 id, IGameDef *gamedef);
|
||||
ClientActiveObject(u16 id, IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~ClientActiveObject();
|
||||
|
||||
virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc){}
|
||||
virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr){}
|
||||
virtual void removeFromScene(){}
|
||||
// 0 <= light_at_pos <= LIGHT_SUN
|
||||
virtual void updateLight(u8 light_at_pos){}
|
||||
@@ -70,7 +71,8 @@ class ClientActiveObject : public ActiveObject
|
||||
virtual void initialize(const std::string &data){}
|
||||
|
||||
// Create a certain type of ClientActiveObject
|
||||
static ClientActiveObject* create(u8 type, IGameDef *gamedef);
|
||||
static ClientActiveObject* create(u8 type, IGameDef *gamedef,
|
||||
ClientEnvironment *env);
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
virtual bool directReportPunch(const std::string &toolname, v3f dir)
|
||||
@@ -78,9 +80,10 @@ class ClientActiveObject : public ActiveObject
|
||||
|
||||
protected:
|
||||
// Used for creating objects based on type
|
||||
typedef ClientActiveObject* (*Factory)(IGameDef *gamedef);
|
||||
typedef ClientActiveObject* (*Factory)(IGameDef *gamedef, ClientEnvironment *env);
|
||||
static void registerType(u16 type, Factory f);
|
||||
IGameDef *m_gamedef;
|
||||
ClientEnvironment *m_env;
|
||||
private:
|
||||
// Used for creating objects based on type
|
||||
static core::map<u16, Factory> m_types;
|
||||
|
||||
@@ -35,9 +35,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
Add TOSERVER_INTERACT
|
||||
Obsolete TOSERVER_CLICK_ACTIVEOBJECT
|
||||
Obsolete TOSERVER_GROUND_ACTION
|
||||
PROTOCOL_VERSION 5:
|
||||
Make players to be handled mostly as ActiveObjects
|
||||
*/
|
||||
|
||||
#define PROTOCOL_VERSION 4
|
||||
#define PROTOCOL_VERSION 5
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
@@ -76,7 +78,7 @@ enum ToClientCommand
|
||||
[N+2+12+12+4] s32 yaw*100
|
||||
*/
|
||||
|
||||
TOCLIENT_PLAYERINFO = 0x24,
|
||||
TOCLIENT_PLAYERINFO = 0x24, // Obsolete
|
||||
/*
|
||||
[0] u16 command
|
||||
// Followed by an arbitary number of these:
|
||||
@@ -100,7 +102,7 @@ enum ToClientCommand
|
||||
[2] serialized inventory
|
||||
*/
|
||||
|
||||
TOCLIENT_OBJECTDATA = 0x28,
|
||||
TOCLIENT_OBJECTDATA = 0x28, // Obsolete
|
||||
/*
|
||||
Sent as unreliable.
|
||||
|
||||
|
||||
@@ -22,20 +22,393 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "environment.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <ITextSceneNode.h>
|
||||
#include "serialization.h" // For decompressZlib
|
||||
#include "gamedef.h"
|
||||
#include "clientobject.h"
|
||||
#include "content_object.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
class Settings;
|
||||
#include "MyBillboardSceneNode.h"
|
||||
|
||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
*/
|
||||
|
||||
struct SmoothTranslator
|
||||
{
|
||||
v3f vect_old;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
f32 anim_counter;
|
||||
f32 anim_time;
|
||||
f32 anim_time_counter;
|
||||
bool aim_is_end;
|
||||
|
||||
SmoothTranslator():
|
||||
vect_old(0,0,0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0),
|
||||
anim_counter(0),
|
||||
anim_time(0),
|
||||
anim_time_counter(0),
|
||||
aim_is_end(true)
|
||||
{}
|
||||
|
||||
void init(v3f vect)
|
||||
{
|
||||
vect_old = vect;
|
||||
vect_show = vect;
|
||||
vect_aim = vect;
|
||||
anim_counter = 0;
|
||||
anim_time = 0;
|
||||
anim_time_counter = 0;
|
||||
aim_is_end = true;
|
||||
}
|
||||
|
||||
void sharpen()
|
||||
{
|
||||
init(vect_show);
|
||||
}
|
||||
|
||||
void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
|
||||
{
|
||||
aim_is_end = is_end_position;
|
||||
vect_old = vect_show;
|
||||
vect_aim = vect_new;
|
||||
if(update_interval > 0){
|
||||
anim_time = update_interval;
|
||||
} else {
|
||||
if(anim_time < 0.001 || anim_time > 1.0)
|
||||
anim_time = anim_time_counter;
|
||||
else
|
||||
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
||||
}
|
||||
anim_time_counter = 0;
|
||||
anim_counter = 0;
|
||||
}
|
||||
|
||||
void translate(f32 dtime)
|
||||
{
|
||||
anim_time_counter = anim_time_counter + dtime;
|
||||
anim_counter = anim_counter + dtime;
|
||||
v3f vect_move = vect_aim - vect_old;
|
||||
f32 moveratio = 1.0;
|
||||
if(anim_time > 0.001)
|
||||
moveratio = anim_time_counter / anim_time;
|
||||
// Move a bit less than should, to avoid oscillation
|
||||
moveratio = moveratio * 0.8;
|
||||
float move_end = 1.5;
|
||||
if(aim_is_end)
|
||||
move_end = 1.0;
|
||||
if(moveratio > move_end)
|
||||
moveratio = move_end;
|
||||
vect_show = vect_old + vect_move * moveratio;
|
||||
}
|
||||
|
||||
bool is_moving()
|
||||
{
|
||||
return ((anim_time_counter / anim_time) < 1.4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
TestCAO
|
||||
*/
|
||||
|
||||
class TestCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
TestCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~TestCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_TEST;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
};
|
||||
|
||||
/*
|
||||
ItemCAO
|
||||
*/
|
||||
|
||||
class ItemCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~ItemCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_ITEM;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_inventorystring;
|
||||
};
|
||||
|
||||
/*
|
||||
RatCAO
|
||||
*/
|
||||
|
||||
class RatCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
RatCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~RatCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_RAT;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
Oerkki1CAO
|
||||
*/
|
||||
|
||||
class Oerkki1CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~Oerkki1CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_OERKKI1;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
float m_damage_visual_timer;
|
||||
bool m_damage_texture_enabled;
|
||||
};
|
||||
|
||||
/*
|
||||
FireflyCAO
|
||||
*/
|
||||
|
||||
class FireflyCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~FireflyCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_FIREFLY;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
class MobV2CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||
virtual ~MobV2CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_MOBV2;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
bool doShowSelectionBox(){return false;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
void setLooks(const std::string &looks);
|
||||
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::MyBillboardSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_texture_name;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
bool m_walking;
|
||||
float m_walking_unset_timer;
|
||||
float m_walk_timer;
|
||||
int m_walk_frame;
|
||||
float m_damage_visual_timer;
|
||||
u8 m_last_light;
|
||||
bool m_shooting;
|
||||
float m_shooting_unset_timer;
|
||||
v2f m_sprite_size;
|
||||
float m_sprite_y;
|
||||
bool m_bright_shooting;
|
||||
std::string m_sprite_type;
|
||||
int m_simple_anim_frames;
|
||||
float m_simple_anim_frametime;
|
||||
bool m_lock_full_brightness;
|
||||
int m_player_hit_damage;
|
||||
float m_player_hit_distance;
|
||||
float m_player_hit_interval;
|
||||
float m_player_hit_timer;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
/*
|
||||
TestCAO
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
TestCAO proto_TestCAO(NULL);
|
||||
TestCAO proto_TestCAO(NULL, NULL);
|
||||
|
||||
TestCAO::TestCAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0))
|
||||
{
|
||||
@@ -46,12 +419,13 @@ TestCAO::~TestCAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* TestCAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new TestCAO(gamedef);
|
||||
return new TestCAO(gamedef, env);
|
||||
}
|
||||
|
||||
void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -147,10 +521,10 @@ void TestCAO::processMessage(const std::string &data)
|
||||
#include "inventory.h"
|
||||
|
||||
// Prototype
|
||||
ItemCAO proto_ItemCAO(NULL);
|
||||
ItemCAO proto_ItemCAO(NULL, NULL);
|
||||
|
||||
ItemCAO::ItemCAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0))
|
||||
@@ -162,12 +536,13 @@ ItemCAO::~ItemCAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* ItemCAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new ItemCAO(gamedef);
|
||||
return new ItemCAO(gamedef, env);
|
||||
}
|
||||
|
||||
void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -288,7 +663,7 @@ void ItemCAO::step(float dtime, ClientEnvironment *env)
|
||||
|
||||
void ItemCAO::processMessage(const std::string &data)
|
||||
{
|
||||
infostream<<"ItemCAO: Got message"<<std::endl;
|
||||
//infostream<<"ItemCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -327,10 +702,10 @@ void ItemCAO::initialize(const std::string &data)
|
||||
#include "inventory.h"
|
||||
|
||||
// Prototype
|
||||
RatCAO proto_RatCAO(NULL);
|
||||
RatCAO proto_RatCAO(NULL, NULL);
|
||||
|
||||
RatCAO::RatCAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
@@ -343,12 +718,13 @@ RatCAO::~RatCAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* RatCAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new RatCAO(gamedef);
|
||||
return new RatCAO(gamedef, env);
|
||||
}
|
||||
|
||||
void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -472,10 +848,10 @@ void RatCAO::initialize(const std::string &data)
|
||||
#include "inventory.h"
|
||||
|
||||
// Prototype
|
||||
Oerkki1CAO proto_Oerkki1CAO(NULL);
|
||||
Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
|
||||
|
||||
Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
@@ -490,12 +866,13 @@ Oerkki1CAO::~Oerkki1CAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new Oerkki1CAO(gamedef);
|
||||
return new Oerkki1CAO(gamedef, env);
|
||||
}
|
||||
|
||||
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -712,10 +1089,10 @@ bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
FireflyCAO proto_FireflyCAO(NULL);
|
||||
FireflyCAO proto_FireflyCAO(NULL, NULL);
|
||||
|
||||
FireflyCAO::FireflyCAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
@@ -728,12 +1105,13 @@ FireflyCAO::~FireflyCAO()
|
||||
{
|
||||
}
|
||||
|
||||
ClientActiveObject* FireflyCAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new FireflyCAO(gamedef);
|
||||
return new FireflyCAO(gamedef, env);
|
||||
}
|
||||
|
||||
void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -855,10 +1233,10 @@ void FireflyCAO::initialize(const std::string &data)
|
||||
*/
|
||||
|
||||
// Prototype
|
||||
MobV2CAO proto_MobV2CAO(NULL);
|
||||
MobV2CAO proto_MobV2CAO(NULL, NULL);
|
||||
|
||||
MobV2CAO::MobV2CAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef),
|
||||
MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
|
||||
m_node(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
@@ -887,12 +1265,13 @@ MobV2CAO::~MobV2CAO()
|
||||
delete m_properties;
|
||||
}
|
||||
|
||||
ClientActiveObject* MobV2CAO::create(IGameDef *gamedef)
|
||||
ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new MobV2CAO(gamedef);
|
||||
return new MobV2CAO(gamedef, env);
|
||||
}
|
||||
|
||||
void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
@@ -1269,7 +1648,7 @@ void MobV2CAO::setLooks(const std::string &looks)
|
||||
|
||||
#include "luaentity_common.h"
|
||||
|
||||
class CLuaEntityCAO : public LuaEntityCAO
|
||||
class LuaEntityCAO : public ClientActiveObject
|
||||
{
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
@@ -1291,8 +1670,8 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
float m_anim_timer;
|
||||
|
||||
public:
|
||||
CLuaEntityCAO(IGameDef *gamedef):
|
||||
LuaEntityCAO(gamedef),
|
||||
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
|
||||
m_meshnode(NULL),
|
||||
m_spritenode(NULL),
|
||||
@@ -1309,12 +1688,13 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
m_anim_framelength(0.2),
|
||||
m_anim_timer(0)
|
||||
{
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
if(gamedef == NULL)
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
}
|
||||
|
||||
void initialize(const std::string &data)
|
||||
{
|
||||
infostream<<"CLuaEntityCAO: Got init data"<<std::endl;
|
||||
infostream<<"LuaEntityCAO: Got init data"<<std::endl;
|
||||
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// version
|
||||
@@ -1346,14 +1726,14 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
~CLuaEntityCAO()
|
||||
~LuaEntityCAO()
|
||||
{
|
||||
delete m_prop;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef)
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new CLuaEntityCAO(gamedef);
|
||||
return new LuaEntityCAO(gamedef, env);
|
||||
}
|
||||
|
||||
u8 getType() const
|
||||
@@ -1369,7 +1749,8 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
return pos_translator.vect_show;
|
||||
}
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_meshnode != NULL || m_spritenode != NULL)
|
||||
return;
|
||||
@@ -1377,7 +1758,7 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
|
||||
if(m_prop->visual == "sprite"){
|
||||
infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl;
|
||||
infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
|
||||
m_spritenode = new scene::MyBillboardSceneNode(
|
||||
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||
m_spritenode->setMaterialTexture(0,
|
||||
@@ -1398,7 +1779,7 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
|
||||
}
|
||||
} else if(m_prop->visual == "cube"){
|
||||
infostream<<"CLuaEntityCAO::addToScene(): cube"<<std::endl;
|
||||
infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
@@ -1461,7 +1842,7 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
// Will be shown when we know the brightness
|
||||
m_meshnode->setVisible(false);
|
||||
} else {
|
||||
infostream<<"CLuaEntityCAO::addToScene(): \""<<m_prop->visual
|
||||
infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
|
||||
<<"\" not supported"<<std::endl;
|
||||
}
|
||||
updateTextures("");
|
||||
@@ -1640,7 +2021,7 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
|
||||
void processMessage(const std::string &data)
|
||||
{
|
||||
infostream<<"CLuaEntityCAO: Got message"<<std::endl;
|
||||
//infostream<<"LuaEntityCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
@@ -1692,6 +2073,272 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
};
|
||||
|
||||
// Prototype
|
||||
CLuaEntityCAO proto_CLuaEntityCAO(NULL);
|
||||
LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
|
||||
|
||||
/*
|
||||
PlayerCAO
|
||||
*/
|
||||
|
||||
class PlayerCAO : public ClientActiveObject
|
||||
{
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
scene::ITextSceneNode* m_text;
|
||||
std::string m_name;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
bool m_is_local_player;
|
||||
LocalPlayer *m_local_player;
|
||||
float m_damage_visual_timer;
|
||||
|
||||
public:
|
||||
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
ClientActiveObject(0, gamedef, env),
|
||||
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
|
||||
m_node(NULL),
|
||||
m_text(NULL),
|
||||
m_position(v3f(0,10*BS,0)),
|
||||
m_yaw(0),
|
||||
m_is_local_player(false),
|
||||
m_local_player(NULL),
|
||||
m_damage_visual_timer(0)
|
||||
{
|
||||
if(gamedef == NULL)
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
}
|
||||
|
||||
void initialize(const std::string &data)
|
||||
{
|
||||
infostream<<"PlayerCAO: Got init data"<<std::endl;
|
||||
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// version
|
||||
u8 version = readU8(is);
|
||||
// check version
|
||||
if(version != 0)
|
||||
return;
|
||||
// name
|
||||
m_name = deSerializeString(is);
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
// yaw
|
||||
m_yaw = readF1000(is);
|
||||
|
||||
pos_translator.init(m_position);
|
||||
|
||||
Player *player = m_env->getPlayer(m_name.c_str());
|
||||
if(player && player->isLocal()){
|
||||
m_is_local_player = true;
|
||||
m_local_player = (LocalPlayer*)player;
|
||||
}
|
||||
}
|
||||
|
||||
~PlayerCAO()
|
||||
{
|
||||
if(m_node)
|
||||
m_node->remove();
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
|
||||
{
|
||||
return new PlayerCAO(gamedef, env);
|
||||
}
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_PLAYER;
|
||||
}
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{
|
||||
if(m_is_local_player)
|
||||
return NULL;
|
||||
return &m_selection_box;
|
||||
}
|
||||
v3f getPosition()
|
||||
{
|
||||
return pos_translator.vect_show;
|
||||
}
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
IrrlichtDevice *irr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
return;
|
||||
if(m_is_local_player)
|
||||
return;
|
||||
|
||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{ // Front
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
{ // Back
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
// Set it to use the materials of the meshbuffers directly.
|
||||
// This is needed for changing the texture in the future
|
||||
m_node->setReadOnlyMaterials(true);
|
||||
updateNodePos();
|
||||
|
||||
// Add a text node for showing the name
|
||||
std::wstring wname = narrow_to_wide(m_name);
|
||||
m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
|
||||
wname.c_str(), video::SColor(255,255,255,255), m_node);
|
||||
m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
|
||||
|
||||
updateTextures("");
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
void removeFromScene()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->remove();
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
void updateLight(u8 light_at_pos)
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->setVisible(true);
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 getLightPosition()
|
||||
{
|
||||
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
||||
}
|
||||
|
||||
void updateNodePos()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
m_node->setPosition(pos_translator.vect_show);
|
||||
|
||||
v3f rot = m_node->getRotation();
|
||||
rot.Y = -m_yaw;
|
||||
m_node->setRotation(rot);
|
||||
}
|
||||
|
||||
void step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
|
||||
if(m_damage_visual_timer > 0){
|
||||
m_damage_visual_timer -= dtime;
|
||||
if(m_damage_visual_timer <= 0){
|
||||
updateTextures("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processMessage(const std::string &data)
|
||||
{
|
||||
//infostream<<"PlayerCAO: Got message"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
// command
|
||||
u8 cmd = readU8(is);
|
||||
if(cmd == 0) // update position
|
||||
{
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
// yaw
|
||||
m_yaw = readF1000(is);
|
||||
|
||||
pos_translator.update(m_position, false);
|
||||
|
||||
updateNodePos();
|
||||
}
|
||||
else if(cmd == 1) // punched
|
||||
{
|
||||
// damage
|
||||
s16 damage = readS16(is);
|
||||
|
||||
if(m_is_local_player)
|
||||
m_env->damageLocalPlayer(damage, false);
|
||||
|
||||
m_damage_visual_timer = 0.5;
|
||||
updateTextures("^[brighten");
|
||||
}
|
||||
}
|
||||
|
||||
void updateTextures(const std::string &mod)
|
||||
{
|
||||
if(!m_node)
|
||||
return;
|
||||
ITextureSource *tsrc = m_gamedef->tsrc();
|
||||
scene::IMesh *mesh = m_node->getMesh();
|
||||
if(mesh){
|
||||
{
|
||||
std::string tname = "player.png";
|
||||
tname += mod;
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
|
||||
buf->getMaterial().setTexture(0,
|
||||
tsrc->getTextureRaw(tname));
|
||||
}
|
||||
{
|
||||
std::string tname = "player_back.png";
|
||||
tname += mod;
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
|
||||
buf->getMaterial().setTexture(0,
|
||||
tsrc->getTextureRaw(tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Prototype
|
||||
PlayerCAO proto_PlayerCAO(NULL, NULL);
|
||||
|
||||
|
||||
|
||||
@@ -20,398 +20,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef CONTENT_CAO_HEADER
|
||||
#define CONTENT_CAO_HEADER
|
||||
|
||||
#include "clientobject.h"
|
||||
#include "content_object.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
class Settings;
|
||||
#include "MyBillboardSceneNode.h"
|
||||
|
||||
/*
|
||||
SmoothTranslator
|
||||
*/
|
||||
|
||||
struct SmoothTranslator
|
||||
{
|
||||
v3f vect_old;
|
||||
v3f vect_show;
|
||||
v3f vect_aim;
|
||||
f32 anim_counter;
|
||||
f32 anim_time;
|
||||
f32 anim_time_counter;
|
||||
bool aim_is_end;
|
||||
|
||||
SmoothTranslator():
|
||||
vect_old(0,0,0),
|
||||
vect_show(0,0,0),
|
||||
vect_aim(0,0,0),
|
||||
anim_counter(0),
|
||||
anim_time(0),
|
||||
anim_time_counter(0),
|
||||
aim_is_end(true)
|
||||
{}
|
||||
|
||||
void init(v3f vect)
|
||||
{
|
||||
vect_old = vect;
|
||||
vect_show = vect;
|
||||
vect_aim = vect;
|
||||
anim_counter = 0;
|
||||
anim_time = 0;
|
||||
anim_time_counter = 0;
|
||||
aim_is_end = true;
|
||||
}
|
||||
|
||||
void sharpen()
|
||||
{
|
||||
init(vect_show);
|
||||
}
|
||||
|
||||
void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
|
||||
{
|
||||
aim_is_end = is_end_position;
|
||||
vect_old = vect_show;
|
||||
vect_aim = vect_new;
|
||||
if(update_interval > 0){
|
||||
anim_time = update_interval;
|
||||
} else {
|
||||
if(anim_time < 0.001 || anim_time > 1.0)
|
||||
anim_time = anim_time_counter;
|
||||
else
|
||||
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
||||
}
|
||||
anim_time_counter = 0;
|
||||
anim_counter = 0;
|
||||
}
|
||||
|
||||
void translate(f32 dtime)
|
||||
{
|
||||
anim_time_counter = anim_time_counter + dtime;
|
||||
anim_counter = anim_counter + dtime;
|
||||
v3f vect_move = vect_aim - vect_old;
|
||||
f32 moveratio = 1.0;
|
||||
if(anim_time > 0.001)
|
||||
moveratio = anim_time_counter / anim_time;
|
||||
// Move a bit less than should, to avoid oscillation
|
||||
moveratio = moveratio * 0.8;
|
||||
float move_end = 1.5;
|
||||
if(aim_is_end)
|
||||
move_end = 1.0;
|
||||
if(moveratio > move_end)
|
||||
moveratio = move_end;
|
||||
vect_show = vect_old + vect_move * moveratio;
|
||||
}
|
||||
|
||||
bool is_moving()
|
||||
{
|
||||
return ((anim_time_counter / anim_time) < 1.4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
TestCAO
|
||||
*/
|
||||
|
||||
class TestCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
TestCAO(IGameDef *gamedef);
|
||||
virtual ~TestCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_TEST;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
};
|
||||
|
||||
/*
|
||||
ItemCAO
|
||||
*/
|
||||
|
||||
class ItemCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
ItemCAO(IGameDef *gamedef);
|
||||
virtual ~ItemCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_ITEM;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_inventorystring;
|
||||
};
|
||||
|
||||
/*
|
||||
RatCAO
|
||||
*/
|
||||
|
||||
class RatCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
RatCAO(IGameDef *gamedef);
|
||||
virtual ~RatCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_RAT;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
Oerkki1CAO
|
||||
*/
|
||||
|
||||
class Oerkki1CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
Oerkki1CAO(IGameDef *gamedef);
|
||||
virtual ~Oerkki1CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_OERKKI1;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
float m_damage_visual_timer;
|
||||
bool m_damage_texture_enabled;
|
||||
};
|
||||
|
||||
/*
|
||||
FireflyCAO
|
||||
*/
|
||||
|
||||
class FireflyCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
FireflyCAO(IGameDef *gamedef);
|
||||
virtual ~FireflyCAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_FIREFLY;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return m_position;}
|
||||
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
};
|
||||
|
||||
/*
|
||||
MobV2CAO
|
||||
*/
|
||||
|
||||
class MobV2CAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
MobV2CAO(IGameDef *gamedef);
|
||||
virtual ~MobV2CAO();
|
||||
|
||||
u8 getType() const
|
||||
{
|
||||
return ACTIVEOBJECT_TYPE_MOBV2;
|
||||
}
|
||||
|
||||
static ClientActiveObject* create(IGameDef *gamedef);
|
||||
|
||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
|
||||
void removeFromScene();
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
void processMessage(const std::string &data);
|
||||
|
||||
void initialize(const std::string &data);
|
||||
|
||||
core::aabbox3d<f32>* getSelectionBox()
|
||||
{return &m_selection_box;}
|
||||
v3f getPosition()
|
||||
{return pos_translator.vect_show;}
|
||||
//{return m_position;}
|
||||
bool doShowSelectionBox(){return false;}
|
||||
|
||||
// If returns true, punch will not be sent to the server
|
||||
bool directReportPunch(const std::string &toolname, v3f dir);
|
||||
|
||||
private:
|
||||
void setLooks(const std::string &looks);
|
||||
|
||||
IntervalLimiter m_attack_interval;
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::MyBillboardSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_texture_name;
|
||||
float m_yaw;
|
||||
SmoothTranslator pos_translator;
|
||||
bool m_walking;
|
||||
float m_walking_unset_timer;
|
||||
float m_walk_timer;
|
||||
int m_walk_frame;
|
||||
float m_damage_visual_timer;
|
||||
u8 m_last_light;
|
||||
bool m_shooting;
|
||||
float m_shooting_unset_timer;
|
||||
v2f m_sprite_size;
|
||||
float m_sprite_y;
|
||||
bool m_bright_shooting;
|
||||
std::string m_sprite_type;
|
||||
int m_simple_anim_frames;
|
||||
float m_simple_anim_frametime;
|
||||
bool m_lock_full_brightness;
|
||||
int m_player_hit_damage;
|
||||
float m_player_hit_distance;
|
||||
float m_player_hit_interval;
|
||||
float m_player_hit_timer;
|
||||
|
||||
Settings *m_properties;
|
||||
};
|
||||
|
||||
/*
|
||||
LuaEntityCAO
|
||||
*/
|
||||
|
||||
class LuaEntityCAO : public ClientActiveObject
|
||||
{
|
||||
public:
|
||||
LuaEntityCAO(IGameDef *gamedef):
|
||||
ClientActiveObject(0, gamedef)
|
||||
{}
|
||||
virtual ~LuaEntityCAO(){}
|
||||
virtual u8 getType() const=0;
|
||||
virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)=0;
|
||||
virtual void removeFromScene()=0;
|
||||
virtual void updateLight(u8 light_at_pos)=0;
|
||||
virtual v3s16 getLightPosition()=0;
|
||||
virtual void updateNodePos()=0;
|
||||
virtual void step(float dtime, ClientEnvironment *env)=0;
|
||||
virtual void processMessage(const std::string &data)=0;
|
||||
virtual void initialize(const std::string &data)=0;
|
||||
virtual core::aabbox3d<f32>* getSelectionBox()=0;
|
||||
virtual v3f getPosition()=0;
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "content_craft.h"
|
||||
#include "inventory.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "player.h"
|
||||
#include "mapnode.h" // For content_t
|
||||
#include "gamedef.h"
|
||||
|
||||
void craft_set_creative_inventory(Player *player, IGameDef *gamedef)
|
||||
{
|
||||
INodeDefManager *ndef = gamedef->ndef();
|
||||
|
||||
player->resetInventory();
|
||||
|
||||
// Give some good tools
|
||||
{
|
||||
InventoryItem *item = new ToolItem(gamedef, "MesePick", 0);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}
|
||||
{
|
||||
InventoryItem *item = new ToolItem(gamedef, "SteelPick", 0);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}
|
||||
{
|
||||
InventoryItem *item = new ToolItem(gamedef, "SteelAxe", 0);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}
|
||||
{
|
||||
InventoryItem *item = new ToolItem(gamedef, "SteelShovel", 0);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
Give materials
|
||||
*/
|
||||
|
||||
// CONTENT_IGNORE-terminated list
|
||||
content_t material_items[] = {
|
||||
LEGN(ndef, "CONTENT_TORCH"),
|
||||
LEGN(ndef, "CONTENT_COBBLE"),
|
||||
LEGN(ndef, "CONTENT_MUD"),
|
||||
LEGN(ndef, "CONTENT_STONE"),
|
||||
LEGN(ndef, "CONTENT_SAND"),
|
||||
LEGN(ndef, "CONTENT_SANDSTONE"),
|
||||
LEGN(ndef, "CONTENT_CLAY"),
|
||||
LEGN(ndef, "CONTENT_BRICK"),
|
||||
LEGN(ndef, "CONTENT_TREE"),
|
||||
LEGN(ndef, "CONTENT_LEAVES"),
|
||||
LEGN(ndef, "CONTENT_CACTUS"),
|
||||
LEGN(ndef, "CONTENT_PAPYRUS"),
|
||||
LEGN(ndef, "CONTENT_BOOKSHELF"),
|
||||
LEGN(ndef, "CONTENT_GLASS"),
|
||||
LEGN(ndef, "CONTENT_FENCE"),
|
||||
LEGN(ndef, "CONTENT_RAIL"),
|
||||
LEGN(ndef, "CONTENT_MESE"),
|
||||
LEGN(ndef, "CONTENT_WATERSOURCE"),
|
||||
LEGN(ndef, "CONTENT_CLOUD"),
|
||||
LEGN(ndef, "CONTENT_CHEST"),
|
||||
LEGN(ndef, "CONTENT_FURNACE"),
|
||||
LEGN(ndef, "CONTENT_SIGN_WALL"),
|
||||
LEGN(ndef, "CONTENT_LAVASOURCE"),
|
||||
CONTENT_IGNORE
|
||||
};
|
||||
|
||||
content_t *mip = material_items;
|
||||
for(u16 i=0; i<PLAYER_INVENTORY_SIZE; i++)
|
||||
{
|
||||
if(*mip == CONTENT_IGNORE)
|
||||
break;
|
||||
|
||||
InventoryItem *item = new MaterialItem(gamedef, *mip, 1);
|
||||
player->inventory.addItem("main", item);
|
||||
|
||||
mip++;
|
||||
}
|
||||
|
||||
#if 0
|
||||
assert(USEFUL_LEGN(ndef, "CONTENT_COUNT") <= PLAYER_INVENTORY_SIZE);
|
||||
|
||||
// add torch first
|
||||
InventoryItem *item = new MaterialItem(gamedef, LEGN(ndef, "CONTENT_TORCH"), 1);
|
||||
player->inventory.addItem("main", item);
|
||||
|
||||
// Then others
|
||||
for(u16 i=0; i<USEFUL_LEGN(ndef, "CONTENT_COUNT"); i++)
|
||||
{
|
||||
// Skip some materials
|
||||
if(i == LEGN(ndef, "CONTENT_WATER") || i == LEGN(ndef, "CONTENT_TORCH")
|
||||
|| i == LEGN(ndef, "CONTENT_COALSTONE"))
|
||||
continue;
|
||||
|
||||
InventoryItem *item = new MaterialItem(gamedef, i, 1);
|
||||
player->inventory.addItem("main", item);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*// Sign
|
||||
{
|
||||
InventoryItem *item = new MapBlockObjectItem(gamedef, "Sign Example text");
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef CONTENT_CRAFT_HEADER
|
||||
#define CONTENT_CRAFT_HEADER
|
||||
|
||||
class InventoryItem;
|
||||
class Player;
|
||||
class IGameDef;
|
||||
|
||||
void craft_set_creative_inventory(Player *player, IGameDef *gamedef);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,9 @@ class Inventory;
|
||||
#define NODEMETA_FURNACE 16
|
||||
#define NODEMETA_LOCKABLE_CHEST 17
|
||||
|
||||
core::map<u16, NodeMetadata::Factory> NodeMetadata::m_types;
|
||||
core::map<std::string, NodeMetadata::Factory2> NodeMetadata::m_names;
|
||||
|
||||
class SignNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#define ACTIVEOBJECT_TYPE_LUAENTITY 7
|
||||
|
||||
// Special type, not stored in active object lists
|
||||
// Special type, not stored as a static object
|
||||
#define ACTIVEOBJECT_TYPE_PLAYER 100
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "main.h" // For g_profiler
|
||||
#include "profiler.h"
|
||||
#include "serialization.h" // For compressZlib
|
||||
#include "materials.h" // For MaterialProperties
|
||||
#include "tooldef.h" // ToolDiggingProperties
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
@@ -241,7 +243,7 @@ InventoryItem * ItemSAO::createInventoryItem()
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSAO::punch(ServerActiveObject *puncher)
|
||||
void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
InventoryItem *item = createInventoryItem();
|
||||
bool fits = puncher->addToInventory(item);
|
||||
@@ -432,7 +434,7 @@ std::string RatSAO::getStaticData()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void RatSAO::punch(ServerActiveObject *puncher)
|
||||
void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
@@ -687,36 +689,28 @@ std::string Oerkki1SAO::getStaticData()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void Oerkki1SAO::punch(ServerActiveObject *puncher)
|
||||
void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
if(!puncher)
|
||||
return;
|
||||
|
||||
v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
|
||||
|
||||
std::string toolname = "";
|
||||
InventoryItem *item = puncher->getWieldedItem();
|
||||
if(item && (std::string)item->getName() == "ToolItem"){
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
toolname = titem->getToolName();
|
||||
}
|
||||
|
||||
m_speed_f += dir*12*BS;
|
||||
|
||||
u16 amount = 5;
|
||||
/* See tool names in inventory.h */
|
||||
if(toolname == "WSword")
|
||||
amount = 10;
|
||||
if(toolname == "STSword")
|
||||
amount = 12;
|
||||
if(toolname == "SteelSword")
|
||||
amount = 16;
|
||||
if(toolname == "STAxe")
|
||||
amount = 7;
|
||||
if(toolname == "SteelAxe")
|
||||
amount = 9;
|
||||
if(toolname == "SteelPick")
|
||||
amount = 7;
|
||||
doDamage(amount);
|
||||
|
||||
puncher->damageWieldedItem(65536/100);
|
||||
// "Material" properties of an oerkki
|
||||
MaterialProperties mp;
|
||||
mp.diggability = DIGGABLE_NORMAL;
|
||||
mp.crackiness = -1.0;
|
||||
mp.cuttability = 1.0;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
|
||||
doDamage(hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
}
|
||||
|
||||
void Oerkki1SAO::doDamage(u16 d)
|
||||
@@ -919,14 +913,6 @@ std::string FireflySAO::getStaticData()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
InventoryItem* FireflySAO::createPickedUpItem()
|
||||
{
|
||||
std::istringstream is("CraftItem firefly 1", std::ios_base::binary);
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
MobV2SAO
|
||||
*/
|
||||
@@ -1365,25 +1351,20 @@ void MobV2SAO::step(float dtime, bool send_recommended)
|
||||
}
|
||||
}
|
||||
|
||||
void MobV2SAO::punch(ServerActiveObject *puncher)
|
||||
void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
if(!puncher)
|
||||
return;
|
||||
|
||||
v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
|
||||
|
||||
std::string toolname = "";
|
||||
InventoryItem *item = puncher->getWieldedItem();
|
||||
if(item && (std::string)item->getName() == "ToolItem"){
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
toolname = titem->getToolName();
|
||||
}
|
||||
|
||||
// A quick hack; SAO description is player name for player
|
||||
std::string playername = puncher->getDescription();
|
||||
|
||||
Map *map = &m_env->getMap();
|
||||
|
||||
actionstream<<playername<<" punches mob id="<<m_id
|
||||
<<" with a \""<<toolname<<"\" at "
|
||||
<<PP(m_base_position/BS)<<std::endl;
|
||||
<<" at "<<PP(m_base_position/BS)<<std::endl;
|
||||
|
||||
m_disturb_timer = 0;
|
||||
m_disturbing_player = playername;
|
||||
@@ -1405,23 +1386,21 @@ void MobV2SAO::punch(ServerActiveObject *puncher)
|
||||
}
|
||||
sendPosition();
|
||||
|
||||
u16 amount = 2;
|
||||
/* See tool names in inventory.h */
|
||||
if(toolname == "WSword")
|
||||
amount = 4;
|
||||
if(toolname == "STSword")
|
||||
amount = 6;
|
||||
if(toolname == "SteelSword")
|
||||
amount = 8;
|
||||
if(toolname == "STAxe")
|
||||
amount = 3;
|
||||
if(toolname == "SteelAxe")
|
||||
amount = 4;
|
||||
if(toolname == "SteelPick")
|
||||
amount = 3;
|
||||
doDamage(amount);
|
||||
|
||||
puncher->damageWieldedItem(65536/100);
|
||||
|
||||
// "Material" properties of the MobV2
|
||||
MaterialProperties mp;
|
||||
mp.diggability = DIGGABLE_NORMAL;
|
||||
mp.crackiness = -1.0;
|
||||
mp.cuttability = 1.0;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
|
||||
doDamage(hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
}
|
||||
|
||||
bool MobV2SAO::isPeaceful()
|
||||
@@ -1677,21 +1656,12 @@ std::string LuaEntitySAO::getStaticData()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
InventoryItem* LuaEntitySAO::createPickedUpItem()
|
||||
{
|
||||
// TODO: Ask item from scriptapi
|
||||
std::istringstream is("CraftItem testobject1 1", std::ios_base::binary);
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||
return item;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::punch(ServerActiveObject *puncher)
|
||||
void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
if(!m_registered)
|
||||
return;
|
||||
lua_State *L = m_env->getLua();
|
||||
scriptapi_luaentity_punch(L, m_id, puncher);
|
||||
scriptapi_luaentity_punch(L, m_id, puncher, time_from_last_punch);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
|
||||
@@ -1799,4 +1769,3 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class ItemSAO : public ServerActiveObject
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createInventoryItem();
|
||||
void punch(ServerActiveObject *puncher);
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
float getMinimumSavedMovement(){ return 0.1*BS; }
|
||||
private:
|
||||
std::string m_inventorystring;
|
||||
@@ -70,7 +70,7 @@ class RatSAO : public ServerActiveObject
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
void punch(ServerActiveObject *puncher);
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
private:
|
||||
bool m_is_active;
|
||||
IntervalLimiter m_inactive_interval;
|
||||
@@ -95,8 +95,7 @@ class Oerkki1SAO : public ServerActiveObject
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
void punch(ServerActiveObject *puncher);
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
bool isPeaceful(){return false;}
|
||||
private:
|
||||
void doDamage(u16 d);
|
||||
@@ -126,7 +125,6 @@ class FireflySAO : public ServerActiveObject
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createPickedUpItem();
|
||||
private:
|
||||
bool m_is_active;
|
||||
IntervalLimiter m_inactive_interval;
|
||||
@@ -155,8 +153,7 @@ class MobV2SAO : public ServerActiveObject
|
||||
std::string getStaticData();
|
||||
std::string getClientInitializationData();
|
||||
void step(float dtime, bool send_recommended);
|
||||
InventoryItem* createPickedUpItem(){return NULL;}
|
||||
void punch(ServerActiveObject *puncher);
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
bool isPeaceful();
|
||||
private:
|
||||
void sendPosition();
|
||||
@@ -209,8 +206,7 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createPickedUpItem();
|
||||
void punch(ServerActiveObject *puncher);
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
void rightClick(ServerActiveObject *clicker);
|
||||
void setPos(v3f pos);
|
||||
void moveTo(v3f pos, bool continuous);
|
||||
|
||||
@@ -93,10 +93,11 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("give_initial_stuff", "false");
|
||||
settings->setDefault("default_password", "");
|
||||
settings->setDefault("default_privs", "build, shout");
|
||||
settings->setDefault("unlimited_player_transfer_distance", "true");
|
||||
settings->setDefault("enable_pvp", "true");
|
||||
|
||||
settings->setDefault("profiler_print_interval", "0");
|
||||
settings->setDefault("enable_mapgen_debug_info", "false");
|
||||
settings->setDefault("objectdata_interval", "0.2");
|
||||
settings->setDefault("active_object_send_range_blocks", "3");
|
||||
settings->setDefault("active_block_range", "2");
|
||||
//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
@@ -107,8 +108,8 @@ void set_default_settings(Settings *settings)
|
||||
settings->setDefault("max_block_generate_distance", "5");
|
||||
settings->setDefault("time_send_interval", "20");
|
||||
settings->setDefault("time_speed", "96");
|
||||
settings->setDefault("server_unload_unused_data_timeout", "19");
|
||||
settings->setDefault("server_map_save_interval", "1.238");
|
||||
settings->setDefault("server_unload_unused_data_timeout", "29");
|
||||
settings->setDefault("server_map_save_interval", "5.3");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("enable_experimental", "false");
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodemetadata.h"
|
||||
#include "main.h" // For g_settings, g_profiler
|
||||
#include "gamedef.h"
|
||||
#include "serverremoteplayer.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -491,7 +492,9 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
}
|
||||
|
||||
if(newplayer)
|
||||
{
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,10 +744,15 @@ void ServerEnvironment::clearAllObjects()
|
||||
obj->m_removed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tell the object about removal
|
||||
obj->removingFromEnvironment();
|
||||
// Deregister in scripting api
|
||||
scriptapi_rm_object_reference(m_lua, obj);
|
||||
|
||||
// Delete active object
|
||||
delete obj;
|
||||
if(obj->environmentDeletes())
|
||||
delete obj;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
}
|
||||
@@ -1175,7 +1183,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
if(obj->environmentDeletes())
|
||||
delete obj;
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
@@ -1209,10 +1218,12 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||
// Discard if removed
|
||||
if(object->m_removed)
|
||||
continue;
|
||||
// Discard if too far
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||
if(distance_f > radius_f)
|
||||
continue;
|
||||
if(object->unlimitedTransferDistance() == false){
|
||||
// Discard if too far
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||
if(distance_f > radius_f)
|
||||
continue;
|
||||
}
|
||||
// Discard if already on current_objects
|
||||
core::map<u16, bool>::Node *n;
|
||||
n = current_objects.find(id);
|
||||
@@ -1247,24 +1258,33 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||
{
|
||||
u16 id = i.getNode()->getKey();
|
||||
ServerActiveObject *object = getActiveObject(id);
|
||||
if(object == NULL)
|
||||
{
|
||||
|
||||
if(object == NULL){
|
||||
infostream<<"ServerEnvironment::getRemovedActiveObjects():"
|
||||
<<" object in current_objects is NULL"<<std::endl;
|
||||
removed_objects.insert(id, false);
|
||||
continue;
|
||||
}
|
||||
else if(object->m_removed == false)
|
||||
|
||||
if(object->m_removed)
|
||||
{
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||
/*infostream<<"removed == false"
|
||||
<<"distance_f = "<<distance_f
|
||||
<<", radius_f = "<<radius_f<<std::endl;*/
|
||||
if(distance_f < radius_f)
|
||||
{
|
||||
// Not removed
|
||||
continue;
|
||||
}
|
||||
removed_objects.insert(id, false);
|
||||
continue;
|
||||
}
|
||||
removed_objects.insert(id, false);
|
||||
|
||||
// If transfer distance is unlimited, don't remove
|
||||
if(object->unlimitedTransferDistance())
|
||||
continue;
|
||||
|
||||
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||
|
||||
if(distance_f >= radius_f)
|
||||
{
|
||||
removed_objects.insert(id, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not removed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,7 +1310,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
{
|
||||
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"no free ids available"<<std::endl;
|
||||
delete object;
|
||||
if(object->environmentDeletes())
|
||||
delete object;
|
||||
return 0;
|
||||
}
|
||||
object->setId(new_id);
|
||||
@@ -1303,7 +1324,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
{
|
||||
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||
delete object;
|
||||
if(object->environmentDeletes())
|
||||
delete object;
|
||||
return 0;
|
||||
}
|
||||
/*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
@@ -1316,34 +1338,38 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||
<<m_active_objects.size()<<" active objects."
|
||||
<<std::endl;
|
||||
|
||||
// Add static object to active static list of the block
|
||||
v3f objectpos = object->getBasePosition();
|
||||
std::string staticdata = object->getStaticData();
|
||||
StaticObject s_obj(object->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.m_active.insert(object->getId(), s_obj);
|
||||
object->m_static_exists = true;
|
||||
object->m_static_block = blockpos;
|
||||
|
||||
if(set_changed)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"addActiveObjectRaw");
|
||||
}
|
||||
else{
|
||||
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"could not find block for storing id="<<object->getId()
|
||||
<<" statically"<<std::endl;
|
||||
}
|
||||
|
||||
// Register reference in scripting api (must be done before post-init)
|
||||
scriptapi_add_object_reference(m_lua, object);
|
||||
// Post-initialize object
|
||||
object->addedToEnvironment();
|
||||
|
||||
// Add static data to block
|
||||
if(object->isStaticAllowed())
|
||||
{
|
||||
// Add static object to active static list of the block
|
||||
v3f objectpos = object->getBasePosition();
|
||||
std::string staticdata = object->getStaticData();
|
||||
StaticObject s_obj(object->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.m_active.insert(object->getId(), s_obj);
|
||||
object->m_static_exists = true;
|
||||
object->m_static_block = blockpos;
|
||||
|
||||
if(set_changed)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"addActiveObjectRaw");
|
||||
}
|
||||
else{
|
||||
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||
<<"could not find block for storing id="<<object->getId()
|
||||
<<" statically"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return object->getId();
|
||||
}
|
||||
|
||||
@@ -1395,11 +1421,14 @@ void ServerEnvironment::removeRemovedObjects()
|
||||
if(obj->m_known_by_count > 0)
|
||||
continue;
|
||||
|
||||
// Tell the object about removal
|
||||
obj->removingFromEnvironment();
|
||||
// Deregister in scripting api
|
||||
scriptapi_rm_object_reference(m_lua, obj);
|
||||
|
||||
// Delete
|
||||
delete obj;
|
||||
if(obj->environmentDeletes())
|
||||
delete obj;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
}
|
||||
@@ -1541,18 +1570,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
errorstream<<"NULL object found in ServerEnvironment"
|
||||
<<std::endl;
|
||||
assert(0);
|
||||
assert(obj);
|
||||
|
||||
// Do not deactivate if static data creation not allowed
|
||||
if(!force_delete && !obj->isStaticAllowed())
|
||||
continue;
|
||||
}
|
||||
|
||||
// If pending deactivation, let removeRemovedObjects() do it
|
||||
if(obj->m_pending_deactivation)
|
||||
if(!force_delete && obj->m_pending_deactivation)
|
||||
continue;
|
||||
|
||||
u16 id = i.getNode()->getKey();
|
||||
@@ -1562,7 +1587,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
|
||||
// If block is active, don't remove
|
||||
if(m_active_blocks.contains(blockpos_o))
|
||||
if(!force_delete && m_active_blocks.contains(blockpos_o))
|
||||
continue;
|
||||
|
||||
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||
@@ -1576,97 +1601,102 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
Update the static data
|
||||
*/
|
||||
|
||||
// Create new static object
|
||||
std::string staticdata_new = obj->getStaticData();
|
||||
StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
|
||||
|
||||
bool stays_in_same_block = false;
|
||||
bool data_changed = true;
|
||||
|
||||
if(obj->m_static_exists){
|
||||
if(obj->m_static_block == blockpos_o)
|
||||
stays_in_same_block = true;
|
||||
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
|
||||
core::map<u16, StaticObject>::Node *n =
|
||||
block->m_static_objects.m_active.find(id);
|
||||
if(n){
|
||||
StaticObject static_old = n->getValue();
|
||||
|
||||
float save_movem = obj->getMinimumSavedMovement();
|
||||
|
||||
if(static_old.data == staticdata_new &&
|
||||
(static_old.pos - objectpos).getLength() < save_movem)
|
||||
data_changed = false;
|
||||
} else {
|
||||
errorstream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||
<<"id="<<id<<" m_static_exists=true but "
|
||||
<<"static data doesn't actually exist in "
|
||||
<<PP(obj->m_static_block)<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool shall_be_written = (!stays_in_same_block || data_changed);
|
||||
|
||||
// Delete old static object
|
||||
if(obj->m_static_exists)
|
||||
if(obj->isStaticAllowed())
|
||||
{
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
// Create new static object
|
||||
std::string staticdata_new = obj->getStaticData();
|
||||
StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
|
||||
|
||||
bool stays_in_same_block = false;
|
||||
bool data_changed = true;
|
||||
|
||||
if(obj->m_static_exists){
|
||||
if(obj->m_static_block == blockpos_o)
|
||||
stays_in_same_block = true;
|
||||
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
|
||||
core::map<u16, StaticObject>::Node *n =
|
||||
block->m_static_objects.m_active.find(id);
|
||||
if(n){
|
||||
StaticObject static_old = n->getValue();
|
||||
|
||||
float save_movem = obj->getMinimumSavedMovement();
|
||||
|
||||
if(static_old.data == staticdata_new &&
|
||||
(static_old.pos - objectpos).getLength() < save_movem)
|
||||
data_changed = false;
|
||||
} else {
|
||||
errorstream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||
<<"id="<<id<<" m_static_exists=true but "
|
||||
<<"static data doesn't actually exist in "
|
||||
<<PP(obj->m_static_block)<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool shall_be_written = (!stays_in_same_block || data_changed);
|
||||
|
||||
// Delete old static object
|
||||
if(obj->m_static_exists)
|
||||
{
|
||||
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
obj->m_static_exists = false;
|
||||
// Only mark block as modified if data changed considerably
|
||||
if(shall_be_written)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"deactivateFarObjects: Static data "
|
||||
"changed considerably");
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
// Get or generate the block
|
||||
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
obj->m_static_exists = false;
|
||||
// Only mark block as modified if data changed considerably
|
||||
if(shall_be_written)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"deactivateFarObjects: Static data "
|
||||
"changed considerably");
|
||||
if(block->m_static_objects.m_stored.size() >= 49){
|
||||
errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
|
||||
<<" statically but block "<<PP(blockpos)
|
||||
<<" already contains "
|
||||
<<block->m_static_objects.m_stored.size()
|
||||
<<" (over 49) objects."
|
||||
<<" Forcing delete."<<std::endl;
|
||||
force_delete = true;
|
||||
} else {
|
||||
u16 new_id = pending_delete ? id : 0;
|
||||
block->m_static_objects.insert(new_id, s_obj);
|
||||
|
||||
// Only mark block as modified if data changed considerably
|
||||
if(shall_be_written)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"deactivateFarObjects: Static data "
|
||||
"changed considerably");
|
||||
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = block->getPos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
// Get or generate the block
|
||||
MapBlock *block = m_map->emergeBlock(blockpos);
|
||||
|
||||
if(block)
|
||||
{
|
||||
if(block->m_static_objects.m_stored.size() >= 49){
|
||||
errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
|
||||
<<" statically but block "<<PP(blockpos)
|
||||
<<" already contains "
|
||||
<<block->m_static_objects.m_stored.size()
|
||||
<<" (over 49) objects."
|
||||
<<" Forcing delete."<<std::endl;
|
||||
force_delete = true;
|
||||
} else {
|
||||
u16 new_id = pending_delete ? id : 0;
|
||||
block->m_static_objects.insert(new_id, s_obj);
|
||||
|
||||
// Only mark block as modified if data changed considerably
|
||||
if(shall_be_written)
|
||||
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
||||
"deactivateFarObjects: Static data "
|
||||
"changed considerably");
|
||||
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = block->getPos();
|
||||
else{
|
||||
if(!force_delete){
|
||||
errorstream<<"ServerEnv: Could not find or generate "
|
||||
<<"a block for storing id="<<obj->getId()
|
||||
<<" statically"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
errorstream<<"ServerEnv: Could not find or generate "
|
||||
<<"a block for storing id="<<obj->getId()
|
||||
<<" statically"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
If known by some client, set pending deactivation.
|
||||
Otherwise delete it immediately.
|
||||
*/
|
||||
|
||||
if(pending_delete)
|
||||
if(pending_delete && !force_delete)
|
||||
{
|
||||
verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
|
||||
<<"object id="<<id<<" is known by clients"
|
||||
@@ -1680,11 +1710,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
<<"object id="<<id<<" is not known by clients"
|
||||
<<"; deleting"<<std::endl;
|
||||
|
||||
// Tell the object about removal
|
||||
obj->removingFromEnvironment();
|
||||
// Deregister in scripting api
|
||||
scriptapi_rm_object_reference(m_lua, obj);
|
||||
|
||||
// Delete active object
|
||||
delete obj;
|
||||
if(obj->environmentDeletes())
|
||||
delete obj;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
}
|
||||
@@ -1705,14 +1738,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||
*/
|
||||
|
||||
ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
|
||||
ITextureSource *texturesource, IGameDef *gamedef):
|
||||
ITextureSource *texturesource, IGameDef *gamedef,
|
||||
IrrlichtDevice *irr):
|
||||
m_map(map),
|
||||
m_smgr(smgr),
|
||||
m_texturesource(texturesource),
|
||||
m_gamedef(gamedef)
|
||||
m_gamedef(gamedef),
|
||||
m_irr(irr)
|
||||
{
|
||||
assert(m_map);
|
||||
assert(m_smgr);
|
||||
}
|
||||
|
||||
ClientEnvironment::~ClientEnvironment()
|
||||
@@ -1887,6 +1920,7 @@ void ClientEnvironment::step(float dtime)
|
||||
ClientEnvEvent event;
|
||||
event.type = CEE_PLAYER_DAMAGE;
|
||||
event.player_damage.amount = damage;
|
||||
event.player_damage.send_to_server = true;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
}
|
||||
@@ -1920,6 +1954,7 @@ void ClientEnvironment::step(float dtime)
|
||||
ClientEnvEvent event;
|
||||
event.type = CEE_PLAYER_DAMAGE;
|
||||
event.player_damage.amount = damage_per_second;
|
||||
event.player_damage.send_to_server = true;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
}
|
||||
@@ -2088,7 +2123,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
<<"added (id="<<object->getId()<<")"<<std::endl;
|
||||
m_active_objects.insert(object->getId(), object);
|
||||
object->addToScene(m_smgr, m_texturesource);
|
||||
object->addToScene(m_smgr, m_texturesource, m_irr);
|
||||
{ // Update lighting immediately
|
||||
u8 light = 0;
|
||||
try{
|
||||
@@ -2106,7 +2141,8 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||
void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||
const std::string &init_data)
|
||||
{
|
||||
ClientActiveObject* obj = ClientActiveObject::create(type, m_gamedef);
|
||||
ClientActiveObject* obj =
|
||||
ClientActiveObject::create(type, m_gamedef, this);
|
||||
if(obj == NULL)
|
||||
{
|
||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||
@@ -2156,19 +2192,22 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||
Callbacks for activeobjects
|
||||
*/
|
||||
|
||||
void ClientEnvironment::damageLocalPlayer(u8 damage)
|
||||
void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
|
||||
{
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
assert(lplayer);
|
||||
|
||||
if(lplayer->hp > damage)
|
||||
lplayer->hp -= damage;
|
||||
else
|
||||
lplayer->hp = 0;
|
||||
|
||||
if(handle_hp){
|
||||
if(lplayer->hp > damage)
|
||||
lplayer->hp -= damage;
|
||||
else
|
||||
lplayer->hp = 0;
|
||||
}
|
||||
|
||||
ClientEnvEvent event;
|
||||
event.type = CEE_PLAYER_DAMAGE;
|
||||
event.player_damage.amount = damage;
|
||||
event.player_damage.send_to_server = handle_hp;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,6 +368,7 @@ struct ClientEnvEvent
|
||||
} none;
|
||||
struct{
|
||||
u8 amount;
|
||||
bool send_to_server;
|
||||
} player_damage;
|
||||
};
|
||||
};
|
||||
@@ -376,7 +377,8 @@ class ClientEnvironment : public Environment
|
||||
{
|
||||
public:
|
||||
ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
|
||||
ITextureSource *texturesource, IGameDef *gamedef);
|
||||
ITextureSource *texturesource, IGameDef *gamedef,
|
||||
IrrlichtDevice *device);
|
||||
~ClientEnvironment();
|
||||
|
||||
Map & getMap()
|
||||
@@ -436,7 +438,7 @@ class ClientEnvironment : public Environment
|
||||
Callbacks for activeobjects
|
||||
*/
|
||||
|
||||
void damageLocalPlayer(u8 damage);
|
||||
void damageLocalPlayer(u8 damage, bool handle_hp=true);
|
||||
|
||||
/*
|
||||
Client likes to call these
|
||||
@@ -454,6 +456,7 @@ class ClientEnvironment : public Environment
|
||||
scene::ISceneManager *m_smgr;
|
||||
ITextureSource *m_texturesource;
|
||||
IGameDef *m_gamedef;
|
||||
IrrlichtDevice *m_irr;
|
||||
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||
Queue<ClientEnvEvent> m_client_event_queue;
|
||||
IntervalLimiter m_active_object_light_update_interval;
|
||||
|
||||
@@ -265,9 +265,17 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, ITextureSource *tsrc)
|
||||
rect.LowerRightCorner + v2s32(1,1)*border),
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
video::SColor bgcolor(255,128,128,128);
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
|
||||
if(rect.isPointInside(m_pointer) && m_selected_item)
|
||||
{
|
||||
video::SColor bgcolor(255,192,192,192);
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::SColor bgcolor(255,128,128,128);
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
if(item)
|
||||
{
|
||||
@@ -319,22 +327,31 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
if(event.EventType==EET_MOUSE_INPUT_EVENT)
|
||||
{
|
||||
char amount = -1;
|
||||
|
||||
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
|
||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||
ItemSpec s = getItemAtPos(p);
|
||||
|
||||
if(event.MouseInput.Event==EMIE_MOUSE_MOVED)
|
||||
m_pointer = v2s32(event.MouseInput.X, event.MouseInput.Y);
|
||||
else if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
amount = 0;
|
||||
else if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
|
||||
amount = 1;
|
||||
else if(event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN)
|
||||
amount = 10;
|
||||
else if(event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP &&
|
||||
m_selected_item &&
|
||||
(m_selected_item->listname != s.listname
|
||||
|| m_selected_item->i != s.i))
|
||||
amount = 0;
|
||||
|
||||
|
||||
if(amount >= 0)
|
||||
{
|
||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||
//infostream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||
ItemSpec s = getItemAtPos(p);
|
||||
//infostream<<"Mouse action at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||
if(s.isValid())
|
||||
{
|
||||
infostream<<"Mouse down on "<<s.inventoryname
|
||||
infostream<<"Mouse action on "<<s.inventoryname
|
||||
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
||||
if(m_selected_item)
|
||||
{
|
||||
@@ -369,7 +386,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
//ispec.actions->push_back(a);
|
||||
m_invmgr->inventoryAction(a);
|
||||
|
||||
if(list_from->getItem(m_selected_item->i)->getCount()==1)
|
||||
if(list_from->getItem(m_selected_item->i)->getCount()<=amount)
|
||||
source_empties = true;
|
||||
}
|
||||
// Remove selection if target was left-clicked or source
|
||||
|
||||
@@ -159,6 +159,7 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
core::array<ListDrawSpec> m_draw_spec;
|
||||
|
||||
ItemSpec *m_selected_item;
|
||||
v2s32 m_pointer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gamedef.h"
|
||||
#include "scriptapi.h"
|
||||
#include "strfnd.h"
|
||||
#include "nameidmapping.h" // For loading legacy MaterialItems
|
||||
#include "serverremoteplayer.h"
|
||||
|
||||
/*
|
||||
InventoryItem
|
||||
@@ -97,7 +99,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
throw SerializationError("Too large material number");
|
||||
return new MaterialItem(gamedef, material, count);
|
||||
}
|
||||
else if(name == "NodeItem" || name == "MaterialItem3")
|
||||
else if(name == "node" || name == "NodeItem" || name == "MaterialItem3")
|
||||
{
|
||||
std::string all;
|
||||
std::getline(is, all, '\n');
|
||||
@@ -124,7 +126,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
std::getline(is, inventorystring, '|');
|
||||
throw SerializationError("MBOItem not supported anymore");
|
||||
}
|
||||
else if(name == "CraftItem")
|
||||
else if(name == "craft" || name == "CraftItem")
|
||||
{
|
||||
std::string all;
|
||||
std::getline(is, all, '\n');
|
||||
@@ -146,7 +148,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
count = 1;
|
||||
return new CraftItem(gamedef, subname, count);
|
||||
}
|
||||
else if(name == "ToolItem")
|
||||
else if(name == "tool" || name == "ToolItem")
|
||||
{
|
||||
std::string all;
|
||||
std::getline(is, all, '\n');
|
||||
@@ -212,7 +214,7 @@ bool InventoryItem::dropOrPlace(ServerEnvironment *env,
|
||||
s16 dropcount = getDropCount();
|
||||
if(count < 0 || count > dropcount)
|
||||
count = dropcount;
|
||||
if(count < 0 || count > getCount());
|
||||
if(count < 0 || count > getCount())
|
||||
count = getCount();
|
||||
if(count > 0)
|
||||
{
|
||||
@@ -250,8 +252,10 @@ MaterialItem::MaterialItem(IGameDef *gamedef, std::string nodename, u16 count):
|
||||
MaterialItem::MaterialItem(IGameDef *gamedef, content_t content, u16 count):
|
||||
InventoryItem(gamedef, count)
|
||||
{
|
||||
INodeDefManager *ndef = m_gamedef->ndef();
|
||||
std::string nodename = ndef->get(content).name;
|
||||
NameIdMapping legacy_nimap;
|
||||
content_mapnode_get_name_id_mapping(&legacy_nimap);
|
||||
std::string nodename;
|
||||
legacy_nimap.getName(content, nodename);
|
||||
if(nodename == "")
|
||||
nodename = "unknown_block";
|
||||
m_nodename = nodename;
|
||||
|
||||
@@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
class ServerActiveObject;
|
||||
class ServerEnvironment;
|
||||
class PointedThing;
|
||||
struct PointedThing;
|
||||
class ITextureSource;
|
||||
class IGameDef;
|
||||
|
||||
@@ -158,7 +158,7 @@ class MaterialItem : public InventoryItem
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<"NodeItem";
|
||||
os<<"node";
|
||||
os<<" \"";
|
||||
os<<m_nodename;
|
||||
os<<"\" ";
|
||||
@@ -249,7 +249,7 @@ class CraftItem : public InventoryItem
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<getName();
|
||||
os<<"craft";
|
||||
os<<" \"";
|
||||
os<<m_subname;
|
||||
os<<"\" ";
|
||||
@@ -345,7 +345,7 @@ class ToolItem : public InventoryItem
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<getName();
|
||||
os<<"tool";
|
||||
os<<" \"";
|
||||
os<<m_toolname;
|
||||
os<<"\" ";
|
||||
|
||||
@@ -49,34 +49,65 @@ void MaterialProperties::deSerialize(std::istream &is)
|
||||
flammability = readF1000(is);
|
||||
}
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp,
|
||||
INodeDefManager *nodemgr)
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch)
|
||||
{
|
||||
assert(tp);
|
||||
const MaterialProperties &mp = nodemgr->get(content).material;
|
||||
if(mp.diggability == DIGGABLE_NOT)
|
||||
if(mp->diggability == DIGGABLE_NOT)
|
||||
return DiggingProperties(false, 0, 0);
|
||||
if(mp.diggability == DIGGABLE_CONSTANT)
|
||||
return DiggingProperties(true, mp.constant_time, 0);
|
||||
if(mp->diggability == DIGGABLE_CONSTANT)
|
||||
return DiggingProperties(true, mp->constant_time, 0);
|
||||
|
||||
float time = tp->basetime;
|
||||
time += tp->dt_weight * mp.weight;
|
||||
time += tp->dt_crackiness * mp.crackiness;
|
||||
time += tp->dt_crumbliness * mp.crumbliness;
|
||||
time += tp->dt_cuttability * mp.cuttability;
|
||||
time += tp->dt_weight * mp->weight;
|
||||
time += tp->dt_crackiness * mp->crackiness;
|
||||
time += tp->dt_crumbliness * mp->crumbliness;
|
||||
time += tp->dt_cuttability * mp->cuttability;
|
||||
if(time < 0.2)
|
||||
time = 0.2;
|
||||
|
||||
float durability = tp->basedurability;
|
||||
durability += tp->dd_weight * mp.weight;
|
||||
durability += tp->dd_crackiness * mp.crackiness;
|
||||
durability += tp->dd_crumbliness * mp.crumbliness;
|
||||
durability += tp->dd_cuttability * mp.cuttability;
|
||||
durability += tp->dd_weight * mp->weight;
|
||||
durability += tp->dd_crackiness * mp->crackiness;
|
||||
durability += tp->dd_crumbliness * mp->crumbliness;
|
||||
durability += tp->dd_cuttability * mp->cuttability;
|
||||
if(durability < 1)
|
||||
durability = 1;
|
||||
|
||||
if(time_from_last_punch < tp->full_punch_interval){
|
||||
float f = time_from_last_punch / tp->full_punch_interval;
|
||||
time /= f;
|
||||
durability /= f;
|
||||
}
|
||||
|
||||
float wear = 1.0 / durability;
|
||||
u16 wear_i = 65535.*wear;
|
||||
return DiggingProperties(true, time, wear_i);
|
||||
}
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp)
|
||||
{
|
||||
return getDiggingProperties(mp, tp, 1000000);
|
||||
}
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content,
|
||||
const ToolDiggingProperties *tp, INodeDefManager *nodemgr)
|
||||
{
|
||||
const MaterialProperties &mp = nodemgr->get(content).material;
|
||||
return getDiggingProperties(&mp, tp);
|
||||
}
|
||||
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch)
|
||||
{
|
||||
DiggingProperties digprop = getDiggingProperties(mp, tp,
|
||||
time_from_last_punch);
|
||||
|
||||
// If digging time would be 1 second, 2 hearts go in 1 second.
|
||||
s16 hp = 2.0 * 2.0 / digprop.time + 0.5;
|
||||
// Wear is the same as for digging a single node
|
||||
s16 wear = (float)digprop.wear + 0.5;
|
||||
|
||||
return HittingProperties(hp, wear);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,30 +74,44 @@ struct MaterialProperties
|
||||
|
||||
struct DiggingProperties
|
||||
{
|
||||
DiggingProperties():
|
||||
diggable(false),
|
||||
time(0.0),
|
||||
wear(0)
|
||||
{
|
||||
}
|
||||
DiggingProperties(bool a_diggable, float a_time, u16 a_wear):
|
||||
diggable(a_diggable),
|
||||
time(a_time),
|
||||
wear(a_wear)
|
||||
{
|
||||
}
|
||||
bool diggable;
|
||||
// Digging time in seconds
|
||||
float time;
|
||||
// Caused wear
|
||||
u16 wear;
|
||||
|
||||
DiggingProperties(bool a_diggable=false, float a_time=0, u16 a_wear=0):
|
||||
diggable(a_diggable),
|
||||
time(a_time),
|
||||
wear(a_wear)
|
||||
{}
|
||||
};
|
||||
|
||||
class ToolDiggingProperties;
|
||||
struct ToolDiggingProperties;
|
||||
class INodeDefManager;
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp,
|
||||
INodeDefManager *nodemgr);
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch);
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp);
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content,
|
||||
const ToolDiggingProperties *tp, INodeDefManager *nodemgr);
|
||||
|
||||
struct HittingProperties
|
||||
{
|
||||
s16 hp;
|
||||
s16 wear;
|
||||
|
||||
HittingProperties(s16 hp_=0, s16 wear_=0):
|
||||
hp(hp_),
|
||||
wear(wear_)
|
||||
{}
|
||||
};
|
||||
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -216,7 +216,8 @@ void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
if(readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i=0; i<6; i++)
|
||||
tname_tiles[i] = deSerializeString(is);
|
||||
setTexture(i, deSerializeString(is));
|
||||
//tname_tiles[i] = deSerializeString(is);
|
||||
tname_inventory = deSerializeString(is);
|
||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
@@ -280,7 +281,7 @@ void ContentFeatures::setSpecialMaterial(u16 i, const MaterialSpec &mspec)
|
||||
|
||||
void ContentFeatures::setInventoryTexture(std::string imgname)
|
||||
{
|
||||
tname_inventory = imgname + "^[forcesingle";
|
||||
tname_inventory = imgname;
|
||||
}
|
||||
|
||||
void ContentFeatures::setInventoryTextureCube(std::string top,
|
||||
@@ -529,10 +530,10 @@ class CNodeDefManager: public IWritableNodeDefManager
|
||||
f->visual_solidness = 1;
|
||||
} else {
|
||||
f->drawtype = NDT_NORMAL;
|
||||
f->solidness = 1;
|
||||
f->solidness = 2;
|
||||
for(u32 i=0; i<6; i++){
|
||||
f->tname_tiles[i] = f->tname_tiles[i]
|
||||
+ std::string("^[noalpha");
|
||||
f->setTexture(i, f->tname_tiles[i]
|
||||
+ std::string("^[noalpha"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -30,9 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
NodeMetadata
|
||||
*/
|
||||
|
||||
core::map<u16, NodeMetadata::Factory> NodeMetadata::m_types;
|
||||
core::map<std::string, NodeMetadata::Factory2> NodeMetadata::m_names;
|
||||
|
||||
NodeMetadata::NodeMetadata(IGameDef *gamedef):
|
||||
m_gamedef(gamedef)
|
||||
{
|
||||
|
||||
269
src/player.cpp
269
src/player.cpp
@@ -175,275 +175,6 @@ void Player::deSerialize(std::istream &is)
|
||||
inventory.deSerialize(is, m_gamedef);
|
||||
}
|
||||
|
||||
/*
|
||||
ServerRemotePlayer
|
||||
*/
|
||||
|
||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
|
||||
Player(env->getGameDef()),
|
||||
ServerActiveObject(env, v3f(0,0,0)),
|
||||
m_last_good_position(0,0,0),
|
||||
m_last_good_position_age(0),
|
||||
m_additional_items(),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false)
|
||||
{
|
||||
}
|
||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
||||
const char *name_):
|
||||
Player(env->getGameDef()),
|
||||
ServerActiveObject(env, pos_),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false)
|
||||
{
|
||||
setPosition(pos_);
|
||||
peer_id = peer_id_;
|
||||
updateName(name_);
|
||||
}
|
||||
ServerRemotePlayer::~ServerRemotePlayer()
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
}
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
|
||||
InventoryItem* ServerRemotePlayer::getWieldedItem()
|
||||
{
|
||||
InventoryList *list = inventory.getList("main");
|
||||
if (list)
|
||||
return list->getItem(m_selected_item);
|
||||
return NULL;
|
||||
}
|
||||
void ServerRemotePlayer::damageWieldedItem(u16 amount)
|
||||
{
|
||||
infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
|
||||
<<amount<<std::endl;
|
||||
InventoryList *list = inventory.getList("main");
|
||||
if(!list)
|
||||
return;
|
||||
InventoryItem *item = list->getItem(m_selected_item);
|
||||
if(item && (std::string)item->getName() == "ToolItem"){
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
bool weared_out = titem->addWear(amount);
|
||||
if(weared_out)
|
||||
list->deleteItem(m_selected_item);
|
||||
}
|
||||
}
|
||||
bool ServerRemotePlayer::addToInventory(InventoryItem *item)
|
||||
{
|
||||
infostream<<"Adding "<<item->getName()<<" into "<<getName()
|
||||
<<"'s inventory"<<std::endl;
|
||||
|
||||
InventoryList *ilist = inventory.getList("main");
|
||||
if(ilist == NULL)
|
||||
return false;
|
||||
|
||||
// In creative mode, just delete the item
|
||||
if(g_settings->getBool("creative_mode")){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip if inventory has no free space
|
||||
if(ilist->roomForItem(item) == false)
|
||||
{
|
||||
infostream<<"Player inventory has no free space"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to inventory
|
||||
InventoryItem *leftover = ilist->addItem(item);
|
||||
assert(!leftover);
|
||||
|
||||
m_inventory_not_sent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
void ServerRemotePlayer::addToInventoryLater(InventoryItem *item)
|
||||
{
|
||||
infostream<<"Adding (later) "<<item->getName()<<" into "<<getName()
|
||||
<<"'s inventory"<<std::endl;
|
||||
m_additional_items.push_back(item);
|
||||
}
|
||||
void ServerRemotePlayer::clearAddToInventoryLater()
|
||||
{
|
||||
for (std::vector<InventoryItem*>::iterator
|
||||
i = m_additional_items.begin();
|
||||
i != m_additional_items.end(); i++)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
m_additional_items.clear();
|
||||
}
|
||||
void ServerRemotePlayer::completeAddToInventoryLater(u16 preferred_index)
|
||||
{
|
||||
InventoryList *ilist = inventory.getList("main");
|
||||
if(ilist == NULL)
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// In creative mode, just delete the items
|
||||
if(g_settings->getBool("creative_mode"))
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<InventoryItem*>::iterator
|
||||
i = m_additional_items.begin();
|
||||
i != m_additional_items.end(); i++)
|
||||
{
|
||||
InventoryItem *item = *i;
|
||||
InventoryItem *leftover = item;
|
||||
leftover = ilist->addItem(preferred_index, leftover);
|
||||
leftover = ilist->addItem(leftover);
|
||||
delete leftover;
|
||||
}
|
||||
m_additional_items.clear();
|
||||
m_inventory_not_sent = true;
|
||||
}
|
||||
void ServerRemotePlayer::setHP(s16 hp_)
|
||||
{
|
||||
s16 oldhp = hp;
|
||||
|
||||
hp = hp_;
|
||||
|
||||
// FIXME: don't hardcode maximum HP, make configurable per object
|
||||
if(hp < 0)
|
||||
hp = 0;
|
||||
else if(hp > 20)
|
||||
hp = 20;
|
||||
|
||||
if(hp != oldhp)
|
||||
m_hp_not_sent = true;
|
||||
}
|
||||
s16 ServerRemotePlayer::getHP()
|
||||
{
|
||||
return hp;
|
||||
}
|
||||
|
||||
/*
|
||||
RemotePlayer
|
||||
*/
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
RemotePlayer::RemotePlayer(
|
||||
IGameDef *gamedef,
|
||||
scene::ISceneNode* parent,
|
||||
IrrlichtDevice *device,
|
||||
s32 id):
|
||||
Player(gamedef),
|
||||
scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id),
|
||||
m_text(NULL)
|
||||
{
|
||||
m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2);
|
||||
|
||||
if(parent != NULL && device != NULL)
|
||||
{
|
||||
// ISceneNode stores a member called SceneManager
|
||||
scene::ISceneManager* mgr = SceneManager;
|
||||
video::IVideoDriver* driver = mgr->getVideoDriver();
|
||||
gui::IGUIEnvironment* gui = device->getGUIEnvironment();
|
||||
|
||||
// Add a text node for showing the name
|
||||
wchar_t wname[1] = {0};
|
||||
m_text = mgr->addTextSceneNode(gui->getBuiltInFont(),
|
||||
wname, video::SColor(255,255,255,255), this);
|
||||
m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
|
||||
|
||||
// Attach a simple mesh to the player for showing an image
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
{ // Front
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
{ // Back
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
|
||||
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
// Set material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
m_node = mgr->addMeshSceneNode(mesh, this);
|
||||
mesh->drop();
|
||||
m_node->setPosition(v3f(0,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
RemotePlayer::~RemotePlayer()
|
||||
{
|
||||
if(SceneManager != NULL)
|
||||
ISceneNode::remove();
|
||||
}
|
||||
|
||||
void RemotePlayer::updateName(const char *name)
|
||||
{
|
||||
Player::updateName(name);
|
||||
if(m_text != NULL)
|
||||
{
|
||||
wchar_t wname[PLAYERNAME_SIZE];
|
||||
mbstowcs(wname, m_name, strlen(m_name)+1);
|
||||
m_text->setText(wname);
|
||||
}
|
||||
}
|
||||
|
||||
void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
{
|
||||
m_pos_animation_time_counter += dtime;
|
||||
m_pos_animation_counter += dtime;
|
||||
v3f movevector = m_position - m_oldpos;
|
||||
f32 moveratio;
|
||||
if(m_pos_animation_time < 0.001)
|
||||
moveratio = 1.0;
|
||||
else
|
||||
moveratio = m_pos_animation_counter / m_pos_animation_time;
|
||||
if(moveratio > 1.5)
|
||||
moveratio = 1.5;
|
||||
m_showpos = m_oldpos + movevector * moveratio;
|
||||
|
||||
ISceneNode::setPosition(m_showpos);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
LocalPlayer
|
||||
|
||||
166
src/player.h
166
src/player.h
@@ -174,172 +174,6 @@ class Player
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Player on the server
|
||||
*/
|
||||
|
||||
#include "serverobject.h"
|
||||
#include "content_object.h" // Object type IDs
|
||||
|
||||
class ServerRemotePlayer : public Player, public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
ServerRemotePlayer(ServerEnvironment *env);
|
||||
ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
||||
const char *name_);
|
||||
|
||||
virtual ~ServerRemotePlayer();
|
||||
|
||||
virtual bool isLocal() const
|
||||
{ return false; }
|
||||
|
||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void setPosition(const v3f &position)
|
||||
{
|
||||
Player::setPosition(position);
|
||||
ServerActiveObject::setBasePosition(position);
|
||||
}
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_PLAYER;}
|
||||
|
||||
virtual void setPos(v3f pos)
|
||||
{
|
||||
setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
virtual void moveTo(v3f pos, bool continuous)
|
||||
{
|
||||
setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
|
||||
virtual std::string getDescription(){return getName();}
|
||||
// Returns a reference
|
||||
virtual InventoryItem* getWieldedItem();
|
||||
virtual void damageWieldedItem(u16 amount);
|
||||
// If all fits, eats item and returns true. Otherwise returns false.
|
||||
virtual bool addToInventory(InventoryItem *item);
|
||||
virtual void addToInventoryLater(InventoryItem *item);
|
||||
void clearAddToInventoryLater();
|
||||
void completeAddToInventoryLater(u16 preferred_index);
|
||||
virtual void setHP(s16 hp_);
|
||||
virtual s16 getHP();
|
||||
|
||||
v3f m_last_good_position;
|
||||
float m_last_good_position_age;
|
||||
std::vector<InventoryItem*> m_additional_items;
|
||||
bool m_inventory_not_sent;
|
||||
bool m_hp_not_sent;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
/*
|
||||
All the other players on the client are these
|
||||
*/
|
||||
|
||||
class RemotePlayer : public Player, public scene::ISceneNode
|
||||
{
|
||||
public:
|
||||
RemotePlayer(
|
||||
IGameDef *gamedef,
|
||||
scene::ISceneNode* parent=NULL,
|
||||
IrrlichtDevice *device=NULL,
|
||||
s32 id=0);
|
||||
|
||||
virtual ~RemotePlayer();
|
||||
|
||||
/*
|
||||
ISceneNode methods
|
||||
*/
|
||||
|
||||
virtual void OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
virtual void render()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const
|
||||
{
|
||||
return m_box;
|
||||
}
|
||||
|
||||
void setPosition(const v3f &position)
|
||||
{
|
||||
m_oldpos = m_showpos;
|
||||
|
||||
if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
|
||||
m_pos_animation_time = m_pos_animation_time_counter;
|
||||
else
|
||||
m_pos_animation_time = m_pos_animation_time * 0.9
|
||||
+ m_pos_animation_time_counter * 0.1;
|
||||
m_pos_animation_time_counter = 0;
|
||||
m_pos_animation_counter = 0;
|
||||
|
||||
Player::setPosition(position);
|
||||
//ISceneNode::setPosition(position);
|
||||
}
|
||||
|
||||
virtual void setYaw(f32 yaw)
|
||||
{
|
||||
Player::setYaw(yaw);
|
||||
ISceneNode::setRotation(v3f(0, -yaw, 0));
|
||||
}
|
||||
|
||||
bool isLocal() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateName(const char *name);
|
||||
|
||||
virtual void updateLight(u8 light_at_pos)
|
||||
{
|
||||
Player::updateLight(light_at_pos);
|
||||
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode *m_node;
|
||||
scene::ITextSceneNode* m_text;
|
||||
core::aabbox3d<f32> m_box;
|
||||
|
||||
v3f m_oldpos;
|
||||
f32 m_pos_animation_counter;
|
||||
f32 m_pos_animation_time;
|
||||
f32 m_pos_animation_time_counter;
|
||||
v3f m_showpos;
|
||||
};
|
||||
|
||||
#endif // !SERVER
|
||||
|
||||
#ifndef SERVER
|
||||
struct PlayerControl
|
||||
{
|
||||
|
||||
@@ -386,13 +386,24 @@ static int getenumfield(lua_State *L, int table,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setfloatfield(lua_State *L, int table,
|
||||
const char *fieldname, float value)
|
||||
{
|
||||
lua_pushnumber(L, value);
|
||||
if(table < 0)
|
||||
table -= 1;
|
||||
lua_setfield(L, table, fieldname);
|
||||
}
|
||||
|
||||
/*
|
||||
Inventory stuff
|
||||
*/
|
||||
|
||||
static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||
lua_State *L, int tableindex, IGameDef *gamedef)
|
||||
lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
|
||||
{
|
||||
if(tableindex < 0)
|
||||
tableindex = lua_gettop(L) + 1 + tableindex;
|
||||
// If nil, delete list
|
||||
if(lua_isnil(L, tableindex)){
|
||||
inv->deleteList(name);
|
||||
@@ -411,10 +422,13 @@ static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
InventoryList *invlist = inv->addList(name, items.size());
|
||||
int listsize = (forcesize != -1) ? forcesize : items.size();
|
||||
InventoryList *invlist = inv->addList(name, listsize);
|
||||
int index = 0;
|
||||
for(std::list<std::string>::const_iterator
|
||||
i = items.begin(); i != items.end(); i++){
|
||||
if(forcesize != -1 && index == forcesize)
|
||||
break;
|
||||
const std::string &itemstring = *i;
|
||||
InventoryItem *newitem = NULL;
|
||||
if(itemstring != "")
|
||||
@@ -424,6 +438,11 @@ static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||
delete olditem;
|
||||
index++;
|
||||
}
|
||||
while(forcesize != -1 && index < forcesize){
|
||||
InventoryItem *olditem = invlist->changeItem(index, NULL);
|
||||
delete olditem;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
||||
@@ -446,7 +465,7 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
||||
lua_pushvalue(L, table_insert);
|
||||
lua_pushvalue(L, table);
|
||||
if(item == NULL){
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "");
|
||||
} else {
|
||||
lua_pushstring(L, item->getItemString().c_str());
|
||||
}
|
||||
@@ -455,6 +474,71 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ToolDiggingProperties
|
||||
*/
|
||||
|
||||
static ToolDiggingProperties read_tool_digging_properties(
|
||||
lua_State *L, int table)
|
||||
{
|
||||
ToolDiggingProperties prop;
|
||||
getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
|
||||
getfloatfield(L, table, "basetime", prop.basetime);
|
||||
getfloatfield(L, table, "dt_weight", prop.dt_weight);
|
||||
getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
|
||||
getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
|
||||
getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
|
||||
getfloatfield(L, table, "basedurability", prop.basedurability);
|
||||
getfloatfield(L, table, "dd_weight", prop.dd_weight);
|
||||
getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
|
||||
getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
|
||||
getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
|
||||
return prop;
|
||||
}
|
||||
|
||||
static void set_tool_digging_properties(lua_State *L, int table,
|
||||
const ToolDiggingProperties &prop)
|
||||
{
|
||||
setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
|
||||
setfloatfield(L, table, "basetime", prop.basetime);
|
||||
setfloatfield(L, table, "dt_weight", prop.dt_weight);
|
||||
setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
|
||||
setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
|
||||
setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
|
||||
setfloatfield(L, table, "basedurability", prop.basedurability);
|
||||
setfloatfield(L, table, "dd_weight", prop.dd_weight);
|
||||
setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
|
||||
setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
|
||||
setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
|
||||
}
|
||||
|
||||
static void push_tool_digging_properties(lua_State *L,
|
||||
const ToolDiggingProperties &prop)
|
||||
{
|
||||
lua_newtable(L);
|
||||
set_tool_digging_properties(L, -1, prop);
|
||||
}
|
||||
|
||||
/*
|
||||
ToolDefinition
|
||||
*/
|
||||
|
||||
static ToolDefinition read_tool_definition(lua_State *L, int table)
|
||||
{
|
||||
ToolDefinition def;
|
||||
getstringfield(L, table, "image", def.imagename);
|
||||
def.properties = read_tool_digging_properties(L, table);
|
||||
return def;
|
||||
}
|
||||
|
||||
static void push_tool_definition(lua_State *L, const ToolDefinition &def)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, def.imagename.c_str());
|
||||
lua_setfield(L, -2, "image");
|
||||
set_tool_digging_properties(L, -1, def.properties);
|
||||
}
|
||||
|
||||
/*
|
||||
EnumString definitions
|
||||
*/
|
||||
@@ -672,19 +756,7 @@ static int l_register_tool(lua_State *L)
|
||||
IWritableToolDefManager *tooldef =
|
||||
server->getWritableToolDefManager();
|
||||
|
||||
ToolDefinition def;
|
||||
|
||||
getstringfield(L, table, "image", def.imagename);
|
||||
getfloatfield(L, table, "basetime", def.properties.basetime);
|
||||
getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
|
||||
getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
|
||||
getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
|
||||
getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
|
||||
getfloatfield(L, table, "basedurability", def.properties.basedurability);
|
||||
getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
|
||||
getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
|
||||
getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
|
||||
getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
|
||||
ToolDefinition def = read_tool_definition(L, table);
|
||||
|
||||
tooldef->registerTool(name, def);
|
||||
return 0; /* number of results */
|
||||
@@ -1688,65 +1760,16 @@ class ObjectRef
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_wielded_itemstring(self)
|
||||
static int l_get_wielded_itemstring(lua_State *L)
|
||||
// get_wield_digging_properties(self)
|
||||
static int l_get_wield_digging_properties(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerActiveObject *co = getobject(ref);
|
||||
if(co == NULL) return 0;
|
||||
// Do it
|
||||
InventoryItem *item = co->getWieldedItem();
|
||||
if(item == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_pushstring(L, item->getItemString().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_wielded_item(self)
|
||||
static int l_get_wielded_item(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerActiveObject *co = getobject(ref);
|
||||
if(co == NULL) return 0;
|
||||
// Do it
|
||||
InventoryItem *item0 = co->getWieldedItem();
|
||||
if(item0 == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
if(std::string("MaterialItem") == item0->getName()){
|
||||
MaterialItem *item = (MaterialItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "NodeItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getNodeName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
}
|
||||
else if(std::string("CraftItem") == item0->getName()){
|
||||
CraftItem *item = (CraftItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "CraftItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getSubName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
}
|
||||
else if(std::string("ToolItem") == item0->getName()){
|
||||
ToolItem *item = (ToolItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "ToolItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getToolName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_pushstring(L, itos(item->getWear()).c_str());
|
||||
lua_setfield(L, -2, "wear");
|
||||
}
|
||||
else{
|
||||
errorstream<<"l_get_wielded_item: Unknown item name: \""
|
||||
<<item0->getName()<<"\""<<std::endl;
|
||||
lua_pushnil(L);
|
||||
}
|
||||
ToolDiggingProperties prop;
|
||||
co->getWieldDiggingProperties(&prop);
|
||||
push_tool_digging_properties(L, prop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1787,7 +1810,7 @@ class ObjectRef
|
||||
// Return
|
||||
lua_pushboolean(L, added);
|
||||
if(!added)
|
||||
lua_pushstring(L, "does not fit");
|
||||
lua_pushstring(L, "failed to add item");
|
||||
return 2;
|
||||
} catch(SerializationError &e){
|
||||
// Return
|
||||
@@ -1957,7 +1980,7 @@ class ObjectRef
|
||||
const char *name = lua_tostring(L, 2);
|
||||
// Do it
|
||||
inventory_set_list_from_lua(&player->inventory, name, L, 3,
|
||||
player->getEnv()->getGameDef());
|
||||
player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
|
||||
player->m_inventory_not_sent = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -1974,6 +1997,68 @@ class ObjectRef
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_wielded_itemstring(self)
|
||||
static int l_get_wielded_itemstring(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
// Do it
|
||||
InventoryItem *item = player->getWieldedItem();
|
||||
if(item == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_pushstring(L, item->getItemString().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_wielded_item(self)
|
||||
static int l_get_wielded_item(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
// Do it
|
||||
InventoryItem *item0 = player->getWieldedItem();
|
||||
if(item0 == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
if(std::string("MaterialItem") == item0->getName()){
|
||||
MaterialItem *item = (MaterialItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "NodeItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getNodeName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
}
|
||||
else if(std::string("CraftItem") == item0->getName()){
|
||||
CraftItem *item = (CraftItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "CraftItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getSubName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
}
|
||||
else if(std::string("ToolItem") == item0->getName()){
|
||||
ToolItem *item = (ToolItem*)item0;
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "ToolItem");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, item->getToolName().c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_pushstring(L, itos(item->getWear()).c_str());
|
||||
lua_setfield(L, -2, "wear");
|
||||
}
|
||||
else{
|
||||
errorstream<<"l_get_wielded_item: Unknown item name: \""
|
||||
<<item0->getName()<<"\""<<std::endl;
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectRef(ServerActiveObject *object):
|
||||
m_object(object)
|
||||
@@ -2044,8 +2129,7 @@ const luaL_reg ObjectRef::methods[] = {
|
||||
method(ObjectRef, moveto),
|
||||
method(ObjectRef, punch),
|
||||
method(ObjectRef, right_click),
|
||||
method(ObjectRef, get_wielded_itemstring),
|
||||
method(ObjectRef, get_wielded_item),
|
||||
method(ObjectRef, get_wield_digging_properties),
|
||||
method(ObjectRef, damage_wielded_item),
|
||||
method(ObjectRef, add_to_inventory),
|
||||
method(ObjectRef, add_to_inventory_later),
|
||||
@@ -2061,6 +2145,8 @@ const luaL_reg ObjectRef::methods[] = {
|
||||
method(ObjectRef, get_player_name),
|
||||
method(ObjectRef, inventory_set_list),
|
||||
method(ObjectRef, inventory_get_list),
|
||||
method(ObjectRef, get_wielded_itemstring),
|
||||
method(ObjectRef, get_wielded_item),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
@@ -2609,6 +2695,15 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||
return positioning_handled_by_some;
|
||||
}
|
||||
|
||||
void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
|
||||
{
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "creative_inventory");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
inventory_set_list_from_lua(&player->inventory, "main", L, -1,
|
||||
player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
craftitem
|
||||
*/
|
||||
@@ -3124,9 +3219,9 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
|
||||
script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
// Calls entity:on_punch(ObjectRef puncher)
|
||||
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
|
||||
void scriptapi_luaentity_punch(lua_State *L, u16 id,
|
||||
ServerActiveObject *puncher)
|
||||
ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
@@ -3144,8 +3239,9 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id,
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
lua_pushvalue(L, object); // self
|
||||
objectref_get_or_create(L, puncher); // Clicker reference
|
||||
lua_pushnumber(L, time_from_last_punch);
|
||||
// Call with 2 arguments, 0 results
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ typedef struct lua_State lua_State;
|
||||
struct LuaEntityProperties;
|
||||
struct PointedThing;
|
||||
//class IGameDef;
|
||||
class ServerRemotePlayer;
|
||||
|
||||
void scriptapi_export(lua_State *L, Server *server);
|
||||
void scriptapi_add_environment(lua_State *L, ServerEnvironment *env);
|
||||
@@ -60,6 +61,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp);
|
||||
/* misc */
|
||||
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player);
|
||||
bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player);
|
||||
void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player);
|
||||
|
||||
/* craftitem */
|
||||
void scriptapi_add_craftitem(lua_State *L, const char *name);
|
||||
@@ -83,7 +85,7 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
|
||||
LuaEntityProperties *prop);
|
||||
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime);
|
||||
void scriptapi_luaentity_punch(lua_State *L, u16 id,
|
||||
ServerActiveObject *puncher);
|
||||
ServerActiveObject *puncher, float time_from_last_punch);
|
||||
void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
|
||||
ServerActiveObject *clicker);
|
||||
|
||||
|
||||
345
src/server.cpp
345
src/server.cpp
@@ -33,7 +33,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "servercommand.h"
|
||||
#include "filesys.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "content_craft.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "mapblock.h"
|
||||
#include "serverobject.h"
|
||||
@@ -48,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "craftitemdef.h"
|
||||
#include "mapgen.h"
|
||||
#include "content_abm.h"
|
||||
#include "content_sao.h" // For PlayerSAO
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@@ -749,105 +749,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||
infostream<<"GetNextBlocks duration: "<<timer_result<<" (!=0)"<<std::endl;*/
|
||||
}
|
||||
|
||||
void RemoteClient::SendObjectData(
|
||||
Server *server,
|
||||
float dtime,
|
||||
core::map<v3s16, bool> &stepped_blocks
|
||||
)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// Can't send anything without knowing version
|
||||
if(serialization_version == SER_FMT_VER_INVALID)
|
||||
{
|
||||
infostream<<"RemoteClient::SendObjectData(): Not sending, no version."
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Send a TOCLIENT_OBJECTDATA packet.
|
||||
Sent as unreliable.
|
||||
|
||||
u16 command
|
||||
u16 number of player positions
|
||||
for each player:
|
||||
u16 peer_id
|
||||
v3s32 position*100
|
||||
v3s32 speed*100
|
||||
s32 pitch*100
|
||||
s32 yaw*100
|
||||
u16 count of blocks
|
||||
for each block:
|
||||
block objects
|
||||
*/
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
u8 buf[12];
|
||||
|
||||
// Write command
|
||||
writeU16(buf, TOCLIENT_OBJECTDATA);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
/*
|
||||
Get and write player data
|
||||
*/
|
||||
|
||||
// Get connected players
|
||||
core::list<Player*> players = server->m_env->getPlayers(true);
|
||||
|
||||
// Write player count
|
||||
u16 playercount = players.size();
|
||||
writeU16(buf, playercount);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
core::list<Player*>::Iterator i;
|
||||
for(i = players.begin();
|
||||
i != players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
v3f pf = player->getPosition();
|
||||
v3f sf = player->getSpeed();
|
||||
|
||||
v3s32 position_i(pf.X*100, pf.Y*100, pf.Z*100);
|
||||
v3s32 speed_i (sf.X*100, sf.Y*100, sf.Z*100);
|
||||
s32 pitch_i (player->getPitch() * 100);
|
||||
s32 yaw_i (player->getYaw() * 100);
|
||||
|
||||
writeU16(buf, player->peer_id);
|
||||
os.write((char*)buf, 2);
|
||||
writeV3S32(buf, position_i);
|
||||
os.write((char*)buf, 12);
|
||||
writeV3S32(buf, speed_i);
|
||||
os.write((char*)buf, 12);
|
||||
writeS32(buf, pitch_i);
|
||||
os.write((char*)buf, 4);
|
||||
writeS32(buf, yaw_i);
|
||||
os.write((char*)buf, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
Get and write object data (dummy, for compatibility)
|
||||
*/
|
||||
|
||||
// Write block count
|
||||
writeU16(buf, 0);
|
||||
os.write((char*)buf, 2);
|
||||
|
||||
/*
|
||||
Send data
|
||||
*/
|
||||
|
||||
//infostream<<"Server: Sending object data to "<<peer_id<<std::endl;
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as unreliable
|
||||
server->m_con.Send(peer_id, 0, data, false);
|
||||
}
|
||||
|
||||
void RemoteClient::GotBlock(v3s16 p)
|
||||
{
|
||||
if(m_blocks_sending.find(p) != NULL)
|
||||
@@ -1430,6 +1331,11 @@ void Server::AsyncRunStep()
|
||||
player->m_last_good_position_age = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle player HPs
|
||||
*/
|
||||
HandlePlayerHP(player, 0);
|
||||
|
||||
/*
|
||||
Send player inventories and HPs if necessary
|
||||
*/
|
||||
@@ -1541,6 +1447,12 @@ void Server::AsyncRunStep()
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
|
||||
// If definitions and textures have not been sent, don't
|
||||
// send objects either
|
||||
if(!client->definitions_sent)
|
||||
continue;
|
||||
|
||||
Player *player = m_env->getPlayer(client->peer_id);
|
||||
if(player==NULL)
|
||||
{
|
||||
@@ -1908,25 +1820,6 @@ void Server::AsyncRunStep()
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Send object positions
|
||||
*/
|
||||
{
|
||||
float &counter = m_objectdata_timer;
|
||||
counter += dtime;
|
||||
if(counter >= g_settings->getFloat("objectdata_interval"))
|
||||
{
|
||||
JMutexAutoLock lock1(m_env_mutex);
|
||||
JMutexAutoLock lock2(m_con_mutex);
|
||||
|
||||
//ScopeProfiler sp(g_profiler, "Server: sending player positions");
|
||||
|
||||
SendObjectData(counter);
|
||||
|
||||
counter = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Trigger emergethread (it somehow gets to a non-triggered but
|
||||
bysy state sometimes)
|
||||
@@ -2121,7 +2014,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
SendAccessDenied(m_con, peer_id, std::wstring(
|
||||
L"Your client's version is not supported.\n"
|
||||
L"Server version is ")
|
||||
+ narrow_to_wide(VERSION_STRING) + L"."
|
||||
+ narrow_to_wide(VERSION_STRING) + L",\n"
|
||||
+ L"server's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(PROTOCOL_VERSION))
|
||||
+ L", client's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(net_proto_version))
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -2171,20 +2068,33 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
password[PASSWORD_SIZE-1] = 0;
|
||||
}
|
||||
|
||||
std::string checkpwd;
|
||||
if(m_authmanager.exists(playername))
|
||||
// Add player to auth manager
|
||||
if(m_authmanager.exists(playername) == false)
|
||||
{
|
||||
checkpwd = m_authmanager.getPassword(playername);
|
||||
std::wstring default_password =
|
||||
narrow_to_wide(g_settings->get("default_password"));
|
||||
std::string translated_default_password =
|
||||
translatePassword(playername, default_password);
|
||||
|
||||
// If default_password is empty, allow any initial password
|
||||
if (default_password.length() == 0)
|
||||
translated_default_password = password;
|
||||
|
||||
infostream<<"Server: adding player "<<playername
|
||||
<<" to auth manager"<<std::endl;
|
||||
m_authmanager.add(playername);
|
||||
m_authmanager.setPassword(playername, translated_default_password);
|
||||
m_authmanager.setPrivs(playername,
|
||||
stringToPrivs(g_settings->get("default_privs")));
|
||||
m_authmanager.save();
|
||||
}
|
||||
else
|
||||
{
|
||||
checkpwd = g_settings->get("default_password");
|
||||
}
|
||||
|
||||
|
||||
std::string checkpwd = m_authmanager.getPassword(playername);
|
||||
|
||||
/*infostream<<"Server: Client gave password '"<<password
|
||||
<<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
|
||||
|
||||
if(password != checkpwd && m_authmanager.exists(playername))
|
||||
|
||||
if(password != checkpwd)
|
||||
{
|
||||
infostream<<"Server: peer_id="<<peer_id
|
||||
<<": supplied invalid password for "
|
||||
@@ -2193,23 +2103,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
return;
|
||||
}
|
||||
|
||||
// Add player to auth manager
|
||||
if(m_authmanager.exists(playername) == false)
|
||||
{
|
||||
infostream<<"Server: adding player "<<playername
|
||||
<<" to auth manager"<<std::endl;
|
||||
m_authmanager.add(playername);
|
||||
m_authmanager.setPassword(playername, checkpwd);
|
||||
m_authmanager.setPrivs(playername,
|
||||
stringToPrivs(g_settings->get("default_privs")));
|
||||
m_authmanager.save();
|
||||
}
|
||||
|
||||
// Enforce user limit.
|
||||
// Don't enforce for users that have some admin right
|
||||
if(m_clients.size() >= g_settings->getU16("max_users") &&
|
||||
(m_authmanager.getPrivs(playername)
|
||||
& (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS)) == 0 &&
|
||||
& (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS|PRIV_PASSWORD)) == 0 &&
|
||||
playername != g_settings->get("name"))
|
||||
{
|
||||
SendAccessDenied(m_con, peer_id, L"Too many users.");
|
||||
@@ -2217,7 +2115,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
|
||||
// Get player
|
||||
Player *player = emergePlayer(playername, password, peer_id);
|
||||
ServerRemotePlayer *player = emergePlayer(playername, peer_id);
|
||||
|
||||
// If failed, cancel
|
||||
if(player == NULL)
|
||||
@@ -2227,6 +2125,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
return;
|
||||
}
|
||||
|
||||
// Add PlayerSAO
|
||||
player->m_removed = false;
|
||||
player->setId(0);
|
||||
m_env->addActiveObject(player);
|
||||
|
||||
/*
|
||||
Answer with a TOCLIENT_INIT
|
||||
*/
|
||||
@@ -2275,12 +2178,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
SendTextures(peer_id);
|
||||
|
||||
// Send player info to all players
|
||||
SendPlayerInfos();
|
||||
//SendPlayerInfos();
|
||||
|
||||
// Send inventory to player
|
||||
UpdateCrafting(peer_id);
|
||||
SendInventory(peer_id);
|
||||
|
||||
|
||||
// Send player items to all players
|
||||
SendPlayerItems();
|
||||
|
||||
@@ -2296,6 +2199,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
// Now the client should know about everything
|
||||
getClient(peer_id)->definitions_sent = true;
|
||||
|
||||
// Send information about server to player in chat
|
||||
SendChatMessage(peer_id, getStatusString());
|
||||
|
||||
@@ -2474,7 +2380,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
else if(command == TOSERVER_SIGNNODETEXT)
|
||||
{
|
||||
if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
|
||||
if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
|
||||
return;
|
||||
/*
|
||||
u16 command
|
||||
@@ -2655,7 +2561,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
|
||||
// Disallow moving items in elsewhere than player's inventory
|
||||
// if not allowed to build
|
||||
if((getPlayerPrivs(player) & PRIV_BUILD) == 0
|
||||
if((getPlayerPrivs(player) & PRIV_INTERACT) == 0
|
||||
&& (ma->from_inv != "current_player"
|
||||
|| ma->to_inv != "current_player"))
|
||||
{
|
||||
@@ -2721,7 +2627,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
{
|
||||
IDropAction *da = (IDropAction*)a;
|
||||
// Disallow dropping items if not allowed to build
|
||||
if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
|
||||
if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
|
||||
{
|
||||
delete a;
|
||||
return;
|
||||
@@ -2973,10 +2879,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
if(player->hp != 0)
|
||||
return;
|
||||
|
||||
srp->m_respawn_active = false;
|
||||
|
||||
RespawnPlayer(player);
|
||||
|
||||
actionstream<<player->getName()<<" respawns at "
|
||||
<<PP(player->getPosition()/BS)<<std::endl;
|
||||
|
||||
srp->m_removed = false;
|
||||
srp->setId(0);
|
||||
m_env->addActiveObject(srp);
|
||||
}
|
||||
else if(command == TOSERVER_INTERACT)
|
||||
{
|
||||
@@ -3063,7 +2975,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
/*
|
||||
Make sure the player is allowed to do it
|
||||
*/
|
||||
bool build_priv = (getPlayerPrivs(player) & PRIV_BUILD) != 0;
|
||||
bool build_priv = (getPlayerPrivs(player) & PRIV_INTERACT) != 0;
|
||||
if(!build_priv)
|
||||
{
|
||||
infostream<<"Ignoring interaction from player "<<player->getName()
|
||||
@@ -3939,64 +3851,6 @@ void Server::SendCraftItemDef(con::Connection &con, u16 peer_id,
|
||||
Non-static send methods
|
||||
*/
|
||||
|
||||
void Server::SendObjectData(float dtime)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
core::map<v3s16, bool> stepped_blocks;
|
||||
|
||||
for(core::map<u16, RemoteClient*>::Iterator
|
||||
i = m_clients.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
u16 peer_id = i.getNode()->getKey();
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
assert(client->peer_id == peer_id);
|
||||
|
||||
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||
continue;
|
||||
|
||||
client->SendObjectData(this, dtime, stepped_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::SendPlayerInfos()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
//JMutexAutoLock envlock(m_env_mutex);
|
||||
|
||||
// Get connected players
|
||||
core::list<Player*> players = m_env->getPlayers(true);
|
||||
|
||||
u32 player_count = players.getSize();
|
||||
u32 datasize = 2+(2+PLAYERNAME_SIZE)*player_count;
|
||||
|
||||
SharedBuffer<u8> data(datasize);
|
||||
writeU16(&data[0], TOCLIENT_PLAYERINFO);
|
||||
|
||||
u32 start = 2;
|
||||
core::list<Player*>::Iterator i;
|
||||
for(i = players.begin();
|
||||
i != players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
/*infostream<<"Server sending player info for player with "
|
||||
"peer_id="<<player->peer_id<<std::endl;*/
|
||||
|
||||
writeU16(&data[start], player->peer_id);
|
||||
memset((char*)&data[start+2], 0, PLAYERNAME_SIZE);
|
||||
snprintf((char*)&data[start+2], PLAYERNAME_SIZE, "%s", player->getName());
|
||||
start += 2+PLAYERNAME_SIZE;
|
||||
}
|
||||
|
||||
//JMutexAutoLock conlock(m_con_mutex);
|
||||
|
||||
// Send as reliable
|
||||
m_con.SendToAll(0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendInventory(u16 peer_id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
@@ -4345,6 +4199,11 @@ void Server::SendBlocks(float dtime)
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
assert(client->peer_id == i.getNode()->getKey());
|
||||
|
||||
// If definitions and textures have not been sent, don't
|
||||
// send MapBlocks either
|
||||
if(!client->definitions_sent)
|
||||
continue;
|
||||
|
||||
total_sending += client->SendingCount();
|
||||
|
||||
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||
@@ -4517,6 +4376,11 @@ void Server::SendTextures(u16 peer_id)
|
||||
|
||||
void Server::HandlePlayerHP(Player *player, s16 damage)
|
||||
{
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
||||
|
||||
if(srp->m_respawn_active)
|
||||
return;
|
||||
|
||||
if(player->hp > damage)
|
||||
{
|
||||
player->hp -= damage;
|
||||
@@ -4543,6 +4407,8 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
|
||||
if(client->net_proto_version >= 3)
|
||||
{
|
||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
||||
srp->m_removed = true;
|
||||
srp->m_respawn_active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4678,6 +4544,22 @@ std::wstring Server::getStatusString()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
|
||||
{
|
||||
// Add player to auth manager
|
||||
if(m_authmanager.exists(name) == false)
|
||||
{
|
||||
infostream<<"Server: adding player "<<name
|
||||
<<" to auth manager"<<std::endl;
|
||||
m_authmanager.add(name);
|
||||
m_authmanager.setPrivs(name,
|
||||
stringToPrivs(g_settings->get("default_privs")));
|
||||
}
|
||||
// Change password and save
|
||||
m_authmanager.setPassword(name, translatePassword(name, password));
|
||||
m_authmanager.save();
|
||||
}
|
||||
|
||||
// Saves g_settings to configpath given at initialization
|
||||
void Server::saveConfig()
|
||||
{
|
||||
@@ -4813,12 +4695,13 @@ v3f findSpawnPos(ServerMap &map)
|
||||
return intToFloat(nodepos, BS);
|
||||
}
|
||||
|
||||
Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id)
|
||||
ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
|
||||
{
|
||||
/*
|
||||
Try to get an existing player
|
||||
*/
|
||||
Player *player = m_env->getPlayer(name);
|
||||
ServerRemotePlayer *player =
|
||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
|
||||
if(player != NULL)
|
||||
{
|
||||
// If player is already connected, cancel
|
||||
@@ -4839,7 +4722,8 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
|
||||
player->inventory_backup = new Inventory();
|
||||
*(player->inventory_backup) = player->inventory;
|
||||
// Set creative inventory
|
||||
craft_set_creative_inventory(player, this);
|
||||
player->resetInventory();
|
||||
scriptapi_get_creative_inventory(m_lua, player);
|
||||
}
|
||||
|
||||
return player;
|
||||
@@ -4859,12 +4743,6 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
|
||||
Create a new player
|
||||
*/
|
||||
{
|
||||
// Add authentication stuff
|
||||
m_authmanager.add(name);
|
||||
m_authmanager.setPassword(name, password);
|
||||
m_authmanager.setPrivs(name,
|
||||
stringToPrivs(g_settings->get("default_privs")));
|
||||
|
||||
/* Set player position */
|
||||
|
||||
infostream<<"Server: Finding spawn place for player \""
|
||||
@@ -4889,7 +4767,8 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
|
||||
player->inventory_backup = new Inventory();
|
||||
*(player->inventory_backup) = player->inventory;
|
||||
// Set creative inventory
|
||||
craft_set_creative_inventory(player, this);
|
||||
player->resetInventory();
|
||||
scriptapi_get_creative_inventory(m_lua, player);
|
||||
}
|
||||
|
||||
return player;
|
||||
@@ -4949,10 +4828,12 @@ void Server::handlePeerChange(PeerChange &c)
|
||||
obj->m_known_by_count--;
|
||||
}
|
||||
|
||||
ServerRemotePlayer* player =
|
||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
|
||||
|
||||
// Collect information about leaving in chat
|
||||
std::wstring message;
|
||||
{
|
||||
Player *player = m_env->getPlayer(c.peer_id);
|
||||
if(player != NULL)
|
||||
{
|
||||
std::wstring name = narrow_to_wide(player->getName());
|
||||
@@ -4963,21 +4844,19 @@ void Server::handlePeerChange(PeerChange &c)
|
||||
message += L" (timed out)";
|
||||
}
|
||||
}
|
||||
|
||||
/*// Delete player
|
||||
{
|
||||
m_env->removePlayer(c.peer_id);
|
||||
}*/
|
||||
|
||||
|
||||
// Remove from environment
|
||||
if(player != NULL)
|
||||
player->m_removed = true;
|
||||
|
||||
// Set player client disconnected
|
||||
if(player != NULL)
|
||||
player->peer_id = 0;
|
||||
|
||||
/*
|
||||
Print out action
|
||||
*/
|
||||
{
|
||||
Player *player = m_env->getPlayer(c.peer_id);
|
||||
if(player != NULL)
|
||||
player->peer_id = 0;
|
||||
|
||||
/*
|
||||
Print out action
|
||||
*/
|
||||
if(player != NULL)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
@@ -5009,7 +4888,7 @@ void Server::handlePeerChange(PeerChange &c)
|
||||
m_clients.remove(c.peer_id);
|
||||
|
||||
// Send player info to all remaining clients
|
||||
SendPlayerInfos();
|
||||
//SendPlayerInfos();
|
||||
|
||||
// Send leave chat message to all remaining clients
|
||||
BroadcastChatMessage(message);
|
||||
|
||||
26
src/server.h
26
src/server.h
@@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "ban.h"
|
||||
#include "gamedef.h"
|
||||
#include "serialization.h" // For SER_FMT_VER_INVALID
|
||||
#include "serverremoteplayer.h"
|
||||
struct LuaState;
|
||||
typedef struct lua_State lua_State;
|
||||
class IWritableToolDefManager;
|
||||
@@ -248,6 +249,8 @@ class RemoteClient
|
||||
// Version is stored in here after INIT before INIT2
|
||||
u8 pending_serialization_version;
|
||||
|
||||
bool definitions_sent;
|
||||
|
||||
RemoteClient():
|
||||
m_time_from_building(9999),
|
||||
m_excess_gotblocks(0)
|
||||
@@ -256,6 +259,7 @@ class RemoteClient
|
||||
serialization_version = SER_FMT_VER_INVALID;
|
||||
net_proto_version = 0;
|
||||
pending_serialization_version = SER_FMT_VER_INVALID;
|
||||
definitions_sent = false;
|
||||
m_nearest_unsent_d = 0;
|
||||
m_nearest_unsent_reset_timer = 0.0;
|
||||
m_nothing_to_send_counter = 0;
|
||||
@@ -273,17 +277,6 @@ class RemoteClient
|
||||
void GetNextBlocks(Server *server, float dtime,
|
||||
core::array<PrioritySortedBlockTransfer> &dest);
|
||||
|
||||
/*
|
||||
Connection and environment should be locked when this is called.
|
||||
steps() objects of blocks not found in active_blocks, then
|
||||
adds those blocks to active_blocks
|
||||
*/
|
||||
void SendObjectData(
|
||||
Server *server,
|
||||
float dtime,
|
||||
core::map<v3s16, bool> &stepped_blocks
|
||||
);
|
||||
|
||||
void GotBlock(v3s16 p);
|
||||
|
||||
void SentBlock(v3s16 p);
|
||||
@@ -456,6 +449,10 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
dstream<<"WARNING: Auth not found for "<<name<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Changes a player's password, password must be given as plaintext
|
||||
// If the player doesn't exist, a new entry is added to the auth manager
|
||||
void setPlayerPassword(const std::string &name, const std::wstring &password);
|
||||
|
||||
// Saves g_settings to configpath given at initialization
|
||||
void saveConfig();
|
||||
@@ -537,8 +534,6 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
*/
|
||||
|
||||
// Envlock and conlock should be locked when calling these
|
||||
void SendObjectData(float dtime);
|
||||
void SendPlayerInfos();
|
||||
void SendInventory(u16 peer_id);
|
||||
// send wielded item info about player to all
|
||||
void SendWieldedItem(const Player *player);
|
||||
@@ -591,12 +586,11 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
/*
|
||||
Get a player from memory or creates one.
|
||||
If player is already connected, return NULL
|
||||
The password is not checked here - it is only used to
|
||||
set the password if a new player is created.
|
||||
Does not verify/modify auth info and password.
|
||||
|
||||
Call with env and con locked.
|
||||
*/
|
||||
Player *emergePlayer(const char *name, const char *password, u16 peer_id);
|
||||
ServerRemotePlayer *emergePlayer(const char *name, u16 peer_id);
|
||||
|
||||
// Locks environment and connection by its own
|
||||
struct PeerChange;
|
||||
|
||||
@@ -281,6 +281,54 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_setclearpassword(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
{
|
||||
if((ctx->privs & PRIV_PASSWORD) == 0)
|
||||
{
|
||||
os<<L"-!- You don't have permission to do that";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string playername;
|
||||
std::wstring password;
|
||||
|
||||
if(ctx->parms[0] == L"setpassword")
|
||||
{
|
||||
if(ctx->parms.size() != 3)
|
||||
{
|
||||
os<<L"-!- Missing parameter";
|
||||
return;
|
||||
}
|
||||
|
||||
playername = wide_to_narrow(ctx->parms[1]);
|
||||
password = ctx->parms[2];
|
||||
|
||||
actionstream<<ctx->player->getName()<<" sets password of "
|
||||
<<playername<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// clearpassword
|
||||
|
||||
if(ctx->parms.size() != 2)
|
||||
{
|
||||
os<<L"-!- Missing parameter";
|
||||
return;
|
||||
}
|
||||
|
||||
playername = wide_to_narrow(ctx->parms[1]);
|
||||
password = L"";
|
||||
|
||||
actionstream<<ctx->player->getName()<<" clears password of"
|
||||
<<playername<<std::endl;
|
||||
}
|
||||
|
||||
ctx->server->setPlayerPassword(playername, password);
|
||||
|
||||
os<<L"-!- Password change for "<<narrow_to_wide(playername)<<" successful";
|
||||
}
|
||||
|
||||
void cmd_clearobjects(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
{
|
||||
@@ -322,9 +370,9 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||
if(ctx->parms.size() == 0 || ctx->parms[0] == L"help")
|
||||
{
|
||||
os<<L"-!- Available commands: ";
|
||||
os<<L"status privs ";
|
||||
os<<L"me status privs";
|
||||
if(privs & PRIV_SERVER)
|
||||
os<<L"shutdown setting ";
|
||||
os<<L" shutdown setting clearobjects";
|
||||
if(privs & PRIV_SETTIME)
|
||||
os<<L" time";
|
||||
if(privs & PRIV_TELEPORT)
|
||||
@@ -333,6 +381,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||
os<<L" grant revoke";
|
||||
if(privs & PRIV_BAN)
|
||||
os<<L" ban unban";
|
||||
if(privs & PRIV_PASSWORD)
|
||||
os<<L" setpassword clearpassword";
|
||||
}
|
||||
else if(ctx->parms[0] == L"status")
|
||||
cmd_status(os, ctx);
|
||||
@@ -350,6 +400,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||
cmd_teleport(os, ctx);
|
||||
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
||||
cmd_banunban(os, ctx);
|
||||
else if(ctx->parms[0] == L"setpassword" || ctx->parms[0] == L"clearpassword")
|
||||
cmd_setclearpassword(os, ctx);
|
||||
else if(ctx->parms[0] == L"me")
|
||||
cmd_me(os, ctx);
|
||||
else if(ctx->parms[0] == L"clearobjects")
|
||||
|
||||
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serverobject.h"
|
||||
#include <fstream>
|
||||
#include "inventory.h"
|
||||
#include "tooldef.h"
|
||||
|
||||
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
|
||||
ActiveObject(0),
|
||||
@@ -37,10 +38,6 @@ ServerActiveObject::~ServerActiveObject()
|
||||
{
|
||||
}
|
||||
|
||||
void ServerActiveObject::addedToEnvironment()
|
||||
{
|
||||
}
|
||||
|
||||
ServerActiveObject* ServerActiveObject::create(u8 type,
|
||||
ServerEnvironment *env, u16 id, v3f pos,
|
||||
const std::string &data)
|
||||
@@ -70,5 +67,10 @@ void ServerActiveObject::registerType(u16 type, Factory f)
|
||||
m_types.insert(type, f);
|
||||
}
|
||||
|
||||
void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
|
||||
{
|
||||
*dst = ToolDiggingProperties();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ Some planning
|
||||
class ServerEnvironment;
|
||||
class InventoryItem;
|
||||
class Player;
|
||||
struct ToolDiggingProperties;
|
||||
|
||||
class ServerActiveObject : public ActiveObject
|
||||
{
|
||||
@@ -54,8 +55,17 @@ class ServerActiveObject : public ActiveObject
|
||||
ServerActiveObject(ServerEnvironment *env, v3f pos);
|
||||
virtual ~ServerActiveObject();
|
||||
|
||||
// Call after id has been set and has been inserted in environment
|
||||
virtual void addedToEnvironment();
|
||||
// Called after id has been set and has been inserted in environment
|
||||
virtual void addedToEnvironment(){};
|
||||
// Called before removing from environment
|
||||
virtual void removingFromEnvironment(){};
|
||||
// Returns true if object's deletion is the job of the
|
||||
// environment
|
||||
virtual bool environmentDeletes() const
|
||||
{ return true; }
|
||||
|
||||
virtual bool unlimitedTransferDistance() const
|
||||
{ return false; }
|
||||
|
||||
// Create a certain type of ServerActiveObject
|
||||
static ServerActiveObject* create(u8 type,
|
||||
@@ -110,25 +120,36 @@ class ServerActiveObject : public ActiveObject
|
||||
when it is created (converted from static to active - actually
|
||||
the data is the static form)
|
||||
*/
|
||||
virtual std::string getStaticData(){return "";}
|
||||
virtual std::string getStaticData()
|
||||
{
|
||||
assert(isStaticAllowed());
|
||||
return "";
|
||||
}
|
||||
/*
|
||||
Return false in here to never save and instead remove object
|
||||
on unload. getStaticData() will not be called in that case.
|
||||
*/
|
||||
virtual bool isStaticAllowed() const
|
||||
{return true;}
|
||||
|
||||
virtual void punch(ServerActiveObject *puncher){}
|
||||
virtual void rightClick(ServerActiveObject *clicker){}
|
||||
|
||||
// Returns a reference
|
||||
virtual InventoryItem* getWieldedItem()
|
||||
{ return NULL; }
|
||||
// time_from_last_punch is used for lessening damage if punching fast
|
||||
virtual void punch(ServerActiveObject *puncher,
|
||||
float time_from_last_punch=1000000)
|
||||
{}
|
||||
virtual void rightClick(ServerActiveObject *clicker)
|
||||
{}
|
||||
virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
|
||||
virtual void damageWieldedItem(u16 amount)
|
||||
{}
|
||||
{}
|
||||
// If all fits, eats item and returns true. Otherwise returns false.
|
||||
virtual bool addToInventory(InventoryItem *item)
|
||||
{return false;}
|
||||
{ return false; }
|
||||
virtual void addToInventoryLater(InventoryItem *item)
|
||||
{}
|
||||
{}
|
||||
virtual void setHP(s16 hp)
|
||||
{}
|
||||
{}
|
||||
virtual s16 getHP()
|
||||
{return 0;}
|
||||
{ return 0; }
|
||||
|
||||
/*
|
||||
Number of players which know about this object. Object won't be
|
||||
@@ -149,12 +170,13 @@ class ServerActiveObject : public ActiveObject
|
||||
bool m_removed;
|
||||
|
||||
/*
|
||||
This is set to true when a block should be removed from the active
|
||||
This is set to true when an object should be removed from the active
|
||||
object list but couldn't be removed because the id has to be
|
||||
reserved for some client.
|
||||
|
||||
The environment checks this periodically. If this is true and also
|
||||
m_known_by_count is true,
|
||||
m_known_by_count is true, object is deleted from the active object
|
||||
list.
|
||||
*/
|
||||
bool m_pending_deactivation;
|
||||
|
||||
|
||||
316
src/serverremoteplayer.cpp
Normal file
316
src/serverremoteplayer.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "serverremoteplayer.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
#include "gamedef.h"
|
||||
#include "tooldef.h"
|
||||
#include "environment.h"
|
||||
#include "materials.h"
|
||||
|
||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
|
||||
Player(env->getGameDef()),
|
||||
ServerActiveObject(env, v3f(0,0,0)),
|
||||
m_last_good_position(0,0,0),
|
||||
m_last_good_position_age(0),
|
||||
m_additional_items(),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false),
|
||||
m_respawn_active(false),
|
||||
m_is_in_environment(false),
|
||||
m_position_not_sent(false)
|
||||
{
|
||||
}
|
||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
||||
const char *name_):
|
||||
Player(env->getGameDef()),
|
||||
ServerActiveObject(env, pos_),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false),
|
||||
m_is_in_environment(false),
|
||||
m_position_not_sent(false)
|
||||
{
|
||||
setPosition(pos_);
|
||||
peer_id = peer_id_;
|
||||
updateName(name_);
|
||||
}
|
||||
ServerRemotePlayer::~ServerRemotePlayer()
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::setPosition(const v3f &position)
|
||||
{
|
||||
Player::setPosition(position);
|
||||
ServerActiveObject::setBasePosition(position);
|
||||
m_position_not_sent = true;
|
||||
}
|
||||
|
||||
InventoryItem* ServerRemotePlayer::getWieldedItem()
|
||||
{
|
||||
InventoryList *list = inventory.getList("main");
|
||||
if (list)
|
||||
return list->getItem(m_selected_item);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
|
||||
void ServerRemotePlayer::addedToEnvironment()
|
||||
{
|
||||
assert(!m_is_in_environment);
|
||||
m_is_in_environment = true;
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::removingFromEnvironment()
|
||||
{
|
||||
assert(m_is_in_environment);
|
||||
m_is_in_environment = false;
|
||||
}
|
||||
|
||||
bool ServerRemotePlayer::unlimitedTransferDistance() const
|
||||
{
|
||||
return g_settings->getBool("unlimited_player_transfer_distance");
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::step(float dtime, bool send_recommended)
|
||||
{
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
|
||||
if(m_position_not_sent)
|
||||
{
|
||||
m_position_not_sent = false;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (0 = update position)
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeV3F1000(os, getPosition());
|
||||
// yaw
|
||||
writeF1000(os, getYaw());
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ServerRemotePlayer::getClientInitializationData()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
writeU8(os, 0);
|
||||
// name
|
||||
os<<serializeString(getName());
|
||||
// pos
|
||||
writeV3F1000(os, getPosition());
|
||||
// yaw
|
||||
writeF1000(os, getYaw());
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string ServerRemotePlayer::getStaticData()
|
||||
{
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::punch(ServerActiveObject *puncher,
|
||||
float time_from_last_punch)
|
||||
{
|
||||
if(!puncher)
|
||||
return;
|
||||
|
||||
// No effect if PvP disabled
|
||||
if(g_settings->getBool("enable_pvp") == false){
|
||||
if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||
return;
|
||||
}
|
||||
|
||||
// "Material" properties of a player
|
||||
MaterialProperties mp;
|
||||
mp.diggability = DIGGABLE_NORMAL;
|
||||
mp.crackiness = -0.5;
|
||||
mp.cuttability = 0.5;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
|
||||
setHP(getHP() - hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (1 = punched)
|
||||
writeU8(os, 1);
|
||||
// damage
|
||||
writeS16(os, hitprop.hp);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::rightClick(ServerActiveObject *clicker)
|
||||
{
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::setPos(v3f pos)
|
||||
{
|
||||
setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
void ServerRemotePlayer::moveTo(v3f pos, bool continuous)
|
||||
{
|
||||
setPosition(pos);
|
||||
// Movement caused by this command is always valid
|
||||
m_last_good_position = pos;
|
||||
m_last_good_position_age = 0;
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::getWieldDiggingProperties(ToolDiggingProperties *dst)
|
||||
{
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
IToolDefManager *tdef = gamedef->tdef();
|
||||
|
||||
InventoryItem *item = getWieldedItem();
|
||||
if(item == NULL || std::string(item->getName()) != "ToolItem"){
|
||||
*dst = ToolDiggingProperties();
|
||||
return;
|
||||
}
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
*dst = tdef->getDiggingProperties(titem->getToolName());
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::damageWieldedItem(u16 amount)
|
||||
{
|
||||
infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
|
||||
<<amount<<std::endl;
|
||||
InventoryList *list = inventory.getList("main");
|
||||
if(!list)
|
||||
return;
|
||||
InventoryItem *item = list->getItem(m_selected_item);
|
||||
if(item && (std::string)item->getName() == "ToolItem"){
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
bool weared_out = titem->addWear(amount);
|
||||
if(weared_out)
|
||||
list->deleteItem(m_selected_item);
|
||||
}
|
||||
}
|
||||
bool ServerRemotePlayer::addToInventory(InventoryItem *item)
|
||||
{
|
||||
infostream<<"Adding "<<item->getName()<<" into "<<getName()
|
||||
<<"'s inventory"<<std::endl;
|
||||
|
||||
InventoryList *ilist = inventory.getList("main");
|
||||
if(ilist == NULL)
|
||||
return false;
|
||||
|
||||
// In creative mode, just delete the item
|
||||
if(g_settings->getBool("creative_mode")){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip if inventory has no free space
|
||||
if(ilist->roomForItem(item) == false)
|
||||
{
|
||||
infostream<<"Player inventory has no free space"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to inventory
|
||||
InventoryItem *leftover = ilist->addItem(item);
|
||||
assert(!leftover);
|
||||
|
||||
m_inventory_not_sent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
void ServerRemotePlayer::addToInventoryLater(InventoryItem *item)
|
||||
{
|
||||
infostream<<"Adding (later) "<<item->getName()<<" into "<<getName()
|
||||
<<"'s inventory"<<std::endl;
|
||||
m_additional_items.push_back(item);
|
||||
}
|
||||
void ServerRemotePlayer::clearAddToInventoryLater()
|
||||
{
|
||||
for (std::vector<InventoryItem*>::iterator
|
||||
i = m_additional_items.begin();
|
||||
i != m_additional_items.end(); i++)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
m_additional_items.clear();
|
||||
}
|
||||
void ServerRemotePlayer::completeAddToInventoryLater(u16 preferred_index)
|
||||
{
|
||||
InventoryList *ilist = inventory.getList("main");
|
||||
if(ilist == NULL)
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// In creative mode, just delete the items
|
||||
if(g_settings->getBool("creative_mode"))
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<InventoryItem*>::iterator
|
||||
i = m_additional_items.begin();
|
||||
i != m_additional_items.end(); i++)
|
||||
{
|
||||
InventoryItem *item = *i;
|
||||
InventoryItem *leftover = item;
|
||||
leftover = ilist->addItem(preferred_index, leftover);
|
||||
leftover = ilist->addItem(leftover);
|
||||
delete leftover;
|
||||
}
|
||||
m_additional_items.clear();
|
||||
m_inventory_not_sent = true;
|
||||
}
|
||||
void ServerRemotePlayer::setHP(s16 hp_)
|
||||
{
|
||||
s16 oldhp = hp;
|
||||
|
||||
// FIXME: don't hardcode maximum HP, make configurable per object
|
||||
if(hp_ < 0)
|
||||
hp_ = 0;
|
||||
else if(hp_ > 20)
|
||||
hp_ = 20;
|
||||
hp = hp_;
|
||||
|
||||
if(hp != oldhp)
|
||||
m_hp_not_sent = true;
|
||||
}
|
||||
s16 ServerRemotePlayer::getHP()
|
||||
{
|
||||
return hp;
|
||||
}
|
||||
|
||||
|
||||
102
src/serverremoteplayer.h
Normal file
102
src/serverremoteplayer.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef SERVERREMOTEPLAYER_HEADER
|
||||
#define SERVERREMOTEPLAYER_HEADER
|
||||
|
||||
#include "player.h"
|
||||
#include "serverobject.h"
|
||||
#include "content_object.h" // Object type IDs
|
||||
|
||||
/*
|
||||
Player on the server
|
||||
*/
|
||||
|
||||
class ServerRemotePlayer : public Player, public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
ServerRemotePlayer(ServerEnvironment *env);
|
||||
ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
||||
const char *name_);
|
||||
|
||||
virtual ~ServerRemotePlayer();
|
||||
|
||||
virtual bool isLocal() const
|
||||
{ return false; }
|
||||
|
||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void setPosition(const v3f &position);
|
||||
|
||||
// Returns a reference
|
||||
virtual InventoryItem* getWieldedItem();
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_PLAYER;}
|
||||
|
||||
// Called after id has been set and has been inserted in environment
|
||||
void addedToEnvironment();
|
||||
// Called before removing from environment
|
||||
void removingFromEnvironment();
|
||||
|
||||
bool environmentDeletes() const
|
||||
{ return false; }
|
||||
|
||||
virtual bool unlimitedTransferDistance() const;
|
||||
|
||||
bool isStaticAllowed() const
|
||||
{ return false; }
|
||||
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
void rightClick(ServerActiveObject *clicker);
|
||||
void setPos(v3f pos);
|
||||
void moveTo(v3f pos, bool continuous);
|
||||
virtual std::string getDescription(){return getName();}
|
||||
|
||||
virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
|
||||
virtual void damageWieldedItem(u16 amount);
|
||||
// If all fits, eats item and returns true. Otherwise returns false.
|
||||
virtual bool addToInventory(InventoryItem *item);
|
||||
virtual void addToInventoryLater(InventoryItem *item);
|
||||
void clearAddToInventoryLater();
|
||||
void completeAddToInventoryLater(u16 preferred_index);
|
||||
virtual void setHP(s16 hp_);
|
||||
virtual s16 getHP();
|
||||
|
||||
v3f m_last_good_position;
|
||||
float m_last_good_position_age;
|
||||
std::vector<InventoryItem*> m_additional_items;
|
||||
bool m_inventory_not_sent;
|
||||
bool m_hp_not_sent;
|
||||
bool m_respawn_active;
|
||||
|
||||
private:
|
||||
bool m_is_in_environment;
|
||||
bool m_position_not_sent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
17
src/tile.cpp
17
src/tile.cpp
@@ -332,7 +332,7 @@ class TextureSource : public IWritableTextureSource
|
||||
// Gets a separate texture
|
||||
video::ITexture* getTextureRaw(const std::string &name)
|
||||
{
|
||||
AtlasPointer ap = getTexture(name);
|
||||
AtlasPointer ap = getTexture(name + "^[forcesingle");
|
||||
return ap.atlas;
|
||||
}
|
||||
|
||||
@@ -906,10 +906,14 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
|
||||
for(u32 j=0; j<xwise_tiling; j++)
|
||||
{
|
||||
// Copy the copy to the atlas
|
||||
img2->copyToWithAlpha(atlas_img,
|
||||
/*img2->copyToWithAlpha(atlas_img,
|
||||
pos_in_atlas + v2s32(j*dim.Width,0),
|
||||
core::rect<s32>(v2s32(0,0), dim),
|
||||
video::SColor(255,255,255,255),
|
||||
NULL);*/
|
||||
img2->copyTo(atlas_img,
|
||||
pos_in_atlas + v2s32(j*dim.Width,0),
|
||||
core::rect<s32>(v2s32(0,0), dim),
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -1166,6 +1170,15 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
*/
|
||||
if(part_of_name == "[forcesingle")
|
||||
{
|
||||
// If base image is NULL, create a random color
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
core::dimension2d<u32> dim(1,1);
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
assert(baseimg);
|
||||
baseimg->setPixel(0,0, video::SColor(255,myrand()%256,
|
||||
myrand()%256,myrand()%256));
|
||||
}
|
||||
}
|
||||
/*
|
||||
[crackN
|
||||
|
||||
@@ -23,9 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <sstream>
|
||||
#include "utility.h"
|
||||
|
||||
ToolDiggingProperties::ToolDiggingProperties(
|
||||
ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_,
|
||||
float a, float b, float c, float d, float e,
|
||||
float f, float g, float h, float i, float j):
|
||||
full_punch_interval(full_punch_interval_),
|
||||
basetime(a),
|
||||
dt_weight(b),
|
||||
dt_crackiness(c),
|
||||
@@ -60,6 +61,7 @@ void ToolDefinition::serialize(std::ostream &os)
|
||||
writeF1000(os, properties.dd_crackiness);
|
||||
writeF1000(os, properties.dd_crumbliness);
|
||||
writeF1000(os, properties.dd_cuttability);
|
||||
writeF1000(os, properties.full_punch_interval);
|
||||
}
|
||||
|
||||
void ToolDefinition::deSerialize(std::istream &is)
|
||||
@@ -78,6 +80,9 @@ void ToolDefinition::deSerialize(std::istream &is)
|
||||
properties.dd_crackiness = readF1000(is);
|
||||
properties.dd_crumbliness = readF1000(is);
|
||||
properties.dd_cuttability = readF1000(is);
|
||||
try{
|
||||
properties.full_punch_interval = readF1000(is);
|
||||
}catch(SerializationError &e){} // Temporary for 0.4.dev
|
||||
}
|
||||
|
||||
class CToolDefManager: public IWritableToolDefManager
|
||||
|
||||
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
struct ToolDiggingProperties
|
||||
{
|
||||
// time = basetime + sum(feature here * feature in MaterialProperties)
|
||||
float full_punch_interval;
|
||||
float basetime;
|
||||
float dt_weight;
|
||||
float dt_crackiness;
|
||||
@@ -37,7 +38,7 @@ struct ToolDiggingProperties
|
||||
float dd_crumbliness;
|
||||
float dd_cuttability;
|
||||
|
||||
ToolDiggingProperties(
|
||||
ToolDiggingProperties(float full_punch_interval_=1.0,
|
||||
float a=0.75, float b=0, float c=0, float d=0, float e=0,
|
||||
float f=50, float g=0, float h=0, float i=0, float j=0);
|
||||
};
|
||||
|
||||
@@ -427,6 +427,10 @@ do
|
||||
}
|
||||
end
|
||||
|
||||
-- TOSERVER_RESPAWN
|
||||
|
||||
minetest_client_commands[0x38] = { "RESPAWN", 2 }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -936,6 +940,40 @@ do
|
||||
}
|
||||
end
|
||||
|
||||
-- TOCLIENT_DEATHSCREEN
|
||||
|
||||
do
|
||||
local vs_set_camera_point_target = {
|
||||
[0] = "False",
|
||||
[1] = "True"
|
||||
}
|
||||
|
||||
local f_set_camera_point_target = ProtoField.uint8(
|
||||
"minetest.server.deathscreen_set_camera_point_target",
|
||||
"Set camera point target", base.DEC, vs_set_camera_point_target)
|
||||
local f_camera_point_target_x = ProtoField.int32(
|
||||
"minetest.server.deathscreen_camera_point_target_x",
|
||||
"Camera point target X", base.DEC)
|
||||
local f_camera_point_target_y = ProtoField.int32(
|
||||
"minetest.server.deathscreen_camera_point_target_y",
|
||||
"Camera point target Y", base.DEC)
|
||||
local f_camera_point_target_z = ProtoField.int32(
|
||||
"minetest.server.deathscreen_camera_point_target_z",
|
||||
"Camera point target Z", base.DEC)
|
||||
|
||||
minetest_server_commands[0x37] = {
|
||||
"DEATHSCREEN", 15,
|
||||
{ f_set_camera_point_target, f_camera_point_target_x,
|
||||
f_camera_point_target_y, f_camera_point_target_z},
|
||||
function(buffer, pinfo, tree, t)
|
||||
t:add(f_set_camera_point_target, buffer(2,1))
|
||||
t:add(f_camera_point_target_x, buffer(3,4))
|
||||
t:add(f_camera_point_target_y, buffer(7,4))
|
||||
t:add(f_camera_point_target_z, buffer(11,4))
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1280,6 +1318,12 @@ function minetest_convert_utf16(tvb, name)
|
||||
hex = hex .. " 3F"
|
||||
end
|
||||
end
|
||||
return ByteArray.new(hex):tvb(name):range()
|
||||
if hex == "" then
|
||||
-- This is a hack to avoid a failed assertion in tvbuff.c
|
||||
-- (function: ensure_contiguous_no_exception)
|
||||
return ByteArray.new("00"):tvb(name):range(0,0)
|
||||
else
|
||||
return ByteArray.new(hex):tvb(name):range()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user