Compare commits
68 Commits
0.4.dev-20
...
0.4.dev-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdf7b3bcdf | ||
|
|
871e6c0c73 | ||
|
|
392485aa45 | ||
|
|
275a348b75 | ||
|
|
189689716c | ||
|
|
3965d432ca | ||
|
|
746b960c0d | ||
|
|
760416b81f | ||
|
|
1c785c32ef | ||
|
|
cd608b1877 | ||
|
|
c6dd75ccfb | ||
|
|
6b2023dc3e | ||
|
|
2f4a92d701 | ||
|
|
324c544922 | ||
|
|
fbbbcf97d8 | ||
|
|
d96cd236f3 | ||
|
|
581f950e10 | ||
|
|
9344816bd6 | ||
|
|
67c21fc42f | ||
|
|
c2d266efc6 | ||
|
|
ec1859b095 | ||
|
|
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-20111203-3)
|
||||
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>
|
||||
|
||||
101
data/builtin.lua
101
data/builtin.lua
@@ -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,56 +253,69 @@ 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()
|
||||
|
||||
--
|
||||
-- nodeitem helpers
|
||||
--
|
||||
|
||||
minetest.inventorycube = function(img1, img2, img3)
|
||||
img2 = img2 or img1
|
||||
img3 = img3 or img1
|
||||
return "[inventorycube"
|
||||
.. "{" .. img1:gsub("%^", "&")
|
||||
.. "{" .. img2:gsub("%^", "&")
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
--
|
||||
-- craftitem helpers
|
||||
--
|
||||
@@ -312,7 +325,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 +340,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,12 +1,12 @@
|
||||
minetest.register_craft({
|
||||
output = 'CraftItem "bucket" 1',
|
||||
output = 'craft "bucket:bucket_empty" 1',
|
||||
recipe = {
|
||||
{'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
|
||||
{'', 'CraftItem "steel_ingot"', ''},
|
||||
{'craft "steel_ingot"', '', 'craft "steel_ingot"'},
|
||||
{'', 'craft "steel_ingot"', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("bucket", {
|
||||
minetest.register_craftitem("bucket:bucket_empty", {
|
||||
image = "bucket.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
@@ -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: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:bucket_lava" 1')
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -28,8 +28,8 @@ minetest.register_craftitem("bucket", {
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("bucket_water", {
|
||||
image = "bucket_water.png",
|
||||
minetest.register_craftitem("bucket:bucket_water", {
|
||||
image = "bucket:bucket_water.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
@@ -43,15 +43,15 @@ 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:bucket_empty" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("bucket_lava", {
|
||||
image = "bucket_lava.png",
|
||||
minetest.register_craftitem("bucket:bucket_lava", {
|
||||
image = "bucket:bucket_lava.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
@@ -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:bucket_empty" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
data/mods/default/textures/wieldhand.png
Normal file
BIN
data/mods/default/textures/wieldhand.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 384 B |
@@ -4,18 +4,18 @@
|
||||
|
||||
-- An example furnace-thing implemented in Lua
|
||||
|
||||
minetest.register_node("luafurnace", {
|
||||
minetest.register_node("experimental:luafurnace", {
|
||||
tile_images = {"lava.png", "furnace_side.png", "furnace_side.png",
|
||||
"furnace_side.png", "furnace_side.png", "furnace_front.png"},
|
||||
--inventory_image = "furnace_front.png",
|
||||
inventory_image = inventorycube("furnace_front.png"),
|
||||
inventory_image = minetest.inventorycube("furnace_front.png"),
|
||||
paramtype = "facedir_simple",
|
||||
metadata_name = "generic",
|
||||
material = digprop_stonelike(3.0),
|
||||
})
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer)
|
||||
if newnode.name == "luafurnace" then
|
||||
if newnode.name == "experimental:luafurnace" then
|
||||
print("get_meta");
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
print("inventory_set_list");
|
||||
@@ -42,7 +42,7 @@ minetest.register_on_placenode(function(pos, newnode, placer)
|
||||
end)
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"luafurnace"},
|
||||
nodenames = {"experimental:luafurnace"},
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
@@ -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 "experimental: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,15 +126,16 @@ minetest.register_tool("horribletool", {
|
||||
--]]
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "somenode" 4',
|
||||
output = 'node "somenode" 4',
|
||||
recipe = {
|
||||
{'CraftItem "Stick" 1'},
|
||||
{'craft "Stick" 1'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("somenode", {
|
||||
minetest.register_node("experimental:somenode", {
|
||||
tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
|
||||
inventory_image = "treeprop.png",
|
||||
inventory_image = minetest.inventorycube("lava.png", "mese.png", "stone.png"),
|
||||
--inventory_image = "treeprop.png",
|
||||
material = {
|
||||
diggability = "normal",
|
||||
weight = 0,
|
||||
@@ -151,15 +152,15 @@ minetest.register_node("somenode", {
|
||||
--
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'NodeItem "TNT" 4',
|
||||
output = 'node "experimental: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'}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("TNT", {
|
||||
minetest.register_node("experimental:tnt", {
|
||||
tile_images = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"},
|
||||
inventory_image = "tnt_side.png",
|
||||
dug_item = '', -- Get nothing
|
||||
@@ -168,6 +169,14 @@ minetest.register_node("TNT", {
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_on_punchnode(function(p, node)
|
||||
if node.name == "experimental:tnt" then
|
||||
minetest.env:remove_node(p)
|
||||
minetest.env:add_luaentity(p, "experimental:tnt")
|
||||
nodeupdate(p)
|
||||
end
|
||||
end)
|
||||
|
||||
local TNT = {
|
||||
-- Static definition
|
||||
physical = true, -- Collides with things
|
||||
@@ -213,7 +222,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
|
||||
@@ -225,16 +234,15 @@ function TNT:on_rightclick(clicker)
|
||||
--self.object:moveto(pos, false)
|
||||
end
|
||||
|
||||
print("TNT dump: "..dump(TNT))
|
||||
|
||||
print("Registering TNT");
|
||||
minetest.register_entity("TNT", TNT)
|
||||
--print("TNT dump: "..dump(TNT))
|
||||
--print("Registering TNT");
|
||||
minetest.register_entity("experimental:tnt", TNT)
|
||||
|
||||
--
|
||||
-- A test entity for testing animated and yaw-modulated sprites
|
||||
--
|
||||
|
||||
minetest.register_entity("testentity", {
|
||||
minetest.register_entity("experimental:testentity", {
|
||||
-- Static definition
|
||||
physical = true, -- Collides with things
|
||||
-- weight = 5,
|
||||
@@ -259,7 +267,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,8 @@ configure_file(
|
||||
)
|
||||
|
||||
set(common_SRCS
|
||||
mods.cpp
|
||||
serverremoteplayer.cpp
|
||||
content_abm.cpp
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
@@ -107,7 +109,6 @@ set(common_SRCS
|
||||
content_sao.cpp
|
||||
mapgen.cpp
|
||||
content_nodemeta.cpp
|
||||
content_craft.cpp
|
||||
content_mapnode.cpp
|
||||
auth.cpp
|
||||
collision.cpp
|
||||
@@ -160,6 +161,7 @@ set(minetest_SRCS
|
||||
MyBillboardSceneNode.cpp
|
||||
content_mapblock.cpp
|
||||
content_cao.cpp
|
||||
mesh.cpp
|
||||
mapblock_mesh.cpp
|
||||
farmesh.cpp
|
||||
keycode.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;
|
||||
|
||||
|
||||
289
src/camera.cpp
289
src/camera.cpp
@@ -22,10 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client.h"
|
||||
#include "main.h" // for g_settings
|
||||
#include "map.h"
|
||||
#include "mesh.h"
|
||||
#include "player.h"
|
||||
#include "tile.h"
|
||||
#include <cmath>
|
||||
#include <SAnimatedMesh.h>
|
||||
#include "settings.h"
|
||||
#include "nodedef.h" // For wield visualization
|
||||
|
||||
@@ -269,7 +269,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
|
||||
|
||||
// Position the wielded item
|
||||
v3f wield_position = v3f(45, -35, 65);
|
||||
v3f wield_rotation = v3f(-100, 110, -100);
|
||||
v3f wield_rotation = v3f(-100, 120, -100);
|
||||
if (m_digging_button != -1)
|
||||
{
|
||||
f32 digfrac = m_digging_anim;
|
||||
@@ -472,7 +472,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
|
||||
case NDT_ALLFACES:
|
||||
case NDT_ALLFACES_OPTIONAL:
|
||||
m_wieldnode->setCube(ndef->get(content).tiles);
|
||||
m_wieldnode->setScale(v3f(30));
|
||||
isCube = true;
|
||||
break;
|
||||
default:
|
||||
@@ -484,7 +483,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
|
||||
if (!isCube)
|
||||
{
|
||||
m_wieldnode->setSprite(item->getImageRaw());
|
||||
m_wieldnode->setScale(v3f(40));
|
||||
}
|
||||
|
||||
m_wieldnode->setVisible(true);
|
||||
@@ -492,7 +490,8 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
|
||||
else
|
||||
{
|
||||
// Bare hands
|
||||
m_wieldnode->setVisible(false);
|
||||
m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png"));
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +525,6 @@ ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
|
||||
ISceneNode(parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
||||
m_thickness = 0.1;
|
||||
m_cubemesh = NULL;
|
||||
m_is_cube = false;
|
||||
m_light = LIGHT_MAX;
|
||||
@@ -541,6 +539,8 @@ ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
{
|
||||
const v3f sprite_scale(40.0, 40.0, 4.0); // width, height, thickness
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
m_meshnode->setVisible(false);
|
||||
@@ -558,7 +558,9 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
else
|
||||
{
|
||||
// Texture was not yet extruded, do it now and save in cache
|
||||
mesh = extrude(texture);
|
||||
mesh = createExtrudedMesh(texture,
|
||||
SceneManager->getVideoDriver(),
|
||||
sprite_scale);
|
||||
if (mesh == NULL)
|
||||
{
|
||||
dstream << "Warning: failed to extrude sprite" << std::endl;
|
||||
@@ -570,7 +572,6 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
mesh->drop();
|
||||
}
|
||||
|
||||
m_meshnode->setScale(v3f(1, 1, m_thickness));
|
||||
m_meshnode->getMaterial(0).setTexture(0, texture);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
|
||||
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
@@ -582,11 +583,14 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
|
||||
|
||||
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
|
||||
{
|
||||
const v3f cube_scale(30.0, 30.0, 30.0);
|
||||
|
||||
if (m_cubemesh == NULL)
|
||||
m_cubemesh = createCubeMesh();
|
||||
{
|
||||
m_cubemesh = createCubeMesh(cube_scale);
|
||||
}
|
||||
|
||||
m_meshnode->setMesh(m_cubemesh);
|
||||
m_meshnode->setScale(v3f(1));
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Get the tile texture and atlas transformation
|
||||
@@ -616,7 +620,7 @@ void ExtrudedSpriteSceneNode::updateLight(u8 light)
|
||||
// Set brightness one lower than incoming light
|
||||
diminish_light(li);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_meshnode->getMesh(), color);
|
||||
setMeshColor(m_meshnode->getMesh(), color);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
|
||||
@@ -627,13 +631,6 @@ void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
|
||||
cache->removeMesh(mesh);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
|
||||
{
|
||||
m_thickness = thickness;
|
||||
if (!m_is_cube)
|
||||
m_meshnode->setScale(v3f(1, 1, thickness));
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
|
||||
{
|
||||
return m_meshnode->getBoundingBox();
|
||||
@@ -657,259 +654,3 @@ io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
|
||||
path.append("/[extruded]");
|
||||
return path;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height, u8* data)
|
||||
{
|
||||
const s32 argb_wstep = 4 * width;
|
||||
const s32 alpha_threshold = 1;
|
||||
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
// Front and back
|
||||
{
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c, 1,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c, 1,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c, 0,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c, 0,1),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
}
|
||||
|
||||
// "Interior"
|
||||
// (add faces where a solid pixel is next to a transparent one)
|
||||
u8* solidity = new u8[(width+2) * (height+2)];
|
||||
u32 wstep = width + 2;
|
||||
for (u32 y = 0; y < height + 2; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep;
|
||||
if (y == 0 || y == height + 1)
|
||||
{
|
||||
for (u32 x = 0; x < width + 2; ++x)
|
||||
scanline[x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanline[0] = 0;
|
||||
u8* argb_scanline = data + (y - 1) * argb_wstep;
|
||||
for (u32 x = 0; x < width; ++x)
|
||||
scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold);
|
||||
scanline[width + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// without this, there would be occasional "holes" in the mesh
|
||||
f32 eps = 0.01;
|
||||
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
u8* scanline = solidity + y * wstep + 1;
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
if (scanline[x] && !scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (scanline[xx] && !scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y - eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y - 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
if (!scanline[x] && scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (!scanline[xx] && scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) width - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) width - 0.5;
|
||||
f32 vy = 0.5 - (y + eps) / (f32) height;
|
||||
f32 tx1 = x / (f32) width;
|
||||
f32 tx2 = xx / (f32) width;
|
||||
f32 ty = (y + 0.5) / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 x = 0; x <= width; ++x)
|
||||
{
|
||||
u8* scancol = solidity + x + wstep;
|
||||
for (u32 y = 0; y <= height; ++y)
|
||||
{
|
||||
if (scancol[y * wstep] && !scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x - eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x - 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
if (!scancol[y * wstep] && scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x + eps) / (f32) width - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) height;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) height;
|
||||
f32 tx = (x + 0.5) / (f32) width;
|
||||
f32 ty1 = y / (f32) height;
|
||||
f32 ty2 = yy / (f32) height;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mesh
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
mesh->recalculateBoundingBox();
|
||||
scene::SAnimatedMesh* anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
|
||||
{
|
||||
scene::IAnimatedMesh* mesh = NULL;
|
||||
core::dimension2d<u32> size = texture->getSize();
|
||||
video::ECOLOR_FORMAT format = texture->getColorFormat();
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
// Texture is in the correct color format, we can pass it
|
||||
// to extrudeARGB right away.
|
||||
void* data = texture->lock(true);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
|
||||
texture->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(true));
|
||||
if (img1 == NULL)
|
||||
return NULL;
|
||||
|
||||
// img1 is in the texture's color format, convert to 8-bit ARGB
|
||||
video::IImage* img2 = driver->createImage(video::ECF_A8R8G8B8, size);
|
||||
if (img2 != NULL)
|
||||
{
|
||||
img1->copyTo(img2);
|
||||
img1->drop();
|
||||
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
|
||||
img2->unlock();
|
||||
img2->drop();
|
||||
}
|
||||
img1->drop();
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh()
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh* mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer* buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
buf->recalculateBoundingBox();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
mesh->recalculateBoundingBox();
|
||||
return mesh;
|
||||
}
|
||||
|
||||
11
src/camera.h
11
src/camera.h
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "inventory.h"
|
||||
#include "mesh.h"
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
@@ -29,7 +30,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;
|
||||
|
||||
@@ -206,9 +207,6 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode
|
||||
void setSprite(video::ITexture* texture);
|
||||
void setCube(const TileSpec tiles[6]);
|
||||
|
||||
f32 getSpriteThickness() const { return m_thickness; }
|
||||
void setSpriteThickness(f32 thickness);
|
||||
|
||||
void updateLight(u8 light);
|
||||
|
||||
void removeSpriteFromCache(video::ITexture* texture);
|
||||
@@ -219,16 +217,11 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode* m_meshnode;
|
||||
f32 m_thickness;
|
||||
scene::IMesh* m_cubemesh;
|
||||
bool m_is_cube;
|
||||
u8 m_light;
|
||||
|
||||
// internal extrusion helper methods
|
||||
io::path getExtrudedName(video::ITexture* texture);
|
||||
scene::IAnimatedMesh* extrudeARGB(u32 width, u32 height, u8* data);
|
||||
scene::IAnimatedMesh* extrude(video::ITexture* texture);
|
||||
scene::IMesh* createCubeMesh();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
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,394 @@ 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 "mesh.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 +420,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 +522,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 +537,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;
|
||||
@@ -255,7 +631,7 @@ void ItemCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
setMeshColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 ItemCAO::getLightPosition()
|
||||
@@ -288,7 +664,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 +703,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 +719,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;
|
||||
@@ -402,7 +779,7 @@ void RatCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
setMeshColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 RatCAO::getLightPosition()
|
||||
@@ -472,10 +849,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 +867,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;
|
||||
@@ -557,7 +935,7 @@ void Oerkki1CAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
setMeshColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 Oerkki1CAO::getLightPosition()
|
||||
@@ -712,10 +1090,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 +1106,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;
|
||||
@@ -787,7 +1166,7 @@ void FireflyCAO::updateLight(u8 light_at_pos)
|
||||
|
||||
u8 li = 255;
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshVerticesColor(m_node->getMesh(), color);
|
||||
setMeshColor(m_node->getMesh(), color);
|
||||
}
|
||||
|
||||
v3s16 FireflyCAO::getLightPosition()
|
||||
@@ -855,10 +1234,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 +1266,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 +1649,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 +1671,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 +1689,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 +1727,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 +1750,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 +1759,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 +1780,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 +1843,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("");
|
||||
@@ -1485,7 +1867,7 @@ class CLuaEntityCAO : public LuaEntityCAO
|
||||
u8 li = decode_light(light_at_pos);
|
||||
video::SColor color(255,li,li,li);
|
||||
if(m_meshnode){
|
||||
setMeshVerticesColor(m_meshnode->getMesh(), color);
|
||||
setMeshColor(m_meshnode->getMesh(), color);
|
||||
m_meshnode->setVisible(true);
|
||||
}
|
||||
if(m_spritenode){
|
||||
@@ -1640,7 +2022,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 +2074,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);
|
||||
setMeshColor(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<<"\" ";
|
||||
|
||||
@@ -429,6 +429,7 @@ Doing currently:
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "log.h"
|
||||
#include "mods.h"
|
||||
|
||||
/*
|
||||
Settings.
|
||||
@@ -1630,7 +1631,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Break out of menu-game loop to shut down cleanly
|
||||
if(device->run() == false)
|
||||
if(device->run() == false || kill == true)
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -1662,6 +1663,11 @@ int main(int argc, char *argv[])
|
||||
errorstream<<"Socket error (port already in use?)"<<std::endl;
|
||||
error_message = L"Socket error (port already in use?)";
|
||||
}
|
||||
catch(ModError &e)
|
||||
{
|
||||
errorstream<<e.what()<<std::endl;
|
||||
error_message = narrow_to_wide(e.what()) + L"\nCheck debug.txt for details.";
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
catch(std::exception &e)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
362
src/mesh.cpp
Normal file
362
src/mesh.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
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 "mesh.h"
|
||||
#include <IAnimatedMesh.h>
|
||||
#include <SAnimatedMesh.h>
|
||||
|
||||
// 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
|
||||
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data)
|
||||
{
|
||||
const s32 argb_wstep = 4 * twidth;
|
||||
const s32 alpha_threshold = 1;
|
||||
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
video::SColor c(255,255,255,255);
|
||||
|
||||
// Front and back
|
||||
{
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c, 1,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c, 1,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c, 0,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c, 0,1),
|
||||
};
|
||||
u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
|
||||
buf->append(vertices, 8, indices, 12);
|
||||
}
|
||||
|
||||
// "Interior"
|
||||
// (add faces where a solid pixel is next to a transparent one)
|
||||
u8 *solidity = new u8[(twidth+2) * (theight+2)];
|
||||
u32 wstep = twidth + 2;
|
||||
for (u32 y = 0; y < theight + 2; ++y)
|
||||
{
|
||||
u8 *scanline = solidity + y * wstep;
|
||||
if (y == 0 || y == theight + 1)
|
||||
{
|
||||
for (u32 x = 0; x < twidth + 2; ++x)
|
||||
scanline[x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanline[0] = 0;
|
||||
u8 *argb_scanline = data + (y - 1) * argb_wstep;
|
||||
for (u32 x = 0; x < twidth; ++x)
|
||||
scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold);
|
||||
scanline[twidth + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// without this, there would be occasional "holes" in the mesh
|
||||
f32 eps = 0.01;
|
||||
|
||||
for (u32 y = 0; y <= theight; ++y)
|
||||
{
|
||||
u8 *scanline = solidity + y * wstep + 1;
|
||||
for (u32 x = 0; x <= twidth; ++x)
|
||||
{
|
||||
if (scanline[x] && !scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (scanline[xx] && !scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) twidth - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) twidth - 0.5;
|
||||
f32 vy = 0.5 - (y - eps) / (f32) theight;
|
||||
f32 tx1 = x / (f32) twidth;
|
||||
f32 tx2 = xx / (f32) twidth;
|
||||
f32 ty = (y - 0.5) / (f32) theight;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
if (!scanline[x] && scanline[x + wstep])
|
||||
{
|
||||
u32 xx = x + 1;
|
||||
while (!scanline[xx] && scanline[xx + wstep])
|
||||
++xx;
|
||||
f32 vx1 = (x - eps) / (f32) twidth - 0.5;
|
||||
f32 vx2 = (xx + eps) / (f32) twidth - 0.5;
|
||||
f32 vy = 0.5 - (y + eps) / (f32) theight;
|
||||
f32 tx1 = x / (f32) twidth;
|
||||
f32 tx2 = xx / (f32) twidth;
|
||||
f32 ty = (y + 0.5) / (f32) theight;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
|
||||
video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
|
||||
video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
x = xx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 x = 0; x <= twidth; ++x)
|
||||
{
|
||||
u8 *scancol = solidity + x + wstep;
|
||||
for (u32 y = 0; y <= theight; ++y)
|
||||
{
|
||||
if (scancol[y * wstep] && !scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x - eps) / (f32) twidth - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) theight;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) theight;
|
||||
f32 tx = (x - 0.5) / (f32) twidth;
|
||||
f32 ty1 = y / (f32) theight;
|
||||
f32 ty2 = yy / (f32) theight;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
if (!scancol[y * wstep] && scancol[y * wstep + 1])
|
||||
{
|
||||
u32 yy = y + 1;
|
||||
while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
|
||||
++yy;
|
||||
f32 vx = (x + eps) / (f32) twidth - 0.5;
|
||||
f32 vy1 = 0.5 - (y - eps) / (f32) theight;
|
||||
f32 vy2 = 0.5 - (yy + eps) / (f32) theight;
|
||||
f32 tx = (x + 0.5) / (f32) twidth;
|
||||
f32 ty1 = y / (f32) theight;
|
||||
f32 ty2 = yy / (f32) theight;
|
||||
video::S3DVertex vertices[8] =
|
||||
{
|
||||
video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
|
||||
video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
|
||||
video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
|
||||
};
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
buf->append(vertices, 4, indices, 6);
|
||||
y = yy - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mesh
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||
video::IVideoDriver *driver, v3f scale)
|
||||
{
|
||||
scene::IAnimatedMesh *mesh = NULL;
|
||||
core::dimension2d<u32> size = texture->getSize();
|
||||
video::ECOLOR_FORMAT format = texture->getColorFormat();
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
// Texture is in the correct color format, we can pass it
|
||||
// to extrudeARGB right away.
|
||||
void *data = texture->lock(MY_ETLM_READ_ONLY);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
|
||||
texture->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
video::IImage *img1 = driver->createImageFromData(format, size, texture->lock(MY_ETLM_READ_ONLY));
|
||||
if (img1 == NULL)
|
||||
return NULL;
|
||||
|
||||
// img1 is in the texture's color format, convert to 8-bit ARGB
|
||||
video::IImage *img2 = driver->createImage(video::ECF_A8R8G8B8, size);
|
||||
if (img2 != NULL)
|
||||
{
|
||||
img1->copyTo(img2);
|
||||
img1->drop();
|
||||
|
||||
mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
|
||||
img2->unlock();
|
||||
img2->drop();
|
||||
}
|
||||
img1->drop();
|
||||
}
|
||||
scaleMesh(mesh, scale); // also recalculates bounding box
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void scaleMesh(scene::IMesh *mesh, v3f scale)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
core::aabbox3d<f32> bbox;
|
||||
bbox.reset(0,0,0);
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Pos *= scale;
|
||||
}
|
||||
buf->recalculateBoundingBox();
|
||||
|
||||
// calculate total bounding box
|
||||
if(j == 0)
|
||||
bbox = buf->getBoundingBox();
|
||||
else
|
||||
bbox.addInternalBox(buf->getBoundingBox());
|
||||
}
|
||||
mesh->setBoundingBox(bbox);
|
||||
}
|
||||
|
||||
void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
const video::SColor &colorX,
|
||||
const video::SColor &colorY,
|
||||
const video::SColor &colorZ)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
f32 x = fabs(vertices[i].Normal.X);
|
||||
f32 y = fabs(vertices[i].Normal.Y);
|
||||
f32 z = fabs(vertices[i].Normal.Z);
|
||||
if(x >= y && x >= z)
|
||||
vertices[i].Color = colorX;
|
||||
else if(y >= z)
|
||||
vertices[i].Color = colorY;
|
||||
else
|
||||
vertices[i].Color = colorZ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/mesh.h
Normal file
66
src/mesh.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
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 MESH_HEADER
|
||||
#define MESH_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
|
||||
/*
|
||||
Create a new cube mesh.
|
||||
Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
|
||||
|
||||
The resulting mesh has 6 materials (up, down, right, left, back, front)
|
||||
which must be defined by the caller.
|
||||
*/
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
||||
|
||||
/*
|
||||
Create a new extruded mesh from a texture.
|
||||
Maximum bounding box is (+-scale.X/2, +-scale.Y/2, +-scale.Z).
|
||||
Thickness is in Z direction.
|
||||
|
||||
The resulting mesh has 1 material which must be defined by the caller.
|
||||
*/
|
||||
scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||
video::IVideoDriver *driver, v3f scale);
|
||||
|
||||
/*
|
||||
Multiplies each vertex coordinate by the specified scaling factors
|
||||
(componentwise vector multiplication).
|
||||
*/
|
||||
void scaleMesh(scene::IMesh *mesh, v3f scale);
|
||||
|
||||
/*
|
||||
Set a constant color for all vertices in the mesh
|
||||
*/
|
||||
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
|
||||
|
||||
/*
|
||||
Set the color of all vertices in the mesh.
|
||||
For each vertex, determine the largest absolute entry in
|
||||
the normal vector, and choose one of colorX, colorY or
|
||||
colorZ accordingly.
|
||||
*/
|
||||
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
const video::SColor &colorX,
|
||||
const video::SColor &colorY,
|
||||
const video::SColor &colorZ);
|
||||
|
||||
#endif
|
||||
116
src/mods.cpp
Normal file
116
src/mods.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 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 "mods.h"
|
||||
#include <queue>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include "filesys.h"
|
||||
#include "strfnd.h"
|
||||
#include "log.h"
|
||||
|
||||
// Get a dependency-sorted list of ModSpecs
|
||||
core::list<ModSpec> getMods(core::list<std::string> &modspaths)
|
||||
throw(ModError)
|
||||
{
|
||||
std::queue<ModSpec> mods_satisfied;
|
||||
core::list<ModSpec> mods_unsorted;
|
||||
core::list<ModSpec> mods_sorted;
|
||||
// name, path: For detecting name conflicts
|
||||
std::map<std::string, std::string> mod_names;
|
||||
for(core::list<std::string>::Iterator i = modspaths.begin();
|
||||
i != modspaths.end(); i++){
|
||||
std::string modspath = *i;
|
||||
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath);
|
||||
for(u32 j=0; j<dirlist.size(); j++){
|
||||
if(!dirlist[j].dir)
|
||||
continue;
|
||||
std::string modname = dirlist[j].name;
|
||||
std::string modpath = modspath + DIR_DELIM + modname;
|
||||
// Detect mod name conflicts
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i;
|
||||
i = mod_names.find(modname);
|
||||
if(i != mod_names.end()){
|
||||
std::string s;
|
||||
infostream<<"WARNING: Mod name conflict detected: "
|
||||
<<std::endl
|
||||
<<"Already loaded: "<<i->second<<std::endl
|
||||
<<"Will not load: "<<modpath<<std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
std::set<std::string> depends;
|
||||
std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(),
|
||||
std::ios_base::binary);
|
||||
while(is.good()){
|
||||
std::string dep;
|
||||
std::getline(is, dep);
|
||||
dep = trim(dep);
|
||||
if(dep != "")
|
||||
depends.insert(dep);
|
||||
}
|
||||
ModSpec spec(modname, modpath, depends);
|
||||
mods_unsorted.push_back(spec);
|
||||
if(depends.empty())
|
||||
mods_satisfied.push(spec);
|
||||
mod_names[modname] = modpath;
|
||||
}
|
||||
}
|
||||
// Sort by depencencies
|
||||
while(!mods_satisfied.empty()){
|
||||
ModSpec mod = mods_satisfied.front();
|
||||
mods_satisfied.pop();
|
||||
mods_sorted.push_back(mod);
|
||||
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
|
||||
i != mods_unsorted.end(); i++){
|
||||
ModSpec &mod2 = *i;
|
||||
if(mod2.unsatisfied_depends.empty())
|
||||
continue;
|
||||
mod2.unsatisfied_depends.erase(mod.name);
|
||||
if(!mod2.unsatisfied_depends.empty())
|
||||
continue;
|
||||
mods_satisfied.push(mod2);
|
||||
}
|
||||
}
|
||||
std::ostringstream errs(std::ios::binary);
|
||||
// Check unsatisfied dependencies
|
||||
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
|
||||
i != mods_unsorted.end(); i++){
|
||||
ModSpec &mod = *i;
|
||||
if(mod.unsatisfied_depends.empty())
|
||||
continue;
|
||||
errs<<"mod \""<<mod.name
|
||||
<<"\" has unsatisfied dependencies:";
|
||||
for(std::set<std::string>::iterator
|
||||
i = mod.unsatisfied_depends.begin();
|
||||
i != mod.unsatisfied_depends.end(); i++){
|
||||
errs<<" \""<<(*i)<<"\"";
|
||||
}
|
||||
errs<<"."<<std::endl;
|
||||
mods_sorted.push_back(mod);
|
||||
}
|
||||
if(errs.str().size() != 0){
|
||||
throw ModError(errs.str());
|
||||
}
|
||||
return mods_sorted;
|
||||
}
|
||||
|
||||
|
||||
61
src/mods.h
Normal file
61
src/mods.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 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 "irrlichttypes.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
class ModError : public std::exception
|
||||
{
|
||||
public:
|
||||
ModError(const std::string &s)
|
||||
{
|
||||
m_s = "ModError: ";
|
||||
m_s += s;
|
||||
}
|
||||
virtual ~ModError() throw()
|
||||
{}
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return m_s.c_str();
|
||||
}
|
||||
std::string m_s;
|
||||
};
|
||||
|
||||
struct ModSpec
|
||||
{
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::set<std::string> depends;
|
||||
std::set<std::string> unsatisfied_depends;
|
||||
|
||||
ModSpec(const std::string &name_="", const std::string path_="",
|
||||
const std::set<std::string> &depends_=std::set<std::string>()):
|
||||
name(name_),
|
||||
path(path_),
|
||||
depends(depends_),
|
||||
unsatisfied_depends(depends_)
|
||||
{}
|
||||
};
|
||||
|
||||
// Get a dependency-sorted list of ModSpecs
|
||||
core::list<ModSpec> getMods(core::list<std::string> &modspaths)
|
||||
throw(ModError);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -31,20 +31,63 @@ extern "C" {
|
||||
#include <lauxlib.h>
|
||||
}
|
||||
|
||||
LuaError::LuaError(lua_State *L, const std::string &s)
|
||||
{
|
||||
m_s = "LuaError: ";
|
||||
m_s += s + "\n";
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
||||
if(lua_istable(L, -1)){
|
||||
lua_getfield(L, -1, "traceback");
|
||||
if(lua_isfunction(L, -1)){
|
||||
lua_call(L, 0, 1);
|
||||
if(lua_isstring(L, -1)){
|
||||
m_s += lua_tostring(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else{
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void script_error(lua_State *L, const char *fmt, ...)
|
||||
{
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
vfprintf(stderr, fmt, argp);
|
||||
char buf[10000];
|
||||
vsnprintf(buf, 10000, fmt, argp);
|
||||
va_end(argp);
|
||||
lua_close(L);
|
||||
exit(EXIT_FAILURE);
|
||||
//errorstream<<"SCRIPT ERROR: "<<buf;
|
||||
throw LuaError(L, buf);
|
||||
}
|
||||
|
||||
int luaErrorHandler(lua_State *L) {
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
lua_getfield(L, -1, "traceback");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
lua_pop(L, 2);
|
||||
return 1;
|
||||
}
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushinteger(L, 2);
|
||||
lua_call(L, 2, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool script_load(lua_State *L, const char *path)
|
||||
{
|
||||
infostream<<"Loading and running script from "<<path<<std::endl;
|
||||
int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
|
||||
|
||||
lua_pushcfunction(L, luaErrorHandler);
|
||||
int errorhandler = lua_gettop(L);
|
||||
|
||||
int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, errorhandler);
|
||||
if(ret){
|
||||
errorstream<<"Failed to load and run script from "<<path<<":"<<std::endl;
|
||||
errorstream<<"[LUA] "<<std::endl;
|
||||
|
||||
18
src/script.h
18
src/script.h
@@ -20,8 +20,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#ifndef SCRIPT_HEADER
|
||||
#define SCRIPT_HEADER
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
//#include <string>
|
||||
|
||||
class LuaError : public std::exception
|
||||
{
|
||||
public:
|
||||
LuaError(lua_State *L, const std::string &s);
|
||||
|
||||
virtual ~LuaError() throw()
|
||||
{}
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return m_s.c_str();
|
||||
}
|
||||
std::string m_s;
|
||||
};
|
||||
|
||||
lua_State* script_init();
|
||||
void script_deinit(lua_State *L);
|
||||
|
||||
@@ -107,6 +107,66 @@ class StackUnroller
|
||||
}
|
||||
};
|
||||
|
||||
class ModNameStorer
|
||||
{
|
||||
private:
|
||||
lua_State *L;
|
||||
public:
|
||||
ModNameStorer(lua_State *L_, const std::string modname):
|
||||
L(L_)
|
||||
{
|
||||
// Store current modname in registry
|
||||
lua_pushstring(L, modname.c_str());
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
|
||||
}
|
||||
~ModNameStorer()
|
||||
{
|
||||
// Clear current modname in registry
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
|
||||
}
|
||||
};
|
||||
|
||||
std::string get_current_modname(lua_State *L)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
|
||||
std::string modname = "";
|
||||
if(lua_type(L, -1) == LUA_TSTRING)
|
||||
modname = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return modname;
|
||||
}
|
||||
|
||||
void check_modname_prefix(lua_State *L, std::string &name)
|
||||
{
|
||||
if(name.size() == 0)
|
||||
throw LuaError(L, std::string("Name is empty"));
|
||||
|
||||
if(name[0] == ':'){
|
||||
name = name.substr(1);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string modname = get_current_modname(L);
|
||||
assert(modname != "");
|
||||
|
||||
// For __builtin, anything goes
|
||||
if(modname == "__builtin")
|
||||
return;
|
||||
|
||||
if(name.substr(0, modname.size()+1) != modname + ":")
|
||||
throw LuaError(L, std::string("Name \"")+name
|
||||
+"\" does not follow naming conventions: "
|
||||
+"\"modname:\" or \":\" prefix required)");
|
||||
|
||||
std::string subname = name.substr(modname.size()+1);
|
||||
if(!string_allowed(subname, "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
|
||||
throw LuaError(L, std::string("Name \"")+name
|
||||
+"\" does not follow naming conventions: "
|
||||
+"\"contains unallowed characters)");
|
||||
}
|
||||
|
||||
static v3f readFloatPos(lua_State *L, int index)
|
||||
{
|
||||
v3f pos;
|
||||
@@ -386,13 +446,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 +482,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 +498,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,15 +525,80 @@ 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());
|
||||
}
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
@@ -527,8 +671,9 @@ static int l_register_nodedef_defaults(lua_State *L)
|
||||
// register_entity(name, prototype)
|
||||
static int l_register_entity(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
infostream<<"register_entity: "<<name<<std::endl;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
check_modname_prefix(L, name);
|
||||
//infostream<<"register_entity: "<<name<<std::endl;
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
// Get minetest.registered_entities
|
||||
@@ -538,7 +683,7 @@ static int l_register_entity(lua_State *L)
|
||||
int registered_entities = lua_gettop(L);
|
||||
lua_pushvalue(L, 2); // Object = param 2 -> stack top
|
||||
// registered_entities[name] = object
|
||||
lua_setfield(L, registered_entities, name);
|
||||
lua_setfield(L, registered_entities, name.c_str());
|
||||
|
||||
// Get registered object to top of stack
|
||||
lua_pushvalue(L, 2);
|
||||
@@ -619,14 +764,14 @@ class LuaABM : public ActiveBlockModifier
|
||||
lua_pushnumber(L, active_object_count);
|
||||
lua_pushnumber(L, active_object_count_wider);
|
||||
if(lua_pcall(L, 4, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
};
|
||||
|
||||
// register_abm({...})
|
||||
static int l_register_abm(lua_State *L)
|
||||
{
|
||||
infostream<<"register_abm"<<std::endl;
|
||||
//infostream<<"register_abm"<<std::endl;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
// Get minetest.registered_abms
|
||||
@@ -660,8 +805,9 @@ static int l_register_abm(lua_State *L)
|
||||
// register_tool(name, {lots of stuff})
|
||||
static int l_register_tool(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
infostream<<"register_tool: "<<name<<std::endl;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
check_modname_prefix(L, name);
|
||||
//infostream<<"register_tool: "<<name<<std::endl;
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int table = 2;
|
||||
|
||||
@@ -672,19 +818,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 */
|
||||
@@ -693,8 +827,9 @@ static int l_register_tool(lua_State *L)
|
||||
// register_craftitem(name, {lots of stuff})
|
||||
static int l_register_craftitem(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
infostream<<"register_craftitem: "<<name<<std::endl;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
check_modname_prefix(L, name);
|
||||
//infostream<<"register_craftitem: "<<name<<std::endl;
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int table = 2;
|
||||
|
||||
@@ -734,7 +869,7 @@ static int l_register_craftitem(lua_State *L)
|
||||
craftitemdef->registerCraftItem(name, def);
|
||||
|
||||
lua_pushvalue(L, table);
|
||||
scriptapi_add_craftitem(L, name);
|
||||
scriptapi_add_craftitem(L, name.c_str());
|
||||
|
||||
return 0; /* number of results */
|
||||
}
|
||||
@@ -742,8 +877,9 @@ static int l_register_craftitem(lua_State *L)
|
||||
// register_node(name, {lots of stuff})
|
||||
static int l_register_node(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
infostream<<"register_node: "<<name<<std::endl;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
check_modname_prefix(L, name);
|
||||
//infostream<<"register_node: "<<name<<std::endl;
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int nodedef_table = 2;
|
||||
|
||||
@@ -777,7 +913,7 @@ static int l_register_node(lua_State *L)
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "registered_nodes");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
lua_pushstring(L, name);
|
||||
lua_pushstring(L, name.c_str());
|
||||
lua_pushvalue(L, nodedef_table);
|
||||
lua_settable(L, -3);
|
||||
|
||||
@@ -982,7 +1118,7 @@ static int l_register_node(lua_State *L)
|
||||
// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
|
||||
static int l_register_craft(lua_State *L)
|
||||
{
|
||||
infostream<<"register_craft"<<std::endl;
|
||||
//infostream<<"register_craft"<<std::endl;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table0 = 1;
|
||||
|
||||
@@ -1029,7 +1165,10 @@ static int l_register_craft(lua_State *L)
|
||||
width = colcount;
|
||||
} else {
|
||||
if(colcount != width){
|
||||
script_error(L, "error: %s\n", "Invalid crafting recipe");
|
||||
std::string error;
|
||||
error += "Invalid crafting recipe (output=\""
|
||||
+ output + "\")";
|
||||
throw LuaError(L, error);
|
||||
}
|
||||
}
|
||||
// removes value, keeps key for next iteration
|
||||
@@ -1688,65 +1827,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 +1877,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 +2047,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 +2064,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 +2196,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 +2212,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}
|
||||
};
|
||||
|
||||
@@ -2383,6 +2536,24 @@ void scriptapi_export(lua_State *L, Server *server)
|
||||
ObjectRef::Register(L);
|
||||
}
|
||||
|
||||
bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
|
||||
const std::string &modname)
|
||||
{
|
||||
ModNameStorer modnamestorer(L, modname);
|
||||
|
||||
bool success = false;
|
||||
|
||||
try{
|
||||
success = script_load(L, scriptpath.c_str());
|
||||
}
|
||||
catch(LuaError &e){
|
||||
errorstream<<"Error loading mod \""<<modname
|
||||
<<"\": "<<e.what()<<std::endl;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
|
||||
{
|
||||
realitycheck(L);
|
||||
@@ -2463,7 +2634,7 @@ static void dump2(lua_State *L, const char *name)
|
||||
lua_pushvalue(L, -2); // Get previous stack top as first parameter
|
||||
lua_pushstring(L, name);
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2541,7 +2712,7 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
|
||||
lua_pushstring(L, name.c_str());
|
||||
lua_pushstring(L, message.c_str());
|
||||
if(lua_pcall(L, 2, 1, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
bool ate = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if(ate)
|
||||
@@ -2574,7 +2745,7 @@ void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
|
||||
// Call function
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 1, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -2599,7 +2770,7 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||
// Call function
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 1, 1, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
bool positioning_handled = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if(positioning_handled)
|
||||
@@ -2609,6 +2780,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
|
||||
*/
|
||||
@@ -2712,7 +2892,7 @@ bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
|
||||
objectref_get_or_create(L, dropper);
|
||||
pushFloatPos(L, pos);
|
||||
if(lua_pcall(L, 3, 1, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
result = lua_toboolean(L, -1);
|
||||
}
|
||||
return result;
|
||||
@@ -2736,7 +2916,7 @@ bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
|
||||
objectref_get_or_create(L, placer);
|
||||
pushFloatPos(L, pos);
|
||||
if(lua_pcall(L, 3, 1, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
result = lua_toboolean(L, -1);
|
||||
}
|
||||
return result;
|
||||
@@ -2760,7 +2940,7 @@ bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
|
||||
objectref_get_or_create(L, user);
|
||||
pushPointedThing(L, pointed);
|
||||
if(lua_pcall(L, 3, 1, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
result = lua_toboolean(L, -1);
|
||||
}
|
||||
return result;
|
||||
@@ -2790,7 +2970,7 @@ void scriptapi_environment_step(lua_State *L, float dtime)
|
||||
// Call function
|
||||
lua_pushnumber(L, dtime);
|
||||
if(lua_pcall(L, 1, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -2825,7 +3005,7 @@ void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
|
||||
pushnode(L, newnode, ndef);
|
||||
objectref_get_or_create(L, placer);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -2860,7 +3040,7 @@ void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
|
||||
pushnode(L, oldnode, ndef);
|
||||
objectref_get_or_create(L, digger);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -2895,7 +3075,7 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
|
||||
pushnode(L, node, ndef);
|
||||
objectref_get_or_create(L, puncher);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -2921,7 +3101,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
|
||||
pushpos(L, minp);
|
||||
pushpos(L, maxp);
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s\n", lua_tostring(L, -1));
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
@@ -3124,9 +3304,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 +3324,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,8 +31,11 @@ typedef struct lua_State lua_State;
|
||||
struct LuaEntityProperties;
|
||||
struct PointedThing;
|
||||
//class IGameDef;
|
||||
class ServerRemotePlayer;
|
||||
|
||||
void scriptapi_export(lua_State *L, Server *server);
|
||||
bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
|
||||
const std::string &modname);
|
||||
void scriptapi_add_environment(lua_State *L, ServerEnvironment *env);
|
||||
|
||||
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj);
|
||||
@@ -60,6 +63,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 +87,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);
|
||||
|
||||
|
||||
519
src/server.cpp
519
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 "mods.h"
|
||||
|
||||
#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)
|
||||
@@ -932,92 +833,6 @@ u32 PIChecksum(core::list<PlayerInfo> &l)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/*
|
||||
Mods
|
||||
*/
|
||||
|
||||
struct ModSpec
|
||||
{
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::set<std::string> depends;
|
||||
std::set<std::string> unsatisfied_depends;
|
||||
|
||||
ModSpec(const std::string &name_="", const std::string path_="",
|
||||
const std::set<std::string> &depends_=std::set<std::string>()):
|
||||
name(name_),
|
||||
path(path_),
|
||||
depends(depends_),
|
||||
unsatisfied_depends(depends_)
|
||||
{}
|
||||
};
|
||||
|
||||
// Get a dependency-sorted list of ModSpecs
|
||||
static core::list<ModSpec> getMods(core::list<std::string> &modspaths)
|
||||
{
|
||||
std::queue<ModSpec> mods_satisfied;
|
||||
core::list<ModSpec> mods_unsorted;
|
||||
core::list<ModSpec> mods_sorted;
|
||||
for(core::list<std::string>::Iterator i = modspaths.begin();
|
||||
i != modspaths.end(); i++){
|
||||
std::string modspath = *i;
|
||||
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath);
|
||||
for(u32 j=0; j<dirlist.size(); j++){
|
||||
if(!dirlist[j].dir)
|
||||
continue;
|
||||
std::string modname = dirlist[j].name;
|
||||
std::string modpath = modspath + DIR_DELIM + modname;
|
||||
std::set<std::string> depends;
|
||||
std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(),
|
||||
std::ios_base::binary);
|
||||
while(is.good()){
|
||||
std::string dep;
|
||||
std::getline(is, dep);
|
||||
dep = trim(dep);
|
||||
if(dep != "")
|
||||
depends.insert(dep);
|
||||
}
|
||||
ModSpec spec(modname, modpath, depends);
|
||||
mods_unsorted.push_back(spec);
|
||||
if(depends.empty())
|
||||
mods_satisfied.push(spec);
|
||||
}
|
||||
}
|
||||
// Sort by depencencies
|
||||
while(!mods_satisfied.empty()){
|
||||
ModSpec mod = mods_satisfied.front();
|
||||
mods_satisfied.pop();
|
||||
mods_sorted.push_back(mod);
|
||||
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
|
||||
i != mods_unsorted.end(); i++){
|
||||
ModSpec &mod2 = *i;
|
||||
if(mod2.unsatisfied_depends.empty())
|
||||
continue;
|
||||
mod2.unsatisfied_depends.erase(mod.name);
|
||||
if(!mod2.unsatisfied_depends.empty())
|
||||
continue;
|
||||
mods_satisfied.push(mod2);
|
||||
}
|
||||
}
|
||||
// Check unsatisfied dependencies
|
||||
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
|
||||
i != mods_unsorted.end(); i++){
|
||||
ModSpec &mod = *i;
|
||||
if(mod.unsatisfied_depends.empty())
|
||||
continue;
|
||||
errorstream<<"mod \""<<mod.name
|
||||
<<"\" has unsatisfied dependencies:";
|
||||
for(std::set<std::string>::iterator
|
||||
i = mod.unsatisfied_depends.begin();
|
||||
i != mod.unsatisfied_depends.end(); i++){
|
||||
errorstream<<" \""<<(*i)<<"\"";
|
||||
}
|
||||
errorstream<<". Loading nevertheless."<<std::endl;
|
||||
mods_sorted.push_back(mod);
|
||||
}
|
||||
return mods_sorted;
|
||||
}
|
||||
|
||||
/*
|
||||
Server
|
||||
*/
|
||||
@@ -1060,13 +875,24 @@ Server::Server(
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
JMutexAutoLock conlock(m_con_mutex);
|
||||
|
||||
infostream<<"m_nodedef="<<m_nodedef<<std::endl;
|
||||
|
||||
// Path to builtin.lua
|
||||
std::string builtinpath = porting::path_data + DIR_DELIM + "builtin.lua";
|
||||
// Add default global mod path
|
||||
m_modspaths.push_back(porting::path_data + DIR_DELIM + "mods");
|
||||
|
||||
// Add default global mod search path
|
||||
m_modspaths.push_front(porting::path_data + DIR_DELIM + "mods");
|
||||
// Add world mod search path
|
||||
m_modspaths.push_front(mapsavedir + DIR_DELIM + "worldmods");
|
||||
// Add user mod search path
|
||||
m_modspaths.push_front(porting::path_userdata + DIR_DELIM + "usermods");
|
||||
|
||||
// Print out mod search paths
|
||||
infostream<<"Mod search paths:"<<std::endl;
|
||||
for(core::list<std::string>::Iterator i = m_modspaths.begin();
|
||||
i != m_modspaths.end(); i++){
|
||||
std::string modspath = *i;
|
||||
infostream<<" "<<modspath<<std::endl;
|
||||
}
|
||||
|
||||
// Initialize scripting
|
||||
|
||||
infostream<<"Server: Initializing scripting"<<std::endl;
|
||||
@@ -1077,11 +903,11 @@ Server::Server(
|
||||
// Load and run builtin.lua
|
||||
infostream<<"Server: Loading builtin Lua stuff from \""<<builtinpath
|
||||
<<"\""<<std::endl;
|
||||
bool success = script_load(m_lua, builtinpath.c_str());
|
||||
bool success = scriptapi_loadmod(m_lua, builtinpath, "__builtin");
|
||||
if(!success){
|
||||
errorstream<<"Server: Failed to load and run "
|
||||
<<builtinpath<<std::endl;
|
||||
assert(0);
|
||||
throw ModError("Failed to load and run "+builtinpath);
|
||||
}
|
||||
// Load and run "mod" scripts
|
||||
core::list<ModSpec> mods = getMods(m_modspaths);
|
||||
@@ -1090,11 +916,11 @@ Server::Server(
|
||||
ModSpec mod = *i;
|
||||
infostream<<"Server: Loading mod \""<<mod.name<<"\""<<std::endl;
|
||||
std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
|
||||
bool success = script_load(m_lua, scriptpath.c_str());
|
||||
bool success = scriptapi_loadmod(m_lua, scriptpath, mod.name);
|
||||
if(!success){
|
||||
errorstream<<"Server: Failed to load and run "
|
||||
<<scriptpath<<std::endl;
|
||||
assert(0);
|
||||
throw ModError("Failed to load and run "+scriptpath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1382,6 +1208,8 @@ void Server::AsyncRunStep()
|
||||
JMutexAutoLock lock(m_env_mutex);
|
||||
JMutexAutoLock lock2(m_con_mutex);
|
||||
|
||||
ScopeProfiler sp(g_profiler, "Server: handle players");
|
||||
|
||||
//float player_max_speed = BS * 4.0; // Normal speed
|
||||
float player_max_speed = BS * 20; // Fast speed
|
||||
float player_max_speed_up = BS * 20;
|
||||
@@ -1430,6 +1258,11 @@ void Server::AsyncRunStep()
|
||||
player->m_last_good_position_age = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle player HPs (die if hp=0)
|
||||
*/
|
||||
HandlePlayerHP(player, 0);
|
||||
|
||||
/*
|
||||
Send player inventories and HPs if necessary
|
||||
*/
|
||||
@@ -1440,6 +1273,15 @@ void Server::AsyncRunStep()
|
||||
if(player->m_hp_not_sent){
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
|
||||
/*
|
||||
Add to environment if is not in respawn screen
|
||||
*/
|
||||
if(!player->m_is_in_environment && !player->m_respawn_active){
|
||||
player->m_removed = false;
|
||||
player->setId(0);
|
||||
m_env->addActiveObject(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1541,6 +1383,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)
|
||||
{
|
||||
@@ -1679,7 +1527,7 @@ void Server::AsyncRunStep()
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
JMutexAutoLock conlock(m_con_mutex);
|
||||
|
||||
//ScopeProfiler sp(g_profiler, "Server: sending object messages");
|
||||
ScopeProfiler sp(g_profiler, "Server: sending object messages");
|
||||
|
||||
// Key = object id
|
||||
// Value = data sent by object
|
||||
@@ -1908,25 +1756,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 +1950,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 +2004,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 +2039,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 +2051,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)
|
||||
@@ -2275,12 +2109,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 +2130,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 +2311,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 +2492,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 +2558,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 +2810,15 @@ 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;
|
||||
|
||||
// ActiveObject is added to environment in AsyncRunStep after
|
||||
// the previous addition has been succesfully removed
|
||||
}
|
||||
else if(command == TOSERVER_INTERACT)
|
||||
{
|
||||
@@ -3063,7 +2905,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 +3781,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);
|
||||
@@ -4129,6 +3913,7 @@ void Server::BroadcastChatMessage(const std::wstring &message)
|
||||
void Server::SendPlayerHP(Player *player)
|
||||
{
|
||||
SendHP(m_con, player->peer_id, player->hp);
|
||||
static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
|
||||
}
|
||||
|
||||
void Server::SendMovePlayer(Player *player)
|
||||
@@ -4345,6 +4130,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,37 +4307,46 @@ 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(damage == 0)
|
||||
return;
|
||||
|
||||
if(player->hp > damage)
|
||||
{
|
||||
player->hp -= damage;
|
||||
SendPlayerHP(player);
|
||||
return;
|
||||
}
|
||||
|
||||
infostream<<"Server::HandlePlayerHP(): Player "
|
||||
<<player->getName()<<" dies"<<std::endl;
|
||||
|
||||
player->hp = 0;
|
||||
|
||||
//TODO: Throw items around
|
||||
|
||||
// Handle players that are not connected
|
||||
if(player->peer_id == PEER_ID_INEXISTENT){
|
||||
RespawnPlayer(player);
|
||||
return;
|
||||
}
|
||||
|
||||
SendPlayerHP(player);
|
||||
|
||||
RemoteClient *client = getClient(player->peer_id);
|
||||
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
|
||||
{
|
||||
infostream<<"Server::HandlePlayerHP(): Player "
|
||||
<<player->getName()<<" dies"<<std::endl;
|
||||
|
||||
player->hp = 0;
|
||||
|
||||
//TODO: Throw items around
|
||||
|
||||
// Handle players that are not connected
|
||||
if(player->peer_id == PEER_ID_INEXISTENT){
|
||||
RespawnPlayer(player);
|
||||
return;
|
||||
}
|
||||
|
||||
SendPlayerHP(player);
|
||||
|
||||
RemoteClient *client = getClient(player->peer_id);
|
||||
if(client->net_proto_version >= 3)
|
||||
{
|
||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
||||
}
|
||||
else
|
||||
{
|
||||
RespawnPlayer(player);
|
||||
}
|
||||
RespawnPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4678,6 +4477,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 +4628,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 +4655,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 +4676,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 +4700,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 +4761,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 +4777,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,10 +4821,11 @@ 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);
|
||||
if(message.length() != 0)
|
||||
BroadcastChatMessage(message);
|
||||
|
||||
} // PEER_REMOVED
|
||||
else
|
||||
|
||||
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,58 @@ 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);
|
||||
|
||||
std::wostringstream msg;
|
||||
msg<<ctx->player->getName()<<L" changed your password";
|
||||
ctx->server->notifyPlayer(playername.c_str(), msg.str());
|
||||
|
||||
os<<L"-!- Password change for "<<narrow_to_wide(playername)<<" successful";
|
||||
}
|
||||
|
||||
void cmd_clearobjects(std::wostringstream &os,
|
||||
ServerCommandContext *ctx)
|
||||
{
|
||||
@@ -322,9 +374,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 +385,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 +404,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")
|
||||
|
||||
@@ -76,6 +76,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include "nodedef.h" // For init_contentfeatures
|
||||
#include "content_mapnode.h" // For content_mapnode_init
|
||||
#include "mods.h"
|
||||
|
||||
/*
|
||||
Settings.
|
||||
@@ -365,6 +366,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
errorstream<<"Connection timed out."<<std::endl;
|
||||
}
|
||||
catch(ModError &e)
|
||||
{
|
||||
errorstream<<e.what()<<std::endl;
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER(errorstream)
|
||||
|
||||
|
||||
@@ -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;
|
||||
bool m_is_in_environment;
|
||||
|
||||
private:
|
||||
bool m_position_not_sent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
55
src/tile.cpp
55
src/tile.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "filesys.h"
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
#include "mesh.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "log.h"
|
||||
#include "mapnode.h" // For texture atlas making
|
||||
@@ -332,7 +333,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 +907,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 +1171,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
|
||||
@@ -1455,11 +1469,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
assert(img_top && img_left && img_right);
|
||||
|
||||
// Create textures from images
|
||||
// TODO: Use them all
|
||||
video::ITexture *texture_top = driver->addTexture(
|
||||
(imagename_top + "__temp__").c_str(), img_top);
|
||||
assert(texture_top);
|
||||
|
||||
video::ITexture *texture_left = driver->addTexture(
|
||||
(imagename_left + "__temp__").c_str(), img_left);
|
||||
video::ITexture *texture_right = driver->addTexture(
|
||||
(imagename_right + "__temp__").c_str(), img_right);
|
||||
assert(texture_top && texture_left && texture_right);
|
||||
|
||||
// Drop images
|
||||
img_top->drop();
|
||||
img_left->drop();
|
||||
@@ -1486,17 +1503,24 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
Create scene:
|
||||
- An unit cube is centered at 0,0,0
|
||||
- Camera looks at cube from Y+, Z- towards Y-, Z+
|
||||
NOTE: Cube has to be changed to something else because
|
||||
the textures cannot be set individually (or can they?)
|
||||
*/
|
||||
|
||||
scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1,
|
||||
v3f(0,0,0), v3f(0, 45, 0));
|
||||
scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1));
|
||||
setMeshColor(cube, video::SColor(255, 255, 255, 255));
|
||||
|
||||
scene::IMeshSceneNode* cubenode = smgr->addMeshSceneNode(cube, NULL, -1, v3f(0,0,0), v3f(0,45,0), v3f(1,1,1), true);
|
||||
cube->drop();
|
||||
|
||||
// Set texture of cube
|
||||
cube->setMaterialTexture(0, texture_top);
|
||||
//cube->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
|
||||
cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
cubenode->getMaterial(0).setTexture(0, texture_top);
|
||||
cubenode->getMaterial(1).setTexture(0, texture_top);
|
||||
cubenode->getMaterial(2).setTexture(0, texture_right);
|
||||
cubenode->getMaterial(3).setTexture(0, texture_right);
|
||||
cubenode->getMaterial(4).setTexture(0, texture_left);
|
||||
cubenode->getMaterial(5).setTexture(0, texture_left);
|
||||
cubenode->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||
cubenode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
|
||||
cubenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
|
||||
|
||||
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
|
||||
v3f(0, 1.0, -1.5), v3f(0, 0, 0));
|
||||
@@ -1506,7 +1530,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
camera->setProjectionMatrix(pm, true);
|
||||
|
||||
/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
|
||||
v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
|
||||
v3f(-50, 100, -75), video::SColorf(0.5,0.5,0.5), 1000);
|
||||
|
||||
smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));
|
||||
|
||||
@@ -1527,8 +1551,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
driver->setRenderTarget(0, true, true, 0);
|
||||
|
||||
// Free textures of images
|
||||
// TODO: When all are used, free them all
|
||||
driver->removeTexture(texture_top);
|
||||
driver->removeTexture(texture_left);
|
||||
driver->removeTexture(texture_right);
|
||||
|
||||
// Create image of render target
|
||||
video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -172,27 +172,6 @@ int myrand_range(int min, int max)
|
||||
return (myrand()%(max-min+1))+min;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color)
|
||||
{
|
||||
if(mesh == NULL)
|
||||
return;
|
||||
|
||||
u16 mc = mesh->getMeshBufferCount();
|
||||
for(u16 j=0; j<mc; j++)
|
||||
{
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||
u16 vc = buf->getVertexCount();
|
||||
for(u16 i=0; i<vc; i++)
|
||||
{
|
||||
vertices[i].Color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
blockpos: position of block in block coordinates
|
||||
camera_pos: position of camera in nodes
|
||||
|
||||
@@ -694,11 +694,6 @@ class TimeTaker
|
||||
u32 *m_result;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
// Sets the color of all vertices in the mesh
|
||||
void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
|
||||
#endif
|
||||
|
||||
// Calculates the borders of a "d-radius" cube
|
||||
inline void getFacePositions(core::list<v3s16> &list, u16 d)
|
||||
{
|
||||
|
||||
@@ -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