mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
The huge item definition and item namespace unification patch (itemdef), see http://c55.me/minetest/wiki/doku.php?id=changes:itemdef
This commit is contained in:
parent
569156b013
commit
6a76c226e1
601
data/builtin.lua
601
data/builtin.lua
@ -80,15 +80,91 @@ function dump(o, dumped)
|
||||
end
|
||||
|
||||
--
|
||||
-- Built-in node definitions. Also defined in C.
|
||||
-- Item definition helpers
|
||||
--
|
||||
|
||||
minetest.register_nodedef_defaults({
|
||||
minetest.inventorycube = function(img1, img2, img3)
|
||||
img2 = img2 or img1
|
||||
img3 = img3 or img1
|
||||
return "[inventorycube"
|
||||
.. "{" .. img1:gsub("%^", "&")
|
||||
.. "{" .. img2:gsub("%^", "&")
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
minetest.get_pointed_thing_position = function(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
return pointed_thing.above
|
||||
else
|
||||
-- The position where a node would be dug
|
||||
return pointed_thing.under
|
||||
end
|
||||
elseif pointed_thing.type == "object" then
|
||||
obj = pointed.thing.ref
|
||||
if obj ~= nil then
|
||||
return obj:getpos()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.item_place(itemstack, placer, pointed_thing)
|
||||
pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
||||
if pos ~= nil then
|
||||
item = itemstack:take_item()
|
||||
if item ~= nil then
|
||||
minetest.env:add_item(pos, item)
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_drop(itemstack, dropper, pos)
|
||||
minetest.env:add_item(pos, itemstack)
|
||||
return ""
|
||||
end
|
||||
|
||||
function minetest.item_eat(hp_change)
|
||||
return function(itemstack, user, pointed_thing) -- closure
|
||||
if itemstack:take_item() ~= nil then
|
||||
user:set_hp(user:get_hp() + hp_change)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Item definition defaults
|
||||
--
|
||||
|
||||
minetest.nodedef_default = {
|
||||
-- Item properties
|
||||
type="node",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
dropcount = -1,
|
||||
usable = false,
|
||||
liquids_pointable = false,
|
||||
tool_digging_properties = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = nil, -- let C handle node placement for now
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
|
||||
-- Node properties
|
||||
drawtype = "normal",
|
||||
visual_scale = 1.0,
|
||||
tile_images = {"unknown_block.png"},
|
||||
inventory_image = "unknown_block.png",
|
||||
tile_images = {""},
|
||||
special_materials = {
|
||||
{image="", backface_culling=true},
|
||||
{image="", backface_culling=true},
|
||||
@ -104,8 +180,7 @@ minetest.register_nodedef_defaults({
|
||||
climbable = false,
|
||||
buildable_to = false,
|
||||
wall_mounted = false,
|
||||
often_contains_mineral = false,
|
||||
dug_item = "",
|
||||
--dug_item intentionally not defined here
|
||||
extra_dug_item = "",
|
||||
extra_dug_item_rarity = 2,
|
||||
metadata_name = "",
|
||||
@ -124,12 +199,325 @@ minetest.register_nodedef_defaults({
|
||||
cuttability = 0,
|
||||
flammability = 0,
|
||||
},
|
||||
cookresult_item = "", -- Cannot be cooked
|
||||
furnace_cooktime = 3.0,
|
||||
furnace_burntime = -1, -- Cannot be used as fuel
|
||||
}
|
||||
|
||||
minetest.craftitemdef_default = {
|
||||
type="craft",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_digging_properties = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.tooldef_default = {
|
||||
type="tool",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 1,
|
||||
liquids_pointable = false,
|
||||
tool_digging_properties = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
minetest.noneitemdef_default = { -- This is used for the hand and unknown items
|
||||
type="none",
|
||||
-- name intentionally not defined here
|
||||
description = "",
|
||||
inventory_image = "",
|
||||
wield_image = "",
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
stack_max = 99,
|
||||
liquids_pointable = false,
|
||||
tool_digging_properties = nil,
|
||||
|
||||
-- Interaction callbacks
|
||||
on_place = nil,
|
||||
on_drop = nil,
|
||||
on_use = nil,
|
||||
}
|
||||
|
||||
--
|
||||
-- Make raw registration functions inaccessible to anyone except builtin.lua
|
||||
--
|
||||
|
||||
local register_item_raw = minetest.register_item_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
local register_alias_raw = minetest.register_alias_raw
|
||||
minetest.register_item_raw = nil
|
||||
|
||||
--
|
||||
-- Item / entity / ABM registration functions
|
||||
--
|
||||
|
||||
minetest.registered_abms = {}
|
||||
minetest.registered_entities = {}
|
||||
minetest.registered_items = {}
|
||||
minetest.registered_nodes = {}
|
||||
minetest.registered_craftitems = {}
|
||||
minetest.registered_tools = {}
|
||||
minetest.registered_aliases = {}
|
||||
|
||||
-- For tables that are indexed by item name:
|
||||
-- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
|
||||
local function set_alias_metatable(table)
|
||||
setmetatable(table, {
|
||||
__index = function(name)
|
||||
return rawget(table, minetest.registered_aliases[name])
|
||||
end
|
||||
})
|
||||
end
|
||||
set_alias_metatable(minetest.registered_items)
|
||||
set_alias_metatable(minetest.registered_nodes)
|
||||
set_alias_metatable(minetest.registered_craftitems)
|
||||
set_alias_metatable(minetest.registered_tools)
|
||||
|
||||
-- These item names may not be used because they would interfere
|
||||
-- with legacy itemstrings
|
||||
local forbidden_item_names = {
|
||||
MaterialItem = true,
|
||||
MaterialItem2 = true,
|
||||
MaterialItem3 = true,
|
||||
NodeItem = true,
|
||||
node = true,
|
||||
CraftItem = true,
|
||||
craft = true,
|
||||
MBOItem = true,
|
||||
ToolItem = true,
|
||||
tool = true,
|
||||
}
|
||||
|
||||
local function check_modname_prefix(name)
|
||||
if name:sub(1,1) == ":" then
|
||||
-- Escape the modname prefix enforcement mechanism
|
||||
return name:sub(2)
|
||||
else
|
||||
-- Modname prefix enforcement
|
||||
local expected_prefix = minetest.get_current_modname() .. ":"
|
||||
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"\"modname:\" or \":\" prefix required")
|
||||
end
|
||||
local subname = name:sub(#expected_prefix+1)
|
||||
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
|
||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||
"contains unallowed characters")
|
||||
end
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.register_abm(spec)
|
||||
-- Add to minetest.registered_abms
|
||||
minetest.registered_abms[#minetest.registered_abms+1] = spec
|
||||
end
|
||||
|
||||
function minetest.register_entity(name, prototype)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register entity: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
|
||||
prototype.name = name
|
||||
prototype.__index = prototype -- so that it can be used as a metatable
|
||||
|
||||
-- Add to minetest.registered_entities
|
||||
minetest.registered_entities[name] = prototype
|
||||
end
|
||||
|
||||
function minetest.register_item(name, itemdef)
|
||||
-- Check name
|
||||
if name == nil then
|
||||
error("Unable to register item: Name is nil")
|
||||
end
|
||||
name = check_modname_prefix(tostring(name))
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register item: Name is forbidden: " .. name)
|
||||
end
|
||||
itemdef.name = name
|
||||
|
||||
-- Apply defaults and add to registered_* table
|
||||
if itemdef.type == "node" then
|
||||
setmetatable(itemdef, {__index = minetest.nodedef_default})
|
||||
minetest.registered_nodes[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "craft" then
|
||||
setmetatable(itemdef, {__index = minetest.craftitemdef_default})
|
||||
minetest.registered_craftitems[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "tool" then
|
||||
setmetatable(itemdef, {__index = minetest.tooldef_default})
|
||||
minetest.registered_tools[itemdef.name] = itemdef
|
||||
elseif itemdef.type == "none" then
|
||||
setmetatable(itemdef, {__index = minetest.noneitemdef_default})
|
||||
else
|
||||
error("Unable to register item: Type is invalid: " .. dump(itemdef))
|
||||
end
|
||||
|
||||
-- Default dug item
|
||||
if itemdef.type == "node" and itemdef.dug_item == nil then
|
||||
itemdef.dug_item = ItemStack({name=itemdef.name}):to_string()
|
||||
end
|
||||
|
||||
-- Legacy stuff
|
||||
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
||||
minetest.register_craft({
|
||||
type="cooking",
|
||||
output=itemdef.cookresult_itemstring,
|
||||
recipe=itemdef.name,
|
||||
cooktime=itemdef.furnace_cooktime
|
||||
})
|
||||
end
|
||||
if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
|
||||
minetest.register_craft({
|
||||
type="fuel",
|
||||
recipe=itemdef.name,
|
||||
burntime=itemdef.furnace_burntime
|
||||
})
|
||||
end
|
||||
|
||||
-- Disable all further modifications
|
||||
getmetatable(itemdef).__newindex = {}
|
||||
|
||||
--minetest.log("Registering item: " .. itemdef.name)
|
||||
minetest.registered_items[itemdef.name] = itemdef
|
||||
minetest.registered_aliases[itemdef.name] = nil
|
||||
register_item_raw(itemdef)
|
||||
end
|
||||
|
||||
function minetest.register_node(name, nodedef)
|
||||
nodedef.type = "node"
|
||||
minetest.register_item(name, nodedef)
|
||||
end
|
||||
|
||||
function minetest.register_craftitem(name, craftitemdef)
|
||||
craftitemdef.type = "craft"
|
||||
|
||||
-- Legacy stuff
|
||||
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
||||
craftitemdef.inventory_image = craftitemdef.image
|
||||
end
|
||||
|
||||
minetest.register_item(name, craftitemdef)
|
||||
end
|
||||
|
||||
function minetest.register_tool(name, tooldef)
|
||||
tooldef.type = "tool"
|
||||
tooldef.stack_max = 1
|
||||
|
||||
-- Legacy stuff
|
||||
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
||||
tooldef.inventory_image = tooldef.image
|
||||
end
|
||||
if tooldef.tool_digging_properties == nil and
|
||||
(tooldef.full_punch_interval ~= nil or
|
||||
tooldef.basetime ~= nil or
|
||||
tooldef.dt_weight ~= nil or
|
||||
tooldef.dt_crackiness ~= nil or
|
||||
tooldef.dt_crumbliness ~= nil or
|
||||
tooldef.dt_cuttability ~= nil or
|
||||
tooldef.basedurability ~= nil or
|
||||
tooldef.dd_weight ~= nil or
|
||||
tooldef.dd_crackiness ~= nil or
|
||||
tooldef.dd_crumbliness ~= nil or
|
||||
tooldef.dd_cuttability ~= nil) then
|
||||
tooldef.tool_digging_properties = {
|
||||
full_punch_interval = tooldef.full_punch_interval,
|
||||
basetime = tooldef.basetime,
|
||||
dt_weight = tooldef.dt_weight,
|
||||
dt_crackiness = tooldef.dt_crackiness,
|
||||
dt_crumbliness = tooldef.dt_crumbliness,
|
||||
dt_cuttability = tooldef.dt_cuttability,
|
||||
basedurability = tooldef.basedurability,
|
||||
dd_weight = tooldef.dd_weight,
|
||||
dd_crackiness = tooldef.dd_crackiness,
|
||||
dd_crumbliness = tooldef.dd_crumbliness,
|
||||
dd_cuttability = tooldef.dd_cuttability,
|
||||
}
|
||||
end
|
||||
|
||||
minetest.register_item(name, tooldef)
|
||||
end
|
||||
|
||||
function minetest.register_alias(name, convert_to)
|
||||
if forbidden_item_names[name] then
|
||||
error("Unable to register alias: Name is forbidden: " .. name)
|
||||
end
|
||||
if minetest.registered_items[name] ~= nil then
|
||||
minetest.log("WARNING: Not registering alias, item with same name" ..
|
||||
" is already defined: " .. name .. " -> " .. convert_to)
|
||||
else
|
||||
--minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
|
||||
minetest.registered_aliases[name] = convert_to
|
||||
register_alias_raw(name, convert_to)
|
||||
end
|
||||
end
|
||||
|
||||
-- Alias the forbidden item names to "" so they can't be
|
||||
-- created via itemstrings (e.g. /give)
|
||||
local name
|
||||
for name in pairs(forbidden_item_names) do
|
||||
minetest.registered_aliases[name] = ""
|
||||
register_alias_raw(name, "")
|
||||
end
|
||||
|
||||
|
||||
-- Deprecated:
|
||||
-- Aliases for minetest.register_alias (how ironic...)
|
||||
--minetest.alias_node = minetest.register_alias
|
||||
--minetest.alias_tool = minetest.register_alias
|
||||
--minetest.alias_craftitem = minetest.register_alias
|
||||
|
||||
--
|
||||
-- Built-in node definitions. Also defined in C.
|
||||
--
|
||||
|
||||
minetest.register_item(":", {
|
||||
type = "none",
|
||||
wield_image = "wieldhand.png",
|
||||
wield_scale = {x=1,y=1,z=2.5},
|
||||
tool_digging_properties = {
|
||||
full_punch_interval = 2.0,
|
||||
basetime = 0.5,
|
||||
dt_weight = 1,
|
||||
dt_crackiness = 0,
|
||||
dt_crumbliness = -1,
|
||||
dt_cuttability = 0,
|
||||
basedurability = 50,
|
||||
dd_weight = 0,
|
||||
dd_crackiness = 0,
|
||||
dd_crumbliness = 0,
|
||||
dd_cuttability = 0,
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("air", {
|
||||
minetest.register_item(":unknown", {
|
||||
type = "none",
|
||||
description = "Unknown Item",
|
||||
inventory_image = "unknown_item.png",
|
||||
on_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
})
|
||||
|
||||
minetest.register_node(":air", {
|
||||
description = "Air (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
@ -140,7 +528,10 @@ minetest.register_node("air", {
|
||||
air_equivalent = true,
|
||||
})
|
||||
|
||||
minetest.register_node("ignore", {
|
||||
minetest.register_node(":ignore", {
|
||||
description = "Ignore (you hacker you!)",
|
||||
inventory_image = "unknown_block.png",
|
||||
wield_image = "unknown_block.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "none",
|
||||
sunlight_propagates = false,
|
||||
@ -151,192 +542,6 @@ minetest.register_node("ignore", {
|
||||
air_equivalent = true,
|
||||
})
|
||||
|
||||
--
|
||||
-- stackstring manipulation functions
|
||||
-- example stackstring: 'craft "apple" 4'
|
||||
-- example item: {type="craft", name="apple"}
|
||||
-- example item: {type="tool", name="SteelPick", wear="23272"}
|
||||
--
|
||||
|
||||
function stackstring_take_item(stackstring)
|
||||
if stackstring == nil then
|
||||
return '', nil
|
||||
end
|
||||
local stacktype = nil
|
||||
stacktype = string.match(stackstring,
|
||||
'([%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]+) "([^"]*)" (%d+)')
|
||||
itemcount = tonumber(itemcount)
|
||||
if itemcount == 0 then
|
||||
return '', nil
|
||||
elseif itemcount == 1 then
|
||||
return '', {type=itemtype, name=itemname}
|
||||
else
|
||||
return itemtype.." \""..itemname.."\" "..(itemcount-1),
|
||||
{type=itemtype, name=itemname}
|
||||
end
|
||||
elseif stacktype == "tool" then
|
||||
local itemtype = nil
|
||||
local itemname = nil
|
||||
local itemwear = nil
|
||||
itemtype, itemname, itemwear = string.match(stackstring,
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemwear = tonumber(itemwear)
|
||||
return '', {type=itemtype, name=itemname, wear=itemwear}
|
||||
end
|
||||
end
|
||||
|
||||
function stackstring_put_item(stackstring, item)
|
||||
if item == nil then
|
||||
return stackstring, false
|
||||
end
|
||||
stackstring = stackstring or ''
|
||||
local stacktype = nil
|
||||
stacktype = string.match(stackstring,
|
||||
'([%a%d]+)')
|
||||
stacktype = stacktype or ''
|
||||
if stacktype ~= '' and stacktype ~= item.type then
|
||||
return stackstring, false
|
||||
end
|
||||
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]+) "([^"]*)" (%d+)')
|
||||
itemtype = itemtype or item.type
|
||||
itemname = itemname or item.name
|
||||
if itemcount == nil then
|
||||
itemcount = 0
|
||||
end
|
||||
itemcount = itemcount + 1
|
||||
return itemtype.." \""..itemname.."\" "..itemcount, true
|
||||
elseif item.type == "tool" then
|
||||
if stacktype ~= nil then
|
||||
return stackstring, false
|
||||
end
|
||||
local itemtype = nil
|
||||
local itemname = nil
|
||||
local itemwear = nil
|
||||
itemtype, itemname, itemwear = string.match(stackstring,
|
||||
'([%a%d]+) "([^"]*)" (%d+)')
|
||||
itemwear = tonumber(itemwear)
|
||||
return itemtype.." \""..itemname.."\" "..itemwear, true
|
||||
end
|
||||
return stackstring, false
|
||||
end
|
||||
|
||||
function stackstring_put_stackstring(stackstring, src)
|
||||
while src ~= '' do
|
||||
--print("src="..dump(src))
|
||||
src, item = stackstring_take_item(src)
|
||||
--print("src="..dump(src).." item="..dump(item))
|
||||
local success
|
||||
stackstring, success = stackstring_put_item(stackstring, item)
|
||||
if not success then
|
||||
return stackstring, false
|
||||
end
|
||||
end
|
||||
return stackstring, true
|
||||
end
|
||||
|
||||
function test_stackstring()
|
||||
local stack
|
||||
local item
|
||||
local success
|
||||
|
||||
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('craft "with spaces" 2')
|
||||
assert(stack == 'craft "with spaces" 1')
|
||||
assert(item.type == 'craft')
|
||||
assert(item.name == 'with spaces')
|
||||
|
||||
stack, item = stackstring_take_item('craft "with spaces" 1')
|
||||
assert(stack == '')
|
||||
assert(item.type == 'craft')
|
||||
assert(item.name == 'with spaces')
|
||||
|
||||
stack, item = stackstring_take_item('craft "s8df2kj3" 0')
|
||||
assert(stack == '')
|
||||
assert(item == nil)
|
||||
|
||||
stack, item = stackstring_take_item('tool "With Spaces" 32487')
|
||||
assert(stack == '')
|
||||
assert(item.type == 'tool')
|
||||
assert(item.name == 'With Spaces')
|
||||
assert(item.wear == 32487)
|
||||
|
||||
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('craft "With Spaces" 40',
|
||||
{type='craft', name='With Spaces'})
|
||||
assert(stack == 'craft "With Spaces" 41')
|
||||
assert(success == true)
|
||||
|
||||
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('node "With Spaces" 40',
|
||||
{type='tool', name='With Spaces'})
|
||||
assert(stack == 'node "With Spaces" 40')
|
||||
assert(success == false)
|
||||
|
||||
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
|
||||
--
|
||||
|
||||
minetest.craftitem_place_item = function(item, placer, pos)
|
||||
--print("craftitem_place_item")
|
||||
--print("item: " .. dump(item))
|
||||
--print("placer: " .. dump(placer))
|
||||
--print("pos: " .. dump(pos))
|
||||
minetest.env:add_item(pos, 'craft "' .. item .. '" 1')
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.craftitem_eat = function(hp_change)
|
||||
return function(item, user, pointed_thing) -- closure
|
||||
--print("craftitem_eat(" .. hp_change .. ")")
|
||||
--print("item: " .. dump(item))
|
||||
--print("user: " .. dump(user))
|
||||
--print("pointed_thing: " .. dump(pointed_thing))
|
||||
user:set_hp(user:get_hp() + hp_change)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Default material types
|
||||
--
|
||||
@ -422,7 +627,7 @@ end
|
||||
-- Callback registration
|
||||
--
|
||||
|
||||
function make_registration()
|
||||
local function make_registration()
|
||||
local t = {}
|
||||
local registerfunc = function(func) table.insert(t, func) end
|
||||
return t, registerfunc
|
||||
|
BIN
data/clienttextures/unknown_item.png
Normal file
BIN
data/clienttextures/unknown_item.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 710 B |
@ -1,80 +1,95 @@
|
||||
-- bucket (Minetest 0.4 mod)
|
||||
-- A bucket, which can pick up water and lava
|
||||
|
||||
minetest.alias_craftitem("bucket", "bucket:bucket_empty")
|
||||
minetest.alias_craftitem("bucket_water", "bucket:bucket_water")
|
||||
minetest.alias_craftitem("bucket_lava", "bucket:bucket_lava")
|
||||
minetest.register_alias("bucket", "bucket:bucket_empty")
|
||||
minetest.register_alias("bucket_water", "bucket:bucket_water")
|
||||
minetest.register_alias("bucket_lava", "bucket:bucket_lava")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'craft "bucket:bucket_empty" 1',
|
||||
output = 'bucket:bucket_empty 1',
|
||||
recipe = {
|
||||
{'craft "steel_ingot"', '', 'craft "steel_ingot"'},
|
||||
{'', 'craft "steel_ingot"', ''},
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
||||
{'', 'default:steel_ingot', ''},
|
||||
}
|
||||
})
|
||||
|
||||
bucket = {}
|
||||
bucket.liquids = {}
|
||||
|
||||
-- Register a new liquid
|
||||
-- source = name of the source node
|
||||
-- flowing = name of the flowing node
|
||||
-- itemname = name of the new bucket item (or nil if liquid is not takeable)
|
||||
-- inventory_image = texture of the new bucket item (ignored if itemname == nil)
|
||||
-- This function can be called from any mod (that depends on bucket).
|
||||
function bucket.register_liquid(source, flowing, itemname, inventory_image)
|
||||
bucket.liquids[source] = {
|
||||
source = source,
|
||||
flowing = flowing,
|
||||
itemname = itemname,
|
||||
}
|
||||
bucket.liquids[flowing] = bucket.liquids[source]
|
||||
|
||||
if itemname ~= nil then
|
||||
minetest.register_craftitem(itemname, {
|
||||
inventory_image = inventory_image,
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
-- Must be pointing to node
|
||||
if pointed_thing.type ~= "node" then
|
||||
return
|
||||
end
|
||||
-- Check if pointing to a liquid
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
if bucket.liquids[n.name] == nil then
|
||||
-- Not a liquid
|
||||
minetest.env:add_node(pointed_thing.above, {name=source})
|
||||
elseif n.name ~= source then
|
||||
-- It's a liquid
|
||||
minetest.env:add_node(pointed_thing.under, {name=source})
|
||||
end
|
||||
return {name="bucket:bucket_empty"}
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_craftitem("bucket:bucket_empty", {
|
||||
image = "bucket.png",
|
||||
inventory_image = "bucket.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
on_use = function(item, player, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
if n.name == "default:water_source" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="air"})
|
||||
player:add_to_inventory_later('craft "bucket:bucket_water" 1')
|
||||
return true
|
||||
elseif n.name == "default:lava_source" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="air"})
|
||||
player:add_to_inventory_later('craft "bucket:bucket_lava" 1')
|
||||
return true
|
||||
end
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
-- Must be pointing to node
|
||||
if pointed_thing.type ~= "node" then
|
||||
return
|
||||
end
|
||||
-- Check if pointing to a liquid source
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
liquiddef = bucket.liquids[n.name]
|
||||
if liquiddef ~= nil and liquiddef.source == n.name and liquiddef.itemname ~= nil then
|
||||
minetest.env:add_node(pointed_thing.under, {name="air"})
|
||||
return {name=liquiddef.itemname}
|
||||
end
|
||||
return false
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("bucket:bucket_water", {
|
||||
image = "bucket_water.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
on_use = function(item, player, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
if n.name == "default:water_source" then
|
||||
-- unchanged
|
||||
elseif n.name == "default:water_flowing" or n.name == "default:lava_source" or n.name == "default:lava_flowing" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="default:water_source"})
|
||||
else
|
||||
minetest.env:add_node(pointed_thing.above, {name="default:water_source"})
|
||||
end
|
||||
player:add_to_inventory_later('craft "bucket:bucket_empty" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end,
|
||||
})
|
||||
bucket.register_liquid(
|
||||
"default:water_source",
|
||||
"default:water_flowing",
|
||||
"bucket:bucket_water",
|
||||
"bucket_water.png"
|
||||
)
|
||||
|
||||
minetest.register_craftitem("bucket:bucket_lava", {
|
||||
image = "bucket_lava.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
on_use = function(item, player, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
n = minetest.env:get_node(pointed_thing.under)
|
||||
if n.name == "default:lava_source" then
|
||||
-- unchanged
|
||||
elseif n.name == "default:water_source" or n.name == "default:water_flowing" or n.name == "default:lava_flowing" then
|
||||
minetest.env:add_node(pointed_thing.under, {name="default:lava_source"})
|
||||
else
|
||||
minetest.env:add_node(pointed_thing.above, {name="default:lava_source"})
|
||||
end
|
||||
player:add_to_inventory_later('craft "bucket:bucket_empty" 1')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end,
|
||||
bucket.register_liquid(
|
||||
"default:lava_source",
|
||||
"default:lava_flowing",
|
||||
"bucket:bucket_lava",
|
||||
"bucket_lava.png"
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "default:bucket_lava",
|
||||
burntime = 60,
|
||||
})
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@ minetest.register_globalstep(on_step)
|
||||
|
||||
-- An example furnace-thing implemented in Lua
|
||||
|
||||
--[[
|
||||
minetest.register_node("experimental:luafurnace", {
|
||||
tile_images = {"default_lava.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png",
|
||||
@ -56,15 +57,6 @@ minetest.register_on_placenode(function(pos, newnode, placer)
|
||||
end
|
||||
end)
|
||||
|
||||
local get_item_definition = function(item)
|
||||
if not item then return nil end
|
||||
if item.type == "node" then
|
||||
return minetest.registered_nodes[item.name]
|
||||
elseif item.type == "craft" then
|
||||
return minetest.registered_craftitems[item.name]
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"experimental:luafurnace"},
|
||||
interval = 1.0,
|
||||
@ -176,7 +168,6 @@ minetest.register_abm({
|
||||
inv:set_stack("fuel", 1, stack)
|
||||
end,
|
||||
})
|
||||
--[[
|
||||
minetest.register_abm({
|
||||
nodenames = {"experimental:luafurnace"},
|
||||
interval = 1.0,
|
||||
@ -231,7 +222,6 @@ minetest.register_abm({
|
||||
meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
|
||||
end,
|
||||
})
|
||||
--]]
|
||||
minetest.register_craft({
|
||||
output = 'node "experimental:luafurnace" 1',
|
||||
recipe = {
|
||||
@ -240,6 +230,7 @@ minetest.register_craft({
|
||||
{'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
|
||||
}
|
||||
})
|
||||
--]]
|
||||
|
||||
--
|
||||
-- Random stuff
|
||||
@ -261,38 +252,16 @@ minetest.register_tool("experimental:horribletool", {
|
||||
})
|
||||
--]]
|
||||
|
||||
--[[minetest.register_craft({
|
||||
output = 'node "somenode" 4',
|
||||
recipe = {
|
||||
{'craft "default_tick" 1'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("experimental:somenode", {
|
||||
tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
|
||||
inventory_image = minetest.inventorycube("lava.png", "mese.png", "stone.png"),
|
||||
--inventory_image = "treeprop.png",
|
||||
material = {
|
||||
diggability = "normal",
|
||||
weight = 0,
|
||||
crackiness = 0,
|
||||
crumbliness = 0,
|
||||
cuttability = 0,
|
||||
flammability = 0
|
||||
},
|
||||
metadata_name = "chest",
|
||||
})]]
|
||||
|
||||
--
|
||||
-- TNT (not functional)
|
||||
--
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'node "experimental:tnt" 4',
|
||||
output = 'experimental:tnt',
|
||||
recipe = {
|
||||
{'node "default:wood" 1'},
|
||||
{'craft "default:coal_lump" 1'},
|
||||
{'node "default:wood" 1'}
|
||||
{'default:wood'},
|
||||
{'default:coal_lump'},
|
||||
{'default:wood'}
|
||||
}
|
||||
})
|
||||
|
||||
@ -363,7 +332,7 @@ function TNT:on_punch(hitter)
|
||||
self.health = self.health - 1
|
||||
if self.health <= 0 then
|
||||
self.object:remove()
|
||||
hitter:add_to_inventory("node TNT 1")
|
||||
hitter:get_inventory():add_item("main", "experimental:tnt")
|
||||
hitter:set_hp(hitter:get_hp() - 1)
|
||||
end
|
||||
end
|
||||
@ -380,7 +349,7 @@ end
|
||||
minetest.register_entity("experimental:tnt", TNT)
|
||||
|
||||
-- Add TNT's old name also
|
||||
minetest.alias_node("TNT", "experimental:tnt")
|
||||
minetest.register_alias("TNT", "experimental:tnt")
|
||||
|
||||
--
|
||||
-- A test entity for testing animated and yaw-modulated sprites
|
||||
@ -547,6 +516,7 @@ minetest.register_abm({
|
||||
end,
|
||||
})--]]
|
||||
|
||||
print("experimental modname="..dump(minetest.get_current_modname()))
|
||||
print("experimental modpath="..dump(minetest.get_modpath("experimental")))
|
||||
|
||||
-- END
|
||||
|
@ -5,97 +5,126 @@
|
||||
-- Aliases to support loading 0.3 and old 0.4 worlds and inventories
|
||||
--
|
||||
|
||||
minetest.alias_node("stone", "default:stone")
|
||||
minetest.alias_node("dirt_with_grass", "default:dirt_with_grass")
|
||||
minetest.alias_node("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps")
|
||||
minetest.alias_node("dirt", "default:dirt")
|
||||
minetest.alias_node("sand", "default:sand")
|
||||
minetest.alias_node("gravel", "default:gravel")
|
||||
minetest.alias_node("sandstone", "default:sandstone")
|
||||
minetest.alias_node("clay", "default:clay")
|
||||
minetest.alias_node("brick", "default:brick")
|
||||
minetest.alias_node("tree", "default:tree")
|
||||
minetest.alias_node("jungletree", "default:jungletree")
|
||||
minetest.alias_node("junglegrass", "default:junglegrass")
|
||||
minetest.alias_node("leaves", "default:leaves")
|
||||
minetest.alias_node("cactus", "default:cactus")
|
||||
minetest.alias_node("papyrus", "default:papyrus")
|
||||
minetest.alias_node("bookshelf", "default:bookshelf")
|
||||
minetest.alias_node("glass", "default:glass")
|
||||
minetest.alias_node("wooden_fence", "default:fence_wood")
|
||||
minetest.alias_node("rail", "default:rail")
|
||||
minetest.alias_node("ladder", "default:ladder")
|
||||
minetest.alias_node("wood", "default:wood")
|
||||
minetest.alias_node("mese", "default:mese")
|
||||
minetest.alias_node("cloud", "default:cloud")
|
||||
minetest.alias_node("water_flowing", "default:water_flowing")
|
||||
minetest.alias_node("water_source", "default:water_source")
|
||||
minetest.alias_node("lava_flowing", "default:lava_flowing")
|
||||
minetest.alias_node("lava_source", "default:lava_source")
|
||||
minetest.alias_node("torch", "default:torch")
|
||||
minetest.alias_node("sign_wall", "default:sign_wall")
|
||||
minetest.alias_node("furnace", "default:furnace")
|
||||
minetest.alias_node("chest", "default:chest")
|
||||
minetest.alias_node("locked_chest", "default:chest_locked")
|
||||
minetest.alias_node("cobble", "default:cobble")
|
||||
minetest.alias_node("mossycobble", "default:mossycobble")
|
||||
minetest.alias_node("steelblock", "default:steelblock")
|
||||
minetest.alias_node("nyancat", "default:nyancat")
|
||||
minetest.alias_node("nyancat_rainbow", "default:nyancat_rainbow")
|
||||
minetest.alias_node("sapling", "default:sapling")
|
||||
minetest.alias_node("apple", "default:apple")
|
||||
minetest.register_alias("stone", "default:stone")
|
||||
minetest.register_alias("dirt_with_grass", "default:dirt_with_grass")
|
||||
minetest.register_alias("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps")
|
||||
minetest.register_alias("dirt", "default:dirt")
|
||||
minetest.register_alias("sand", "default:sand")
|
||||
minetest.register_alias("gravel", "default:gravel")
|
||||
minetest.register_alias("sandstone", "default:sandstone")
|
||||
minetest.register_alias("clay", "default:clay")
|
||||
minetest.register_alias("brick", "default:brick")
|
||||
minetest.register_alias("tree", "default:tree")
|
||||
minetest.register_alias("jungletree", "default:jungletree")
|
||||
minetest.register_alias("junglegrass", "default:junglegrass")
|
||||
minetest.register_alias("leaves", "default:leaves")
|
||||
minetest.register_alias("cactus", "default:cactus")
|
||||
minetest.register_alias("papyrus", "default:papyrus")
|
||||
minetest.register_alias("bookshelf", "default:bookshelf")
|
||||
minetest.register_alias("glass", "default:glass")
|
||||
minetest.register_alias("wooden_fence", "default:fence_wood")
|
||||
minetest.register_alias("rail", "default:rail")
|
||||
minetest.register_alias("ladder", "default:ladder")
|
||||
minetest.register_alias("wood", "default:wood")
|
||||
minetest.register_alias("mese", "default:mese")
|
||||
minetest.register_alias("cloud", "default:cloud")
|
||||
minetest.register_alias("water_flowing", "default:water_flowing")
|
||||
minetest.register_alias("water_source", "default:water_source")
|
||||
minetest.register_alias("lava_flowing", "default:lava_flowing")
|
||||
minetest.register_alias("lava_source", "default:lava_source")
|
||||
minetest.register_alias("torch", "default:torch")
|
||||
minetest.register_alias("sign_wall", "default:sign_wall")
|
||||
minetest.register_alias("furnace", "default:furnace")
|
||||
minetest.register_alias("chest", "default:chest")
|
||||
minetest.register_alias("locked_chest", "default:chest_locked")
|
||||
minetest.register_alias("cobble", "default:cobble")
|
||||
minetest.register_alias("mossycobble", "default:mossycobble")
|
||||
minetest.register_alias("steelblock", "default:steelblock")
|
||||
minetest.register_alias("nyancat", "default:nyancat")
|
||||
minetest.register_alias("nyancat_rainbow", "default:nyancat_rainbow")
|
||||
minetest.register_alias("sapling", "default:sapling")
|
||||
minetest.register_alias("apple", "default:apple")
|
||||
|
||||
minetest.alias_tool("WPick", "default:pick_wood")
|
||||
minetest.alias_tool("STPick", "default:pick_stone")
|
||||
minetest.alias_tool("SteelPick", "default:pick_steel")
|
||||
minetest.alias_tool("MesePick", "default:pick_mese")
|
||||
minetest.alias_tool("WShovel", "default:shovel_wood")
|
||||
minetest.alias_tool("STShovel", "default:shovel_stone")
|
||||
minetest.alias_tool("SteelShovel", "default:shovel_steel")
|
||||
minetest.alias_tool("WAxe", "default:axe_wood")
|
||||
minetest.alias_tool("STAxe", "default:axe_stone")
|
||||
minetest.alias_tool("SteelAxe", "default:axe_steel")
|
||||
minetest.alias_tool("WSword", "default:sword_wood")
|
||||
minetest.alias_tool("STSword", "default:sword_stone")
|
||||
minetest.alias_tool("SteelSword", "default:sword_steel")
|
||||
minetest.register_alias("WPick", "default:pick_wood")
|
||||
minetest.register_alias("STPick", "default:pick_stone")
|
||||
minetest.register_alias("SteelPick", "default:pick_steel")
|
||||
minetest.register_alias("MesePick", "default:pick_mese")
|
||||
minetest.register_alias("WShovel", "default:shovel_wood")
|
||||
minetest.register_alias("STShovel", "default:shovel_stone")
|
||||
minetest.register_alias("SteelShovel", "default:shovel_steel")
|
||||
minetest.register_alias("WAxe", "default:axe_wood")
|
||||
minetest.register_alias("STAxe", "default:axe_stone")
|
||||
minetest.register_alias("SteelAxe", "default:axe_steel")
|
||||
minetest.register_alias("WSword", "default:sword_wood")
|
||||
minetest.register_alias("STSword", "default:sword_stone")
|
||||
minetest.register_alias("SteelSword", "default:sword_steel")
|
||||
|
||||
minetest.alias_craftitem("Stick", "default:stick")
|
||||
minetest.alias_craftitem("paper", "default:paper")
|
||||
minetest.alias_craftitem("book", "default:book")
|
||||
minetest.alias_craftitem("lump_of_coal", "default:coal_lump")
|
||||
minetest.alias_craftitem("lump_of_iron", "default:iron_lump")
|
||||
minetest.alias_craftitem("lump_of_clay", "default:clay_lump")
|
||||
minetest.alias_craftitem("steel_ingot", "default:steel_ingot")
|
||||
minetest.alias_craftitem("clay_brick", "default:clay_brick")
|
||||
minetest.alias_craftitem("scorched_stuff", "default:scorched_stuff")
|
||||
minetest.alias_craftitem("apple", "default:apple")
|
||||
minetest.register_alias("Stick", "default:stick")
|
||||
minetest.register_alias("paper", "default:paper")
|
||||
minetest.register_alias("book", "default:book")
|
||||
minetest.register_alias("lump_of_coal", "default:coal_lump")
|
||||
minetest.register_alias("lump_of_iron", "default:iron_lump")
|
||||
minetest.register_alias("lump_of_clay", "default:clay_lump")
|
||||
minetest.register_alias("steel_ingot", "default:steel_ingot")
|
||||
minetest.register_alias("clay_brick", "default:clay_brick")
|
||||
minetest.register_alias("scorched_stuff", "default:scorched_stuff")
|
||||
|
||||
--
|
||||
-- Old items
|
||||
--
|
||||
|
||||
minetest.register_craftitem(":rat", {
|
||||
image = "rat.png",
|
||||
cookresult_itemstring = 'craft "cooked_rat" 1',
|
||||
description = "Rat",
|
||||
inventory_image = "rat.png",
|
||||
on_drop = function(item, dropper, pos)
|
||||
minetest.env:add_rat(pos)
|
||||
return true
|
||||
item:take_item()
|
||||
return item
|
||||
end,
|
||||
on_place = function(item, dropped, pointed)
|
||||
pos = minetest.get_pointed_thing_position(pointed, true)
|
||||
if pos ~= nil then
|
||||
minetest.env:add_rat(pos)
|
||||
item:take_item()
|
||||
return item
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craftitem(":cooked_rat", {
|
||||
image = "cooked_rat.png",
|
||||
cookresult_itemstring = 'craft "scorched_stuff" 1',
|
||||
on_place_on_ground = minetest.craftitem_place_item,
|
||||
on_use = minetest.craftitem_eat(6),
|
||||
description = "Cooked rat",
|
||||
inventory_image = "cooked_rat.png",
|
||||
on_use = minetest.item_eat(6),
|
||||
})
|
||||
|
||||
minetest.register_craftitem(":firefly", {
|
||||
image = "firefly.png",
|
||||
description = "Firefly",
|
||||
inventory_image = "firefly.png",
|
||||
on_drop = function(item, dropper, pos)
|
||||
minetest.env:add_firefly(pos)
|
||||
return true
|
||||
item:take_item()
|
||||
return item
|
||||
end,
|
||||
on_place = function(item, dropped, pointed)
|
||||
pos = minetest.get_pointed_thing_position(pointed, true)
|
||||
if pos ~= nil then
|
||||
minetest.env:add_firefly(pos)
|
||||
item:take_item()
|
||||
return item
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "cooked_rat",
|
||||
recipe = "rat",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "scorched_stuff",
|
||||
recipe = "cooked_rat",
|
||||
})
|
||||
|
||||
-- END
|
||||
|
@ -100,9 +100,8 @@ set(common_SRCS
|
||||
content_abm.cpp
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
tooldef.cpp
|
||||
itemdef.cpp
|
||||
nodedef.cpp
|
||||
craftitemdef.cpp
|
||||
luaentity_common.cpp
|
||||
scriptapi.cpp
|
||||
script.cpp
|
||||
|
219
src/camera.cpp
219
src/camera.cpp
@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "tile.h"
|
||||
#include <cmath>
|
||||
#include "settings.h"
|
||||
#include "nodedef.h" // For wield visualization
|
||||
#include "itemdef.h" // For wield visualization
|
||||
|
||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
m_smgr(smgr),
|
||||
@ -37,6 +37,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
|
||||
m_wieldmgr(NULL),
|
||||
m_wieldnode(NULL),
|
||||
m_wieldlight(0),
|
||||
|
||||
m_draw_control(draw_control),
|
||||
m_viewing_range_min(5.0),
|
||||
@ -77,15 +78,15 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
|
||||
// all other 3D scene nodes and before the GUI.
|
||||
m_wieldmgr = smgr->createNewSceneManager();
|
||||
m_wieldmgr->addCameraSceneNode();
|
||||
m_wieldnode = new ExtrudedSpriteSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr);
|
||||
m_wieldnode = m_wieldmgr->addMeshSceneNode(createCubeMesh(v3f(1,1,1)), NULL); // need a dummy mesh
|
||||
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
m_wieldnode->setMesh(NULL);
|
||||
m_wieldmgr->drop();
|
||||
m_wieldnode->drop();
|
||||
}
|
||||
|
||||
bool Camera::successfullyCreated(std::wstring& error_message)
|
||||
@ -292,7 +293,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
|
||||
}
|
||||
m_wieldnode->setPosition(wield_position);
|
||||
m_wieldnode->setRotation(wield_rotation);
|
||||
m_wieldnode->updateLight(player->light);
|
||||
m_wieldlight = player->light;
|
||||
|
||||
// Render distance feedback loop
|
||||
updateViewingRange(frametime);
|
||||
@ -449,62 +450,38 @@ void Camera::updateSettings()
|
||||
m_wanted_frametime = 1.0 / wanted_fps;
|
||||
}
|
||||
|
||||
void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
|
||||
{
|
||||
//ITextureSource *tsrc = gamedef->tsrc();
|
||||
INodeDefManager *ndef = gamedef->ndef();
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
bool isCube = false;
|
||||
|
||||
// Try to make a MaterialItem cube.
|
||||
if (std::string(item->getName()) == "MaterialItem")
|
||||
{
|
||||
// A block-type material
|
||||
MaterialItem* mat_item = (MaterialItem*) item;
|
||||
content_t content = mat_item->getMaterial();
|
||||
switch(ndef->get(content).drawtype){
|
||||
case NDT_NORMAL:
|
||||
case NDT_LIQUID:
|
||||
case NDT_FLOWINGLIQUID:
|
||||
case NDT_GLASSLIKE:
|
||||
case NDT_ALLFACES:
|
||||
case NDT_ALLFACES_OPTIONAL:
|
||||
m_wieldnode->setCube(ndef->get(content).tiles);
|
||||
isCube = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, make an extruded sprite.
|
||||
if (!isCube)
|
||||
{
|
||||
m_wieldnode->setSprite(item->getImageRaw());
|
||||
}
|
||||
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bare hands
|
||||
m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png"));
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::setDigging(s32 button)
|
||||
{
|
||||
if (m_digging_button == -1)
|
||||
m_digging_button = button;
|
||||
}
|
||||
|
||||
void Camera::wield(const ItemStack &item, IGameDef *gamedef)
|
||||
{
|
||||
IItemDefManager *idef = gamedef->idef();
|
||||
scene::IMesh *wield_mesh = item.getDefinition(idef).wield_mesh;
|
||||
if(wield_mesh)
|
||||
{
|
||||
m_wieldnode->setMesh(wield_mesh);
|
||||
m_wieldnode->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_wieldnode->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::drawWieldedTool()
|
||||
{
|
||||
// Set vertex colors of wield mesh according to light level
|
||||
u8 li = decode_light(m_wieldlight);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshColor(m_wieldnode->getMesh(), color);
|
||||
|
||||
// Clear Z buffer
|
||||
m_wieldmgr->getVideoDriver()->clearZBuffer();
|
||||
|
||||
// Draw the wielded node (in a separate scene manager)
|
||||
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
|
||||
cam->setAspectRatio(m_cameranode->getAspectRatio());
|
||||
cam->setFOV(m_cameranode->getFOV());
|
||||
@ -512,145 +489,3 @@ void Camera::drawWieldedTool()
|
||||
cam->setFarValue(100);
|
||||
m_wieldmgr->drawAll();
|
||||
}
|
||||
|
||||
|
||||
ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id,
|
||||
const v3f& position,
|
||||
const v3f& rotation,
|
||||
const v3f& scale
|
||||
):
|
||||
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_cubemesh = NULL;
|
||||
m_is_cube = false;
|
||||
m_light = LIGHT_MAX;
|
||||
}
|
||||
|
||||
ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
|
||||
{
|
||||
removeChild(m_meshnode);
|
||||
if (m_cubemesh)
|
||||
m_cubemesh->drop();
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
io::path name = getExtrudedName(texture);
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
|
||||
if (mesh != NULL)
|
||||
{
|
||||
// Extruded texture has been found in cache.
|
||||
m_meshnode->setMesh(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Texture was not yet extruded, do it now and save in cache
|
||||
mesh = createExtrudedMesh(texture,
|
||||
SceneManager->getVideoDriver(),
|
||||
sprite_scale);
|
||||
if (mesh == NULL)
|
||||
{
|
||||
dstream << "Warning: failed to extrude sprite" << std::endl;
|
||||
m_meshnode->setVisible(false);
|
||||
return;
|
||||
}
|
||||
cache->addMesh(name, mesh);
|
||||
m_meshnode->setMesh(mesh);
|
||||
mesh->drop();
|
||||
}
|
||||
|
||||
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);
|
||||
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = false;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
|
||||
{
|
||||
const v3f cube_scale(30.0, 30.0, 30.0);
|
||||
|
||||
if (m_cubemesh == NULL)
|
||||
{
|
||||
m_cubemesh = createCubeMesh(cube_scale);
|
||||
}
|
||||
|
||||
m_meshnode->setMesh(m_cubemesh);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = tiles[i].texture.atlas;
|
||||
v2f pos = tiles[i].texture.pos;
|
||||
v2f size = tiles[i].texture.size;
|
||||
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
tiles[i].applyMaterialOptions(material);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
}
|
||||
m_meshnode->setVisible(true);
|
||||
m_is_cube = true;
|
||||
updateLight(m_light);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::updateLight(u8 light)
|
||||
{
|
||||
m_light = light;
|
||||
|
||||
u8 li = decode_light(light);
|
||||
// Set brightness one lower than incoming light
|
||||
diminish_light(li);
|
||||
video::SColor color(255,li,li,li);
|
||||
setMeshColor(m_meshnode->getMesh(), color);
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
|
||||
{
|
||||
scene::IMeshCache* cache = SceneManager->getMeshCache();
|
||||
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
|
||||
if (mesh != NULL)
|
||||
cache->removeMesh(mesh);
|
||||
}
|
||||
|
||||
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
|
||||
{
|
||||
return m_meshnode->getBoundingBox();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
void ExtrudedSpriteSceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
|
||||
{
|
||||
io::path path = texture->getName();
|
||||
path.append("/[extruded]");
|
||||
return path;
|
||||
}
|
||||
|
54
src/camera.h
54
src/camera.h
@ -26,12 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "tile.h"
|
||||
#include "utility.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <IMeshCache.h>
|
||||
#include <IAnimatedMesh.h>
|
||||
|
||||
class LocalPlayer;
|
||||
struct MapDrawControl;
|
||||
class ExtrudedSpriteSceneNode;
|
||||
class IGameDef;
|
||||
|
||||
/*
|
||||
@ -116,13 +113,13 @@ public:
|
||||
// Update settings from g_settings
|
||||
void updateSettings();
|
||||
|
||||
// Replace the wielded item mesh
|
||||
void wield(const InventoryItem* item, IGameDef *gamedef);
|
||||
|
||||
// Start digging animation
|
||||
// Pass 0 for left click, 1 for right click
|
||||
void setDigging(s32 button);
|
||||
|
||||
// Replace the wielded item mesh
|
||||
void wield(const ItemStack &item, IGameDef *gamedef);
|
||||
|
||||
// Draw the wielded tool.
|
||||
// This has to happen *after* the main scene is drawn.
|
||||
// Warning: This clears the Z buffer.
|
||||
@ -136,7 +133,8 @@ private:
|
||||
scene::ICameraSceneNode* m_cameranode;
|
||||
|
||||
scene::ISceneManager* m_wieldmgr;
|
||||
ExtrudedSpriteSceneNode* m_wieldnode;
|
||||
scene::IMeshSceneNode* m_wieldnode;
|
||||
u8 m_wieldlight;
|
||||
|
||||
// draw control
|
||||
MapDrawControl& m_draw_control;
|
||||
@ -182,46 +180,4 @@ private:
|
||||
s32 m_digging_button;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A scene node that displays a 2D mesh extruded into the third dimension,
|
||||
to add an illusion of depth.
|
||||
|
||||
Since this class was created to display the wielded tool of the local
|
||||
player, and only tools and items are rendered like this (but not solid
|
||||
content like stone and mud, which are shown as cubes), the option to
|
||||
draw a textured cube instead is provided.
|
||||
*/
|
||||
class ExtrudedSpriteSceneNode: public scene::ISceneNode
|
||||
{
|
||||
public:
|
||||
ExtrudedSpriteSceneNode(
|
||||
scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr,
|
||||
s32 id = -1,
|
||||
const v3f& position = v3f(0,0,0),
|
||||
const v3f& rotation = v3f(0,0,0),
|
||||
const v3f& scale = v3f(1,1,1));
|
||||
~ExtrudedSpriteSceneNode();
|
||||
|
||||
void setSprite(video::ITexture* texture);
|
||||
void setCube(const TileSpec tiles[6]);
|
||||
|
||||
void updateLight(u8 light);
|
||||
|
||||
void removeSpriteFromCache(video::ITexture* texture);
|
||||
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual void OnRegisterSceneNode();
|
||||
virtual void render();
|
||||
|
||||
private:
|
||||
scene::IMeshSceneNode* m_meshnode;
|
||||
scene::IMesh* m_cubemesh;
|
||||
bool m_is_cube;
|
||||
u8 m_light;
|
||||
|
||||
io::path getExtrudedName(video::ITexture* texture);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
261
src/client.cpp
261
src/client.cpp
@ -33,8 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include "nodemetadata.h"
|
||||
#include "nodedef.h"
|
||||
#include "tooldef.h"
|
||||
#include "craftitemdef.h"
|
||||
#include "itemdef.h"
|
||||
#include <IFileSystem.h>
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
@ -207,14 +206,12 @@ Client::Client(
|
||||
std::string password,
|
||||
MapDrawControl &control,
|
||||
IWritableTextureSource *tsrc,
|
||||
IWritableToolDefManager *tooldef,
|
||||
IWritableNodeDefManager *nodedef,
|
||||
IWritableCraftItemDefManager *craftitemdef
|
||||
IWritableItemDefManager *itemdef,
|
||||
IWritableNodeDefManager *nodedef
|
||||
):
|
||||
m_tsrc(tsrc),
|
||||
m_tooldef(tooldef),
|
||||
m_itemdef(itemdef),
|
||||
m_nodedef(nodedef),
|
||||
m_craftitemdef(craftitemdef),
|
||||
m_mesh_update_thread(this),
|
||||
m_env(
|
||||
new ClientMap(this, this, control,
|
||||
@ -234,9 +231,8 @@ Client::Client(
|
||||
m_access_denied(false),
|
||||
m_texture_receive_progress(0),
|
||||
m_textures_received(false),
|
||||
m_tooldef_received(false),
|
||||
m_nodedef_received(false),
|
||||
m_craftitemdef_received(false)
|
||||
m_itemdef_received(false),
|
||||
m_nodedef_received(false)
|
||||
{
|
||||
m_packetcounter_timer = 0.0;
|
||||
//m_delete_unused_sectors_timer = 0.0;
|
||||
@ -251,12 +247,6 @@ Client::Client(
|
||||
else
|
||||
infostream<<"Not building texture atlas."<<std::endl;
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
|
||||
// Start threads after setting up content definitions
|
||||
m_mesh_update_thread.Start();
|
||||
|
||||
/*
|
||||
Add local player
|
||||
*/
|
||||
@ -266,9 +256,6 @@ Client::Client(
|
||||
player->updateName(playername);
|
||||
|
||||
m_env.addPlayer(player);
|
||||
|
||||
// Initialize player in the inventory context
|
||||
m_inventory_context.current_player = player;
|
||||
}
|
||||
}
|
||||
|
||||
@ -983,7 +970,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
//t4.stop();
|
||||
|
||||
//TimeTaker t1("inventory.deSerialize()", m_device);
|
||||
player->inventory.deSerialize(is, this);
|
||||
player->inventory.deSerialize(is);
|
||||
//t1.stop();
|
||||
|
||||
m_inventory_updated = true;
|
||||
@ -1216,18 +1203,18 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
} else {
|
||||
InventoryList *inv = player->inventory.getList("main");
|
||||
std::string itemstring(deSerializeString(is));
|
||||
if (itemstring.empty()) {
|
||||
inv->deleteItem(0);
|
||||
infostream
|
||||
<<"Client: empty player item for peer "
|
||||
<< peer_id << std::endl;
|
||||
} else {
|
||||
std::istringstream iss(itemstring);
|
||||
delete inv->changeItem(0,
|
||||
InventoryItem::deSerialize(iss, this));
|
||||
infostream<<"Client: player item for peer " << peer_id << ": ";
|
||||
player->getWieldItem()->serialize(infostream);
|
||||
infostream<<std::endl;
|
||||
ItemStack item;
|
||||
item.deSerialize(itemstring, m_itemdef);
|
||||
inv->changeItem(0, item);
|
||||
if(itemstring.empty())
|
||||
{
|
||||
infostream<<"Client: empty player item for peer "
|
||||
<<peer_id<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: player item for peer "
|
||||
<<peer_id<<": "<<itemstring<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1256,14 +1243,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
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();
|
||||
}
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
assert(!m_mesh_update_thread.IsRunning());
|
||||
|
||||
int num_textures = readU16(is);
|
||||
|
||||
@ -1362,9 +1344,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
|
||||
}
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_TEXTURES_UPDATED;
|
||||
@ -1412,14 +1391,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
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();
|
||||
}
|
||||
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
assert(!m_mesh_update_thread.IsRunning());
|
||||
|
||||
/*
|
||||
u16 command
|
||||
u16 total number of texture bunches
|
||||
@ -1484,22 +1459,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
img->drop();
|
||||
rfile->drop();
|
||||
}
|
||||
|
||||
if(m_nodedef_received && m_textures_received){
|
||||
// Rebuild inherited images and recreate textures
|
||||
m_tsrc->rebuildImagesAndTextures();
|
||||
|
||||
// Update texture atlas
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
m_tsrc->buildMainAtlas(this);
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
}
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_TEXTURES_UPDATED;
|
||||
@ -1507,82 +1466,53 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
else if(command == TOCLIENT_TOOLDEF)
|
||||
{
|
||||
infostream<<"Client: Received tool definitions: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_tooldef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
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);
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
infostream<<"Client: WARNING: Ignoring TOCLIENT_TOOLDEF"<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_NODEDEF)
|
||||
{
|
||||
infostream<<"Client: Received node definitions: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
assert(!m_mesh_update_thread.IsRunning());
|
||||
|
||||
// Decompress node definitions
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_nodedef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_nodedef->deSerialize(tmp_is, this);
|
||||
|
||||
if(m_textures_received){
|
||||
// Update texture atlas
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
m_tsrc->buildMainAtlas(this);
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
}
|
||||
std::ostringstream tmp_os;
|
||||
decompressZlib(tmp_is, tmp_os);
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
// Deserialize node definitions
|
||||
std::istringstream tmp_is2(tmp_os.str());
|
||||
m_nodedef->deSerialize(tmp_is2);
|
||||
m_nodedef_received = true;
|
||||
}
|
||||
else if(command == TOCLIENT_CRAFTITEMDEF)
|
||||
{
|
||||
infostream<<"Client: Received CraftItem definitions: packet size: "
|
||||
infostream<<"Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF"<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_ITEMDEF)
|
||||
{
|
||||
infostream<<"Client: Received item definitions: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
assert(!m_mesh_update_thread.IsRunning());
|
||||
|
||||
// Decompress item definitions
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_craftitemdef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
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);
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
std::ostringstream tmp_os;
|
||||
decompressZlib(tmp_is, tmp_os);
|
||||
|
||||
// Deserialize node definitions
|
||||
std::istringstream tmp_is2(tmp_os.str());
|
||||
m_itemdef->deSerialize(tmp_is2);
|
||||
m_itemdef_received = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1943,11 +1873,6 @@ void Client::selectPlayerItem(u16 item)
|
||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||
m_playeritem = item;
|
||||
m_inventory_updated = true;
|
||||
|
||||
LocalPlayer *player = m_env.getLocalPlayer();
|
||||
assert(player != NULL);
|
||||
player->wieldItem(item);
|
||||
|
||||
sendPlayerItem(item);
|
||||
}
|
||||
|
||||
@ -1971,17 +1896,19 @@ void Client::getLocalInventory(Inventory &dst)
|
||||
dst = player->inventory;
|
||||
}
|
||||
|
||||
InventoryContext *Client::getInventoryContext()
|
||||
{
|
||||
return &m_inventory_context;
|
||||
}
|
||||
|
||||
Inventory* Client::getInventory(const InventoryLocation &loc)
|
||||
{
|
||||
switch(loc.type){
|
||||
case InventoryLocation::UNDEFINED:
|
||||
{}
|
||||
break;
|
||||
case InventoryLocation::CURRENT_PLAYER:
|
||||
{
|
||||
Player *player = m_env.getLocalPlayer();
|
||||
assert(player != NULL);
|
||||
return &player->inventory;
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::PLAYER:
|
||||
{
|
||||
Player *player = m_env.getPlayer(loc.name.c_str());
|
||||
@ -2003,36 +1930,6 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#if 0
|
||||
Inventory* Client::getInventory(InventoryContext *c, std::string id)
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
return &(c->current_player->inventory);
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
{
|
||||
v3s16 p;
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
NodeMetadata* meta = getNodeMetadata(p);
|
||||
if(meta)
|
||||
return meta->getInventory();
|
||||
infostream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
||||
<<"no metadata found"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
void Client::inventoryAction(InventoryAction *a)
|
||||
{
|
||||
sendInventoryAction(a);
|
||||
@ -2234,6 +2131,32 @@ ClientEvent Client::getClientEvent()
|
||||
return m_client_event_queue.pop_front();
|
||||
}
|
||||
|
||||
void Client::afterContentReceived()
|
||||
{
|
||||
assert(m_itemdef_received);
|
||||
assert(m_nodedef_received);
|
||||
assert(m_textures_received);
|
||||
|
||||
// Rebuild inherited images and recreate textures
|
||||
m_tsrc->rebuildImagesAndTextures();
|
||||
|
||||
// Update texture atlas
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
m_tsrc->buildMainAtlas(this);
|
||||
|
||||
// Update node aliases
|
||||
m_nodedef->updateAliases(m_itemdef);
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
|
||||
// Update item textures and meshes
|
||||
m_itemdef->updateTexturesAndMeshes(this);
|
||||
|
||||
// Start mesh update thread after setting up content definitions
|
||||
m_mesh_update_thread.Start();
|
||||
}
|
||||
|
||||
float Client::getRTT(void)
|
||||
{
|
||||
try{
|
||||
@ -2245,9 +2168,9 @@ float Client::getRTT(void)
|
||||
|
||||
// IGameDef interface
|
||||
// Under envlock
|
||||
IToolDefManager* Client::getToolDefManager()
|
||||
IItemDefManager* Client::getItemDefManager()
|
||||
{
|
||||
return m_tooldef;
|
||||
return m_itemdef;
|
||||
}
|
||||
INodeDefManager* Client::getNodeDefManager()
|
||||
{
|
||||
@ -2258,10 +2181,6 @@ ICraftDefManager* Client::getCraftDefManager()
|
||||
return NULL;
|
||||
//return m_craftdef;
|
||||
}
|
||||
ICraftItemDefManager* Client::getCraftItemDefManager()
|
||||
{
|
||||
return m_craftitemdef;
|
||||
}
|
||||
ITextureSource* Client::getTextureSource()
|
||||
{
|
||||
return m_tsrc;
|
||||
|
29
src/client.h
29
src/client.h
@ -36,10 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
struct MeshMakeData;
|
||||
class IGameDef;
|
||||
class IWritableTextureSource;
|
||||
class IWritableToolDefManager;
|
||||
class IWritableItemDefManager;
|
||||
class IWritableNodeDefManager;
|
||||
//class IWritableCraftDefManager;
|
||||
class IWritableCraftItemDefManager;
|
||||
|
||||
class ClientNotReadyException : public BaseException
|
||||
{
|
||||
@ -167,9 +166,8 @@ public:
|
||||
std::string password,
|
||||
MapDrawControl &control,
|
||||
IWritableTextureSource *tsrc,
|
||||
IWritableToolDefManager *tooldef,
|
||||
IWritableNodeDefManager *nodedef,
|
||||
IWritableCraftItemDefManager *craftitemdef
|
||||
IWritableItemDefManager *itemdef,
|
||||
IWritableNodeDefManager *nodedef
|
||||
);
|
||||
|
||||
~Client();
|
||||
@ -245,11 +243,8 @@ public:
|
||||
// Copies the inventory of the local player to parameter
|
||||
void getLocalInventory(Inventory &dst);
|
||||
|
||||
InventoryContext *getInventoryContext();
|
||||
|
||||
/* InventoryManager interface */
|
||||
Inventory* getInventory(const InventoryLocation &loc);
|
||||
//Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
void inventoryAction(InventoryAction *a);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
@ -323,20 +318,19 @@ public:
|
||||
|
||||
bool texturesReceived()
|
||||
{ return m_textures_received; }
|
||||
bool tooldefReceived()
|
||||
{ return m_tooldef_received; }
|
||||
bool itemdefReceived()
|
||||
{ return m_itemdef_received; }
|
||||
bool nodedefReceived()
|
||||
{ return m_nodedef_received; }
|
||||
bool craftitemdefReceived()
|
||||
{ return m_craftitemdef_received; }
|
||||
|
||||
void afterContentReceived();
|
||||
|
||||
float getRTT(void);
|
||||
|
||||
// IGameDef interface
|
||||
virtual IToolDefManager* getToolDefManager();
|
||||
virtual IItemDefManager* getItemDefManager();
|
||||
virtual INodeDefManager* getNodeDefManager();
|
||||
virtual ICraftDefManager* getCraftDefManager();
|
||||
virtual ICraftItemDefManager* getCraftItemDefManager();
|
||||
virtual ITextureSource* getTextureSource();
|
||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||
|
||||
@ -363,9 +357,8 @@ private:
|
||||
IntervalLimiter m_map_timer_and_unload_interval;
|
||||
|
||||
IWritableTextureSource *m_tsrc;
|
||||
IWritableToolDefManager *m_tooldef;
|
||||
IWritableItemDefManager *m_itemdef;
|
||||
IWritableNodeDefManager *m_nodedef;
|
||||
IWritableCraftItemDefManager *m_craftitemdef;
|
||||
MeshUpdateThread m_mesh_update_thread;
|
||||
ClientEnvironment m_env;
|
||||
con::Connection m_con;
|
||||
@ -387,13 +380,11 @@ private:
|
||||
std::string m_password;
|
||||
bool m_access_denied;
|
||||
std::wstring m_access_denied_reason;
|
||||
InventoryContext m_inventory_context;
|
||||
Queue<ClientEvent> m_client_event_queue;
|
||||
float m_texture_receive_progress;
|
||||
bool m_textures_received;
|
||||
bool m_tooldef_received;
|
||||
bool m_itemdef_received;
|
||||
bool m_nodedef_received;
|
||||
bool m_craftitemdef_received;
|
||||
friend class FarMesh;
|
||||
};
|
||||
|
||||
|
@ -39,9 +39,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
Make players to be handled mostly as ActiveObjects
|
||||
PROTOCOL_VERSION 6:
|
||||
Only non-cached textures are sent
|
||||
PROTOCOL_VERSION 7:
|
||||
Add TOCLIENT_ITEMDEF
|
||||
Obsolete TOCLIENT_TOOLDEF
|
||||
Obsolete TOCLIENT_CRAFTITEMDEF
|
||||
Compress the contents of TOCLIENT_ITEMDEF and TOCLIENT_NODEDEF
|
||||
*/
|
||||
|
||||
#define PROTOCOL_VERSION 6
|
||||
#define PROTOCOL_VERSION 7
|
||||
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
@ -252,6 +257,14 @@ enum ToClientCommand
|
||||
string sha1_digest
|
||||
}
|
||||
*/
|
||||
|
||||
TOCLIENT_ITEMDEF = 0x3d,
|
||||
/*
|
||||
u16 command
|
||||
u32 length of next item
|
||||
serialized ItemDefManager
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
@ -666,7 +666,7 @@ void Connection::send(float dtime)
|
||||
// Receive packets from the network and buffers and create ConnectionEvents
|
||||
void Connection::receive()
|
||||
{
|
||||
u32 datasize = 100000;
|
||||
u32 datasize = m_max_packet_size * 2; // Double it just to be safe
|
||||
// TODO: We can not know how many layers of header there are.
|
||||
// For now, just assume there are no other than the base headers.
|
||||
u32 packet_maxsize = datasize + BASE_HEADER_SIZE;
|
||||
@ -854,10 +854,6 @@ void Connection::receive()
|
||||
dout_con<<"ProcessPacket returned data of size "
|
||||
<<resultdata.getSize()<<std::endl;
|
||||
|
||||
if(datasize < resultdata.getSize())
|
||||
throw InvalidIncomingDataException
|
||||
("Buffer too small for received data");
|
||||
|
||||
ConnectionEvent e;
|
||||
e.dataReceived(peer_id, resultdata);
|
||||
putEvent(e);
|
||||
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_cao.h"
|
||||
#include "tile.h"
|
||||
#include "environment.h"
|
||||
#include "collision.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <ITextSceneNode.h>
|
||||
@ -172,6 +173,8 @@ public:
|
||||
void updateLight(u8 light_at_pos);
|
||||
v3s16 getLightPosition();
|
||||
void updateNodePos();
|
||||
void updateInfoText();
|
||||
void updateTexture();
|
||||
|
||||
void step(float dtime, ClientEnvironment *env);
|
||||
|
||||
@ -191,7 +194,7 @@ private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
scene::IMeshSceneNode *m_node;
|
||||
v3f m_position;
|
||||
std::string m_inventorystring;
|
||||
std::string m_itemstring;
|
||||
std::string m_infotext;
|
||||
};
|
||||
|
||||
@ -595,39 +598,13 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||
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();
|
||||
|
||||
/*
|
||||
Update image of node
|
||||
*/
|
||||
|
||||
// Create an inventory item to see what is its image
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
video::ITexture *texture = NULL;
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(is, m_gamedef);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
<<std::endl;
|
||||
if(item)
|
||||
{
|
||||
texture = item->getImage();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing inventorystring \""
|
||||
<<m_inventorystring<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
// Set meshbuffer texture
|
||||
buf->getMaterial().setTexture(0, texture);
|
||||
updateTexture();
|
||||
}
|
||||
|
||||
void ItemCAO::removeFromScene()
|
||||
@ -662,6 +639,51 @@ void ItemCAO::updateNodePos()
|
||||
m_node->setPosition(m_position);
|
||||
}
|
||||
|
||||
void ItemCAO::updateInfoText()
|
||||
{
|
||||
try{
|
||||
IItemDefManager *idef = m_gamedef->idef();
|
||||
ItemStack item;
|
||||
item.deSerialize(m_itemstring, idef);
|
||||
if(item.isKnown(idef))
|
||||
m_infotext = item.getDefinition(idef).description;
|
||||
else
|
||||
m_infotext = "Unknown item: '" + m_itemstring + "'";
|
||||
if(item.count >= 2)
|
||||
m_infotext += " (" + itos(item.count) + ")";
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
m_infotext = "Unknown item: '" + m_itemstring + "'";
|
||||
}
|
||||
}
|
||||
|
||||
void ItemCAO::updateTexture()
|
||||
{
|
||||
if(m_node == NULL)
|
||||
return;
|
||||
|
||||
// Create an inventory item to see what is its image
|
||||
std::istringstream is(m_itemstring, std::ios_base::binary);
|
||||
video::ITexture *texture = NULL;
|
||||
try{
|
||||
IItemDefManager *idef = m_gamedef->idef();
|
||||
ItemStack item;
|
||||
item.deSerialize(is, idef);
|
||||
texture = item.getDefinition(idef).inventory_texture;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<"WARNING: "<<__FUNCTION_NAME
|
||||
<<": error deSerializing itemstring \""
|
||||
<<m_itemstring<<std::endl;
|
||||
}
|
||||
|
||||
// Set meshbuffer texture
|
||||
m_node->getMaterial(0).setTexture(0, texture);
|
||||
}
|
||||
|
||||
|
||||
void ItemCAO::step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
if(m_node)
|
||||
@ -689,6 +711,13 @@ void ItemCAO::processMessage(const std::string &data)
|
||||
m_position = readV3F1000(is);
|
||||
updateNodePos();
|
||||
}
|
||||
if(cmd == 1)
|
||||
{
|
||||
// itemstring
|
||||
m_itemstring = deSerializeString(is);
|
||||
updateInfoText();
|
||||
updateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemCAO::initialize(const std::string &data)
|
||||
@ -704,28 +733,12 @@ void ItemCAO::initialize(const std::string &data)
|
||||
return;
|
||||
// pos
|
||||
m_position = readV3F1000(is);
|
||||
// inventorystring
|
||||
m_inventorystring = deSerializeString(is);
|
||||
// itemstring
|
||||
m_itemstring = deSerializeString(is);
|
||||
}
|
||||
|
||||
updateNodePos();
|
||||
|
||||
/*
|
||||
Set infotext to item name if item cannot be deserialized
|
||||
*/
|
||||
try{
|
||||
InventoryItem *item = NULL;
|
||||
item = InventoryItem::deSerialize(m_inventorystring, m_gamedef);
|
||||
if(item){
|
||||
if(!item->isKnown())
|
||||
m_infotext = "Unknown item: '" + m_inventorystring + "'";
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
m_infotext = "Unknown item: '" + m_inventorystring + "'";
|
||||
}
|
||||
updateInfoText();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -20,112 +20,105 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_mapblock.h"
|
||||
|
||||
#include "main.h" // For g_settings
|
||||
#include "mineral.h"
|
||||
#include "mapblock_mesh.h" // For MapBlock_LightColor()
|
||||
#include "mapblock_mesh.h" // For MapBlock_LightColor() and MeshCollector
|
||||
#include "settings.h"
|
||||
#include "nodedef.h"
|
||||
#include "tile.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
#ifndef SERVER
|
||||
// Create a cuboid.
|
||||
// material - the material to use (for all 6 faces)
|
||||
// collector - the MeshCollector for the resulting polygons
|
||||
// pa - texture atlas pointer for the material
|
||||
// box - the position and size of the box
|
||||
// materials - the materials to use (for all 6 faces)
|
||||
// pa - texture atlas pointers for the materials
|
||||
// matcount - number of entries in "materials" and "pa", 1<=matcount<=6
|
||||
// c - vertex colour - used for all
|
||||
// pos - the position of the centre of the cuboid
|
||||
// rz,ry,rz - the radius of the cuboid in each dimension
|
||||
// txc - texture coordinates - this is a list of texture coordinates
|
||||
// for the opposite corners of each face - therefore, there
|
||||
// should be (2+2)*6=24 values in the list. Alternatively, pass
|
||||
// NULL to use the entire texture for each face. The order of
|
||||
// the faces in the list is top-backi-right-front-left-bottom
|
||||
// If you specified 0,0,1,1 for each face, that would be the
|
||||
// same as passing NULL.
|
||||
void makeCuboid(video::SMaterial &material, MeshCollector *collector,
|
||||
AtlasPointer* pa, video::SColor &c,
|
||||
v3f &pos, f32 rx, f32 ry, f32 rz, f32* txc)
|
||||
// the faces in the list is up-down-right-left-back-front
|
||||
// (compatible with ContentFeatures). If you specified 0,0,1,1
|
||||
// for each face, that would be the same as passing NULL.
|
||||
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||
const video::SMaterial *materials, const AtlasPointer *pa, int matcount,
|
||||
video::SColor &c, const f32* txc)
|
||||
{
|
||||
f32 tu0=pa->x0();
|
||||
f32 tu1=pa->x1();
|
||||
f32 tv0=pa->y0();
|
||||
f32 tv1=pa->y1();
|
||||
f32 txus=tu1-tu0;
|
||||
f32 txvs=tv1-tv0;
|
||||
assert(matcount >= 1);
|
||||
|
||||
video::S3DVertex v[4] =
|
||||
v3f min = box.MinEdge;
|
||||
v3f max = box.MaxEdge;
|
||||
|
||||
if(txc == NULL)
|
||||
{
|
||||
video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv1),
|
||||
video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv1),
|
||||
video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv0),
|
||||
video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv0)
|
||||
};
|
||||
|
||||
for(int i=0;i<6;i++)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: // top
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 1: // back
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 2: //right
|
||||
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
|
||||
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
case 3: // front
|
||||
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
|
||||
break;
|
||||
case 4: // left
|
||||
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
|
||||
break;
|
||||
case 5: // bottom
|
||||
v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
|
||||
v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
|
||||
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
|
||||
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
|
||||
break;
|
||||
}
|
||||
|
||||
if(txc!=NULL)
|
||||
{
|
||||
v[0].TCoords.X=tu0+txus*txc[0]; v[0].TCoords.Y=tv0+txvs*txc[3];
|
||||
v[1].TCoords.X=tu0+txus*txc[2]; v[1].TCoords.Y=tv0+txvs*txc[3];
|
||||
v[2].TCoords.X=tu0+txus*txc[2]; v[2].TCoords.Y=tv0+txvs*txc[1];
|
||||
v[3].TCoords.X=tu0+txus*txc[0]; v[3].TCoords.Y=tv0+txvs*txc[1];
|
||||
txc+=4;
|
||||
}
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
v[i].Pos += pos;
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
collector->append(material, v, 4, indices, 6);
|
||||
|
||||
static const f32 txc_default[24] = {
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1
|
||||
};
|
||||
txc = txc_default;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// up
|
||||
video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
|
||||
video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
|
||||
video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
|
||||
video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
|
||||
// down
|
||||
video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
|
||||
video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
|
||||
video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
|
||||
video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
|
||||
// right
|
||||
video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
|
||||
video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
|
||||
video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
|
||||
video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
|
||||
// left
|
||||
video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
|
||||
video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
|
||||
video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
|
||||
video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
|
||||
// back
|
||||
video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[16],txc[17]),
|
||||
video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[18],txc[17]),
|
||||
video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[18],txc[19]),
|
||||
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[16],txc[19]),
|
||||
// front
|
||||
video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[20],txc[21]),
|
||||
video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[22],txc[21]),
|
||||
video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[22],txc[23]),
|
||||
video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[20],txc[23]),
|
||||
};
|
||||
|
||||
for(s32 j=0; j<24; j++)
|
||||
{
|
||||
int matindex = MYMIN(j/4, matcount-1);
|
||||
vertices[j].TCoords *= pa[matindex].size;
|
||||
vertices[j].TCoords += pa[matindex].pos;
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
|
||||
// Add to mesh collector
|
||||
for(s32 j=0; j<24; j+=4)
|
||||
{
|
||||
int matindex = MYMIN(j/4, matcount-1);
|
||||
collector->append(materials[matindex],
|
||||
vertices+j, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
MeshCollector &collector, IGameDef *gamedef)
|
||||
{
|
||||
INodeDefManager *nodedef = gamedef->ndef();
|
||||
ITextureSource *tsrc = gamedef->getTextureSource();
|
||||
|
||||
// 0ms
|
||||
//TimeTaker timer("mapblock_mesh_generate_special()");
|
||||
@ -521,7 +514,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
material_glass.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_glass.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
AtlasPointer pa_glass = f.tiles[0].texture;
|
||||
TileSpec tile_glass = getNodeTile(n, p, v3s16(0,0,0),
|
||||
&data->m_temp_mods, tsrc, nodedef);
|
||||
AtlasPointer pa_glass = tile_glass.texture;
|
||||
material_glass.setTexture(0, pa_glass.atlas);
|
||||
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
|
||||
@ -585,54 +580,21 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
AtlasPointer pa_leaves1 = f.tiles[0].texture;
|
||||
TileSpec tile_leaves1 = getNodeTile(n, p, v3s16(0,0,0),
|
||||
&data->m_temp_mods, tsrc, nodedef);
|
||||
AtlasPointer pa_leaves1 = tile_leaves1.texture;
|
||||
material_leaves1.setTexture(0, pa_leaves1.atlas);
|
||||
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
for(u32 j=0; j<6; j++)
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
pa_leaves1.x0(), pa_leaves1.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
pa_leaves1.x1(), pa_leaves1.y1()),
|
||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
|
||||
pa_leaves1.x1(), pa_leaves1.y0()),
|
||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
|
||||
pa_leaves1.x0(), pa_leaves1.y0()),
|
||||
};
|
||||
|
||||
// Rotations in the g_6dirs format
|
||||
if(j == 0) // Z+
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(0);
|
||||
else if(j == 1) // Y+
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateYZBy(-90);
|
||||
else if(j == 2) // X+
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-90);
|
||||
else if(j == 3) // Z-
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(180);
|
||||
else if(j == 4) // Y-
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateYZBy(90);
|
||||
else if(j == 5) // X-
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(90);
|
||||
|
||||
for(u16 i=0; i<4; i++){
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material_leaves1, vertices, 4, indices, 6);
|
||||
}
|
||||
v3f pos = intToFloat(p+blockpos_nodes, BS);
|
||||
aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
makeCuboid(&collector, box,
|
||||
&material_leaves1, &pa_leaves1, 1,
|
||||
c, NULL);
|
||||
break;}
|
||||
case NDT_ALLFACES_OPTIONAL:
|
||||
// This is always pre-converted to something else
|
||||
@ -824,9 +786,22 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
material_wood.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_wood.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_wood.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
AtlasPointer pa_wood = f.tiles[0].texture;
|
||||
TileSpec tile_wood = getNodeTile(n, p, v3s16(0,0,0),
|
||||
&data->m_temp_mods, tsrc, nodedef);
|
||||
AtlasPointer pa_wood = tile_wood.texture;
|
||||
material_wood.setTexture(0, pa_wood.atlas);
|
||||
|
||||
video::SMaterial material_wood_nomod;
|
||||
material_wood_nomod.setFlag(video::EMF_LIGHTING, false);
|
||||
material_wood_nomod.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_wood_nomod.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_wood_nomod.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
TileSpec tile_wood_nomod = getNodeTile(n, p, v3s16(0,0,0),
|
||||
NULL, tsrc, nodedef);
|
||||
AtlasPointer pa_wood_nomod = tile_wood_nomod.texture;
|
||||
material_wood_nomod.setTexture(0, pa_wood_nomod.atlas);
|
||||
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
@ -834,18 +809,21 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
const f32 bar_rad=(f32)BS/20;
|
||||
const f32 bar_len=(f32)(BS/2)-post_rad;
|
||||
|
||||
// The post - always present
|
||||
v3f pos = intToFloat(p+blockpos_nodes, BS);
|
||||
|
||||
// The post - always present
|
||||
aabb3f post(-post_rad,-BS/2,-post_rad,post_rad,BS/2,post_rad);
|
||||
post.MinEdge += pos;
|
||||
post.MaxEdge += pos;
|
||||
f32 postuv[24]={
|
||||
0.4,0.4,0.6,0.6,
|
||||
0.4,0.4,0.6,0.6,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1,
|
||||
0.35,0,0.65,1,
|
||||
0.4,0.4,0.6,0.6};
|
||||
makeCuboid(material_wood, &collector,
|
||||
&pa_wood, c, pos,
|
||||
post_rad,BS/2,post_rad, postuv);
|
||||
0.35,0,0.65,1};
|
||||
makeCuboid(&collector, post, &material_wood,
|
||||
&pa_wood, 1, c, postuv);
|
||||
|
||||
// Now a section of fence, +X, if there's a post there
|
||||
v3s16 p2 = p;
|
||||
@ -854,9 +832,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
const ContentFeatures *f2 = &nodedef->get(n2);
|
||||
if(f2->drawtype == NDT_FENCELIKE)
|
||||
{
|
||||
pos = intToFloat(p+blockpos_nodes, BS);
|
||||
pos.X += BS/2;
|
||||
pos.Y += BS/4;
|
||||
aabb3f bar(-bar_len+BS/2,-bar_rad+BS/4,-bar_rad,
|
||||
bar_len+BS/2,bar_rad+BS/4,bar_rad);
|
||||
bar.MinEdge += pos;
|
||||
bar.MaxEdge += pos;
|
||||
f32 xrailuv[24]={
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
@ -864,14 +843,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6};
|
||||
makeCuboid(material_wood, &collector,
|
||||
&pa_wood, c, pos,
|
||||
bar_len,bar_rad,bar_rad, xrailuv);
|
||||
|
||||
pos.Y -= BS/2;
|
||||
makeCuboid(material_wood, &collector,
|
||||
&pa_wood, c, pos,
|
||||
bar_len,bar_rad,bar_rad, xrailuv);
|
||||
makeCuboid(&collector, bar, &material_wood_nomod,
|
||||
&pa_wood_nomod, 1, c, xrailuv);
|
||||
bar.MinEdge.Y -= BS/2;
|
||||
bar.MaxEdge.Y -= BS/2;
|
||||
makeCuboid(&collector, bar, &material_wood_nomod,
|
||||
&pa_wood_nomod, 1, c, xrailuv);
|
||||
}
|
||||
|
||||
// Now a section of fence, +Z, if there's a post there
|
||||
@ -881,9 +858,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
f2 = &nodedef->get(n2);
|
||||
if(f2->drawtype == NDT_FENCELIKE)
|
||||
{
|
||||
pos = intToFloat(p+blockpos_nodes, BS);
|
||||
pos.Z += BS/2;
|
||||
pos.Y += BS/4;
|
||||
aabb3f bar(-bar_rad,-bar_rad+BS/4,-bar_len+BS/2,
|
||||
bar_rad,bar_rad+BS/4,bar_len+BS/2);
|
||||
bar.MinEdge += pos;
|
||||
bar.MaxEdge += pos;
|
||||
f32 zrailuv[24]={
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
@ -891,14 +869,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6,
|
||||
0,0.4,1,0.6};
|
||||
makeCuboid(material_wood, &collector,
|
||||
&pa_wood, c, pos,
|
||||
bar_rad,bar_rad,bar_len, zrailuv);
|
||||
pos.Y -= BS/2;
|
||||
makeCuboid(material_wood, &collector,
|
||||
&pa_wood, c, pos,
|
||||
bar_rad,bar_rad,bar_len, zrailuv);
|
||||
|
||||
makeCuboid(&collector, bar, &material_wood_nomod,
|
||||
&pa_wood_nomod, 1, c, zrailuv);
|
||||
bar.MinEdge.Y -= BS/2;
|
||||
bar.MaxEdge.Y -= BS/2;
|
||||
makeCuboid(&collector, bar, &material_wood_nomod,
|
||||
&pa_wood_nomod, 1, c, zrailuv);
|
||||
}
|
||||
break;}
|
||||
case NDT_RAILLIKE:
|
||||
@ -1011,5 +988,4 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -26,75 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nameidmapping.h"
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
Legacy node definitions
|
||||
*/
|
||||
|
||||
#define WATER_ALPHA 160
|
||||
|
||||
#define WATER_VISC 1
|
||||
#define LAVA_VISC 7
|
||||
|
||||
void setConstantMaterialProperties(MaterialProperties &mprop, float time)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_CONSTANT;
|
||||
mprop.constant_time = time;
|
||||
}
|
||||
|
||||
void setStoneLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = 5.0 * toughness;
|
||||
mprop.crackiness = 1.0;
|
||||
mprop.crumbliness = -0.1;
|
||||
mprop.cuttability = -0.2;
|
||||
}
|
||||
|
||||
void setDirtLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = toughness * 1.2;
|
||||
mprop.crackiness = 0;
|
||||
mprop.crumbliness = 1.2;
|
||||
mprop.cuttability = -0.4;
|
||||
}
|
||||
|
||||
void setGravelLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = toughness * 2.0;
|
||||
mprop.crackiness = 0.2;
|
||||
mprop.crumbliness = 1.5;
|
||||
mprop.cuttability = -1.0;
|
||||
}
|
||||
|
||||
void setWoodLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = toughness * 1.0;
|
||||
mprop.crackiness = 0.75;
|
||||
mprop.crumbliness = -1.0;
|
||||
mprop.cuttability = 1.5;
|
||||
}
|
||||
|
||||
void setLeavesLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = -0.5 * toughness;
|
||||
mprop.crackiness = 0;
|
||||
mprop.crumbliness = 0;
|
||||
mprop.cuttability = 2.0;
|
||||
}
|
||||
|
||||
void setGlassLikeMaterialProperties(MaterialProperties &mprop, float toughness)
|
||||
{
|
||||
mprop.diggability = DIGGABLE_NORMAL;
|
||||
mprop.weight = 0.1 * toughness;
|
||||
mprop.crackiness = 2.0;
|
||||
mprop.crumbliness = -1.0;
|
||||
mprop.cuttability = -1.0;
|
||||
}
|
||||
|
||||
/*
|
||||
Legacy node content type IDs
|
||||
Ranges:
|
||||
@ -209,46 +140,46 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
|
||||
|
||||
void content_mapnode_get_name_id_mapping(NameIdMapping *nimap)
|
||||
{
|
||||
nimap->set(0, "stone");
|
||||
nimap->set(2, "water_flowing");
|
||||
nimap->set(3, "torch");
|
||||
nimap->set(9, "water_source");
|
||||
nimap->set(14, "sign_wall");
|
||||
nimap->set(15, "chest");
|
||||
nimap->set(16, "furnace");
|
||||
nimap->set(17, "locked_chest");
|
||||
nimap->set(21, "wooden_fence");
|
||||
nimap->set(30, "rail");
|
||||
nimap->set(31, "ladder");
|
||||
nimap->set(32, "lava_flowing");
|
||||
nimap->set(33, "lava_source");
|
||||
nimap->set(0x800, "dirt_with_grass");
|
||||
nimap->set(0x801, "tree");
|
||||
nimap->set(0x802, "leaves");
|
||||
nimap->set(0x803, "dirt_with_grass_footsteps");
|
||||
nimap->set(0x804, "mese");
|
||||
nimap->set(0x805, "dirt");
|
||||
nimap->set(0x806, "cloud");
|
||||
nimap->set(0x807, "coalstone");
|
||||
nimap->set(0x808, "wood");
|
||||
nimap->set(0x809, "sand");
|
||||
nimap->set(0x80a, "cobble");
|
||||
nimap->set(0x80b, "steel");
|
||||
nimap->set(0x80c, "glass");
|
||||
nimap->set(0x80d, "mossycobble");
|
||||
nimap->set(0x80e, "gravel");
|
||||
nimap->set(0x80f, "sandstone");
|
||||
nimap->set(0x810, "cactus");
|
||||
nimap->set(0x811, "brick");
|
||||
nimap->set(0x812, "clay");
|
||||
nimap->set(0x813, "papyrus");
|
||||
nimap->set(0x814, "bookshelf");
|
||||
nimap->set(0x815, "jungletree");
|
||||
nimap->set(0x816, "junglegrass");
|
||||
nimap->set(0x817, "nyancat");
|
||||
nimap->set(0x818, "nyancat_rainbow");
|
||||
nimap->set(0x819, "apple");
|
||||
nimap->set(0x820, "sapling");
|
||||
nimap->set(0, "default:stone");
|
||||
nimap->set(2, "default:water_flowing");
|
||||
nimap->set(3, "default:torch");
|
||||
nimap->set(9, "default:water_source");
|
||||
nimap->set(14, "default:sign_wall");
|
||||
nimap->set(15, "default:chest");
|
||||
nimap->set(16, "default:furnace");
|
||||
nimap->set(17, "default:chest_locked");
|
||||
nimap->set(21, "default:fence_wood");
|
||||
nimap->set(30, "default:rail");
|
||||
nimap->set(31, "default:ladder");
|
||||
nimap->set(32, "default:lava_flowing");
|
||||
nimap->set(33, "default:lava_source");
|
||||
nimap->set(0x800, "default:dirt_with_grass");
|
||||
nimap->set(0x801, "default:tree");
|
||||
nimap->set(0x802, "default:leaves");
|
||||
nimap->set(0x803, "default:dirt_with_grass_footsteps");
|
||||
nimap->set(0x804, "default:mese");
|
||||
nimap->set(0x805, "default:dirt");
|
||||
nimap->set(0x806, "default:cloud");
|
||||
nimap->set(0x807, "default:coalstone");
|
||||
nimap->set(0x808, "default:wood");
|
||||
nimap->set(0x809, "default:sand");
|
||||
nimap->set(0x80a, "default:cobble");
|
||||
nimap->set(0x80b, "default:steelblock");
|
||||
nimap->set(0x80c, "default:glass");
|
||||
nimap->set(0x80d, "default:mossycobble");
|
||||
nimap->set(0x80e, "default:gravel");
|
||||
nimap->set(0x80f, "default:sandstone");
|
||||
nimap->set(0x810, "default:cactus");
|
||||
nimap->set(0x811, "default:brick");
|
||||
nimap->set(0x812, "default:clay");
|
||||
nimap->set(0x813, "default:papyrus");
|
||||
nimap->set(0x814, "default:bookshelf");
|
||||
nimap->set(0x815, "default:jungletree");
|
||||
nimap->set(0x816, "default:junglegrass");
|
||||
nimap->set(0x817, "default:nyancat");
|
||||
nimap->set(0x818, "default:nyancat_rainbow");
|
||||
nimap->set(0x819, "default:apple");
|
||||
nimap->set(0x820, "default:sapling");
|
||||
// Static types
|
||||
nimap->set(CONTENT_IGNORE, "ignore");
|
||||
nimap->set(CONTENT_AIR, "air");
|
||||
@ -259,46 +190,46 @@ class NewNameGetter
|
||||
public:
|
||||
NewNameGetter()
|
||||
{
|
||||
old_to_new["CONTENT_STONE"] = "stone";
|
||||
old_to_new["CONTENT_WATER"] = "water_flowing";
|
||||
old_to_new["CONTENT_TORCH"] = "torch";
|
||||
old_to_new["CONTENT_WATERSOURCE"] = "water_source";
|
||||
old_to_new["CONTENT_SIGN_WALL"] = "sign_wall";
|
||||
old_to_new["CONTENT_CHEST"] = "chest";
|
||||
old_to_new["CONTENT_FURNACE"] = "furnace";
|
||||
old_to_new["CONTENT_LOCKABLE_CHEST"] = "locked_chest";
|
||||
old_to_new["CONTENT_FENCE"] = "wooden_fence";
|
||||
old_to_new["CONTENT_RAIL"] = "rail";
|
||||
old_to_new["CONTENT_LADDER"] = "ladder";
|
||||
old_to_new["CONTENT_LAVA"] = "lava_flowing";
|
||||
old_to_new["CONTENT_LAVASOURCE"] = "lava_source";
|
||||
old_to_new["CONTENT_GRASS"] = "dirt_with_grass";
|
||||
old_to_new["CONTENT_TREE"] = "tree";
|
||||
old_to_new["CONTENT_LEAVES"] = "leaves";
|
||||
old_to_new["CONTENT_GRASS_FOOTSTEPS"] = "dirt_with_grass_footsteps";
|
||||
old_to_new["CONTENT_MESE"] = "mese";
|
||||
old_to_new["CONTENT_MUD"] = "dirt";
|
||||
old_to_new["CONTENT_CLOUD"] = "cloud";
|
||||
old_to_new["CONTENT_COALSTONE"] = "coalstone";
|
||||
old_to_new["CONTENT_WOOD"] = "wood";
|
||||
old_to_new["CONTENT_SAND"] = "sand";
|
||||
old_to_new["CONTENT_COBBLE"] = "cobble";
|
||||
old_to_new["CONTENT_STEEL"] = "steel";
|
||||
old_to_new["CONTENT_GLASS"] = "glass";
|
||||
old_to_new["CONTENT_MOSSYCOBBLE"] = "mossycobble";
|
||||
old_to_new["CONTENT_GRAVEL"] = "gravel";
|
||||
old_to_new["CONTENT_SANDSTONE"] = "sandstone";
|
||||
old_to_new["CONTENT_CACTUS"] = "cactus";
|
||||
old_to_new["CONTENT_BRICK"] = "brick";
|
||||
old_to_new["CONTENT_CLAY"] = "clay";
|
||||
old_to_new["CONTENT_PAPYRUS"] = "papyrus";
|
||||
old_to_new["CONTENT_BOOKSHELF"] = "bookshelf";
|
||||
old_to_new["CONTENT_JUNGLETREE"] = "jungletree";
|
||||
old_to_new["CONTENT_JUNGLEGRASS"] = "junglegrass";
|
||||
old_to_new["CONTENT_NC"] = "nyancat";
|
||||
old_to_new["CONTENT_NC_RB"] = "nyancat_rainbow";
|
||||
old_to_new["CONTENT_APPLE"] = "apple";
|
||||
old_to_new["CONTENT_SAPLING"] = "sapling";
|
||||
old_to_new["CONTENT_STONE"] = "default:stone";
|
||||
old_to_new["CONTENT_WATER"] = "default:water_flowing";
|
||||
old_to_new["CONTENT_TORCH"] = "default:torch";
|
||||
old_to_new["CONTENT_WATERSOURCE"] = "default:water_source";
|
||||
old_to_new["CONTENT_SIGN_WALL"] = "default:sign_wall";
|
||||
old_to_new["CONTENT_CHEST"] = "default:chest";
|
||||
old_to_new["CONTENT_FURNACE"] = "default:furnace";
|
||||
old_to_new["CONTENT_LOCKABLE_CHEST"] = "default:locked_chest";
|
||||
old_to_new["CONTENT_FENCE"] = "default:wooden_fence";
|
||||
old_to_new["CONTENT_RAIL"] = "default:rail";
|
||||
old_to_new["CONTENT_LADDER"] = "default:ladder";
|
||||
old_to_new["CONTENT_LAVA"] = "default:lava_flowing";
|
||||
old_to_new["CONTENT_LAVASOURCE"] = "default:lava_source";
|
||||
old_to_new["CONTENT_GRASS"] = "default:dirt_with_grass";
|
||||
old_to_new["CONTENT_TREE"] = "default:tree";
|
||||
old_to_new["CONTENT_LEAVES"] = "default:leaves";
|
||||
old_to_new["CONTENT_GRASS_FOOTSTEPS"] = "default:dirt_with_grass_footsteps";
|
||||
old_to_new["CONTENT_MESE"] = "default:mese";
|
||||
old_to_new["CONTENT_MUD"] = "default:dirt";
|
||||
old_to_new["CONTENT_CLOUD"] = "default:cloud";
|
||||
old_to_new["CONTENT_COALSTONE"] = "default:coalstone";
|
||||
old_to_new["CONTENT_WOOD"] = "default:wood";
|
||||
old_to_new["CONTENT_SAND"] = "default:sand";
|
||||
old_to_new["CONTENT_COBBLE"] = "default:cobble";
|
||||
old_to_new["CONTENT_STEEL"] = "default:steel";
|
||||
old_to_new["CONTENT_GLASS"] = "default:glass";
|
||||
old_to_new["CONTENT_MOSSYCOBBLE"] = "default:mossycobble";
|
||||
old_to_new["CONTENT_GRAVEL"] = "default:gravel";
|
||||
old_to_new["CONTENT_SANDSTONE"] = "default:sandstone";
|
||||
old_to_new["CONTENT_CACTUS"] = "default:cactus";
|
||||
old_to_new["CONTENT_BRICK"] = "default:brick";
|
||||
old_to_new["CONTENT_CLAY"] = "default:clay";
|
||||
old_to_new["CONTENT_PAPYRUS"] = "default:papyrus";
|
||||
old_to_new["CONTENT_BOOKSHELF"] = "default:bookshelf";
|
||||
old_to_new["CONTENT_JUNGLETREE"] = "default:jungletree";
|
||||
old_to_new["CONTENT_JUNGLEGRASS"] = "default:junglegrass";
|
||||
old_to_new["CONTENT_NC"] = "default:nyancat";
|
||||
old_to_new["CONTENT_NC_RB"] = "default:nyancat_rainbow";
|
||||
old_to_new["CONTENT_APPLE"] = "default:apple";
|
||||
old_to_new["CONTENT_SAPLING"] = "default:sapling";
|
||||
// Just in case
|
||||
old_to_new["CONTENT_IGNORE"] = "ignore";
|
||||
old_to_new["CONTENT_AIR"] = "air";
|
||||
@ -334,605 +265,3 @@ content_t legacy_get_id(const std::string &oldname, INodeDefManager *ndef)
|
||||
return id;
|
||||
}
|
||||
|
||||
// Initialize default (legacy) node definitions
|
||||
void content_mapnode_init(IWritableNodeDefManager *nodemgr)
|
||||
{
|
||||
content_t i;
|
||||
ContentFeatures f;
|
||||
|
||||
i = CONTENT_STONE;
|
||||
f = ContentFeatures();
|
||||
f.name = "stone";
|
||||
f.setAllTextures("stone.png");
|
||||
f.setInventoryTextureCube("stone.png", "stone.png", "stone.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.often_contains_mineral = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_GRASS;
|
||||
f = ContentFeatures();
|
||||
f.name = "dirt_with_grass";
|
||||
f.setAllTextures("mud.png^grass_side.png");
|
||||
f.setTexture(0, "grass.png");
|
||||
f.setTexture(1, "mud.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_GRASS_FOOTSTEPS;
|
||||
f = ContentFeatures();
|
||||
f.name = "dirt_with_grass_footsteps";
|
||||
f.setAllTextures("mud.png^grass_side.png");
|
||||
f.setTexture(0, "grass_footsteps.png");
|
||||
f.setTexture(1, "mud.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_MUD;
|
||||
f = ContentFeatures();
|
||||
f.name = "dirt";
|
||||
f.setAllTextures("mud.png");
|
||||
f.setInventoryTextureCube("mud.png", "mud.png", "mud.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_SAND;
|
||||
f = ContentFeatures();
|
||||
f.name = "sand";
|
||||
f.setAllTextures("sand.png");
|
||||
f.setInventoryTextureCube("sand.png", "sand.png", "sand.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_GLASS)+" 1";
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_GRAVEL;
|
||||
f = ContentFeatures();
|
||||
f.name = "gravel";
|
||||
f.setAllTextures("gravel.png");
|
||||
f.setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setGravelLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_SANDSTONE;
|
||||
f = ContentFeatures();
|
||||
f.name = "sandstone";
|
||||
f.setAllTextures("sandstone.png");
|
||||
f.setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 1";
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_CLAY;
|
||||
f = ContentFeatures();
|
||||
f.name = "clay";
|
||||
f.setAllTextures("clay.png");
|
||||
f.setInventoryTextureCube("clay.png", "clay.png", "clay.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("CraftItem lump_of_clay 4");
|
||||
setDirtLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_BRICK;
|
||||
f = ContentFeatures();
|
||||
f.name = "brick";
|
||||
f.setAllTextures("brick.png");
|
||||
f.setInventoryTextureCube("brick.png", "brick.png", "brick.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("CraftItem clay_brick 4");
|
||||
setStoneLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_TREE;
|
||||
f = ContentFeatures();
|
||||
f.name = "tree";
|
||||
f.setAllTextures("tree.png");
|
||||
f.setTexture(0, "tree_top.png");
|
||||
f.setTexture(1, "tree_top.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.cookresult_item = "CraftItem lump_of_coal 1";
|
||||
f.furnace_burntime = 30;
|
||||
setWoodLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_JUNGLETREE;
|
||||
f = ContentFeatures();
|
||||
f.name = "jungletree";
|
||||
f.setAllTextures("jungletree.png");
|
||||
f.setTexture(0, "jungletree_top.png");
|
||||
f.setTexture(1, "jungletree_top.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.furnace_burntime = 30;
|
||||
setWoodLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_JUNGLEGRASS;
|
||||
f = ContentFeatures();
|
||||
f.name = "junglegrass";
|
||||
f.drawtype = NDT_PLANTLIKE;
|
||||
f.visual_scale = 1.3;
|
||||
f.setAllTextures("junglegrass.png");
|
||||
f.setInventoryTexture("junglegrass.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.walkable = false;
|
||||
setLeavesLikeMaterialProperties(f.material, 1.0);
|
||||
f.furnace_burntime = 2;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_LEAVES;
|
||||
f = ContentFeatures();
|
||||
f.name = "leaves";
|
||||
f.drawtype = NDT_ALLFACES_OPTIONAL;
|
||||
f.setAllTextures("leaves.png");
|
||||
//f.setAllTextures("[noalpha:leaves.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
|
||||
f.extra_dug_item_rarity = 20;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setLeavesLikeMaterialProperties(f.material, 1.0);
|
||||
f.furnace_burntime = 1.0;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_CACTUS;
|
||||
f = ContentFeatures();
|
||||
f.name = "cactus";
|
||||
f.setAllTextures("cactus_side.png");
|
||||
f.setTexture(0, "cactus_top.png");
|
||||
f.setTexture(1, "cactus_top.png");
|
||||
f.setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setWoodLikeMaterialProperties(f.material, 0.75);
|
||||
f.furnace_burntime = 15;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_PAPYRUS;
|
||||
f = ContentFeatures();
|
||||
f.name = "papyrus";
|
||||
f.drawtype = NDT_PLANTLIKE;
|
||||
f.setAllTextures("papyrus.png");
|
||||
f.setInventoryTexture("papyrus.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.walkable = false;
|
||||
setLeavesLikeMaterialProperties(f.material, 0.5);
|
||||
f.furnace_burntime = 1;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_BOOKSHELF;
|
||||
f = ContentFeatures();
|
||||
f.name = "bookshelf";
|
||||
f.setAllTextures("bookshelf.png");
|
||||
f.setTexture(0, "wood.png");
|
||||
f.setTexture(1, "wood.png");
|
||||
// FIXME: setInventoryTextureCube() only cares for the first texture
|
||||
f.setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
|
||||
//f.setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
setWoodLikeMaterialProperties(f.material, 0.75);
|
||||
f.furnace_burntime = 30;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_GLASS;
|
||||
f = ContentFeatures();
|
||||
f.name = "glass";
|
||||
f.drawtype = NDT_GLASSLIKE;
|
||||
f.setAllTextures("glass.png");
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.setInventoryTextureCube("glass.png", "glass.png", "glass.png");
|
||||
setGlassLikeMaterialProperties(f.material, 1.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_FENCE;
|
||||
f = ContentFeatures();
|
||||
f.name = "wooden_fence";
|
||||
f.drawtype = NDT_FENCELIKE;
|
||||
f.setInventoryTexture("fence.png");
|
||||
f.setTexture(0, "wood.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.selection_box.type = NODEBOX_FIXED;
|
||||
f.selection_box.fixed = core::aabbox3d<f32>(
|
||||
-BS/7, -BS/2, -BS/7, BS/7, BS/2, BS/7);
|
||||
f.furnace_burntime = 30/2;
|
||||
setWoodLikeMaterialProperties(f.material, 0.75);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_RAIL;
|
||||
f = ContentFeatures();
|
||||
f.name = "rail";
|
||||
f.drawtype = NDT_RAILLIKE;
|
||||
f.setInventoryTexture("rail.png");
|
||||
f.setTexture(0, "rail.png");
|
||||
f.setTexture(1, "rail_curved.png");
|
||||
f.setTexture(2, "rail_t_junction.png");
|
||||
f.setTexture(3, "rail_crossing.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.walkable = false;
|
||||
f.selection_box.type = NODEBOX_FIXED;
|
||||
f.furnace_burntime = 5;
|
||||
setDirtLikeMaterialProperties(f.material, 0.75);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_LADDER;
|
||||
f = ContentFeatures();
|
||||
f.name = "ladder";
|
||||
f.drawtype = NDT_SIGNLIKE;
|
||||
f.setAllTextures("ladder.png");
|
||||
f.setInventoryTexture("ladder.png");
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
f.wall_mounted = true;
|
||||
f.walkable = false;
|
||||
f.climbable = true;
|
||||
f.selection_box.type = NODEBOX_WALLMOUNTED;
|
||||
f.furnace_burntime = 5;
|
||||
setWoodLikeMaterialProperties(f.material, 0.5);
|
||||
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_COALSTONE;
|
||||
f = ContentFeatures();
|
||||
f.name = "coalstone";
|
||||
f.setAllTextures("stone.png^mineral_coal.png");
|
||||
f.is_ground_content = true;
|
||||
setStoneLikeMaterialProperties(f.material, 1.5);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_WOOD;
|
||||
f = ContentFeatures();
|
||||
f.name = "wood";
|
||||
f.setAllTextures("wood.png");
|
||||
f.setInventoryTextureCube("wood.png", "wood.png", "wood.png");
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.furnace_burntime = 30/4;
|
||||
setWoodLikeMaterialProperties(f.material, 0.75);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_MESE;
|
||||
f = ContentFeatures();
|
||||
f.name = "mese";
|
||||
f.setAllTextures("mese.png");
|
||||
f.setInventoryTextureCube("mese.png", "mese.png", "mese.png");
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.furnace_burntime = 30;
|
||||
setStoneLikeMaterialProperties(f.material, 0.5);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_CLOUD;
|
||||
f = ContentFeatures();
|
||||
f.name = "cloud";
|
||||
f.setAllTextures("cloud.png");
|
||||
f.setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_AIR;
|
||||
f = ContentFeatures();
|
||||
f.name = "air";
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.walkable = false;
|
||||
f.pointable = false;
|
||||
f.diggable = false;
|
||||
f.buildable_to = true;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_WATER;
|
||||
f = ContentFeatures();
|
||||
f.name = "water_flowing";
|
||||
f.drawtype = NDT_FLOWINGLIQUID;
|
||||
f.setAllTextures("water.png");
|
||||
f.alpha = WATER_ALPHA;
|
||||
f.setInventoryTextureCube("water.png", "water.png", "water.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.walkable = false;
|
||||
f.pointable = false;
|
||||
f.diggable = false;
|
||||
f.buildable_to = true;
|
||||
f.liquid_type = LIQUID_FLOWING;
|
||||
f.liquid_alternative_flowing = "water_flowing";
|
||||
f.liquid_alternative_source = "water_source";
|
||||
f.liquid_viscosity = WATER_VISC;
|
||||
f.post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
f.setSpecialMaterial(0, MaterialSpec("water.png", false));
|
||||
f.setSpecialMaterial(1, MaterialSpec("water.png", true));
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_WATERSOURCE;
|
||||
f = ContentFeatures();
|
||||
f.name = "water_source";
|
||||
f.drawtype = NDT_LIQUID;
|
||||
f.setAllTextures("water.png");
|
||||
f.alpha = WATER_ALPHA;
|
||||
f.setInventoryTextureCube("water.png", "water.png", "water.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.walkable = false;
|
||||
f.pointable = false;
|
||||
f.diggable = false;
|
||||
f.buildable_to = true;
|
||||
f.liquid_type = LIQUID_SOURCE;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.liquid_alternative_flowing = "water_flowing";
|
||||
f.liquid_alternative_source = "water_source";
|
||||
f.liquid_viscosity = WATER_VISC;
|
||||
f.post_effect_color = video::SColor(64, 100, 100, 200);
|
||||
// New-style water source material (mostly unused)
|
||||
f.setSpecialMaterial(0, MaterialSpec("water.png", false));
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_LAVA;
|
||||
f = ContentFeatures();
|
||||
f.name = "lava_flowing";
|
||||
f.drawtype = NDT_FLOWINGLIQUID;
|
||||
f.setAllTextures("lava.png");
|
||||
f.setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = false;
|
||||
f.light_source = LIGHT_MAX-1;
|
||||
f.walkable = false;
|
||||
f.pointable = false;
|
||||
f.diggable = false;
|
||||
f.buildable_to = true;
|
||||
f.liquid_type = LIQUID_FLOWING;
|
||||
f.liquid_alternative_flowing = "lava_flowing";
|
||||
f.liquid_alternative_source = "lava_source";
|
||||
f.liquid_viscosity = LAVA_VISC;
|
||||
f.damage_per_second = 4*2;
|
||||
f.post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
f.setSpecialMaterial(0, MaterialSpec("lava.png", false));
|
||||
f.setSpecialMaterial(1, MaterialSpec("lava.png", true));
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_LAVASOURCE;
|
||||
f = ContentFeatures();
|
||||
f.name = "lava_source";
|
||||
f.drawtype = NDT_LIQUID;
|
||||
f.setAllTextures("lava.png");
|
||||
f.setInventoryTextureCube("lava.png", "lava.png", "lava.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = false;
|
||||
f.light_source = LIGHT_MAX-1;
|
||||
f.walkable = false;
|
||||
f.pointable = false;
|
||||
f.diggable = false;
|
||||
f.buildable_to = true;
|
||||
f.liquid_type = LIQUID_SOURCE;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.liquid_alternative_flowing = "lava_flowing";
|
||||
f.liquid_alternative_source = "lava_source";
|
||||
f.liquid_viscosity = LAVA_VISC;
|
||||
f.damage_per_second = 4*2;
|
||||
f.post_effect_color = video::SColor(192, 255, 64, 0);
|
||||
// New-style lava source material (mostly unused)
|
||||
f.setSpecialMaterial(0, MaterialSpec("lava.png", false));
|
||||
f.furnace_burntime = 60;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_TORCH;
|
||||
f = ContentFeatures();
|
||||
f.name = "torch";
|
||||
f.drawtype = NDT_TORCHLIKE;
|
||||
f.setTexture(0, "torch_on_floor.png");
|
||||
f.setTexture(1, "torch_on_ceiling.png");
|
||||
f.setTexture(2, "torch.png");
|
||||
f.setInventoryTexture("torch_on_floor.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.walkable = false;
|
||||
f.wall_mounted = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.light_source = LIGHT_MAX-1;
|
||||
f.selection_box.type = NODEBOX_WALLMOUNTED;
|
||||
f.selection_box.wall_top = core::aabbox3d<f32>(
|
||||
-BS/10, BS/2-BS/3.333*2, -BS/10, BS/10, BS/2, BS/10);
|
||||
f.selection_box.wall_bottom = core::aabbox3d<f32>(
|
||||
-BS/10, -BS/2, -BS/10, BS/10, -BS/2+BS/3.333*2, BS/10);
|
||||
f.selection_box.wall_side = core::aabbox3d<f32>(
|
||||
-BS/2, -BS/3.333, -BS/10, -BS/2+BS/3.333, BS/3.333, BS/10);
|
||||
setConstantMaterialProperties(f.material, 0.0);
|
||||
f.furnace_burntime = 4;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_SIGN_WALL;
|
||||
f = ContentFeatures();
|
||||
f.name = "sign_wall";
|
||||
f.drawtype = NDT_SIGNLIKE;
|
||||
f.setAllTextures("sign_wall.png");
|
||||
f.setInventoryTexture("sign_wall.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.walkable = false;
|
||||
f.wall_mounted = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.metadata_name = "sign";
|
||||
setConstantMaterialProperties(f.material, 0.5);
|
||||
f.selection_box.type = NODEBOX_WALLMOUNTED;
|
||||
f.furnace_burntime = 10;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_CHEST;
|
||||
f = ContentFeatures();
|
||||
f.name = "chest";
|
||||
f.param_type = CPT_FACEDIR_SIMPLE;
|
||||
f.setAllTextures("chest_side.png");
|
||||
f.setTexture(0, "chest_top.png");
|
||||
f.setTexture(1, "chest_top.png");
|
||||
f.setTexture(5, "chest_front.png"); // Z-
|
||||
f.setInventoryTexture("chest_top.png");
|
||||
//f.setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.metadata_name = "chest";
|
||||
setWoodLikeMaterialProperties(f.material, 1.0);
|
||||
f.furnace_burntime = 30;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_LOCKABLE_CHEST;
|
||||
f = ContentFeatures();
|
||||
f.name = "locked_chest";
|
||||
f.param_type = CPT_FACEDIR_SIMPLE;
|
||||
f.setAllTextures("chest_side.png");
|
||||
f.setTexture(0, "chest_top.png");
|
||||
f.setTexture(1, "chest_top.png");
|
||||
f.setTexture(5, "chest_lock.png"); // Z-
|
||||
f.setInventoryTexture("chest_lock.png");
|
||||
//f.setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.metadata_name = "locked_chest";
|
||||
setWoodLikeMaterialProperties(f.material, 1.0);
|
||||
f.furnace_burntime = 30;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_FURNACE;
|
||||
f = ContentFeatures();
|
||||
f.name = "furnace";
|
||||
f.param_type = CPT_FACEDIR_SIMPLE;
|
||||
f.setAllTextures("furnace_side.png");
|
||||
f.setTexture(5, "furnace_front.png"); // Z-
|
||||
f.setInventoryTexture("furnace_front.png");
|
||||
//f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 6";
|
||||
f.metadata_name = "furnace";
|
||||
setStoneLikeMaterialProperties(f.material, 3.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_COBBLE;
|
||||
f = ContentFeatures();
|
||||
f.name = "cobble";
|
||||
f.setAllTextures("cobble.png");
|
||||
f.setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
|
||||
f.param_type = CPT_NONE;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_STONE)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 0.9);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_MOSSYCOBBLE;
|
||||
f = ContentFeatures();
|
||||
f.name = "mossycobble";
|
||||
f.setAllTextures("mossycobble.png");
|
||||
f.setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
|
||||
f.param_type = CPT_NONE;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 0.8);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_STEEL;
|
||||
f = ContentFeatures();
|
||||
f.name = "steelblock";
|
||||
f.setAllTextures("steel_block.png");
|
||||
f.setInventoryTextureCube("steel_block.png", "steel_block.png",
|
||||
"steel_block.png");
|
||||
f.param_type = CPT_NONE;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 5.0);
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_NC;
|
||||
f = ContentFeatures();
|
||||
f.name = "nyancat";
|
||||
f.param_type = CPT_FACEDIR_SIMPLE;
|
||||
f.setAllTextures("nc_side.png");
|
||||
f.setTexture(5, "nc_front.png"); // Z-
|
||||
f.setTexture(4, "nc_back.png"); // Z+
|
||||
f.setInventoryTexture("nc_front.png");
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 3.0);
|
||||
f.furnace_burntime = 1;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_NC_RB;
|
||||
f = ContentFeatures();
|
||||
f.name = "nyancat_rainbow";
|
||||
f.setAllTextures("nc_rb.png");
|
||||
f.setInventoryTexture("nc_rb.png");
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
setStoneLikeMaterialProperties(f.material, 3.0);
|
||||
f.furnace_burntime = 1;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_SAPLING;
|
||||
f = ContentFeatures();
|
||||
f.name = "sapling";
|
||||
f.drawtype = NDT_PLANTLIKE;
|
||||
f.visual_scale = 1.0;
|
||||
f.setAllTextures("sapling.png");
|
||||
f.setInventoryTexture("sapling.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
|
||||
f.light_propagates = true;
|
||||
f.walkable = false;
|
||||
setConstantMaterialProperties(f.material, 0.0);
|
||||
f.furnace_burntime = 10;
|
||||
nodemgr->set(i, f);
|
||||
|
||||
i = CONTENT_APPLE;
|
||||
f = ContentFeatures();
|
||||
f.name = "apple";
|
||||
f.drawtype = NDT_PLANTLIKE;
|
||||
f.visual_scale = 1.0;
|
||||
f.setAllTextures("apple.png");
|
||||
f.setInventoryTexture("apple.png");
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.walkable = false;
|
||||
f.dug_item = std::string("CraftItem apple 1");
|
||||
setConstantMaterialProperties(f.material, 0.0);
|
||||
f.furnace_burntime = 3;
|
||||
nodemgr->set(i, f);
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,12 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
Legacy node definitions
|
||||
*/
|
||||
|
||||
class IWritableNodeDefManager;
|
||||
|
||||
// Initialize legacy node definitions
|
||||
// Not used used anywhere else than in test.cpp (and SHALL NOT BE)
|
||||
void content_mapnode_init(IWritableNodeDefManager *nodemgr);
|
||||
|
||||
// Backwards compatibility for non-extended content types in v19
|
||||
extern content_t trans_table_19[21][2];
|
||||
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version);
|
||||
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "utility.h"
|
||||
#include "craftdef.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
class Inventory;
|
||||
|
||||
@ -125,9 +127,14 @@ public:
|
||||
virtual bool step(float dtime);
|
||||
virtual bool nodeRemovalDisabled();
|
||||
virtual std::string getInventoryDrawSpecString();
|
||||
|
||||
protected:
|
||||
bool getCookResult(bool remove, std::string &cookresult, float &cooktime);
|
||||
bool getBurnResult(bool remove, float &burntime);
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
std::string m_infotext;
|
||||
float m_step_accumulator;
|
||||
float m_fuel_totaltime;
|
||||
float m_fuel_time;
|
||||
@ -185,9 +192,7 @@ ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("0", 8*4);
|
||||
m_inventory = NULL;
|
||||
}
|
||||
ChestNodeMetadata::~ChestNodeMetadata()
|
||||
{
|
||||
@ -200,18 +205,21 @@ u16 ChestNodeMetadata::typeId() const
|
||||
NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
d->m_inventory->deSerialize(is, gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("0", 8*4);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
|
||||
*d->m_inventory = *m_inventory;
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
void ChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
@ -253,9 +261,7 @@ LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef)
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("0", 8*4);
|
||||
m_inventory = NULL;
|
||||
}
|
||||
LockingChestNodeMetadata::~LockingChestNodeMetadata()
|
||||
{
|
||||
@ -269,18 +275,21 @@ NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamed
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
d->setOwner(deSerializeString(is));
|
||||
d->m_inventory->deSerialize(is, gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("0", 8*4);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
|
||||
*d->m_inventory = *m_inventory;
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
void LockingChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
@ -324,10 +333,9 @@ FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), typeName(), create, create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("fuel", 1);
|
||||
m_inventory->addList("src", 1);
|
||||
m_inventory->addList("dst", 4);
|
||||
m_inventory = NULL;
|
||||
|
||||
m_infotext = "Furnace is inactive";
|
||||
|
||||
m_step_accumulator = 0;
|
||||
m_fuel_totaltime = 0;
|
||||
@ -346,26 +354,52 @@ u16 FurnaceNodeMetadata::typeId() const
|
||||
NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef);
|
||||
*d->m_inventory = *m_inventory;
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
|
||||
|
||||
d->m_inventory->deSerialize(is, gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
|
||||
int temp;
|
||||
int temp = 0;
|
||||
is>>temp;
|
||||
d->m_fuel_totaltime = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_fuel_time = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_src_totaltime = (float)temp/10;
|
||||
temp = 0;
|
||||
is>>temp;
|
||||
d->m_src_time = (float)temp/10;
|
||||
|
||||
if(is.eof())
|
||||
{
|
||||
// Old furnaces didn't serialize src_totaltime and src_time
|
||||
d->m_src_totaltime = 0;
|
||||
d->m_src_time = 0;
|
||||
d->m_infotext = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
// New furnaces also serialize the infotext (so that the
|
||||
// client doesn't need to have the list of cooking recipes).
|
||||
d->m_infotext = deSerializeJsonString(is);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef)
|
||||
{
|
||||
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->addList("fuel", 1);
|
||||
d->m_inventory->addList("src", 1);
|
||||
d->m_inventory->addList("dst", 4);
|
||||
return d;
|
||||
}
|
||||
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
|
||||
@ -373,36 +407,13 @@ void FurnaceNodeMetadata::serializeBody(std::ostream &os)
|
||||
m_inventory->serialize(os);
|
||||
os<<itos(m_fuel_totaltime*10)<<" ";
|
||||
os<<itos(m_fuel_time*10)<<" ";
|
||||
os<<itos(m_src_totaltime*10)<<" ";
|
||||
os<<itos(m_src_time*10)<<" ";
|
||||
os<<serializeJsonString(m_infotext);
|
||||
}
|
||||
std::string FurnaceNodeMetadata::infoText()
|
||||
{
|
||||
//return "Furnace";
|
||||
if(m_fuel_time >= m_fuel_totaltime)
|
||||
{
|
||||
const InventoryList *src_list = m_inventory->getList("src");
|
||||
assert(src_list);
|
||||
const InventoryItem *src_item = src_list->getItem(0);
|
||||
|
||||
if(src_item && src_item->isCookable()) {
|
||||
InventoryList *dst_list = m_inventory->getList("dst");
|
||||
if(!dst_list->roomForCookedItem(src_item))
|
||||
return "Furnace is overloaded";
|
||||
return "Furnace is out of fuel";
|
||||
}
|
||||
else
|
||||
return "Furnace is inactive";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s = "Furnace is active";
|
||||
// Do this so it doesn't always show (0%) for weak fuel
|
||||
if(m_fuel_totaltime > 3) {
|
||||
s += " (";
|
||||
s += itos(m_fuel_time/m_fuel_totaltime*100);
|
||||
s += "%)";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return m_infotext;
|
||||
}
|
||||
bool FurnaceNodeMetadata::nodeRemovalDisabled()
|
||||
{
|
||||
@ -440,86 +451,107 @@ bool FurnaceNodeMetadata::step(float dtime)
|
||||
dtime = interval;
|
||||
|
||||
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
|
||||
|
||||
|
||||
InventoryList *dst_list = m_inventory->getList("dst");
|
||||
assert(dst_list);
|
||||
|
||||
InventoryList *src_list = m_inventory->getList("src");
|
||||
assert(src_list);
|
||||
InventoryItem *src_item = src_list->getItem(0);
|
||||
|
||||
// Check
|
||||
// 1. if the source item is cookable
|
||||
// 2. if there is room for the cooked item
|
||||
std::string cookresult;
|
||||
float cooktime;
|
||||
bool cookable = getCookResult(false, cookresult, cooktime);
|
||||
ItemStack cookresult_item;
|
||||
bool room_available = false;
|
||||
|
||||
if(src_item && src_item->isCookable())
|
||||
room_available = dst_list->roomForCookedItem(src_item);
|
||||
|
||||
// Start only if there are free slots in dst, so that it can
|
||||
// accomodate any result item
|
||||
if(cookable)
|
||||
{
|
||||
cookresult_item.deSerialize(cookresult, m_gamedef->idef());
|
||||
room_available = dst_list->roomForItem(cookresult_item);
|
||||
}
|
||||
|
||||
// Step fuel time
|
||||
bool burning = (m_fuel_time < m_fuel_totaltime);
|
||||
if(burning)
|
||||
{
|
||||
changed = true;
|
||||
m_fuel_time += dtime;
|
||||
}
|
||||
|
||||
std::string infotext;
|
||||
if(room_available)
|
||||
{
|
||||
m_src_totaltime = src_item->getCookTime();
|
||||
float burntime;
|
||||
if(burning)
|
||||
{
|
||||
changed = true;
|
||||
m_src_time += dtime;
|
||||
m_src_totaltime = cooktime;
|
||||
infotext = "Furnace is cooking";
|
||||
}
|
||||
else if(getBurnResult(true, burntime))
|
||||
{
|
||||
// Fuel inserted
|
||||
changed = true;
|
||||
m_fuel_time = 0;
|
||||
m_fuel_totaltime = burntime;
|
||||
//m_src_time += dtime;
|
||||
//m_src_totaltime = cooktime;
|
||||
infotext = "Furnace is cooking";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_src_time = 0;
|
||||
m_src_totaltime = 0;
|
||||
infotext = "Furnace is out of fuel";
|
||||
}
|
||||
if(m_src_totaltime > 0.001 && m_src_time >= m_src_totaltime)
|
||||
{
|
||||
// One item fully cooked
|
||||
changed = true;
|
||||
dst_list->addItem(cookresult_item);
|
||||
getCookResult(true, cookresult, cooktime); // decrement source
|
||||
m_src_totaltime = 0;
|
||||
m_src_time = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_src_time = 0;
|
||||
// Not cookable or no room available
|
||||
m_src_totaltime = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
If fuel is burning, increment the burn counters.
|
||||
If item finishes cooking, move it to result.
|
||||
*/
|
||||
if(m_fuel_time < m_fuel_totaltime)
|
||||
{
|
||||
//infostream<<"Furnace is active"<<std::endl;
|
||||
m_fuel_time += dtime;
|
||||
m_src_time += dtime;
|
||||
if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
|
||||
&& src_item)
|
||||
m_src_time = 0;
|
||||
if(cookable)
|
||||
infotext = "Furnace is overloaded";
|
||||
else if(burning)
|
||||
infotext = "Furnace is active";
|
||||
else
|
||||
{
|
||||
InventoryItem *cookresult = src_item->createCookResult();
|
||||
dst_list->addItem(cookresult);
|
||||
src_list->decrementMaterials(1);
|
||||
m_src_time = 0;
|
||||
m_src_totaltime = 0;
|
||||
infotext = "Furnace is inactive";
|
||||
m_fuel_totaltime = 0;
|
||||
m_fuel_time = 0;
|
||||
}
|
||||
changed = true;
|
||||
|
||||
// If the fuel was not used up this step, just keep burning it
|
||||
if(m_fuel_time < m_fuel_totaltime)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
Get the source again in case it has all burned
|
||||
*/
|
||||
src_item = src_list->getItem(0);
|
||||
|
||||
/*
|
||||
If there is no source item, or the source item is not cookable,
|
||||
or the furnace is still cooking, or the furnace became overloaded, stop loop.
|
||||
*/
|
||||
if(src_item == NULL || !room_available || m_fuel_time < m_fuel_totaltime ||
|
||||
dst_list->roomForCookedItem(src_item) == false)
|
||||
|
||||
// Do this so it doesn't always show (0%) for weak fuel
|
||||
if(m_fuel_totaltime > 3) {
|
||||
infotext += " (";
|
||||
infotext += itos(m_fuel_time/m_fuel_totaltime*100);
|
||||
infotext += "%)";
|
||||
}
|
||||
|
||||
if(infotext != m_infotext)
|
||||
{
|
||||
m_step_accumulator = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
//infostream<<"Furnace is out of fuel"<<std::endl;
|
||||
|
||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||
assert(fuel_list);
|
||||
const InventoryItem *fuel_item = fuel_list->getItem(0);
|
||||
|
||||
if(fuel_item && fuel_item->getBurnTime() >= 0){
|
||||
m_fuel_totaltime = fuel_item->getBurnTime();
|
||||
m_fuel_time = 0;
|
||||
fuel_list->decrementMaterials(1);
|
||||
m_infotext = infotext;
|
||||
changed = true;
|
||||
} else {
|
||||
//infostream<<"No fuel found"<<std::endl;
|
||||
// No fuel, stop loop.
|
||||
}
|
||||
|
||||
if(burning && m_fuel_time >= m_fuel_totaltime)
|
||||
{
|
||||
m_fuel_time = 0;
|
||||
m_fuel_totaltime = 0;
|
||||
}
|
||||
|
||||
if(!changed)
|
||||
{
|
||||
m_step_accumulator = 0;
|
||||
break;
|
||||
}
|
||||
@ -535,6 +567,43 @@ std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
|
||||
"list[current_name;dst;5,1;2,2;]"
|
||||
"list[current_player;main;0,5;8,4;]";
|
||||
}
|
||||
bool FurnaceNodeMetadata::getCookResult(bool remove,
|
||||
std::string &cookresult, float &cooktime)
|
||||
{
|
||||
std::vector<ItemStack> items;
|
||||
InventoryList *src_list = m_inventory->getList("src");
|
||||
assert(src_list);
|
||||
items.push_back(src_list->getItem(0));
|
||||
|
||||
CraftInput ci(CRAFT_METHOD_COOKING, 1, items);
|
||||
CraftOutput co;
|
||||
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
|
||||
ci, co, remove, m_gamedef);
|
||||
if(remove)
|
||||
src_list->changeItem(0, ci.items[0]);
|
||||
|
||||
cookresult = co.item;
|
||||
cooktime = co.time;
|
||||
return found;
|
||||
}
|
||||
bool FurnaceNodeMetadata::getBurnResult(bool remove, float &burntime)
|
||||
{
|
||||
std::vector<ItemStack> items;
|
||||
InventoryList *fuel_list = m_inventory->getList("fuel");
|
||||
assert(fuel_list);
|
||||
items.push_back(fuel_list->getItem(0));
|
||||
|
||||
CraftInput ci(CRAFT_METHOD_FUEL, 1, items);
|
||||
CraftOutput co;
|
||||
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
|
||||
ci, co, remove, m_gamedef);
|
||||
if(remove)
|
||||
fuel_list->changeItem(0, ci.items[0]);
|
||||
|
||||
burntime = co.time;
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
GenericNodeMetadata
|
||||
@ -571,7 +640,7 @@ public:
|
||||
GenericNodeMetadata(IGameDef *gamedef):
|
||||
NodeMetadata(gamedef),
|
||||
|
||||
m_inventory(new Inventory()),
|
||||
m_inventory(NULL),
|
||||
m_text(""),
|
||||
m_owner(""),
|
||||
|
||||
@ -594,7 +663,7 @@ public:
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
|
||||
|
||||
*d->m_inventory = *m_inventory;
|
||||
d->m_inventory = new Inventory(*m_inventory);
|
||||
d->m_text = m_text;
|
||||
d->m_owner = m_owner;
|
||||
|
||||
@ -610,13 +679,15 @@ public:
|
||||
static NodeMetadata* create(IGameDef *gamedef)
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
return d;
|
||||
}
|
||||
static NodeMetadata* create(std::istream &is, IGameDef *gamedef)
|
||||
{
|
||||
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
|
||||
|
||||
d->m_inventory->deSerialize(is, gamedef);
|
||||
d->m_inventory = new Inventory(gamedef->idef());
|
||||
d->m_inventory->deSerialize(is);
|
||||
d->m_text = deSerializeLongString(is);
|
||||
d->m_owner = deSerializeString(is);
|
||||
|
||||
|
@ -24,8 +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
|
||||
#include "materials.h" // For MaterialProperties and ToolDiggingProperties
|
||||
#include "gamedef.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
@ -114,9 +114,10 @@ void TestSAO::step(float dtime, bool send_recommended)
|
||||
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
|
||||
|
||||
ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos,
|
||||
const std::string inventorystring):
|
||||
const std::string itemstring):
|
||||
ServerActiveObject(env, pos),
|
||||
m_inventorystring(inventorystring),
|
||||
m_itemstring(itemstring),
|
||||
m_itemstring_changed(false),
|
||||
m_speed_f(0,0,0),
|
||||
m_last_sent_position(0,0,0)
|
||||
{
|
||||
@ -134,10 +135,10 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos,
|
||||
// check if version is supported
|
||||
if(version != 0)
|
||||
return NULL;
|
||||
std::string inventorystring = deSerializeString(is);
|
||||
std::string itemstring = deSerializeString(is);
|
||||
infostream<<"ItemSAO::create(): Creating item \""
|
||||
<<inventorystring<<"\""<<std::endl;
|
||||
return new ItemSAO(env, pos, inventorystring);
|
||||
<<itemstring<<"\""<<std::endl;
|
||||
return new ItemSAO(env, pos, itemstring);
|
||||
}
|
||||
|
||||
void ItemSAO::step(float dtime, bool send_recommended)
|
||||
@ -175,17 +176,23 @@ void ItemSAO::step(float dtime, bool send_recommended)
|
||||
m_last_sent_position = pos_f;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[6];
|
||||
// command (0 = update position)
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeS32((u8*)buf, m_base_position.X*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||
os.write(buf, 4);
|
||||
writeV3F1000(os, m_base_position);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
}
|
||||
if(m_itemstring_changed)
|
||||
{
|
||||
m_itemstring_changed = false;
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command (1 = update itemstring)
|
||||
writeU8(os, 1);
|
||||
// itemstring
|
||||
os<<serializeString(m_itemstring);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
@ -195,19 +202,12 @@ void ItemSAO::step(float dtime, bool send_recommended)
|
||||
std::string ItemSAO::getClientInitializationData()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[6];
|
||||
// version
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
writeU8(os, 0);
|
||||
// pos
|
||||
writeS32((u8*)buf, m_base_position.X*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Y*1000);
|
||||
os.write(buf, 4);
|
||||
writeS32((u8*)buf, m_base_position.Z*1000);
|
||||
os.write(buf, 4);
|
||||
// inventorystring
|
||||
os<<serializeString(m_inventorystring);
|
||||
writeV3F1000(os, m_base_position);
|
||||
// itemstring
|
||||
os<<serializeString(m_itemstring);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -215,42 +215,58 @@ std::string ItemSAO::getStaticData()
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<std::endl;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char buf[1];
|
||||
// version
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
// inventorystring
|
||||
os<<serializeString(m_inventorystring);
|
||||
writeU8(os, 0);
|
||||
// itemstring
|
||||
os<<serializeString(m_itemstring);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
InventoryItem * ItemSAO::createInventoryItem()
|
||||
ItemStack ItemSAO::createItemStack()
|
||||
{
|
||||
try{
|
||||
std::istringstream is(m_inventorystring, std::ios_base::binary);
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
|
||||
<<m_inventorystring<<"\" -> item="<<item
|
||||
IItemDefManager *idef = m_env->getGameDef()->idef();
|
||||
ItemStack item;
|
||||
item.deSerialize(m_itemstring, idef);
|
||||
infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
|
||||
<<"\" -> item=\""<<item.getItemString()<<"\""
|
||||
<<std::endl;
|
||||
return item;
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
infostream<<__FUNCTION_NAME<<": serialization error: "
|
||||
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
|
||||
return NULL;
|
||||
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
|
||||
return ItemStack();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
{
|
||||
InventoryItem *item = createInventoryItem();
|
||||
bool fits = puncher->addToInventory(item);
|
||||
if(fits)
|
||||
// Allow removing items in creative mode
|
||||
if(g_settings->getBool("creative_mode") == true)
|
||||
{
|
||||
m_removed = true;
|
||||
else
|
||||
delete item;
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = createItemStack();
|
||||
Inventory *inv = puncher->getInventory();
|
||||
if(inv != NULL)
|
||||
{
|
||||
std::string wieldlist = puncher->getWieldList();
|
||||
ItemStack leftover = inv->addItem(wieldlist, item);
|
||||
puncher->setInventoryModified();
|
||||
if(leftover.empty())
|
||||
{
|
||||
m_removed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_itemstring = leftover.getItemString();
|
||||
m_itemstring_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -436,14 +452,24 @@ std::string RatSAO::getStaticData()
|
||||
|
||||
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();
|
||||
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
|
||||
bool fits = puncher->addToInventory(item);
|
||||
if(fits)
|
||||
// Allow removing rats in creative mode
|
||||
if(g_settings->getBool("creative_mode") == true)
|
||||
{
|
||||
m_removed = true;
|
||||
else
|
||||
delete item;
|
||||
return;
|
||||
}
|
||||
|
||||
IItemDefManager *idef = m_env->getGameDef()->idef();
|
||||
ItemStack item("rat", 1, 0, "", idef);
|
||||
Inventory *inv = puncher->getInventory();
|
||||
if(inv != NULL)
|
||||
{
|
||||
std::string wieldlist = puncher->getWieldList();
|
||||
ItemStack leftover = inv->addItem(wieldlist, item);
|
||||
puncher->setInventoryModified();
|
||||
if(leftover.empty())
|
||||
m_removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -703,14 +729,20 @@ void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
mp.crackiness = -1.0;
|
||||
mp.cuttability = 1.0;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
IItemDefManager *idef = m_env->getGameDef()->idef();
|
||||
ItemStack punchitem = puncher->getWieldedItem();
|
||||
ToolDiggingProperties tp =
|
||||
punchitem.getToolDiggingProperties(idef);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
|
||||
doDamage(hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
{
|
||||
punchitem.addWear(hitprop.wear, idef);
|
||||
puncher->setWieldedItem(punchitem);
|
||||
}
|
||||
}
|
||||
|
||||
void Oerkki1SAO::doDamage(u16 d)
|
||||
@ -1393,14 +1425,20 @@ void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
|
||||
mp.crackiness = -1.0;
|
||||
mp.cuttability = 1.0;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
IItemDefManager *idef = m_env->getGameDef()->idef();
|
||||
ItemStack punchitem = puncher->getWieldedItem();
|
||||
ToolDiggingProperties tp =
|
||||
punchitem.getToolDiggingProperties(idef);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
|
||||
doDamage(hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
{
|
||||
punchitem.addWear(hitprop.wear, idef);
|
||||
puncher->setWieldedItem(punchitem);
|
||||
}
|
||||
}
|
||||
|
||||
bool MobV2SAO::isPeaceful()
|
||||
|
@ -40,8 +40,7 @@ private:
|
||||
class ItemSAO : public ServerActiveObject
|
||||
{
|
||||
public:
|
||||
ItemSAO(ServerEnvironment *env, v3f pos,
|
||||
const std::string inventorystring);
|
||||
ItemSAO(ServerEnvironment *env, v3f pos, const std::string itemstring);
|
||||
u8 getType() const
|
||||
{return ACTIVEOBJECT_TYPE_ITEM;}
|
||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||
@ -49,11 +48,12 @@ public:
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getStaticData();
|
||||
InventoryItem* createInventoryItem();
|
||||
ItemStack createItemStack();
|
||||
void punch(ServerActiveObject *puncher, float time_from_last_punch);
|
||||
float getMinimumSavedMovement(){ return 0.1*BS; }
|
||||
private:
|
||||
std::string m_inventorystring;
|
||||
std::string m_itemstring;
|
||||
bool m_itemstring_changed;
|
||||
v3f m_speed_f;
|
||||
v3f m_last_sent_position;
|
||||
IntervalLimiter m_move_interval;
|
||||
|
852
src/craftdef.cpp
852
src/craftdef.cpp
@ -22,88 +22,738 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes.h"
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include "utility.h"
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
#include "inventorymanager.h" // checkItemCombination
|
||||
|
||||
CraftPointerInput::~CraftPointerInput()
|
||||
|
||||
// Deserialize an itemstring then return the name of the item
|
||||
static std::string craftGetItemName(const std::string &itemstring, IGameDef *gamedef)
|
||||
{
|
||||
for(u32 i=0; i<items.size(); i++)
|
||||
delete items[i];
|
||||
ItemStack item;
|
||||
item.deSerialize(itemstring, gamedef->idef());
|
||||
return item.name;
|
||||
}
|
||||
|
||||
CraftPointerInput createPointerInput(const CraftInput &ci, IGameDef *gamedef)
|
||||
// (mapcar craftGetItemName itemstrings)
|
||||
static std::vector<std::string> craftGetItemNames(
|
||||
const std::vector<std::string> &itemstrings, IGameDef *gamedef)
|
||||
{
|
||||
std::vector<InventoryItem*> items;
|
||||
for(u32 i=0; i<ci.items.size(); i++){
|
||||
InventoryItem *item = NULL;
|
||||
if(ci.items[i] != ""){
|
||||
std::istringstream iss(ci.items[i], std::ios::binary);
|
||||
item = InventoryItem::deSerialize(iss, gamedef);
|
||||
}
|
||||
items.push_back(item);
|
||||
std::vector<std::string> result;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = itemstrings.begin();
|
||||
i != itemstrings.end(); i++)
|
||||
{
|
||||
result.push_back(craftGetItemName(*i, gamedef));
|
||||
}
|
||||
return CraftPointerInput(ci.width, items);
|
||||
return result;
|
||||
}
|
||||
|
||||
CraftInput createInput(const CraftPointerInput &cpi)
|
||||
// Get name of each item, and return them as a new list.
|
||||
static std::vector<std::string> craftGetItemNames(
|
||||
const std::vector<ItemStack> &items, IGameDef *gamedef)
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
for(u32 i=0; i<cpi.items.size(); i++){
|
||||
if(cpi.items[i] == NULL)
|
||||
items.push_back("");
|
||||
else{
|
||||
std::ostringstream oss(std::ios::binary);
|
||||
cpi.items[i]->serialize(oss);
|
||||
items.push_back(oss.str());
|
||||
std::vector<std::string> result;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++)
|
||||
{
|
||||
result.push_back(i->name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute bounding rectangle given a matrix of items
|
||||
// Returns false if every item is ""
|
||||
static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
|
||||
unsigned int &min_x, unsigned int &max_x,
|
||||
unsigned int &min_y, unsigned int &max_y)
|
||||
{
|
||||
bool success = false;
|
||||
unsigned int x = 0;
|
||||
unsigned int y = 0;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++)
|
||||
{
|
||||
if(*i != "") // Is this an actual item?
|
||||
{
|
||||
if(!success)
|
||||
{
|
||||
// This is the first nonempty item
|
||||
min_x = max_x = x;
|
||||
min_y = max_y = y;
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x < min_x) min_x = x;
|
||||
if(x > max_x) max_x = x;
|
||||
if(y < min_y) min_y = y;
|
||||
if(y > max_y) max_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// Step coordinate
|
||||
x++;
|
||||
if(x == width)
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
return CraftInput(cpi.width, items);
|
||||
return success;
|
||||
}
|
||||
|
||||
// Convert a list of item names to a multiset
|
||||
static std::multiset<std::string> craftMakeMultiset(const std::vector<std::string> &names)
|
||||
{
|
||||
std::multiset<std::string> set;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = names.begin();
|
||||
i != names.end(); i++)
|
||||
{
|
||||
if(*i != "")
|
||||
set.insert(*i);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
// Removes 1 from each item stack
|
||||
static void craftDecrementInput(CraftInput &input, IGameDef *gamedef)
|
||||
{
|
||||
for(std::vector<ItemStack>::iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(i->count != 0)
|
||||
i->remove(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Removes 1 from each item stack with replacement support
|
||||
// Example: if replacements contains the pair ("bucket:bucket_water", "bucket:bucket_empty"),
|
||||
// a water bucket will not be removed but replaced by an empty bucket.
|
||||
static void craftDecrementOrReplaceInput(CraftInput &input,
|
||||
const CraftReplacements &replacements,
|
||||
IGameDef *gamedef)
|
||||
{
|
||||
if(replacements.pairs.empty())
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a copy of the replacements pair list
|
||||
std::vector<std::pair<std::string, std::string> > pairs = replacements.pairs;
|
||||
|
||||
for(std::vector<ItemStack>::iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(i->count == 1)
|
||||
{
|
||||
// Find an appropriate replacement
|
||||
bool found_replacement = false;
|
||||
for(std::vector<std::pair<std::string, std::string> >::iterator
|
||||
j = pairs.begin();
|
||||
j != pairs.end(); j++)
|
||||
{
|
||||
ItemStack from_item;
|
||||
from_item.deSerialize(j->first, gamedef->idef());
|
||||
if(i->name == from_item.name)
|
||||
{
|
||||
i->deSerialize(j->second, gamedef->idef());
|
||||
found_replacement = true;
|
||||
pairs.erase(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// No replacement was found, simply decrement count to zero
|
||||
if(!found_replacement)
|
||||
i->remove(1);
|
||||
}
|
||||
else if(i->count >= 2)
|
||||
{
|
||||
// Ignore replacements for items with count >= 2
|
||||
i->remove(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump an itemstring matrix
|
||||
static std::string craftDumpMatrix(const std::vector<std::string> &items,
|
||||
unsigned int width)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"{ ";
|
||||
unsigned int x = 0;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++, x++)
|
||||
{
|
||||
if(x == width)
|
||||
{
|
||||
os<<"; ";
|
||||
x = 0;
|
||||
}
|
||||
else if(x != 0)
|
||||
{
|
||||
os<<",";
|
||||
}
|
||||
os<<"\""<<(*i)<<"\"";
|
||||
}
|
||||
os<<" }";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// Dump an item matrix
|
||||
std::string craftDumpMatrix(const std::vector<ItemStack> &items,
|
||||
unsigned int width)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"{ ";
|
||||
unsigned int x = 0;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = items.begin();
|
||||
i != items.end(); i++, x++)
|
||||
{
|
||||
if(x == width)
|
||||
{
|
||||
os<<"; ";
|
||||
x = 0;
|
||||
}
|
||||
else if(x != 0)
|
||||
{
|
||||
os<<",";
|
||||
}
|
||||
os<<"\""<<(i->getItemString())<<"\"";
|
||||
}
|
||||
os<<" }";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CraftInput
|
||||
*/
|
||||
|
||||
std::string CraftInput::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(width="<<width<<"){";
|
||||
for(u32 i=0; i<items.size(); i++)
|
||||
os<<"\""<<items[i]<<"\",";
|
||||
os<<"(method="<<((int)method)<<", items="<<craftDumpMatrix(items, width)<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*
|
||||
CraftOutput
|
||||
*/
|
||||
|
||||
std::string CraftOutput::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(item=\""<<item<<"\", time="<<time<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*
|
||||
CraftReplacements
|
||||
*/
|
||||
std::string CraftReplacements::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"{";
|
||||
const char *sep = "";
|
||||
for(std::vector<std::pair<std::string, std::string> >::const_iterator
|
||||
i = pairs.begin();
|
||||
i != pairs.end(); i++)
|
||||
{
|
||||
os<<sep<<"\""<<(i->first)<<"\"=>\""<<(i->second)<<"\"";
|
||||
sep = ",";
|
||||
}
|
||||
os<<"}";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string CraftDefinition::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"{output=\""<<output<<"\", input={";
|
||||
for(u32 i=0; i<input.items.size(); i++)
|
||||
os<<"\""<<input.items[i]<<"\",";
|
||||
os<<"}, (input.width="<<input.width<<")}";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinition
|
||||
*/
|
||||
|
||||
void CraftDefinition::serialize(std::ostream &os) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(output);
|
||||
writeU8(os, input.width);
|
||||
writeU16(os, input.items.size());
|
||||
for(u32 i=0; i<input.items.size(); i++)
|
||||
os<<serializeString(input.items[i]);
|
||||
writeU8(os, 1); // version
|
||||
os<<serializeString(getName());
|
||||
serializeBody(os);
|
||||
}
|
||||
|
||||
void CraftDefinition::deSerialize(std::istream &is)
|
||||
CraftDefinition* CraftDefinition::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinition version");
|
||||
std::string name = deSerializeString(is);
|
||||
CraftDefinition *def = NULL;
|
||||
if(name == "shaped")
|
||||
{
|
||||
def = new CraftDefinitionShaped;
|
||||
}
|
||||
else if(name == "shapeless")
|
||||
{
|
||||
def = new CraftDefinitionShapeless;
|
||||
}
|
||||
else if(name == "toolrepair")
|
||||
{
|
||||
def = new CraftDefinitionToolRepair;
|
||||
}
|
||||
else if(name == "cooking")
|
||||
{
|
||||
def = new CraftDefinitionCooking;
|
||||
}
|
||||
else if(name == "fuel")
|
||||
{
|
||||
def = new CraftDefinitionFuel;
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Unknown CraftDefinition name=\""<<name<<"\""<<std::endl;
|
||||
throw SerializationError("Unknown CraftDefinition name");
|
||||
}
|
||||
def->deSerializeBody(is, version);
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinitionShaped
|
||||
*/
|
||||
|
||||
std::string CraftDefinitionShaped::getName() const
|
||||
{
|
||||
return "shaped";
|
||||
}
|
||||
|
||||
bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_NORMAL)
|
||||
return false;
|
||||
|
||||
// Get input item matrix
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
unsigned int inp_width = input.width;
|
||||
if(inp_width == 0)
|
||||
return false;
|
||||
while(inp_names.size() % inp_width != 0)
|
||||
inp_names.push_back("");
|
||||
|
||||
// Get input bounds
|
||||
unsigned int inp_min_x=0, inp_max_x=0, inp_min_y=0, inp_max_y=0;
|
||||
if(!craftGetBounds(inp_names, inp_width, inp_min_x, inp_max_x, inp_min_y, inp_max_y))
|
||||
return false; // it was empty
|
||||
|
||||
// Get recipe item matrix
|
||||
std::vector<std::string> rec_names = craftGetItemNames(recipe, gamedef);
|
||||
unsigned int rec_width = width;
|
||||
if(rec_width == 0)
|
||||
return false;
|
||||
while(rec_names.size() % rec_width != 0)
|
||||
rec_names.push_back("");
|
||||
|
||||
// Get recipe bounds
|
||||
unsigned int rec_min_x=0, rec_max_x=0, rec_min_y=0, rec_max_y=0;
|
||||
if(!craftGetBounds(rec_names, rec_width, rec_min_x, rec_max_x, rec_min_y, rec_max_y))
|
||||
return false; // it was empty
|
||||
|
||||
// Different sizes?
|
||||
if(inp_max_x - inp_min_x != rec_max_x - rec_min_x)
|
||||
return false;
|
||||
if(inp_max_y - inp_min_y != rec_max_y - rec_min_y)
|
||||
return false;
|
||||
|
||||
// Verify that all item names in the bounding box are equal
|
||||
unsigned int w = inp_max_x - inp_min_x + 1;
|
||||
unsigned int h = inp_max_y - inp_min_y + 1;
|
||||
for(unsigned int y=0; y<h; y++)
|
||||
for(unsigned int x=0; x<w; x++)
|
||||
{
|
||||
unsigned int inp_x = inp_min_x + x;
|
||||
unsigned int inp_y = inp_min_y + y;
|
||||
unsigned int rec_x = rec_min_x + x;
|
||||
unsigned int rec_y = rec_min_y + y;
|
||||
|
||||
if(
|
||||
inp_names[inp_y * inp_width + inp_x] !=
|
||||
rec_names[rec_y * rec_width + rec_x]
|
||||
){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionShaped::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(shaped, output=\""<<output
|
||||
<<"\", recipe="<<craftDumpMatrix(recipe, width)
|
||||
<<", replacements="<<replacements.dump()<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::serializeBody(std::ostream &os) const
|
||||
{
|
||||
os<<serializeString(output);
|
||||
writeU16(os, width);
|
||||
writeU16(os, recipe.size());
|
||||
for(u32 i=0; i<recipe.size(); i++)
|
||||
os<<serializeString(recipe[i]);
|
||||
writeU16(os, replacements.pairs.size());
|
||||
for(u32 i=0; i<replacements.pairs.size(); i++)
|
||||
{
|
||||
os<<serializeString(replacements.pairs[i].first);
|
||||
os<<serializeString(replacements.pairs[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
|
||||
{
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinitionShaped version");
|
||||
output = deSerializeString(is);
|
||||
input.width = readU8(is);
|
||||
width = readU16(is);
|
||||
recipe.clear();
|
||||
u32 count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
input.items.push_back(deSerializeString(is));
|
||||
recipe.push_back(deSerializeString(is));
|
||||
replacements.pairs.clear();
|
||||
count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
std::string first = deSerializeString(is);
|
||||
std::string second = deSerializeString(is);
|
||||
replacements.pairs.push_back(std::make_pair(first, second));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinitionShapeless
|
||||
*/
|
||||
|
||||
std::string CraftDefinitionShapeless::getName() const
|
||||
{
|
||||
return "shapeless";
|
||||
}
|
||||
|
||||
bool CraftDefinitionShapeless::check(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_NORMAL)
|
||||
return false;
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
|
||||
// Get recipe item multiset
|
||||
std::vector<std::string> rec_names = craftGetItemNames(recipe, gamedef);
|
||||
std::multiset<std::string> rec_names_multiset = craftMakeMultiset(rec_names);
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftOutput(output, 0);
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionShapeless::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(shapeless, output=\""<<output
|
||||
<<"\", recipe="<<craftDumpMatrix(recipe, recipe.size())
|
||||
<<", replacements="<<replacements.dump()<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
|
||||
{
|
||||
os<<serializeString(output);
|
||||
writeU16(os, recipe.size());
|
||||
for(u32 i=0; i<recipe.size(); i++)
|
||||
os<<serializeString(recipe[i]);
|
||||
writeU16(os, replacements.pairs.size());
|
||||
for(u32 i=0; i<replacements.pairs.size(); i++)
|
||||
{
|
||||
os<<serializeString(replacements.pairs[i].first);
|
||||
os<<serializeString(replacements.pairs[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
|
||||
{
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinitionShapeless version");
|
||||
output = deSerializeString(is);
|
||||
recipe.clear();
|
||||
u32 count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
recipe.push_back(deSerializeString(is));
|
||||
replacements.pairs.clear();
|
||||
count = readU16(is);
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
std::string first = deSerializeString(is);
|
||||
std::string second = deSerializeString(is);
|
||||
replacements.pairs.push_back(std::make_pair(first, second));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinitionToolRepair
|
||||
*/
|
||||
|
||||
static ItemStack craftToolRepair(
|
||||
const ItemStack &item1,
|
||||
const ItemStack &item2,
|
||||
float additional_wear,
|
||||
IGameDef *gamedef)
|
||||
{
|
||||
IItemDefManager *idef = gamedef->idef();
|
||||
if(item1.count != 1 || item2.count != 1 || item1.name != item2.name
|
||||
|| idef->get(item1.name).type != ITEM_TOOL
|
||||
|| idef->get(item2.name).type != ITEM_TOOL)
|
||||
{
|
||||
// Failure
|
||||
return ItemStack();
|
||||
}
|
||||
|
||||
s32 item1_uses = 65536 - (u32) item1.wear;
|
||||
s32 item2_uses = 65536 - (u32) item2.wear;
|
||||
s32 new_uses = item1_uses + item2_uses;
|
||||
s32 new_wear = 65536 - new_uses + floor(additional_wear * 65536 + 0.5);
|
||||
if(new_wear >= 65536)
|
||||
return ItemStack();
|
||||
if(new_wear < 0)
|
||||
new_wear = 0;
|
||||
|
||||
ItemStack repaired = item1;
|
||||
repaired.wear = new_wear;
|
||||
return repaired;
|
||||
}
|
||||
|
||||
std::string CraftDefinitionToolRepair::getName() const
|
||||
{
|
||||
return "toolrepair";
|
||||
}
|
||||
|
||||
bool CraftDefinitionToolRepair::check(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_NORMAL)
|
||||
return false;
|
||||
|
||||
ItemStack item1;
|
||||
ItemStack item2;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(!i->empty())
|
||||
{
|
||||
if(item1.empty())
|
||||
item1 = *i;
|
||||
else if(item2.empty())
|
||||
item2 = *i;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
|
||||
return !repaired.empty();
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
ItemStack item1;
|
||||
ItemStack item2;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
if(!i->empty())
|
||||
{
|
||||
if(item1.empty())
|
||||
item1 = *i;
|
||||
else if(item2.empty())
|
||||
item2 = *i;
|
||||
}
|
||||
}
|
||||
ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
|
||||
return CraftOutput(repaired.getItemString(), 0);
|
||||
}
|
||||
|
||||
void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionToolRepair::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(toolrepair, additional_wear="<<additional_wear<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftDefinitionToolRepair::serializeBody(std::ostream &os) const
|
||||
{
|
||||
writeF1000(os, additional_wear);
|
||||
}
|
||||
|
||||
void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version)
|
||||
{
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinitionToolRepair version");
|
||||
additional_wear = readF1000(is);
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinitionCooking
|
||||
*/
|
||||
|
||||
std::string CraftDefinitionCooking::getName() const
|
||||
{
|
||||
return "cooking";
|
||||
}
|
||||
|
||||
bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_COOKING)
|
||||
return false;
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
|
||||
// Get recipe item multiset
|
||||
std::multiset<std::string> rec_names_multiset;
|
||||
rec_names_multiset.insert(craftGetItemName(recipe, gamedef));
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftOutput(output, cooktime);
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionCooking::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(cooking, output=\""<<output
|
||||
<<"\", recipe=\""<<recipe
|
||||
<<"\", cooktime="<<cooktime<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::serializeBody(std::ostream &os) const
|
||||
{
|
||||
os<<serializeString(output);
|
||||
os<<serializeString(recipe);
|
||||
writeF1000(os, cooktime);
|
||||
}
|
||||
|
||||
void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
|
||||
{
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinitionCooking version");
|
||||
output = deSerializeString(is);
|
||||
recipe = deSerializeString(is);
|
||||
cooktime = readF1000(is);
|
||||
}
|
||||
|
||||
/*
|
||||
CraftDefinitionFuel
|
||||
*/
|
||||
|
||||
std::string CraftDefinitionFuel::getName() const
|
||||
{
|
||||
return "fuel";
|
||||
}
|
||||
|
||||
bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
if(input.method != CRAFT_METHOD_FUEL)
|
||||
return false;
|
||||
|
||||
// Get input item multiset
|
||||
std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
|
||||
std::multiset<std::string> inp_names_multiset = craftMakeMultiset(inp_names);
|
||||
|
||||
// Get recipe item multiset
|
||||
std::multiset<std::string> rec_names_multiset;
|
||||
rec_names_multiset.insert(craftGetItemName(recipe, gamedef));
|
||||
|
||||
// Recipe is matched when the multisets coincide
|
||||
return inp_names_multiset == rec_names_multiset;
|
||||
}
|
||||
|
||||
CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
return CraftOutput("", burntime);
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||
{
|
||||
craftDecrementInput(input, gamedef);
|
||||
}
|
||||
|
||||
std::string CraftDefinitionFuel::dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"(fuel, recipe=\""<<recipe
|
||||
<<"\", burntime="<<burntime<<")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::serializeBody(std::ostream &os) const
|
||||
{
|
||||
os<<serializeString(recipe);
|
||||
writeF1000(os, burntime);
|
||||
}
|
||||
|
||||
void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
|
||||
{
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported CraftDefinitionFuel version");
|
||||
recipe = deSerializeString(is);
|
||||
burntime = readF1000(is);
|
||||
}
|
||||
|
||||
/*
|
||||
Craft definition manager
|
||||
*/
|
||||
|
||||
class CCraftDefManager: public IWritableCraftDefManager
|
||||
{
|
||||
public:
|
||||
@ -111,58 +761,46 @@ public:
|
||||
{
|
||||
clear();
|
||||
}
|
||||
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
|
||||
IGameDef *gamedef) const
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const
|
||||
{
|
||||
if(input_cpi.width > 3){
|
||||
errorstream<<"getCraftResult(): ERROR: "
|
||||
<<"input_cpi.width > 3; Failing to craft."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
InventoryItem *input_items[9];
|
||||
for(u32 y=0; y<3; y++)
|
||||
for(u32 x=0; x<3; x++)
|
||||
output.item = "";
|
||||
output.time = 0;
|
||||
|
||||
// If all input items are empty, abort.
|
||||
bool all_empty = true;
|
||||
for(std::vector<ItemStack>::const_iterator
|
||||
i = input.items.begin();
|
||||
i != input.items.end(); i++)
|
||||
{
|
||||
u32 i=y*3+x;
|
||||
if(x >= input_cpi.width || y >= input_cpi.height())
|
||||
input_items[i] = NULL;
|
||||
else
|
||||
input_items[i] = input_cpi.items[y*input_cpi.width+x];
|
||||
if(!i->empty())
|
||||
{
|
||||
all_empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(core::list<CraftDefinition*>::ConstIterator
|
||||
i = m_craft_definitions.begin();
|
||||
i != m_craft_definitions.end(); i++)
|
||||
if(all_empty)
|
||||
return false;
|
||||
|
||||
// Walk crafting definitions from back to front, so that later
|
||||
// definitions can override earlier ones.
|
||||
for(std::vector<CraftDefinition*>::const_reverse_iterator
|
||||
i = m_craft_definitions.rbegin();
|
||||
i != m_craft_definitions.rend(); i++)
|
||||
{
|
||||
CraftDefinition *def = *i;
|
||||
|
||||
/*infostream<<"Checking "<<createInput(input_cpi).dump()<<std::endl
|
||||
<<" against "<<def->input.dump()
|
||||
<<" (output=\""<<def->output<<"\")"<<std::endl;*/
|
||||
/*infostream<<"Checking "<<input.dump()<<std::endl
|
||||
<<" against "<<def->dump()<<std::endl;*/
|
||||
|
||||
try {
|
||||
CraftPointerInput spec_cpi = createPointerInput(def->input, gamedef);
|
||||
if(spec_cpi.width > 3){
|
||||
errorstream<<"getCraftResult: ERROR: "
|
||||
<<"spec_cpi.width > 3 in recipe "
|
||||
<<def->dump()<<std::endl;
|
||||
continue;
|
||||
}
|
||||
InventoryItem *spec_items[9];
|
||||
for(u32 y=0; y<3; y++)
|
||||
for(u32 x=0; x<3; x++)
|
||||
if(def->check(input, gamedef))
|
||||
{
|
||||
u32 i=y*3+x;
|
||||
if(x >= spec_cpi.width || y >= spec_cpi.height())
|
||||
spec_items[i] = NULL;
|
||||
else
|
||||
spec_items[i] = spec_cpi.items[y*spec_cpi.width+x];
|
||||
}
|
||||
|
||||
bool match = checkItemCombination(input_items, spec_items);
|
||||
|
||||
if(match){
|
||||
std::istringstream iss(def->output, std::ios::binary);
|
||||
return InventoryItem::deSerialize(iss, gamedef);
|
||||
// Get output, then decrement input (if requested)
|
||||
output = def->getOutput(input, gamedef);
|
||||
if(decrementInput)
|
||||
def->decrementInput(input, gamedef);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
@ -173,34 +811,41 @@ public:
|
||||
// then go on with the next craft definition
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
virtual void registerCraft(const CraftDefinition &def)
|
||||
virtual std::string dump() const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"Crafting definitions:\n";
|
||||
for(std::vector<CraftDefinition*>::const_iterator
|
||||
i = m_craft_definitions.begin();
|
||||
i != m_craft_definitions.end(); i++)
|
||||
{
|
||||
os<<(*i)->dump()<<"\n";
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
virtual void registerCraft(CraftDefinition *def)
|
||||
{
|
||||
infostream<<"registerCraft: registering craft definition: "
|
||||
<<def.dump()<<std::endl;
|
||||
if(def.input.width > 3 || def.input.height() > 3){
|
||||
errorstream<<"registerCraft: input size is larger than 3x3,"
|
||||
<<" ignoring"<<std::endl;
|
||||
return;
|
||||
}
|
||||
m_craft_definitions.push_back(new CraftDefinition(def));
|
||||
<<def->dump()<<std::endl;
|
||||
m_craft_definitions.push_back(def);
|
||||
}
|
||||
virtual void clear()
|
||||
{
|
||||
for(core::list<CraftDefinition*>::Iterator
|
||||
for(std::vector<CraftDefinition*>::iterator
|
||||
i = m_craft_definitions.begin();
|
||||
i != m_craft_definitions.end(); i++){
|
||||
delete *i;
|
||||
}
|
||||
m_craft_definitions.clear();
|
||||
}
|
||||
virtual void serialize(std::ostream &os)
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
u16 count = m_craft_definitions.size();
|
||||
writeU16(os, count);
|
||||
for(core::list<CraftDefinition*>::Iterator
|
||||
for(std::vector<CraftDefinition*>::const_iterator
|
||||
i = m_craft_definitions.begin();
|
||||
i != m_craft_definitions.end(); i++){
|
||||
CraftDefinition *def = *i;
|
||||
@ -222,14 +867,13 @@ public:
|
||||
for(u16 i=0; i<count; i++){
|
||||
// Deserialize a string and grab a CraftDefinition from it
|
||||
std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
|
||||
CraftDefinition def;
|
||||
def.deSerialize(tmp_is);
|
||||
CraftDefinition *def = CraftDefinition::deSerialize(tmp_is);
|
||||
// Register
|
||||
registerCraft(def);
|
||||
}
|
||||
}
|
||||
private:
|
||||
core::list<CraftDefinition*> m_craft_definitions;
|
||||
std::vector<CraftDefinition*> m_craft_definitions;
|
||||
};
|
||||
|
||||
IWritableCraftDefManager* createCraftDefManager()
|
||||
|
355
src/craftdef.h
355
src/craftdef.h
@ -23,71 +23,328 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
class IGameDef;
|
||||
class InventoryItem;
|
||||
#include <utility>
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
|
||||
struct CraftPointerInput
|
||||
/*
|
||||
Crafting methods.
|
||||
|
||||
The crafting method depends on the inventory list
|
||||
that the crafting input comes from.
|
||||
*/
|
||||
enum CraftMethod
|
||||
{
|
||||
unsigned int width;
|
||||
std::vector<InventoryItem*> items;
|
||||
|
||||
CraftPointerInput(unsigned int width_, const std::vector<InventoryItem*> &items_):
|
||||
width(width_),
|
||||
items(items_)
|
||||
{}
|
||||
CraftPointerInput():
|
||||
width(0)
|
||||
{}
|
||||
~CraftPointerInput();
|
||||
unsigned int height() const{
|
||||
return (items.size() + width - 1) / width;
|
||||
}
|
||||
// Crafting grid
|
||||
CRAFT_METHOD_NORMAL,
|
||||
// Cooking something in a furnace
|
||||
CRAFT_METHOD_COOKING,
|
||||
// Using something as fuel for a furnace
|
||||
CRAFT_METHOD_FUEL,
|
||||
};
|
||||
|
||||
/*
|
||||
Input: The contents of the crafting slots, arranged in matrix form
|
||||
*/
|
||||
struct CraftInput
|
||||
{
|
||||
CraftMethod method;
|
||||
unsigned int width;
|
||||
std::vector<std::string> items;
|
||||
std::vector<ItemStack> items;
|
||||
|
||||
CraftInput(unsigned int width_, const std::vector<std::string> &items_):
|
||||
width(width_),
|
||||
items(items_)
|
||||
{}
|
||||
CraftInput():
|
||||
width(0)
|
||||
method(CRAFT_METHOD_NORMAL), width(0), items()
|
||||
{}
|
||||
CraftInput(CraftMethod method_, unsigned int width_,
|
||||
const std::vector<ItemStack> &items_):
|
||||
method(method_), width(width_), items(items_)
|
||||
{}
|
||||
unsigned int height() const{
|
||||
return (items.size() + width - 1) / width;
|
||||
}
|
||||
std::string dump() const;
|
||||
};
|
||||
|
||||
struct CraftDefinition
|
||||
/*
|
||||
Output: Result of crafting operation
|
||||
*/
|
||||
struct CraftOutput
|
||||
{
|
||||
std::string output;
|
||||
CraftInput input;
|
||||
// Used for normal crafting and cooking, itemstring
|
||||
std::string item;
|
||||
// Used for cooking (cook time) and fuel (burn time), seconds
|
||||
float time;
|
||||
|
||||
CraftDefinition(){}
|
||||
CraftDefinition(const std::string &output_, unsigned int width_,
|
||||
const std::vector<std::string> &input_):
|
||||
output(output_),
|
||||
input(width_, input_)
|
||||
CraftOutput():
|
||||
item(""), time(0)
|
||||
{}
|
||||
CraftOutput(std::string item_, float time_):
|
||||
item(item_), time(time_)
|
||||
{}
|
||||
|
||||
std::string dump() const;
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
/*
|
||||
A list of replacements. A replacement indicates that a specific
|
||||
input item should not be deleted (when crafting) but replaced with
|
||||
a different item. Each replacements is a pair (itemstring to remove,
|
||||
itemstring to replace with)
|
||||
|
||||
Example: If ("bucket:bucket_water", "bucket:bucket_empty") is a
|
||||
replacement pair, the crafting input slot that contained a water
|
||||
bucket will contain an empty bucket after crafting.
|
||||
|
||||
Note: replacements only work correctly when stack_max of the item
|
||||
to be replaced is 1. It is up to the mod writer to ensure this.
|
||||
*/
|
||||
struct CraftReplacements
|
||||
{
|
||||
// List of replacements
|
||||
std::vector<std::pair<std::string, std::string> > pairs;
|
||||
|
||||
CraftReplacements():
|
||||
pairs()
|
||||
{}
|
||||
CraftReplacements(std::vector<std::pair<std::string, std::string> > pairs_):
|
||||
pairs(pairs_)
|
||||
{}
|
||||
std::string dump() const;
|
||||
};
|
||||
|
||||
/*
|
||||
Crafting definition base class
|
||||
*/
|
||||
class CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinition(){}
|
||||
virtual ~CraftDefinition(){}
|
||||
|
||||
void serialize(std::ostream &os) const;
|
||||
static CraftDefinition* deSerialize(std::istream &is);
|
||||
|
||||
// Returns type of crafting definition
|
||||
virtual std::string getName() const=0;
|
||||
|
||||
// Checks whether the recipe is applicable
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||
// Returns the output structure, meaning depends on crafting method
|
||||
// The implementation can assume that check(input) returns true
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||
// Decreases count of every input item
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
|
||||
|
||||
virtual std::string dump() const=0;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const=0;
|
||||
virtual void deSerializeBody(std::istream &is, int version)=0;
|
||||
};
|
||||
|
||||
/*
|
||||
A plain-jane (shaped) crafting definition
|
||||
|
||||
Supported crafting method: CRAFT_METHOD_NORMAL.
|
||||
Requires the input items to be arranged exactly like in the recipe.
|
||||
*/
|
||||
class CraftDefinitionShaped: public CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinitionShaped():
|
||||
output(""), width(1), recipe(), replacements()
|
||||
{}
|
||||
CraftDefinitionShaped(
|
||||
const std::string &output_,
|
||||
unsigned int width_,
|
||||
const std::vector<std::string> &recipe_,
|
||||
const CraftReplacements &replacements_):
|
||||
output(output_), width(width_), recipe(recipe_), replacements(replacements_)
|
||||
{}
|
||||
virtual ~CraftDefinitionShaped(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const;
|
||||
virtual void deSerializeBody(std::istream &is, int version);
|
||||
|
||||
private:
|
||||
// Output itemstring
|
||||
std::string output;
|
||||
// Width of recipe
|
||||
unsigned int width;
|
||||
// Recipe matrix (itemstrings)
|
||||
std::vector<std::string> recipe;
|
||||
// Replacement items for decrementInput()
|
||||
CraftReplacements replacements;
|
||||
};
|
||||
|
||||
/*
|
||||
A shapeless crafting definition
|
||||
Supported crafting method: CRAFT_METHOD_NORMAL.
|
||||
Input items can arranged in any way.
|
||||
*/
|
||||
class CraftDefinitionShapeless: public CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinitionShapeless():
|
||||
output(""), recipe(), replacements()
|
||||
{}
|
||||
CraftDefinitionShapeless(
|
||||
const std::string &output_,
|
||||
const std::vector<std::string> &recipe_,
|
||||
const CraftReplacements &replacements_):
|
||||
output(output_), recipe(recipe_), replacements(replacements_)
|
||||
{}
|
||||
virtual ~CraftDefinitionShapeless(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const;
|
||||
virtual void deSerializeBody(std::istream &is, int version);
|
||||
|
||||
private:
|
||||
// Output itemstring
|
||||
std::string output;
|
||||
// Recipe list (itemstrings)
|
||||
std::vector<std::string> recipe;
|
||||
// Replacement items for decrementInput()
|
||||
CraftReplacements replacements;
|
||||
};
|
||||
|
||||
/*
|
||||
Tool repair crafting definition
|
||||
Supported crafting method: CRAFT_METHOD_NORMAL.
|
||||
Put two damaged tools into the crafting grid, get one tool back.
|
||||
There should only be one crafting definition of this type.
|
||||
*/
|
||||
class CraftDefinitionToolRepair: public CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinitionToolRepair():
|
||||
additional_wear(0)
|
||||
{}
|
||||
CraftDefinitionToolRepair(float additional_wear_):
|
||||
additional_wear(additional_wear_)
|
||||
{}
|
||||
virtual ~CraftDefinitionToolRepair(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const;
|
||||
virtual void deSerializeBody(std::istream &is, int version);
|
||||
|
||||
private:
|
||||
// This is a constant that is added to the wear of the result.
|
||||
// May be positive or negative, allowed range [-1,1].
|
||||
// 1 = new tool is completely broken
|
||||
// 0 = simply add remaining uses of both input tools
|
||||
// -1 = new tool is completely pristine
|
||||
float additional_wear;
|
||||
};
|
||||
|
||||
/*
|
||||
A cooking (in furnace) definition
|
||||
Supported crafting method: CRAFT_METHOD_COOKING.
|
||||
*/
|
||||
class CraftDefinitionCooking: public CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinitionCooking():
|
||||
output(""), recipe(""), cooktime()
|
||||
{}
|
||||
CraftDefinitionCooking(
|
||||
const std::string &output_,
|
||||
const std::string &recipe_,
|
||||
float cooktime_):
|
||||
output(output_), recipe(recipe_), cooktime(cooktime_)
|
||||
{}
|
||||
virtual ~CraftDefinitionCooking(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const;
|
||||
virtual void deSerializeBody(std::istream &is, int version);
|
||||
|
||||
private:
|
||||
// Output itemstring
|
||||
std::string output;
|
||||
// Recipe itemstring
|
||||
std::string recipe;
|
||||
// Time in seconds
|
||||
float cooktime;
|
||||
};
|
||||
|
||||
/*
|
||||
A fuel (for furnace) definition
|
||||
Supported crafting method: CRAFT_METHOD_FUEL.
|
||||
*/
|
||||
class CraftDefinitionFuel: public CraftDefinition
|
||||
{
|
||||
public:
|
||||
CraftDefinitionFuel():
|
||||
recipe(""), burntime()
|
||||
{}
|
||||
CraftDefinitionFuel(std::string recipe_, float burntime_):
|
||||
recipe(recipe_), burntime(burntime_)
|
||||
{}
|
||||
virtual ~CraftDefinitionFuel(){}
|
||||
|
||||
virtual std::string getName() const;
|
||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||
|
||||
virtual std::string dump() const;
|
||||
|
||||
protected:
|
||||
virtual void serializeBody(std::ostream &os) const;
|
||||
virtual void deSerializeBody(std::istream &is, int version);
|
||||
|
||||
private:
|
||||
// Recipe itemstring
|
||||
std::string recipe;
|
||||
// Time in seconds
|
||||
float burntime;
|
||||
};
|
||||
|
||||
/*
|
||||
Crafting definition manager
|
||||
*/
|
||||
class ICraftDefManager
|
||||
{
|
||||
public:
|
||||
ICraftDefManager(){}
|
||||
virtual ~ICraftDefManager(){}
|
||||
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
|
||||
virtual void serialize(std::ostream &os) const=0;
|
||||
};
|
||||
|
||||
class IWritableCraftDefManager : public ICraftDefManager
|
||||
@ -95,13 +352,21 @@ class IWritableCraftDefManager : public ICraftDefManager
|
||||
public:
|
||||
IWritableCraftDefManager(){}
|
||||
virtual ~IWritableCraftDefManager(){}
|
||||
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
|
||||
IGameDef *gamedef) const=0;
|
||||
|
||||
virtual void registerCraft(const CraftDefinition &def)=0;
|
||||
|
||||
// The main crafting function
|
||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||
bool decrementInput, IGameDef *gamedef) const=0;
|
||||
|
||||
// Print crafting recipes for debugging
|
||||
virtual std::string dump() const=0;
|
||||
|
||||
// Add a crafting definition.
|
||||
// After calling this, the pointer belongs to the manager.
|
||||
virtual void registerCraft(CraftDefinition *def)=0;
|
||||
// Delete all crafting definitions
|
||||
virtual void clear()=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void serialize(std::ostream &os) const=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
|
@ -1,214 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2011 Kahrl <kahrl@gmx.net>
|
||||
|
||||
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 "craftitemdef.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include "utility.h"
|
||||
#include <map>
|
||||
|
||||
CraftItemDefinition::CraftItemDefinition():
|
||||
imagename(""),
|
||||
cookresult_item(""),
|
||||
furnace_cooktime(3.0),
|
||||
furnace_burntime(-1.0),
|
||||
usable(false),
|
||||
liquids_pointable(false),
|
||||
dropcount(-1),
|
||||
stack_max(99)
|
||||
{}
|
||||
|
||||
std::string CraftItemDefinition::dump()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"imagename="<<imagename;
|
||||
os<<", cookresult_item="<<cookresult_item;
|
||||
os<<", furnace_cooktime="<<furnace_cooktime;
|
||||
os<<", furnace_burntime="<<furnace_burntime;
|
||||
os<<", usable="<<usable;
|
||||
os<<", liquids_pointable="<<liquids_pointable;
|
||||
os<<", dropcount="<<dropcount;
|
||||
os<<", stack_max="<<stack_max;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void CraftItemDefinition::serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(imagename);
|
||||
os<<serializeString(cookresult_item);
|
||||
writeF1000(os, furnace_cooktime);
|
||||
writeF1000(os, furnace_burntime);
|
||||
writeU8(os, usable);
|
||||
writeU8(os, liquids_pointable);
|
||||
writeS16(os, dropcount);
|
||||
writeS16(os, stack_max);
|
||||
}
|
||||
|
||||
void CraftItemDefinition::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
"unsupported CraftItemDefinition version");
|
||||
imagename = deSerializeString(is);
|
||||
cookresult_item = deSerializeString(is);
|
||||
furnace_cooktime = readF1000(is);
|
||||
furnace_burntime = readF1000(is);
|
||||
usable = readU8(is);
|
||||
liquids_pointable = readU8(is);
|
||||
dropcount = readS16(is);
|
||||
stack_max = readS16(is);
|
||||
}
|
||||
|
||||
class CCraftItemDefManager: public IWritableCraftItemDefManager
|
||||
{
|
||||
public:
|
||||
virtual ~CCraftItemDefManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
virtual const CraftItemDefinition* getCraftItemDefinition(const std::string &itemname_) const
|
||||
{
|
||||
// Convert name according to possible alias
|
||||
std::string itemname = getAlias(itemname_);
|
||||
// Get the definition
|
||||
core::map<std::string, CraftItemDefinition*>::Node *n;
|
||||
n = m_item_definitions.find(itemname);
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
return n->getValue();
|
||||
}
|
||||
virtual std::string getImagename(const std::string &itemname) const
|
||||
{
|
||||
const CraftItemDefinition *def = getCraftItemDefinition(itemname);
|
||||
if(def == NULL)
|
||||
return "";
|
||||
return def->imagename;
|
||||
}
|
||||
virtual std::string getAlias(const std::string &name) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i;
|
||||
i = m_aliases.find(name);
|
||||
if(i != m_aliases.end())
|
||||
return i->second;
|
||||
return name;
|
||||
}
|
||||
virtual bool registerCraftItem(std::string itemname, const CraftItemDefinition &def)
|
||||
{
|
||||
infostream<<"registerCraftItem: registering CraftItem \""<<itemname<<"\""<<std::endl;
|
||||
m_item_definitions[itemname] = new CraftItemDefinition(def);
|
||||
|
||||
// Remove conflicting alias if it exists
|
||||
bool alias_removed = (m_aliases.erase(itemname) != 0);
|
||||
if(alias_removed)
|
||||
infostream<<"cidef: erased alias "<<itemname
|
||||
<<" because item was defined"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
virtual void clear()
|
||||
{
|
||||
for(core::map<std::string, CraftItemDefinition*>::Iterator
|
||||
i = m_item_definitions.getIterator();
|
||||
i.atEnd() == false; i++){
|
||||
delete i.getNode()->getValue();
|
||||
}
|
||||
m_item_definitions.clear();
|
||||
m_aliases.clear();
|
||||
}
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)
|
||||
{
|
||||
if(getCraftItemDefinition(name) != NULL){
|
||||
infostream<<"nidef: not setting alias "<<name<<" -> "<<convert_to
|
||||
<<": "<<name<<" is already defined"<<std::endl;
|
||||
return;
|
||||
}
|
||||
infostream<<"nidef: setting alias "<<name<<" -> "<<convert_to
|
||||
<<std::endl;
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
virtual void serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
u16 count = m_item_definitions.size();
|
||||
writeU16(os, count);
|
||||
for(core::map<std::string, CraftItemDefinition*>::Iterator
|
||||
i = m_item_definitions.getIterator();
|
||||
i.atEnd() == false; i++){
|
||||
std::string name = i.getNode()->getKey();
|
||||
CraftItemDefinition *def = i.getNode()->getValue();
|
||||
// Serialize name
|
||||
os<<serializeString(name);
|
||||
// Serialize CraftItemDefinition and write wrapped in a string
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
def->serialize(tmp_os);
|
||||
os<<serializeString(tmp_os.str());
|
||||
}
|
||||
|
||||
writeU16(os, m_aliases.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_aliases.begin(); i != m_aliases.end(); i++)
|
||||
{
|
||||
os<<serializeString(i->first);
|
||||
os<<serializeString(i->second);
|
||||
}
|
||||
}
|
||||
virtual void deSerialize(std::istream &is)
|
||||
{
|
||||
// Clear everything
|
||||
clear();
|
||||
// Deserialize
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
"unsupported CraftItemDefManager version");
|
||||
u16 count = readU16(is);
|
||||
for(u16 i=0; i<count; i++){
|
||||
// Deserialize name
|
||||
std::string name = deSerializeString(is);
|
||||
// Deserialize a string and grab a CraftItemDefinition from it
|
||||
std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
|
||||
CraftItemDefinition def;
|
||||
def.deSerialize(tmp_is);
|
||||
// Register
|
||||
registerCraftItem(name, def);
|
||||
}
|
||||
|
||||
u16 num_aliases = readU16(is);
|
||||
if(!is.eof()){
|
||||
for(u16 i=0; i<num_aliases; i++){
|
||||
std::string name = deSerializeString(is);
|
||||
std::string convert_to = deSerializeString(is);
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
// Key is name
|
||||
core::map<std::string, CraftItemDefinition*> m_item_definitions;
|
||||
// Aliases
|
||||
std::map<std::string, std::string> m_aliases;
|
||||
};
|
||||
|
||||
IWritableCraftItemDefManager* createCraftItemDefManager()
|
||||
{
|
||||
return new CCraftItemDefManager();
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2011 Kahrl <kahrl@gmx.net>
|
||||
|
||||
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 CRAFTITEMDEF_HEADER
|
||||
#define CRAFTITEMDEF_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
struct CraftItemDefinition
|
||||
{
|
||||
std::string imagename;
|
||||
std::string cookresult_item;
|
||||
float furnace_cooktime;
|
||||
float furnace_burntime;
|
||||
bool usable;
|
||||
bool liquids_pointable;
|
||||
s16 dropcount;
|
||||
s16 stack_max;
|
||||
|
||||
CraftItemDefinition();
|
||||
std::string dump();
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
class ICraftItemDefManager
|
||||
{
|
||||
public:
|
||||
ICraftItemDefManager(){}
|
||||
virtual ~ICraftItemDefManager(){}
|
||||
virtual const CraftItemDefinition* getCraftItemDefinition(const std::string &itemname) const=0;
|
||||
virtual std::string getImagename(const std::string &itemname) const =0;
|
||||
virtual std::string getAlias(const std::string &name) const =0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
};
|
||||
|
||||
class IWritableCraftItemDefManager : public ICraftItemDefManager
|
||||
{
|
||||
public:
|
||||
IWritableCraftItemDefManager(){}
|
||||
virtual ~IWritableCraftItemDefManager(){}
|
||||
virtual const CraftItemDefinition* getCraftItemDefinition(const std::string &itemname) const=0;
|
||||
virtual std::string getImagename(const std::string &itemname) const =0;
|
||||
|
||||
virtual bool registerCraftItem(std::string itemname, const CraftItemDefinition &def)=0;
|
||||
virtual void clear()=0;
|
||||
// Set an alias so that entries named <name> will load as <convert_to>.
|
||||
// Alias is not set if <name> has already been defined.
|
||||
// Alias will be removed if <name> is defined at a later point of time.
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
IWritableCraftItemDefManager* createCraftItemDefManager();
|
||||
|
||||
#endif
|
@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "activeobject.h"
|
||||
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
class ActiveBlockModifier;
|
||||
class ServerActiveObject;
|
||||
typedef struct lua_State lua_State;
|
||||
|
134
src/game.cpp
134
src/game.cpp
@ -40,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "mainmenumanager.h"
|
||||
#include "craftitemdef.h"
|
||||
#include "gettext.h"
|
||||
#include "log.h"
|
||||
#include "filesys.h"
|
||||
@ -48,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "nodemetadata.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "tooldef.h"
|
||||
#include "itemdef.h"
|
||||
#include "tile.h" // For TextureSource
|
||||
#include "logoutputbuffer.h"
|
||||
|
||||
@ -79,15 +78,6 @@ struct ChatLine
|
||||
std::wstring text;
|
||||
};
|
||||
|
||||
/*
|
||||
Inventory stuff
|
||||
*/
|
||||
|
||||
// Inventory actions from the menu are buffered here before sending
|
||||
Queue<InventoryAction*> inventory_action_queue;
|
||||
// This is a copy of the inventory that the client's environment has
|
||||
Inventory local_inventory;
|
||||
|
||||
/*
|
||||
Text input system
|
||||
*/
|
||||
@ -156,7 +146,7 @@ private:
|
||||
Hotbar draw routine
|
||||
*/
|
||||
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
ITextureSource *tsrc,
|
||||
IGameDef *gamedef,
|
||||
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
|
||||
Inventory *inventory, s32 halfheartcount, u16 playeritem)
|
||||
{
|
||||
@ -184,7 +174,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
|
||||
for(s32 i=0; i<itemcount; i++)
|
||||
{
|
||||
InventoryItem *item = mainlist->getItem(i);
|
||||
const ItemStack &item = mainlist->getItem(i);
|
||||
|
||||
core::rect<s32> rect = imgrect + pos
|
||||
+ v2s32(padding+i*(imgsize+padding*2), padding);
|
||||
@ -245,17 +235,14 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
|
||||
video::SColor bgcolor2(128,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor2, rect, NULL);
|
||||
|
||||
if(item != NULL)
|
||||
{
|
||||
drawInventoryItem(driver, font, item, rect, NULL, tsrc);
|
||||
}
|
||||
drawItemStack(driver, font, item, rect, NULL, gamedef);
|
||||
}
|
||||
|
||||
/*
|
||||
Draw hearts
|
||||
*/
|
||||
video::ITexture *heart_texture = tsrc->getTextureRaw("heart.png");
|
||||
video::ITexture *heart_texture =
|
||||
gamedef->getTextureSource()->getTextureRaw("heart.png");
|
||||
if(heart_texture)
|
||||
{
|
||||
v2s32 p = pos + v2s32(0, -20);
|
||||
@ -691,12 +678,10 @@ void the_game(
|
||||
IWritableTextureSource *tsrc = createTextureSource(device);
|
||||
|
||||
// These will be filled by data received from the server
|
||||
// Create tool definition manager
|
||||
IWritableToolDefManager *tooldef = createToolDefManager();
|
||||
// Create item definition manager
|
||||
IWritableItemDefManager *itemdef = createItemDefManager();
|
||||
// Create node definition manager
|
||||
IWritableNodeDefManager *nodedef = createNodeDefManager();
|
||||
// Create CraftItem definition manager
|
||||
IWritableCraftItemDefManager *craftitemdef = createCraftItemDefManager();
|
||||
|
||||
// Add chat log output for errors to be shown in chat
|
||||
LogOutputBuffer chat_log_error_buf(LMT_ERROR);
|
||||
@ -725,7 +710,7 @@ void the_game(
|
||||
MapDrawControl draw_control;
|
||||
|
||||
Client client(device, playername.c_str(), password, draw_control,
|
||||
tsrc, tooldef, nodedef, craftitemdef);
|
||||
tsrc, itemdef, nodedef);
|
||||
|
||||
// Client acts as our GameDef
|
||||
IGameDef *gamedef = &client;
|
||||
@ -835,9 +820,8 @@ void the_game(
|
||||
|
||||
// End condition
|
||||
if(client.texturesReceived() &&
|
||||
client.tooldefReceived() &&
|
||||
client.nodedefReceived() &&
|
||||
client.craftitemdefReceived()){
|
||||
client.itemdefReceived() &&
|
||||
client.nodedefReceived()){
|
||||
got_content = true;
|
||||
break;
|
||||
}
|
||||
@ -853,12 +837,10 @@ void the_game(
|
||||
ss<<(int)(timeout - time_counter + 1.0);
|
||||
ss<<L" seconds)\n";
|
||||
|
||||
ss<<(client.tooldefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Tool definitions\n";
|
||||
ss<<(client.itemdefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Item definitions\n";
|
||||
ss<<(client.nodedefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Node definitions\n";
|
||||
ss<<(client.craftitemdefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Item definitions\n";
|
||||
//ss<<(client.texturesReceived()?L"[X]":L"[ ]");
|
||||
ss<<L"["<<(int)(client.textureReceiveProgress()*100+0.5)<<L"%] ";
|
||||
ss<<L" Textures\n";
|
||||
@ -871,6 +853,12 @@ void the_game(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
After all content has been received:
|
||||
Update cached textures, meshes and materials
|
||||
*/
|
||||
client.afterContentReceived();
|
||||
|
||||
/*
|
||||
Create skybox
|
||||
*/
|
||||
@ -910,6 +898,11 @@ void the_game(
|
||||
farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed(), &client);
|
||||
}
|
||||
|
||||
/*
|
||||
A copy of the local inventory
|
||||
*/
|
||||
Inventory local_inventory(itemdef);
|
||||
|
||||
/*
|
||||
Move into game
|
||||
*/
|
||||
@ -1289,7 +1282,7 @@ void the_game(
|
||||
// drop selected item
|
||||
IDropAction *a = new IDropAction();
|
||||
a->count = 0;
|
||||
a->from_inv = "current_player";
|
||||
a->from_inv.setCurrentPlayer();
|
||||
a->from_list = "main";
|
||||
a->from_i = client.getPlayerItem();
|
||||
client.inventoryAction(a);
|
||||
@ -1302,18 +1295,20 @@ void the_game(
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, v2s16(8,7),
|
||||
client.getInventoryContext(),
|
||||
&client, tsrc);
|
||||
&client, gamedef);
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setCurrentPlayer();
|
||||
|
||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "main",
|
||||
"list", inventoryloc, "main",
|
||||
v2s32(0, 3), v2s32(8, 4)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "craft",
|
||||
"list", inventoryloc, "craft",
|
||||
v2s32(3, 0), v2s32(3, 3)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "craftresult",
|
||||
"list", inventoryloc, "craftresult",
|
||||
v2s32(7, 1), v2s32(1, 1)));
|
||||
|
||||
menu->setDrawSpec(draw_spec);
|
||||
@ -1691,31 +1686,20 @@ void the_game(
|
||||
|
||||
/*
|
||||
For interaction purposes, get info about the held item
|
||||
- Is it a tool, and what is the toolname?
|
||||
- What item is it?
|
||||
- Is it a usable item?
|
||||
- Can it point to liquids?
|
||||
*/
|
||||
std::string playeritem_toolname = "";
|
||||
ItemStack playeritem;
|
||||
bool playeritem_usable = false;
|
||||
bool playeritem_liquids_pointable = false;
|
||||
{
|
||||
InventoryList *mlist = local_inventory.getList("main");
|
||||
if(mlist != NULL)
|
||||
{
|
||||
InventoryItem *item = mlist->getItem(client.getPlayerItem());
|
||||
if(item)
|
||||
{
|
||||
if((std::string)item->getName() == "ToolItem")
|
||||
{
|
||||
ToolItem *titem = (ToolItem*)item;
|
||||
playeritem_toolname = titem->getToolName();
|
||||
}
|
||||
|
||||
playeritem_usable = item->isUsable();
|
||||
|
||||
playeritem_liquids_pointable =
|
||||
item->areLiquidsPointable();
|
||||
}
|
||||
playeritem = mlist->getItem(client.getPlayerItem());
|
||||
playeritem_usable = playeritem.getDefinition(itemdef).usable;
|
||||
playeritem_liquids_pointable = playeritem.getDefinition(itemdef).liquids_pointable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1845,7 +1829,7 @@ void the_game(
|
||||
// Get digging properties for material and tool
|
||||
content_t material = n.getContent();
|
||||
ToolDiggingProperties tp =
|
||||
tooldef->getDiggingProperties(playeritem_toolname);
|
||||
playeritem.getToolDiggingProperties(itemdef);
|
||||
DiggingProperties prop =
|
||||
getDiggingProperties(material, &tp, nodedef);
|
||||
|
||||
@ -1853,9 +1837,6 @@ void the_game(
|
||||
|
||||
if(prop.diggable == false)
|
||||
{
|
||||
/*infostream<<"Material "<<(int)material
|
||||
<<" not diggable with \""
|
||||
<<playeritem_toolname<<"\""<<std::endl;*/
|
||||
// I guess nobody will wait for this long
|
||||
dig_time_complete = 10000000.0;
|
||||
}
|
||||
@ -1922,17 +1903,11 @@ void the_game(
|
||||
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
|
||||
{
|
||||
infostream<<"Launching custom inventory view"<<std::endl;
|
||||
/*
|
||||
Construct the unique identification string of the node
|
||||
*/
|
||||
std::string current_name;
|
||||
current_name += "nodemeta:";
|
||||
current_name += itos(nodepos.X);
|
||||
current_name += ",";
|
||||
current_name += itos(nodepos.Y);
|
||||
current_name += ",";
|
||||
current_name += itos(nodepos.Z);
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setNodeMeta(nodepos);
|
||||
|
||||
|
||||
/*
|
||||
Create menu
|
||||
*/
|
||||
@ -1942,13 +1917,12 @@ void the_game(
|
||||
GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
draw_spec,
|
||||
meta->getInventoryDrawSpecString(),
|
||||
current_name);
|
||||
inventoryloc);
|
||||
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, invsize,
|
||||
client.getInventoryContext(),
|
||||
&client, tsrc);
|
||||
&client, gamedef);
|
||||
menu->setDrawSpec(draw_spec);
|
||||
menu->drop();
|
||||
}
|
||||
@ -2001,7 +1975,7 @@ void the_game(
|
||||
v3f objpos = selected_object->getPosition();
|
||||
v3f dir = (objpos - player_position).normalize();
|
||||
|
||||
bool disable_send = selected_object->directReportPunch(playeritem_toolname, dir);
|
||||
bool disable_send = selected_object->directReportPunch(playeritem.name, dir);
|
||||
if(!disable_send)
|
||||
client.interact(0, pointed);
|
||||
}
|
||||
@ -2285,24 +2259,12 @@ void the_game(
|
||||
update_wielded_item_trigger = false;
|
||||
// Update wielded tool
|
||||
InventoryList *mlist = local_inventory.getList("main");
|
||||
InventoryItem *item = NULL;
|
||||
ItemStack item;
|
||||
if(mlist != NULL)
|
||||
item = mlist->getItem(client.getPlayerItem());
|
||||
camera.wield(item, gamedef);
|
||||
}
|
||||
|
||||
/*
|
||||
Send actions returned by the inventory menu
|
||||
*/
|
||||
while(inventory_action_queue.size() != 0)
|
||||
{
|
||||
InventoryAction *a = inventory_action_queue.pop_front();
|
||||
|
||||
client.sendInventoryAction(a);
|
||||
// Eat it
|
||||
delete a;
|
||||
}
|
||||
|
||||
/*
|
||||
Drawing begins
|
||||
*/
|
||||
@ -2411,7 +2373,7 @@ void the_game(
|
||||
Draw hotbar
|
||||
*/
|
||||
{
|
||||
draw_hotbar(driver, font, tsrc,
|
||||
draw_hotbar(driver, font, gamedef,
|
||||
v2s32(displaycenter.X, screensize.Y),
|
||||
hotbar_imagesize, hotbar_itemcount, &local_inventory,
|
||||
client.getHP(), client.getPlayerItem());
|
||||
@ -2482,9 +2444,9 @@ void the_game(
|
||||
|
||||
} // Client scope (must be destructed before destructing *def and tsrc
|
||||
|
||||
delete tooldef;
|
||||
delete tsrc;
|
||||
delete nodedef;
|
||||
delete itemdef;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,11 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define GAMEDEF_HEADER
|
||||
|
||||
#include <string>
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
class IToolDefManager;
|
||||
class IItemDefManager;
|
||||
class INodeDefManager;
|
||||
class ICraftDefManager;
|
||||
class ICraftItemDefManager;
|
||||
// Mineral too?
|
||||
class ITextureSource;
|
||||
|
||||
@ -39,10 +39,9 @@ class IGameDef
|
||||
public:
|
||||
// These are thread-safe IF they are not edited while running threads.
|
||||
// Thus, first they are set up and then they are only read.
|
||||
virtual IToolDefManager* getToolDefManager()=0;
|
||||
virtual IItemDefManager* getItemDefManager()=0;
|
||||
virtual INodeDefManager* getNodeDefManager()=0;
|
||||
virtual ICraftDefManager* getCraftDefManager()=0;
|
||||
virtual ICraftItemDefManager* getCraftItemDefManager()=0;
|
||||
|
||||
// This is always thread-safe, but referencing the irrlicht texture
|
||||
// pointers in other threads than main thread will make things explode.
|
||||
@ -52,10 +51,9 @@ public:
|
||||
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
|
||||
|
||||
// Shorthands
|
||||
IToolDefManager* tdef(){return getToolDefManager();}
|
||||
IItemDefManager* idef(){return getItemDefManager();}
|
||||
INodeDefManager* ndef(){return getNodeDefManager();}
|
||||
ICraftDefManager* cdef(){return getCraftDefManager();}
|
||||
ICraftItemDefManager* cidef(){return getCraftItemDefManager();}
|
||||
ITextureSource* tsrc(){return getTextureSource();}
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "guiInventoryMenu.h"
|
||||
#include "constants.h"
|
||||
#include "gamedef.h"
|
||||
#include "keycode.h"
|
||||
#include "strfnd.h"
|
||||
#include <IGUICheckBox.h>
|
||||
@ -28,20 +29,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "log.h"
|
||||
#include "inventorymanager.h"
|
||||
|
||||
void drawInventoryItem(video::IVideoDriver *driver,
|
||||
void drawItemStack(video::IVideoDriver *driver,
|
||||
gui::IGUIFont *font,
|
||||
InventoryItem *item, core::rect<s32> rect,
|
||||
const ItemStack &item,
|
||||
const core::rect<s32> &rect,
|
||||
const core::rect<s32> *clip,
|
||||
ITextureSource *tsrc)
|
||||
IGameDef *gamedef)
|
||||
{
|
||||
if(item == NULL)
|
||||
if(item.empty())
|
||||
return;
|
||||
|
||||
video::ITexture *texture = NULL;
|
||||
texture = item->getImage();
|
||||
const ItemDefinition &def = item.getDefinition(gamedef->idef());
|
||||
video::ITexture *texture = def.inventory_texture;
|
||||
|
||||
// Draw the inventory texture
|
||||
if(texture != NULL)
|
||||
{
|
||||
const video::SColor color(255,255,255,255);
|
||||
@ -51,34 +53,59 @@ void drawInventoryItem(video::IVideoDriver *driver,
|
||||
core::dimension2di(texture->getOriginalSize())),
|
||||
clip, colors, true);
|
||||
}
|
||||
else
|
||||
|
||||
if(def.type == ITEM_TOOL && item.wear != 0)
|
||||
{
|
||||
video::SColor bgcolor(255,50,50,128);
|
||||
driver->draw2DRectangle(bgcolor, rect, clip);
|
||||
// Draw a progressbar
|
||||
float barheight = rect.getHeight()/16;
|
||||
float barpad_x = rect.getWidth()/16;
|
||||
float barpad_y = rect.getHeight()/16;
|
||||
core::rect<s32> progressrect(
|
||||
rect.UpperLeftCorner.X + barpad_x,
|
||||
rect.LowerRightCorner.Y - barpad_y - barheight,
|
||||
rect.LowerRightCorner.X - barpad_x,
|
||||
rect.LowerRightCorner.Y - barpad_y);
|
||||
|
||||
// Shrink progressrect by amount of tool damage
|
||||
float wear = item.wear / 65535.0;
|
||||
progressrect.LowerRightCorner.X =
|
||||
wear * progressrect.UpperLeftCorner.X +
|
||||
(1-wear) * progressrect.LowerRightCorner.X;
|
||||
|
||||
// Compute progressbar color
|
||||
// wear = 0.0: green
|
||||
// wear = 0.5: yellow
|
||||
// wear = 1.0: red
|
||||
video::SColor color(255,255,255,255);
|
||||
int wear_i = floor(wear * 511);
|
||||
wear_i = MYMIN(wear_i + 10, 511);
|
||||
if(wear_i <= 255)
|
||||
color.set(255, wear_i, 255, 0);
|
||||
else
|
||||
color.set(255, 255, 511-wear_i, 0);
|
||||
|
||||
driver->draw2DRectangle(color, progressrect, clip);
|
||||
}
|
||||
|
||||
if(font != NULL)
|
||||
if(font != NULL && item.count >= 2)
|
||||
{
|
||||
std::string text = item->getText();
|
||||
if(font && text != "")
|
||||
{
|
||||
v2u32 dim = font->getDimension(narrow_to_wide(text).c_str());
|
||||
v2s32 sdim(dim.X,dim.Y);
|
||||
// Get the item count as a string
|
||||
std::string text = itos(item.count);
|
||||
v2u32 dim = font->getDimension(narrow_to_wide(text).c_str());
|
||||
v2s32 sdim(dim.X,dim.Y);
|
||||
|
||||
core::rect<s32> rect2(
|
||||
/*rect.UpperLeftCorner,
|
||||
core::dimension2d<u32>(rect.getWidth(), 15)*/
|
||||
rect.LowerRightCorner - sdim,
|
||||
sdim
|
||||
);
|
||||
core::rect<s32> rect2(
|
||||
/*rect.UpperLeftCorner,
|
||||
core::dimension2d<u32>(rect.getWidth(), 15)*/
|
||||
rect.LowerRightCorner - sdim,
|
||||
sdim
|
||||
);
|
||||
|
||||
video::SColor bgcolor(128,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, rect2, clip);
|
||||
|
||||
font->draw(text.c_str(), rect2,
|
||||
video::SColor(255,255,255,255), false, false,
|
||||
clip);
|
||||
}
|
||||
video::SColor bgcolor(128,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, rect2, clip);
|
||||
|
||||
video::SColor color(255,255,255,255);
|
||||
font->draw(text.c_str(), rect2, color, false, false, clip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,15 +117,13 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
v2s16 menu_size,
|
||||
InventoryContext *c,
|
||||
InventoryManager *invmgr,
|
||||
ITextureSource *tsrc
|
||||
IGameDef *gamedef
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_menu_size(menu_size),
|
||||
m_c(c),
|
||||
m_invmgr(invmgr),
|
||||
m_tsrc(tsrc)
|
||||
m_gamedef(gamedef)
|
||||
{
|
||||
m_selected_item = NULL;
|
||||
}
|
||||
@ -214,15 +239,15 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
|
||||
core::rect<s32> rect = imgrect + s.pos + p0;
|
||||
if(rect.isPointInside(p))
|
||||
{
|
||||
return ItemSpec(s.inventoryname, s.listname, i);
|
||||
return ItemSpec(s.inventoryloc, s.listname, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ItemSpec("", "", -1);
|
||||
return ItemSpec(InventoryLocation(), "", -1);
|
||||
}
|
||||
|
||||
void GUIInventoryMenu::drawList(const ListDrawSpec &s, ITextureSource *tsrc)
|
||||
void GUIInventoryMenu::drawList(const ListDrawSpec &s)
|
||||
{
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
@ -232,7 +257,7 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, ITextureSource *tsrc)
|
||||
if (skin)
|
||||
font = skin->getFont();
|
||||
|
||||
Inventory *inv = m_invmgr->getInventory(m_c, s.inventoryname);
|
||||
Inventory *inv = m_invmgr->getInventory(s.inventoryloc);
|
||||
assert(inv);
|
||||
InventoryList *ilist = inv->getList(s.listname);
|
||||
|
||||
@ -244,7 +269,7 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, ITextureSource *tsrc)
|
||||
s32 y = (i/s.geom.X) * spacing.Y;
|
||||
v2s32 p(x,y);
|
||||
core::rect<s32> rect = imgrect + s.pos + p;
|
||||
InventoryItem *item = NULL;
|
||||
ItemStack item;
|
||||
if(ilist)
|
||||
item = ilist->getItem(i);
|
||||
|
||||
@ -278,10 +303,10 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, ITextureSource *tsrc)
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
if(item)
|
||||
if(!item.empty())
|
||||
{
|
||||
drawInventoryItem(driver, font, item,
|
||||
rect, &AbsoluteClippingRect, tsrc);
|
||||
drawItemStack(driver, font, item,
|
||||
rect, &AbsoluteClippingRect, m_gamedef);
|
||||
}
|
||||
|
||||
}
|
||||
@ -303,8 +328,7 @@ void GUIInventoryMenu::drawMenu()
|
||||
|
||||
for(u32 i=0; i<m_draw_spec.size(); i++)
|
||||
{
|
||||
ListDrawSpec &s = m_draw_spec[i];
|
||||
drawList(s, m_tsrc);
|
||||
drawList(m_draw_spec[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -352,14 +376,14 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
//infostream<<"Mouse action at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||
if(s.isValid())
|
||||
{
|
||||
infostream<<"Mouse action on "<<s.inventoryname
|
||||
infostream<<"Mouse action on "<<s.inventoryloc.dump()
|
||||
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
||||
if(m_selected_item)
|
||||
{
|
||||
Inventory *inv_from = m_invmgr->getInventory(m_c,
|
||||
m_selected_item->inventoryname);
|
||||
Inventory *inv_to = m_invmgr->getInventory(m_c,
|
||||
s.inventoryname);
|
||||
Inventory *inv_from = m_invmgr->getInventory(
|
||||
m_selected_item->inventoryloc);
|
||||
Inventory *inv_to = m_invmgr->getInventory(
|
||||
s.inventoryloc);
|
||||
assert(inv_from);
|
||||
assert(inv_to);
|
||||
InventoryList *list_from =
|
||||
@ -373,21 +397,21 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
// Indicates whether source slot completely empties
|
||||
bool source_empties = false;
|
||||
if(list_from && list_to
|
||||
&& list_from->getItem(m_selected_item->i) != NULL)
|
||||
&& !list_from->getItem(m_selected_item->i).empty())
|
||||
{
|
||||
infostream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = amount;
|
||||
a->from_inv = m_selected_item->inventoryname;
|
||||
a->from_inv = m_selected_item->inventoryloc;
|
||||
a->from_list = m_selected_item->listname;
|
||||
a->from_i = m_selected_item->i;
|
||||
a->to_inv = s.inventoryname;
|
||||
a->to_inv = s.inventoryloc;
|
||||
a->to_list = s.listname;
|
||||
a->to_i = s.i;
|
||||
//ispec.actions->push_back(a);
|
||||
m_invmgr->inventoryAction(a);
|
||||
|
||||
if(list_from->getItem(m_selected_item->i)->getCount()<=amount)
|
||||
if(list_from->getItem(m_selected_item->i).count<=amount)
|
||||
source_empties = true;
|
||||
}
|
||||
// Remove selection if target was left-clicked or source
|
||||
@ -401,13 +425,13 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
else
|
||||
{
|
||||
/*
|
||||
Select if non-NULL
|
||||
Select if nonempty
|
||||
*/
|
||||
Inventory *inv = m_invmgr->getInventory(m_c,
|
||||
s.inventoryname);
|
||||
Inventory *inv = m_invmgr->getInventory(
|
||||
s.inventoryloc);
|
||||
assert(inv);
|
||||
InventoryList *list = inv->getList(s.listname);
|
||||
if(list->getItem(s.i) != NULL)
|
||||
if(!list->getItem(s.i).empty())
|
||||
{
|
||||
m_selected_item = new ItemSpec(s);
|
||||
}
|
||||
@ -489,7 +513,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
core::array<GUIInventoryMenu::DrawSpec> &draw_spec,
|
||||
const std::string &data,
|
||||
const std::string ¤t_name)
|
||||
const InventoryLocation ¤t_location)
|
||||
{
|
||||
v2s16 invsize(8,9);
|
||||
Strfnd f(data);
|
||||
@ -500,8 +524,11 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
if(type == "list")
|
||||
{
|
||||
std::string name = f.next(";");
|
||||
InventoryLocation loc;
|
||||
if(name == "current_name")
|
||||
name = current_name;
|
||||
loc = current_location;
|
||||
else
|
||||
loc.deSerialize(name);
|
||||
std::string subname = f.next(";");
|
||||
s32 pos_x = stoi(f.next(","));
|
||||
s32 pos_y = stoi(f.next(";"));
|
||||
@ -512,7 +539,7 @@ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString(
|
||||
<<", geom=("<<geom_x<<","<<geom_y<<")"
|
||||
<<std::endl;
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
type, name, subname,
|
||||
type, loc, subname,
|
||||
v2s32(pos_x,pos_y),v2s32(geom_x,geom_y)));
|
||||
f.next("]");
|
||||
}
|
||||
|
@ -23,18 +23,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "inventory.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "utility.h"
|
||||
#include "modalMenu.h"
|
||||
|
||||
class ITextureSource;
|
||||
class InventoryContext;
|
||||
class IGameDef;
|
||||
class InventoryManager;
|
||||
|
||||
void drawInventoryItem(video::IVideoDriver *driver,
|
||||
void drawItemStack(video::IVideoDriver *driver,
|
||||
gui::IGUIFont *font,
|
||||
InventoryItem *item, core::rect<s32> rect,
|
||||
const ItemStack &item,
|
||||
const core::rect<s32> &rect,
|
||||
const core::rect<s32> *clip,
|
||||
ITextureSource *tsrc);
|
||||
IGameDef *gamedef);
|
||||
|
||||
class GUIInventoryMenu : public GUIModalMenu
|
||||
{
|
||||
@ -44,11 +45,11 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
{
|
||||
i = -1;
|
||||
}
|
||||
ItemSpec(const std::string &a_inventoryname,
|
||||
ItemSpec(const InventoryLocation &a_inventoryloc,
|
||||
const std::string &a_listname,
|
||||
s32 a_i)
|
||||
{
|
||||
inventoryname = a_inventoryname;
|
||||
inventoryloc = a_inventoryloc;
|
||||
listname = a_listname;
|
||||
i = a_i;
|
||||
}
|
||||
@ -57,7 +58,7 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
return i != -1;
|
||||
}
|
||||
|
||||
std::string inventoryname;
|
||||
InventoryLocation inventoryloc;
|
||||
std::string listname;
|
||||
s32 i;
|
||||
};
|
||||
@ -67,17 +68,17 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
ListDrawSpec()
|
||||
{
|
||||
}
|
||||
ListDrawSpec(const std::string &a_inventoryname,
|
||||
ListDrawSpec(const InventoryLocation &a_inventoryloc,
|
||||
const std::string &a_listname,
|
||||
v2s32 a_pos, v2s32 a_geom)
|
||||
{
|
||||
inventoryname = a_inventoryname;
|
||||
inventoryloc = a_inventoryloc;
|
||||
listname = a_listname;
|
||||
pos = a_pos;
|
||||
geom = a_geom;
|
||||
}
|
||||
|
||||
std::string inventoryname;
|
||||
InventoryLocation inventoryloc;
|
||||
std::string listname;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
@ -89,7 +90,7 @@ public:
|
||||
{
|
||||
}
|
||||
DrawSpec(const std::string &a_type,
|
||||
const std::string &a_name,
|
||||
const InventoryLocation &a_name,
|
||||
const std::string &a_subname,
|
||||
v2s32 a_pos,
|
||||
v2s32 a_geom)
|
||||
@ -102,7 +103,7 @@ public:
|
||||
}
|
||||
|
||||
std::string type;
|
||||
std::string name;
|
||||
InventoryLocation name;
|
||||
std::string subname;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
@ -112,15 +113,14 @@ public:
|
||||
static v2s16 makeDrawSpecArrayFromString(
|
||||
core::array<GUIInventoryMenu::DrawSpec> &draw_spec,
|
||||
const std::string &data,
|
||||
const std::string ¤t_name);
|
||||
const InventoryLocation ¤t_location);
|
||||
|
||||
GUIInventoryMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
v2s16 menu_size,
|
||||
InventoryContext *c,
|
||||
InventoryManager *invmgr,
|
||||
ITextureSource *tsrc
|
||||
IGameDef *gamedef
|
||||
);
|
||||
~GUIInventoryMenu();
|
||||
|
||||
@ -136,7 +136,7 @@ public:
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
ItemSpec getItemAtPos(v2s32 p) const;
|
||||
void drawList(const ListDrawSpec &s, ITextureSource *tsrc);
|
||||
void drawList(const ListDrawSpec &s);
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
@ -153,9 +153,8 @@ protected:
|
||||
v2s32 spacing;
|
||||
v2s32 imgsize;
|
||||
|
||||
InventoryContext *m_c;
|
||||
InventoryManager *m_invmgr;
|
||||
ITextureSource *m_tsrc;
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
core::array<DrawSpec> m_init_draw_spec;
|
||||
core::array<ListDrawSpec> m_draw_spec;
|
||||
|
1003
src/inventory.cpp
1003
src/inventory.cpp
File diff suppressed because it is too large
Load Diff
523
src/inventory.h
523
src/inventory.h
@ -23,460 +23,221 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
#include "mapnode.h" // For content_t
|
||||
#include "itemdef.h"
|
||||
|
||||
#define QUANTITY_ITEM_MAX_COUNT 99
|
||||
struct ToolDiggingProperties;
|
||||
|
||||
class ServerActiveObject;
|
||||
class ServerEnvironment;
|
||||
struct PointedThing;
|
||||
class ITextureSource;
|
||||
class IGameDef;
|
||||
|
||||
class InventoryItem
|
||||
struct ItemStack
|
||||
{
|
||||
public:
|
||||
InventoryItem(IGameDef *gamedef, u16 count);
|
||||
virtual ~InventoryItem();
|
||||
|
||||
static InventoryItem* deSerialize(std::istream &is, IGameDef *gamedef);
|
||||
static InventoryItem* deSerialize(const std::string &str,
|
||||
IGameDef *gamedef);
|
||||
|
||||
virtual const char* getName() const = 0;
|
||||
// Shall write the name and the parameters
|
||||
virtual void serialize(std::ostream &os) const = 0;
|
||||
// Shall make an exact clone of the item
|
||||
virtual InventoryItem* clone() = 0;
|
||||
// Return the name of the image for this item
|
||||
virtual std::string getImageBasename() const { return ""; }
|
||||
#ifndef SERVER
|
||||
// Shall return an image of the item (or NULL)
|
||||
virtual video::ITexture * getImage() const
|
||||
{ return NULL; }
|
||||
// Shall return an image of the item without embellishments (or NULL)
|
||||
virtual video::ITexture * getImageRaw() const
|
||||
{ return getImage(); }
|
||||
#endif
|
||||
// Shall return a text to show in the GUI
|
||||
virtual std::string getText() { return ""; }
|
||||
ItemStack(): name(""), count(0), wear(0), metadata("") {}
|
||||
ItemStack(std::string name_, u16 count_,
|
||||
u16 wear, std::string metadata_,
|
||||
IItemDefManager *itemdef);
|
||||
~ItemStack() {}
|
||||
|
||||
// Serialization
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is, IItemDefManager *itemdef);
|
||||
void deSerialize(const std::string &s, IItemDefManager *itemdef);
|
||||
|
||||
// Returns the string used for inventory
|
||||
virtual std::string getItemString();
|
||||
|
||||
// Shall return false if item is not known and cannot be used
|
||||
virtual bool isKnown() const { return true; }
|
||||
std::string getItemString() const;
|
||||
|
||||
/*
|
||||
Quantity methods
|
||||
*/
|
||||
|
||||
// Return true if the item can be add()ed to the other
|
||||
virtual bool addableTo(const InventoryItem *other) const
|
||||
{ return false; }
|
||||
// Return true if the other item contains this item
|
||||
virtual bool isSubsetOf(const InventoryItem *other) const
|
||||
{ return false; }
|
||||
// Remove the other item from this one if possible and return true
|
||||
// Return false if not possible
|
||||
virtual bool removeOther(const InventoryItem *other)
|
||||
{ return false; }
|
||||
|
||||
u16 getCount() const
|
||||
{ return m_count; }
|
||||
void setCount(u16 count)
|
||||
{ m_count = count; }
|
||||
|
||||
u16 freeSpace() const
|
||||
bool empty() const
|
||||
{
|
||||
u16 max = getStackMax();
|
||||
if(m_count > max)
|
||||
return 0;
|
||||
return max - m_count;
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
void add(u16 count)
|
||||
void clear()
|
||||
{
|
||||
m_count += count;
|
||||
}
|
||||
void remove(u16 count)
|
||||
{
|
||||
assert(m_count >= count);
|
||||
m_count -= count;
|
||||
name = "";
|
||||
count = 0;
|
||||
wear = 0;
|
||||
metadata = "";
|
||||
}
|
||||
|
||||
/*
|
||||
Other properties
|
||||
*/
|
||||
void add(u16 n)
|
||||
{
|
||||
count += n;
|
||||
}
|
||||
|
||||
void remove(u16 n)
|
||||
{
|
||||
assert(count >= n);
|
||||
count -= n;
|
||||
if(count == 0)
|
||||
clear(); // reset name, wear and metadata too
|
||||
}
|
||||
|
||||
// Maximum size of a stack
|
||||
virtual u16 getStackMax() const {return 1;}
|
||||
// Whether it can be used
|
||||
virtual bool isUsable() const {return false;}
|
||||
// Whether it can be cooked
|
||||
virtual bool isCookable() const {return false;}
|
||||
// Result of cooking (can randomize)
|
||||
virtual InventoryItem *createCookResult() const {return NULL;}
|
||||
// Time of cooking
|
||||
virtual float getCookTime() const {return 3.0;}
|
||||
// Whether it can be burned (<0 = cannot be burned)
|
||||
virtual float getBurnTime() const {return -1;}
|
||||
// Gets amount of items that dropping one ItemSAO will decrement
|
||||
// -1 means as many as possible
|
||||
virtual s16 getDropCount() const { return -1; }
|
||||
// Whether this item can point to liquids
|
||||
virtual bool areLiquidsPointable() const { return false; }
|
||||
|
||||
// Creates an object from the item and places it in the world.
|
||||
// If return value is true, item should be removed.
|
||||
virtual bool dropOrPlace(ServerEnvironment *env,
|
||||
ServerActiveObject *dropper,
|
||||
v3f pos, bool place, s16 count);
|
||||
|
||||
// Eat, press, activate, whatever.
|
||||
// Called when item is left-clicked while in hand.
|
||||
// If returns true, item shall be deleted.
|
||||
virtual bool use(ServerEnvironment *env,
|
||||
ServerActiveObject *user,
|
||||
const PointedThing& pointed){return false;}
|
||||
|
||||
protected:
|
||||
IGameDef *m_gamedef;
|
||||
u16 m_count;
|
||||
};
|
||||
|
||||
class MaterialItem : public InventoryItem
|
||||
{
|
||||
public:
|
||||
MaterialItem(IGameDef *gamedef, std::string nodename, u16 count);
|
||||
// Legacy constructor
|
||||
MaterialItem(IGameDef *gamedef, content_t content, u16 count);
|
||||
/*
|
||||
Implementation interface
|
||||
*/
|
||||
virtual const char* getName() const
|
||||
u16 getStackMax(IItemDefManager *itemdef) const
|
||||
{
|
||||
return "MaterialItem";
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<"node";
|
||||
os<<" \"";
|
||||
os<<m_nodename;
|
||||
os<<"\" ";
|
||||
os<<m_count;
|
||||
}
|
||||
virtual InventoryItem* clone()
|
||||
{
|
||||
return new MaterialItem(m_gamedef, m_nodename, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage() const;
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<m_count;
|
||||
return os.str();
|
||||
s16 max = itemdef->get(name).stack_max;
|
||||
return (max >= 0) ? max : 0;
|
||||
}
|
||||
|
||||
virtual bool addableTo(const InventoryItem *other) const
|
||||
// Number of items that can be added to this stack
|
||||
u16 freeSpace(IItemDefManager *itemdef) const
|
||||
{
|
||||
if(std::string(other->getName()) != "MaterialItem")
|
||||
return false;
|
||||
MaterialItem *m = (MaterialItem*)other;
|
||||
if(m->m_nodename != m_nodename)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool isSubsetOf(const InventoryItem *other) const
|
||||
{
|
||||
if(std::string(other->getName()) != "MaterialItem")
|
||||
return false;
|
||||
MaterialItem *m = (MaterialItem*)other;
|
||||
if(m->m_nodename != m_nodename)
|
||||
return false;
|
||||
return m_count <= m->m_count;
|
||||
}
|
||||
virtual bool removeOther(const InventoryItem *other)
|
||||
{
|
||||
if(!other->isSubsetOf(this))
|
||||
return false;
|
||||
MaterialItem *m = (MaterialItem*)other;
|
||||
m_count += m->m_count;
|
||||
return true;
|
||||
u16 max = getStackMax(itemdef);
|
||||
if(count > max)
|
||||
return 0;
|
||||
return max - count;
|
||||
}
|
||||
|
||||
u16 getStackMax() const
|
||||
// Returns false if item is not known and cannot be used
|
||||
bool isKnown(IItemDefManager *itemdef) const
|
||||
{
|
||||
return QUANTITY_ITEM_MAX_COUNT;
|
||||
return itemdef->isKnown(name);
|
||||
}
|
||||
|
||||
/*
|
||||
Other properties
|
||||
*/
|
||||
bool isCookable() const;
|
||||
InventoryItem *createCookResult() const;
|
||||
float getCookTime() const;
|
||||
float getBurnTime() const;
|
||||
/*
|
||||
Special properties (not part of virtual interface)
|
||||
*/
|
||||
std::string getNodeName() const
|
||||
{ return m_nodename; }
|
||||
content_t getMaterial() const;
|
||||
private:
|
||||
std::string m_nodename;
|
||||
};
|
||||
|
||||
/*
|
||||
An item that is used as a mid-product when crafting.
|
||||
Subnames:
|
||||
- Stick
|
||||
*/
|
||||
class CraftItem : public InventoryItem
|
||||
{
|
||||
public:
|
||||
CraftItem(IGameDef *gamedef, std::string subname, u16 count);
|
||||
/*
|
||||
Implementation interface
|
||||
*/
|
||||
virtual const char* getName() const
|
||||
// Returns a pointer to the item definition struct,
|
||||
// or a fallback one (name="unknown") if the item is unknown.
|
||||
const ItemDefinition& getDefinition(
|
||||
IItemDefManager *itemdef) const
|
||||
{
|
||||
return "CraftItem";
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<"craft";
|
||||
os<<" \"";
|
||||
os<<m_subname;
|
||||
os<<"\" ";
|
||||
os<<m_count;
|
||||
}
|
||||
virtual InventoryItem* clone()
|
||||
{
|
||||
return new CraftItem(m_gamedef, m_subname, m_count);
|
||||
}
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage() const;
|
||||
#endif
|
||||
std::string getText()
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<m_count;
|
||||
return os.str();
|
||||
return itemdef->get(name);
|
||||
}
|
||||
|
||||
virtual bool isKnown() const;
|
||||
|
||||
virtual bool addableTo(const InventoryItem *other) const
|
||||
// Get tool digging properties, or those of the hand if not a tool
|
||||
const ToolDiggingProperties& getToolDiggingProperties(
|
||||
IItemDefManager *itemdef) const
|
||||
{
|
||||
if(std::string(other->getName()) != "CraftItem")
|
||||
return false;
|
||||
CraftItem *m = (CraftItem*)other;
|
||||
if(m->m_subname != m_subname)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool isSubsetOf(const InventoryItem *other) const
|
||||
{
|
||||
if(std::string(other->getName()) != "CraftItem")
|
||||
return false;
|
||||
CraftItem *m = (CraftItem*)other;
|
||||
if(m->m_subname != m_subname)
|
||||
return false;
|
||||
return m_count <= m->m_count;
|
||||
}
|
||||
virtual bool removeOther(const InventoryItem *other)
|
||||
{
|
||||
if(!other->isSubsetOf(this))
|
||||
return false;
|
||||
CraftItem *m = (CraftItem*)other;
|
||||
m_count += m->m_count;
|
||||
return true;
|
||||
ToolDiggingProperties *prop;
|
||||
prop = itemdef->get(name).tool_digging_properties;
|
||||
if(prop == NULL)
|
||||
prop = itemdef->get("").tool_digging_properties;
|
||||
assert(prop != NULL);
|
||||
return *prop;
|
||||
}
|
||||
|
||||
/*
|
||||
Other properties
|
||||
*/
|
||||
|
||||
u16 getStackMax() const;
|
||||
bool isUsable() const;
|
||||
bool isCookable() const;
|
||||
InventoryItem *createCookResult() const;
|
||||
float getCookTime() const;
|
||||
float getBurnTime() const;
|
||||
s16 getDropCount() const;
|
||||
bool areLiquidsPointable() const;
|
||||
|
||||
bool dropOrPlace(ServerEnvironment *env,
|
||||
ServerActiveObject *dropper,
|
||||
v3f pos, bool place, s16 count);
|
||||
bool use(ServerEnvironment *env,
|
||||
ServerActiveObject *user,
|
||||
const PointedThing& pointed);
|
||||
|
||||
/*
|
||||
Special methods
|
||||
*/
|
||||
std::string getSubName()
|
||||
// Wear out (only tools)
|
||||
// Returns true if the item is (was) a tool
|
||||
bool addWear(s32 amount, IItemDefManager *itemdef)
|
||||
{
|
||||
return m_subname;
|
||||
}
|
||||
private:
|
||||
std::string m_subname;
|
||||
};
|
||||
|
||||
class ToolItem : public InventoryItem
|
||||
{
|
||||
public:
|
||||
ToolItem(IGameDef *gamedef, std::string toolname, u16 wear);
|
||||
/*
|
||||
Implementation interface
|
||||
*/
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "ToolItem";
|
||||
}
|
||||
virtual void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<"tool";
|
||||
os<<" \"";
|
||||
os<<m_toolname;
|
||||
os<<"\" ";
|
||||
os<<m_wear;
|
||||
}
|
||||
virtual InventoryItem* clone()
|
||||
{
|
||||
return new ToolItem(m_gamedef, m_toolname, m_wear);
|
||||
}
|
||||
|
||||
std::string getImageBasename() const;
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage() const;
|
||||
video::ITexture * getImageRaw() const;
|
||||
#endif
|
||||
|
||||
std::string getText()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool isKnown() const;
|
||||
|
||||
virtual bool isSubsetOf(const InventoryItem *other) const
|
||||
{
|
||||
if(std::string(other->getName()) != "ToolItem")
|
||||
return false;
|
||||
ToolItem *m = (ToolItem*)other;
|
||||
if(m->m_toolname != m_toolname)
|
||||
return false;
|
||||
return m_wear <= m->m_wear;
|
||||
}
|
||||
virtual bool removeOther(const InventoryItem *other)
|
||||
{
|
||||
if(!other->isSubsetOf(this))
|
||||
return false;
|
||||
ToolItem *m = (ToolItem*)other;
|
||||
m_wear -= m->m_wear;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Special methods
|
||||
*/
|
||||
std::string getToolName()
|
||||
{
|
||||
return m_toolname;
|
||||
}
|
||||
u16 getWear()
|
||||
{
|
||||
return m_wear;
|
||||
}
|
||||
// Returns true if weared out
|
||||
bool addWear(u16 add)
|
||||
{
|
||||
if(m_wear >= 65535 - add)
|
||||
if(getDefinition(itemdef).type == ITEM_TOOL)
|
||||
{
|
||||
m_wear = 65535;
|
||||
if(amount > 65535 - wear)
|
||||
clear();
|
||||
else if(amount < -wear)
|
||||
wear = 0;
|
||||
else
|
||||
wear += amount;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_wear += add;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string m_toolname;
|
||||
u16 m_wear;
|
||||
|
||||
// If possible, adds newitem to this item.
|
||||
// If cannot be added at all, returns the item back.
|
||||
// If can be added partly, decremented item is returned back.
|
||||
// If can be added fully, empty item is returned.
|
||||
ItemStack addItem(const ItemStack &newitem,
|
||||
IItemDefManager *itemdef);
|
||||
|
||||
// Checks whether newitem could be added.
|
||||
// If restitem is non-NULL, it receives the part of newitem that
|
||||
// would be left over after adding.
|
||||
bool itemFits(const ItemStack &newitem,
|
||||
ItemStack *restitem, // may be NULL
|
||||
IItemDefManager *itemdef) const;
|
||||
|
||||
// Takes some items.
|
||||
// If there are not enough, takes as many as it can.
|
||||
// Returns empty item if couldn't take any.
|
||||
ItemStack takeItem(u32 takecount);
|
||||
|
||||
// Similar to takeItem, but keeps this ItemStack intact.
|
||||
ItemStack peekItem(u32 peekcount) const;
|
||||
|
||||
/*
|
||||
Properties
|
||||
*/
|
||||
std::string name;
|
||||
u16 count;
|
||||
u16 wear;
|
||||
std::string metadata;
|
||||
};
|
||||
|
||||
class InventoryList
|
||||
{
|
||||
public:
|
||||
InventoryList(std::string name, u32 size);
|
||||
InventoryList(std::string name, u32 size, IItemDefManager *itemdef);
|
||||
~InventoryList();
|
||||
void clearItems();
|
||||
void setSize(u32 newsize);
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is, IGameDef *gamedef);
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
InventoryList(const InventoryList &other);
|
||||
InventoryList & operator = (const InventoryList &other);
|
||||
|
||||
const std::string &getName() const;
|
||||
u32 getSize();
|
||||
u32 getSize() const;
|
||||
// Count used slots
|
||||
u32 getUsedSlots();
|
||||
u32 getFreeSlots();
|
||||
u32 getUsedSlots() const;
|
||||
u32 getFreeSlots() const;
|
||||
|
||||
/*bool getDirty(){ return m_dirty; }
|
||||
void setDirty(bool dirty=true){ m_dirty = dirty; }*/
|
||||
|
||||
// Get pointer to item
|
||||
const InventoryItem * getItem(u32 i) const;
|
||||
InventoryItem * getItem(u32 i);
|
||||
// Returns old item (or NULL). Parameter can be NULL.
|
||||
InventoryItem * changeItem(u32 i, InventoryItem *newitem);
|
||||
// Get reference to item
|
||||
const ItemStack& getItem(u32 i) const;
|
||||
ItemStack& getItem(u32 i);
|
||||
// Returns old item. Parameter can be an empty item.
|
||||
ItemStack changeItem(u32 i, const ItemStack &newitem);
|
||||
// Delete item
|
||||
void deleteItem(u32 i);
|
||||
|
||||
// Adds an item to a suitable place. Returns leftover item.
|
||||
// If all went into the list, returns NULL.
|
||||
InventoryItem * addItem(InventoryItem *newitem);
|
||||
// Adds an item to a suitable place. Returns leftover item (possibly empty).
|
||||
ItemStack addItem(const ItemStack &newitem);
|
||||
|
||||
// If possible, adds item to given slot.
|
||||
// If cannot be added at all, returns the item back.
|
||||
// If can be added partly, decremented item is returned back.
|
||||
// If can be added fully, NULL is returned.
|
||||
InventoryItem * addItem(u32 i, InventoryItem *newitem);
|
||||
// If can be added fully, empty item is returned.
|
||||
ItemStack addItem(u32 i, const ItemStack &newitem);
|
||||
|
||||
// Checks whether the item could be added to the given slot
|
||||
bool itemFits(const u32 i, const InventoryItem *newitem);
|
||||
// If restitem is non-NULL, it receives the part of newitem that
|
||||
// would be left over after adding.
|
||||
bool itemFits(const u32 i, const ItemStack &newitem,
|
||||
ItemStack *restitem = NULL) const;
|
||||
|
||||
// Checks whether there is room for a given item
|
||||
bool roomForItem(const InventoryItem *item);
|
||||
bool roomForItem(const ItemStack &item) const;
|
||||
|
||||
// Checks whether there is room for a given item aftr it has been cooked
|
||||
bool roomForCookedItem(const InventoryItem *item);
|
||||
// Checks whether the given count of the given item name
|
||||
// exists in this inventory list.
|
||||
bool containsItem(const ItemStack &item) const;
|
||||
|
||||
// Removes the given count of the given item name from
|
||||
// this inventory list. Walks the list in reverse order.
|
||||
// If not as many items exist as requested, removes as
|
||||
// many as possible.
|
||||
// Returns the items that were actually removed.
|
||||
ItemStack removeItem(const ItemStack &item);
|
||||
|
||||
// Takes some items from a slot.
|
||||
// If there are not enough, takes as many as it can.
|
||||
// Returns NULL if couldn't take any.
|
||||
InventoryItem * takeItem(u32 i, u32 count);
|
||||
// Returns empty item if couldn't take any.
|
||||
ItemStack takeItem(u32 i, u32 takecount);
|
||||
|
||||
// Decrements amount of every material item
|
||||
void decrementMaterials(u16 count);
|
||||
// Similar to takeItem, but keeps the slot intact.
|
||||
ItemStack peekItem(u32 i, u32 peekcount) const;
|
||||
|
||||
void print(std::ostream &o);
|
||||
|
||||
private:
|
||||
core::array<InventoryItem*> m_items;
|
||||
std::vector<ItemStack> m_items;
|
||||
u32 m_size;
|
||||
std::string m_name;
|
||||
//bool m_dirty;
|
||||
IItemDefManager *m_itemdef;
|
||||
};
|
||||
|
||||
class Inventory
|
||||
@ -486,20 +247,19 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
Inventory();
|
||||
Inventory(IItemDefManager *itemdef);
|
||||
Inventory(const Inventory &other);
|
||||
Inventory & operator = (const Inventory &other);
|
||||
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is, IGameDef *gamedef);
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
InventoryList * addList(const std::string &name, u32 size);
|
||||
InventoryList * getList(const std::string &name);
|
||||
const InventoryList * getList(const std::string &name) const;
|
||||
bool deleteList(const std::string &name);
|
||||
// A shorthand for adding items.
|
||||
// Returns NULL if the item was fully added, leftover otherwise.
|
||||
InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
|
||||
// A shorthand for adding items. Returns leftover item (possibly empty).
|
||||
ItemStack addItem(const std::string &listname, const ItemStack &newitem)
|
||||
{
|
||||
InventoryList *list = getList(listname);
|
||||
if(list == NULL)
|
||||
@ -511,7 +271,8 @@ private:
|
||||
// -1 if not found
|
||||
const s32 getListIndex(const std::string &name) const;
|
||||
|
||||
core::array<InventoryList*> m_lists;
|
||||
std::vector<InventoryList*> m_lists;
|
||||
IItemDefManager *m_itemdef;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -18,73 +18,91 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "inventorymanager.h"
|
||||
#include "serverremoteplayer.h"
|
||||
#include "log.h"
|
||||
#include "mapblock.h" // getNodeBlockPos
|
||||
#include "environment.h"
|
||||
#include "scriptapi.h"
|
||||
#include "serverobject.h"
|
||||
#include "main.h" // for g_settings
|
||||
#include "settings.h"
|
||||
#include "utility.h"
|
||||
|
||||
/*
|
||||
InventoryManager
|
||||
InventoryLocation
|
||||
*/
|
||||
|
||||
// Wrapper for old code
|
||||
Inventory* InventoryManager::getInventory(InventoryContext *c, std::string id)
|
||||
std::string InventoryLocation::dump() const
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
InventoryLocation loc;
|
||||
loc.setPlayer(c->current_player->getName());
|
||||
return getInventory(loc);
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
{
|
||||
v3s16 p;
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
|
||||
InventoryLocation loc;
|
||||
loc.setNodeMeta(p);
|
||||
return getInventory(loc);
|
||||
}
|
||||
|
||||
errorstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
return NULL;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
serialize(os);
|
||||
return os.str();
|
||||
}
|
||||
// Wrapper for old code
|
||||
void InventoryManager::inventoryModified(InventoryContext *c, std::string id)
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
InventoryLocation loc;
|
||||
loc.setPlayer(c->current_player->getName());
|
||||
setInventoryModified(loc);
|
||||
return;
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
void InventoryLocation::serialize(std::ostream &os) const
|
||||
{
|
||||
switch(type){
|
||||
case InventoryLocation::UNDEFINED:
|
||||
{
|
||||
os<<"undefined";
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::CURRENT_PLAYER:
|
||||
{
|
||||
os<<"current_player";
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::PLAYER:
|
||||
{
|
||||
os<<"player:"<<name;
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::NODEMETA:
|
||||
{
|
||||
os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryLocation::deSerialize(std::istream &is)
|
||||
{
|
||||
std::string tname;
|
||||
std::getline(is, tname, ':');
|
||||
if(tname == "undefined")
|
||||
{
|
||||
v3s16 p;
|
||||
type = InventoryLocation::UNDEFINED;
|
||||
}
|
||||
else if(tname == "current_player")
|
||||
{
|
||||
type = InventoryLocation::CURRENT_PLAYER;
|
||||
}
|
||||
else if(tname == "player")
|
||||
{
|
||||
type = InventoryLocation::PLAYER;
|
||||
std::getline(is, name, '\n');
|
||||
}
|
||||
else if(tname == "nodemeta")
|
||||
{
|
||||
type = InventoryLocation::NODEMETA;
|
||||
std::string pos;
|
||||
std::getline(is, pos, '\n');
|
||||
Strfnd fn(pos);
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
|
||||
InventoryLocation loc;
|
||||
loc.setNodeMeta(p);
|
||||
setInventoryModified(loc);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Unknown InventoryLocation type=\""<<tname<<"\""<<std::endl;
|
||||
throw SerializationError("Unknown InventoryLocation type");
|
||||
}
|
||||
}
|
||||
|
||||
errorstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
void InventoryLocation::deSerialize(std::string s)
|
||||
{
|
||||
std::istringstream is(s, std::ios::binary);
|
||||
deSerialize(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -110,14 +128,6 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||
return a;
|
||||
}
|
||||
|
||||
static std::string describeC(const struct InventoryContext *c)
|
||||
{
|
||||
if(c->current_player == NULL)
|
||||
return "current_player=NULL";
|
||||
else
|
||||
return std::string("current_player=") + c->current_player->getName();
|
||||
}
|
||||
|
||||
IMoveAction::IMoveAction(std::istream &is)
|
||||
{
|
||||
std::string ts;
|
||||
@ -125,14 +135,16 @@ IMoveAction::IMoveAction(std::istream &is)
|
||||
std::getline(is, ts, ' ');
|
||||
count = stoi(ts);
|
||||
|
||||
std::getline(is, from_inv, ' ');
|
||||
std::getline(is, ts, ' ');
|
||||
from_inv.deSerialize(ts);
|
||||
|
||||
std::getline(is, from_list, ' ');
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
from_i = stoi(ts);
|
||||
|
||||
std::getline(is, to_inv, ' ');
|
||||
std::getline(is, ts, ' ');
|
||||
to_inv.deSerialize(ts);
|
||||
|
||||
std::getline(is, to_list, ' ');
|
||||
|
||||
@ -140,22 +152,21 @@ IMoveAction::IMoveAction(std::istream &is)
|
||||
to_i = stoi(ts);
|
||||
}
|
||||
|
||||
void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
ServerEnvironment *env)
|
||||
void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player)
|
||||
{
|
||||
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
||||
Inventory *inv_to = mgr->getInventory(c, to_inv);
|
||||
Inventory *inv_from = mgr->getInventory(from_inv);
|
||||
Inventory *inv_to = mgr->getInventory(to_inv);
|
||||
|
||||
if(!inv_from){
|
||||
infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""
|
||||
<<", to_inv=\""<<to_inv.dump()<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(!inv_to){
|
||||
infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
|
||||
"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", to_inv=\""<<to_inv<<"\""<<std::endl;
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""
|
||||
<<", to_inv=\""<<to_inv.dump()<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -167,20 +178,20 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
*/
|
||||
if(!list_from){
|
||||
infostream<<"IMoveAction::apply(): FAIL: source list not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(!list_to){
|
||||
infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
|
||||
<<"context=["<<describeC(c)<<"], to_inv=\""<<to_inv<<"\""
|
||||
<<"to_inv=\""<<to_inv.dump()<<"\""
|
||||
<<", to_list=\""<<to_list<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(list_from->getItem(from_i) == NULL)
|
||||
if(list_from->getItem(from_i).empty())
|
||||
{
|
||||
infostream<<"IMoveAction::apply(): FAIL: source item not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""
|
||||
<<" from_i="<<from_i<<std::endl;
|
||||
return;
|
||||
@ -191,27 +202,28 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
if(inv_from == inv_to && list_from == list_to && from_i == to_i)
|
||||
{
|
||||
infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
|
||||
<<"are the same: inv=\""<<from_inv<<"\" list=\""<<from_list
|
||||
<<"are the same: inv=\""<<from_inv.dump()
|
||||
<<"\" list=\""<<from_list
|
||||
<<"\" i="<<from_i<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Take item from source list
|
||||
InventoryItem *item1 = NULL;
|
||||
ItemStack item1;
|
||||
if(count == 0)
|
||||
item1 = list_from->changeItem(from_i, NULL);
|
||||
item1 = list_from->changeItem(from_i, ItemStack());
|
||||
else
|
||||
item1 = list_from->takeItem(from_i, count);
|
||||
|
||||
// Try to add the item to destination list
|
||||
InventoryItem *olditem = item1;
|
||||
int oldcount = item1.count;
|
||||
item1 = list_to->addItem(to_i, item1);
|
||||
|
||||
// If something is returned, the item was not fully added
|
||||
if(item1 != NULL)
|
||||
if(!item1.empty())
|
||||
{
|
||||
// If olditem is returned, nothing was added.
|
||||
bool nothing_added = (item1 == olditem);
|
||||
bool nothing_added = (item1.count == oldcount);
|
||||
|
||||
// If something else is returned, part of the item was left unadded.
|
||||
// Add the other part back to the source item
|
||||
@ -222,24 +234,24 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
if(nothing_added)
|
||||
{
|
||||
// Take item from source list
|
||||
item1 = list_from->changeItem(from_i, NULL);
|
||||
item1 = list_from->changeItem(from_i, ItemStack());
|
||||
// Adding was not possible, swap the items.
|
||||
InventoryItem *item2 = list_to->changeItem(to_i, item1);
|
||||
ItemStack item2 = list_to->changeItem(to_i, item1);
|
||||
// Put item from destination list to the source list
|
||||
list_from->changeItem(from_i, item2);
|
||||
}
|
||||
}
|
||||
|
||||
mgr->inventoryModified(c, from_inv);
|
||||
if(from_inv != to_inv)
|
||||
mgr->inventoryModified(c, to_inv);
|
||||
mgr->setInventoryModified(from_inv);
|
||||
if(inv_from != inv_to)
|
||||
mgr->setInventoryModified(to_inv);
|
||||
|
||||
infostream<<"IMoveAction::apply(): moved at "
|
||||
<<"["<<describeC(c)<<"]"
|
||||
<<" from inv=\""<<from_inv<<"\""
|
||||
<<" count="<<count<<"\""
|
||||
<<" from inv=\""<<from_inv.dump()<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<" to inv=\""<<to_inv<<"\""
|
||||
<<" to inv=\""<<to_inv.dump()<<"\""
|
||||
<<" list=\""<<to_list<<"\""
|
||||
<<" i="<<to_i
|
||||
<<std::endl;
|
||||
@ -252,7 +264,8 @@ IDropAction::IDropAction(std::istream &is)
|
||||
std::getline(is, ts, ' ');
|
||||
count = stoi(ts);
|
||||
|
||||
std::getline(is, from_inv, ' ');
|
||||
std::getline(is, ts, ' ');
|
||||
from_inv.deSerialize(ts);
|
||||
|
||||
std::getline(is, from_list, ' ');
|
||||
|
||||
@ -260,27 +273,13 @@ IDropAction::IDropAction(std::istream &is)
|
||||
from_i = stoi(ts);
|
||||
}
|
||||
|
||||
void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
ServerEnvironment *env)
|
||||
void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player)
|
||||
{
|
||||
if(c->current_player == NULL){
|
||||
infostream<<"IDropAction::apply(): FAIL: current_player is NULL"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do NOT cast directly to ServerActiveObject*, it breaks
|
||||
// because of multiple inheritance.
|
||||
ServerActiveObject *dropper =
|
||||
static_cast<ServerActiveObject*>(
|
||||
static_cast<ServerRemotePlayer*>(
|
||||
c->current_player
|
||||
));
|
||||
|
||||
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
||||
Inventory *inv_from = mgr->getInventory(from_inv);
|
||||
|
||||
if(!inv_from){
|
||||
infostream<<"IDropAction::apply(): FAIL: source inventory not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""<<std::endl;
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -291,254 +290,35 @@ void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
|
||||
*/
|
||||
if(!list_from){
|
||||
infostream<<"IDropAction::apply(): FAIL: source list not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""<<std::endl;
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
InventoryItem *item = list_from->getItem(from_i);
|
||||
if(item == NULL)
|
||||
if(list_from->getItem(from_i).empty())
|
||||
{
|
||||
infostream<<"IDropAction::apply(): FAIL: source item not found: "
|
||||
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
|
||||
<<"from_inv=\""<<from_inv.dump()<<"\""
|
||||
<<", from_list=\""<<from_list<<"\""
|
||||
<<" from_i="<<from_i<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
v3f pos = dropper->getBasePosition();
|
||||
pos.Y += 0.5*BS;
|
||||
|
||||
s16 count2 = count;
|
||||
if(count2 == 0)
|
||||
count2 = -1;
|
||||
|
||||
/*
|
||||
Drop the item
|
||||
*/
|
||||
bool remove = item->dropOrPlace(env, dropper, pos, false, count2);
|
||||
if(remove)
|
||||
list_from->deleteItem(from_i);
|
||||
|
||||
mgr->inventoryModified(c, from_inv);
|
||||
ItemStack item = list_from->getItem(from_i);
|
||||
if(scriptapi_item_on_drop(player->getEnv()->getLua(), item, player,
|
||||
player->getBasePosition() + v3f(0,1,0)))
|
||||
{
|
||||
// Apply returned ItemStack
|
||||
if(g_settings->getBool("creative_mode") == false
|
||||
|| from_inv.type != InventoryLocation::PLAYER)
|
||||
list_from->changeItem(from_i, item);
|
||||
mgr->setInventoryModified(from_inv);
|
||||
}
|
||||
|
||||
infostream<<"IDropAction::apply(): dropped "
|
||||
<<"["<<describeC(c)<<"]"
|
||||
<<" from inv=\""<<from_inv<<"\""
|
||||
<<" from inv=\""<<from_inv.dump()<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Craft checking system
|
||||
*/
|
||||
|
||||
bool ItemSpec::checkItem(const InventoryItem *item) const
|
||||
{
|
||||
if(type == ITEM_NONE)
|
||||
{
|
||||
// Has to be no item
|
||||
if(item != NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// There should be an item
|
||||
if(item == NULL)
|
||||
return false;
|
||||
|
||||
std::string itemname = item->getName();
|
||||
|
||||
if(type == ITEM_MATERIAL)
|
||||
{
|
||||
if(itemname != "MaterialItem")
|
||||
return false;
|
||||
MaterialItem *mitem = (MaterialItem*)item;
|
||||
if(num != 65535){
|
||||
if(mitem->getMaterial() != num)
|
||||
return false;
|
||||
} else {
|
||||
if(mitem->getNodeName() != name)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(type == ITEM_CRAFT)
|
||||
{
|
||||
if(itemname != "CraftItem")
|
||||
return false;
|
||||
CraftItem *mitem = (CraftItem*)item;
|
||||
if(mitem->getSubName() != name)
|
||||
return false;
|
||||
}
|
||||
else if(type == ITEM_TOOL)
|
||||
{
|
||||
// Not supported yet
|
||||
assert(0);
|
||||
}
|
||||
else if(type == ITEM_MBO)
|
||||
{
|
||||
// Not supported yet
|
||||
assert(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not supported yet
|
||||
assert(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *specs)
|
||||
{
|
||||
u16 items_min_x = 100;
|
||||
u16 items_max_x = 100;
|
||||
u16 items_min_y = 100;
|
||||
u16 items_max_y = 100;
|
||||
for(u16 y=0; y<3; y++)
|
||||
for(u16 x=0; x<3; x++)
|
||||
{
|
||||
if(items[y*3 + x] == NULL)
|
||||
continue;
|
||||
if(items_min_x == 100 || x < items_min_x)
|
||||
items_min_x = x;
|
||||
if(items_min_y == 100 || y < items_min_y)
|
||||
items_min_y = y;
|
||||
if(items_max_x == 100 || x > items_max_x)
|
||||
items_max_x = x;
|
||||
if(items_max_y == 100 || y > items_max_y)
|
||||
items_max_y = y;
|
||||
}
|
||||
// No items at all, just return false
|
||||
if(items_min_x == 100)
|
||||
return false;
|
||||
|
||||
u16 items_w = items_max_x - items_min_x + 1;
|
||||
u16 items_h = items_max_y - items_min_y + 1;
|
||||
|
||||
u16 specs_min_x = 100;
|
||||
u16 specs_max_x = 100;
|
||||
u16 specs_min_y = 100;
|
||||
u16 specs_max_y = 100;
|
||||
for(u16 y=0; y<3; y++)
|
||||
for(u16 x=0; x<3; x++)
|
||||
{
|
||||
if(specs[y*3 + x].type == ITEM_NONE)
|
||||
continue;
|
||||
if(specs_min_x == 100 || x < specs_min_x)
|
||||
specs_min_x = x;
|
||||
if(specs_min_y == 100 || y < specs_min_y)
|
||||
specs_min_y = y;
|
||||
if(specs_max_x == 100 || x > specs_max_x)
|
||||
specs_max_x = x;
|
||||
if(specs_max_y == 100 || y > specs_max_y)
|
||||
specs_max_y = y;
|
||||
}
|
||||
// No specs at all, just return false
|
||||
if(specs_min_x == 100)
|
||||
return false;
|
||||
|
||||
u16 specs_w = specs_max_x - specs_min_x + 1;
|
||||
u16 specs_h = specs_max_y - specs_min_y + 1;
|
||||
|
||||
// Different sizes
|
||||
if(items_w != specs_w || items_h != specs_h)
|
||||
return false;
|
||||
|
||||
for(u16 y=0; y<specs_h; y++)
|
||||
for(u16 x=0; x<specs_w; x++)
|
||||
{
|
||||
u16 items_x = items_min_x + x;
|
||||
u16 items_y = items_min_y + y;
|
||||
u16 specs_x = specs_min_x + x;
|
||||
u16 specs_y = specs_min_y + y;
|
||||
const InventoryItem *item = items[items_y * 3 + items_x];
|
||||
const ItemSpec &spec = specs[specs_y * 3 + specs_x];
|
||||
|
||||
if(spec.checkItem(item) == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkItemCombination(const InventoryItem * const * items,
|
||||
const InventoryItem * const * specs)
|
||||
{
|
||||
u16 items_min_x = 100;
|
||||
u16 items_max_x = 100;
|
||||
u16 items_min_y = 100;
|
||||
u16 items_max_y = 100;
|
||||
for(u16 y=0; y<3; y++)
|
||||
for(u16 x=0; x<3; x++)
|
||||
{
|
||||
if(items[y*3 + x] == NULL)
|
||||
continue;
|
||||
if(items_min_x == 100 || x < items_min_x)
|
||||
items_min_x = x;
|
||||
if(items_min_y == 100 || y < items_min_y)
|
||||
items_min_y = y;
|
||||
if(items_max_x == 100 || x > items_max_x)
|
||||
items_max_x = x;
|
||||
if(items_max_y == 100 || y > items_max_y)
|
||||
items_max_y = y;
|
||||
}
|
||||
// No items at all, just return false
|
||||
if(items_min_x == 100)
|
||||
return false;
|
||||
|
||||
u16 items_w = items_max_x - items_min_x + 1;
|
||||
u16 items_h = items_max_y - items_min_y + 1;
|
||||
|
||||
u16 specs_min_x = 100;
|
||||
u16 specs_max_x = 100;
|
||||
u16 specs_min_y = 100;
|
||||
u16 specs_max_y = 100;
|
||||
for(u16 y=0; y<3; y++)
|
||||
for(u16 x=0; x<3; x++)
|
||||
{
|
||||
if(specs[y*3 + x] == NULL)
|
||||
continue;
|
||||
if(specs_min_x == 100 || x < specs_min_x)
|
||||
specs_min_x = x;
|
||||
if(specs_min_y == 100 || y < specs_min_y)
|
||||
specs_min_y = y;
|
||||
if(specs_max_x == 100 || x > specs_max_x)
|
||||
specs_max_x = x;
|
||||
if(specs_max_y == 100 || y > specs_max_y)
|
||||
specs_max_y = y;
|
||||
}
|
||||
// No specs at all, just return false
|
||||
if(specs_min_x == 100)
|
||||
return false;
|
||||
|
||||
u16 specs_w = specs_max_x - specs_min_x + 1;
|
||||
u16 specs_h = specs_max_y - specs_min_y + 1;
|
||||
|
||||
// Different sizes
|
||||
if(items_w != specs_w || items_h != specs_h)
|
||||
return false;
|
||||
|
||||
for(u16 y=0; y<specs_h; y++)
|
||||
for(u16 x=0; x<specs_w; x++)
|
||||
{
|
||||
u16 items_x = items_min_x + x;
|
||||
u16 items_y = items_min_y + y;
|
||||
u16 specs_x = specs_min_x + x;
|
||||
u16 specs_y = specs_min_y + y;
|
||||
const InventoryItem *item = items[items_y * 3 + items_x];
|
||||
const InventoryItem *spec = specs[specs_y * 3 + specs_x];
|
||||
|
||||
if(item == NULL && spec == NULL)
|
||||
continue;
|
||||
if(item == NULL && spec != NULL)
|
||||
return false;
|
||||
if(item != NULL && spec == NULL)
|
||||
return false;
|
||||
if(!spec->isSubsetOf(item))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,19 +21,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define INVENTORYMANAGER_HEADER
|
||||
|
||||
#include "inventory.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
class ServerActiveObject;
|
||||
|
||||
// Should probably somehow replace InventoryContext over time
|
||||
struct InventoryLocation
|
||||
{
|
||||
enum Type{
|
||||
UNDEFINED,
|
||||
CURRENT_PLAYER,
|
||||
PLAYER,
|
||||
NODEMETA
|
||||
NODEMETA,
|
||||
} type;
|
||||
|
||||
std::string name; // PLAYER
|
||||
v3s16 p; // NODEMETA
|
||||
|
||||
InventoryLocation()
|
||||
{
|
||||
setUndefined();
|
||||
}
|
||||
void setUndefined()
|
||||
{
|
||||
type = UNDEFINED;
|
||||
}
|
||||
void setCurrentPlayer()
|
||||
{
|
||||
type = CURRENT_PLAYER;
|
||||
}
|
||||
void setPlayer(const std::string &name_)
|
||||
{
|
||||
type = PLAYER;
|
||||
@ -44,17 +59,17 @@ struct InventoryLocation
|
||||
type = NODEMETA;
|
||||
p = p_;
|
||||
}
|
||||
};
|
||||
|
||||
class Player;
|
||||
void applyCurrentPlayer(const std::string &name_)
|
||||
{
|
||||
if(type == CURRENT_PLAYER)
|
||||
setPlayer(name_);
|
||||
}
|
||||
|
||||
struct InventoryContext
|
||||
{
|
||||
Player *current_player;
|
||||
|
||||
InventoryContext():
|
||||
current_player(NULL)
|
||||
{}
|
||||
std::string dump() const;
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is);
|
||||
void deSerialize(std::string s);
|
||||
};
|
||||
|
||||
struct InventoryAction;
|
||||
@ -68,18 +83,11 @@ public:
|
||||
// Get an inventory or set it modified (so it will be updated over
|
||||
// network or so)
|
||||
virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;}
|
||||
virtual std::string getInventoryOwner(const InventoryLocation &loc){return "";}
|
||||
virtual void setInventoryModified(const InventoryLocation &loc){}
|
||||
|
||||
// Used on the client to send an action to the server
|
||||
virtual void inventoryAction(InventoryAction *a){}
|
||||
|
||||
// (Deprecated; these wrap to the latter ones)
|
||||
// Get a pointer to an inventory specified by id. id can be:
|
||||
// - "current_player"
|
||||
// - "nodemeta:X,Y,Z"
|
||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
// Used on the server by InventoryAction::apply and other stuff
|
||||
void inventoryModified(InventoryContext *c, std::string id);
|
||||
};
|
||||
|
||||
#define IACTION_MOVE 0
|
||||
@ -91,18 +99,17 @@ struct InventoryAction
|
||||
|
||||
virtual u16 getType() const = 0;
|
||||
virtual void serialize(std::ostream &os) const = 0;
|
||||
virtual void apply(InventoryContext *c, InventoryManager *mgr,
|
||||
ServerEnvironment *env) = 0;
|
||||
virtual void apply(InventoryManager *mgr, ServerActiveObject *player) = 0;
|
||||
};
|
||||
|
||||
struct IMoveAction : public InventoryAction
|
||||
{
|
||||
// count=0 means "everything"
|
||||
u16 count;
|
||||
std::string from_inv;
|
||||
InventoryLocation from_inv;
|
||||
std::string from_list;
|
||||
s16 from_i;
|
||||
std::string to_inv;
|
||||
InventoryLocation to_inv;
|
||||
std::string to_list;
|
||||
s16 to_i;
|
||||
|
||||
@ -124,23 +131,22 @@ struct IMoveAction : public InventoryAction
|
||||
{
|
||||
os<<"Move ";
|
||||
os<<count<<" ";
|
||||
os<<from_inv<<" ";
|
||||
os<<from_inv.dump()<<" ";
|
||||
os<<from_list<<" ";
|
||||
os<<from_i<<" ";
|
||||
os<<to_inv<<" ";
|
||||
os<<to_inv.dump()<<" ";
|
||||
os<<to_list<<" ";
|
||||
os<<to_i;
|
||||
}
|
||||
|
||||
void apply(InventoryContext *c, InventoryManager *mgr,
|
||||
ServerEnvironment *env);
|
||||
void apply(InventoryManager *mgr, ServerActiveObject *player);
|
||||
};
|
||||
|
||||
struct IDropAction : public InventoryAction
|
||||
{
|
||||
// count=0 means "everything"
|
||||
u16 count;
|
||||
std::string from_inv;
|
||||
InventoryLocation from_inv;
|
||||
std::string from_list;
|
||||
s16 from_i;
|
||||
|
||||
@ -161,68 +167,13 @@ struct IDropAction : public InventoryAction
|
||||
{
|
||||
os<<"Drop ";
|
||||
os<<count<<" ";
|
||||
os<<from_inv<<" ";
|
||||
os<<from_inv.dump()<<" ";
|
||||
os<<from_list<<" ";
|
||||
os<<from_i;
|
||||
}
|
||||
|
||||
void apply(InventoryContext *c, InventoryManager *mgr,
|
||||
ServerEnvironment *env);
|
||||
void apply(InventoryManager *mgr, ServerActiveObject *player);
|
||||
};
|
||||
|
||||
/*
|
||||
Craft checking system
|
||||
*/
|
||||
|
||||
enum ItemSpecType
|
||||
{
|
||||
ITEM_NONE,
|
||||
ITEM_MATERIAL,
|
||||
ITEM_CRAFT,
|
||||
ITEM_TOOL,
|
||||
ITEM_MBO
|
||||
};
|
||||
|
||||
struct ItemSpec
|
||||
{
|
||||
enum ItemSpecType type;
|
||||
// Only other one of these is used
|
||||
std::string name;
|
||||
u16 num;
|
||||
|
||||
ItemSpec():
|
||||
type(ITEM_NONE)
|
||||
{
|
||||
}
|
||||
ItemSpec(enum ItemSpecType a_type, std::string a_name):
|
||||
type(a_type),
|
||||
name(a_name),
|
||||
num(65535)
|
||||
{
|
||||
}
|
||||
ItemSpec(enum ItemSpecType a_type, u16 a_num):
|
||||
type(a_type),
|
||||
name(""),
|
||||
num(a_num)
|
||||
{
|
||||
}
|
||||
|
||||
bool checkItem(const InventoryItem *item) const;
|
||||
};
|
||||
|
||||
/*
|
||||
items: a pointer to an array of 9 pointers to items
|
||||
specs: a pointer to an array of 9 ItemSpecs
|
||||
*/
|
||||
bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
|
||||
|
||||
/*
|
||||
items: a pointer to an array of 9 pointers to items
|
||||
specs: a pointer to an array of 9 pointers to items
|
||||
*/
|
||||
bool checkItemCombination(const InventoryItem * const * items,
|
||||
const InventoryItem * const * specs);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -39,6 +39,8 @@ typedef core::vector2d<s32> v2s32;
|
||||
typedef core::vector2d<u32> v2u32;
|
||||
typedef core::vector2d<f32> v2f32;
|
||||
|
||||
typedef core::aabbox3d<f32> aabb3f;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Windows
|
||||
typedef unsigned long long u64;
|
||||
|
502
src/itemdef.cpp
Normal file
502
src/itemdef.cpp
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2011 Kahrl <kahrl@gmx.net>
|
||||
|
||||
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 "itemdef.h"
|
||||
|
||||
#include "gamedef.h"
|
||||
#include "nodedef.h"
|
||||
#include "materials.h"
|
||||
#include "inventory.h"
|
||||
#ifndef SERVER
|
||||
#include "mapblock_mesh.h"
|
||||
#include "mesh.h"
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "log.h"
|
||||
#include "utility.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
/*
|
||||
ItemDefinition
|
||||
*/
|
||||
ItemDefinition::ItemDefinition()
|
||||
{
|
||||
resetInitial();
|
||||
}
|
||||
|
||||
ItemDefinition::ItemDefinition(const ItemDefinition &def)
|
||||
{
|
||||
resetInitial();
|
||||
*this = def;
|
||||
}
|
||||
|
||||
ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
||||
{
|
||||
if(this == &def)
|
||||
return *this;
|
||||
|
||||
reset();
|
||||
|
||||
type = def.type;
|
||||
name = def.name;
|
||||
description = def.description;
|
||||
inventory_image = def.inventory_image;
|
||||
wield_image = def.wield_image;
|
||||
wield_scale = def.wield_scale;
|
||||
stack_max = def.stack_max;
|
||||
usable = def.usable;
|
||||
liquids_pointable = def.liquids_pointable;
|
||||
if(def.tool_digging_properties)
|
||||
{
|
||||
tool_digging_properties = new ToolDiggingProperties(
|
||||
*def.tool_digging_properties);
|
||||
}
|
||||
#ifndef SERVER
|
||||
inventory_texture = def.inventory_texture;
|
||||
if(def.wield_mesh)
|
||||
{
|
||||
wield_mesh = def.wield_mesh;
|
||||
wield_mesh->grab();
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
ItemDefinition::~ItemDefinition()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void ItemDefinition::resetInitial()
|
||||
{
|
||||
// Initialize pointers to NULL so reset() does not delete undefined pointers
|
||||
tool_digging_properties = NULL;
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
wield_mesh = NULL;
|
||||
#endif
|
||||
reset();
|
||||
}
|
||||
|
||||
void ItemDefinition::reset()
|
||||
{
|
||||
type = ITEM_NONE;
|
||||
name = "";
|
||||
description = "";
|
||||
inventory_image = "";
|
||||
wield_image = "";
|
||||
wield_scale = v3f(1.0, 1.0, 1.0);
|
||||
stack_max = 99;
|
||||
usable = false;
|
||||
liquids_pointable = false;
|
||||
if(tool_digging_properties)
|
||||
{
|
||||
delete tool_digging_properties;
|
||||
tool_digging_properties = NULL;
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
if(wield_mesh)
|
||||
{
|
||||
wield_mesh->drop();
|
||||
wield_mesh = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ItemDefinition::serialize(std::ostream &os) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
writeU8(os, type);
|
||||
os<<serializeString(name);
|
||||
os<<serializeString(description);
|
||||
os<<serializeString(inventory_image);
|
||||
os<<serializeString(wield_image);
|
||||
writeV3F1000(os, wield_scale);
|
||||
writeS16(os, stack_max);
|
||||
writeU8(os, usable);
|
||||
writeU8(os, liquids_pointable);
|
||||
std::string tool_digging_properties_s = "";
|
||||
if(tool_digging_properties)
|
||||
{
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
tool_digging_properties->serialize(tmp_os);
|
||||
tool_digging_properties_s = tmp_os.str();
|
||||
}
|
||||
os<<serializeString(tool_digging_properties_s);
|
||||
}
|
||||
|
||||
void ItemDefinition::deSerialize(std::istream &is)
|
||||
{
|
||||
// Reset everything
|
||||
reset();
|
||||
|
||||
// Deserialize
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
throw SerializationError("unsupported ItemDefinition version");
|
||||
type = (enum ItemType)readU8(is);
|
||||
name = deSerializeString(is);
|
||||
description = deSerializeString(is);
|
||||
inventory_image = deSerializeString(is);
|
||||
wield_image = deSerializeString(is);
|
||||
wield_scale = readV3F1000(is);
|
||||
stack_max = readS16(is);
|
||||
usable = readU8(is);
|
||||
liquids_pointable = readU8(is);
|
||||
std::string tool_digging_properties_s = deSerializeString(is);
|
||||
if(!tool_digging_properties_s.empty())
|
||||
{
|
||||
std::istringstream tmp_is(tool_digging_properties_s, std::ios::binary);
|
||||
tool_digging_properties = new ToolDiggingProperties;
|
||||
tool_digging_properties->deSerialize(tmp_is);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CItemDefManager
|
||||
*/
|
||||
|
||||
// SUGG: Support chains of aliases?
|
||||
|
||||
class CItemDefManager: public IWritableItemDefManager
|
||||
{
|
||||
public:
|
||||
CItemDefManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
virtual ~CItemDefManager()
|
||||
{
|
||||
}
|
||||
virtual const ItemDefinition& get(const std::string &name_) const
|
||||
{
|
||||
// Convert name according to possible alias
|
||||
std::string name = getAlias(name_);
|
||||
// Get the definition
|
||||
std::map<std::string, ItemDefinition*>::const_iterator i;
|
||||
i = m_item_definitions.find(name);
|
||||
if(i == m_item_definitions.end())
|
||||
i = m_item_definitions.find("unknown");
|
||||
assert(i != m_item_definitions.end());
|
||||
return *(i->second);
|
||||
}
|
||||
virtual std::string getAlias(const std::string &name) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i;
|
||||
i = m_aliases.find(name);
|
||||
if(i != m_aliases.end())
|
||||
return i->second;
|
||||
return name;
|
||||
}
|
||||
virtual std::set<std::string> getAll() const
|
||||
{
|
||||
std::set<std::string> result;
|
||||
for(std::map<std::string, ItemDefinition*>::const_iterator
|
||||
i = m_item_definitions.begin();
|
||||
i != m_item_definitions.end(); i++)
|
||||
{
|
||||
result.insert(i->first);
|
||||
}
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_aliases.begin();
|
||||
i != m_aliases.end(); i++)
|
||||
{
|
||||
result.insert(i->first);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
virtual bool isKnown(const std::string &name_) const
|
||||
{
|
||||
// Convert name according to possible alias
|
||||
std::string name = getAlias(name_);
|
||||
// Get the definition
|
||||
std::map<std::string, ItemDefinition*>::const_iterator i;
|
||||
return m_item_definitions.find(name) != m_item_definitions.end();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
for(std::map<std::string, ItemDefinition*>::const_iterator
|
||||
i = m_item_definitions.begin();
|
||||
i != m_item_definitions.end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
m_item_definitions.clear();
|
||||
m_aliases.clear();
|
||||
|
||||
// Add the four builtin items:
|
||||
// "" is the hand
|
||||
// "unknown" is returned whenever an undefined item is accessed
|
||||
// "air" is the air node
|
||||
// "ignore" is the ignore node
|
||||
|
||||
ItemDefinition* hand_def = new ItemDefinition;
|
||||
hand_def->name = "";
|
||||
hand_def->wield_image = "wieldhand.png";
|
||||
hand_def->tool_digging_properties = new ToolDiggingProperties;
|
||||
m_item_definitions.insert(std::make_pair("", hand_def));
|
||||
|
||||
ItemDefinition* unknown_def = new ItemDefinition;
|
||||
unknown_def->name = "unknown";
|
||||
m_item_definitions.insert(std::make_pair("unknown", unknown_def));
|
||||
|
||||
ItemDefinition* air_def = new ItemDefinition;
|
||||
air_def->type = ITEM_NODE;
|
||||
air_def->name = "air";
|
||||
m_item_definitions.insert(std::make_pair("air", air_def));
|
||||
|
||||
ItemDefinition* ignore_def = new ItemDefinition;
|
||||
ignore_def->type = ITEM_NODE;
|
||||
ignore_def->name = "ignore";
|
||||
m_item_definitions.insert(std::make_pair("ignore", ignore_def));
|
||||
}
|
||||
virtual void registerItem(const ItemDefinition &def)
|
||||
{
|
||||
infostream<<"ItemDefManager: registering \""<<def.name<<"\""<<std::endl;
|
||||
// Ensure that the "" item (the hand) always has ToolDiggingProperties
|
||||
if(def.name == "")
|
||||
assert(def.tool_digging_properties != NULL);
|
||||
|
||||
m_item_definitions[def.name] = new ItemDefinition(def);
|
||||
|
||||
// Remove conflicting alias if it exists
|
||||
bool alias_removed = (m_aliases.erase(def.name) != 0);
|
||||
if(alias_removed)
|
||||
infostream<<"ItemDefManager: erased alias "<<def.name
|
||||
<<" because item was defined"<<std::endl;
|
||||
}
|
||||
virtual void registerAlias(const std::string &name,
|
||||
const std::string &convert_to)
|
||||
{
|
||||
if(m_item_definitions.find(name) == m_item_definitions.end())
|
||||
{
|
||||
infostream<<"ItemDefManager: setting alias "<<name
|
||||
<<" -> "<<convert_to<<std::endl;
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void updateTexturesAndMeshes(IGameDef *gamedef)
|
||||
{
|
||||
#ifndef SERVER
|
||||
infostream<<"ItemDefManager::updateTexturesAndMeshes(): Updating "
|
||||
<<"textures and meshes in item definitions"<<std::endl;
|
||||
|
||||
ITextureSource *tsrc = gamedef->getTextureSource();
|
||||
INodeDefManager *nodedef = gamedef->getNodeDefManager();
|
||||
IrrlichtDevice *device = tsrc->getDevice();
|
||||
video::IVideoDriver *driver = device->getVideoDriver();
|
||||
|
||||
for(std::map<std::string, ItemDefinition*>::iterator
|
||||
i = m_item_definitions.begin();
|
||||
i != m_item_definitions.end(); i++)
|
||||
{
|
||||
ItemDefinition *def = i->second;
|
||||
|
||||
bool need_node_mesh = false;
|
||||
|
||||
// Create an inventory texture
|
||||
def->inventory_texture = NULL;
|
||||
if(def->inventory_image != "")
|
||||
{
|
||||
def->inventory_texture = tsrc->getTextureRaw(def->inventory_image);
|
||||
}
|
||||
else if(def->type == ITEM_NODE)
|
||||
{
|
||||
need_node_mesh = true;
|
||||
}
|
||||
|
||||
// Create a wield mesh
|
||||
if(def->wield_mesh != NULL)
|
||||
{
|
||||
def->wield_mesh->drop();
|
||||
def->wield_mesh = NULL;
|
||||
}
|
||||
if(def->type == ITEM_NODE && def->wield_image == "")
|
||||
{
|
||||
need_node_mesh = true;
|
||||
}
|
||||
else if(def->wield_image != "" || def->inventory_image != "")
|
||||
{
|
||||
// Extrude the wield image into a mesh
|
||||
|
||||
std::string imagename;
|
||||
if(def->wield_image != "")
|
||||
imagename = def->wield_image;
|
||||
else
|
||||
imagename = def->inventory_image;
|
||||
|
||||
def->wield_mesh = createExtrudedMesh(
|
||||
tsrc->getTextureRaw(imagename),
|
||||
driver,
|
||||
def->wield_scale * v3f(40.0, 40.0, 4.0));
|
||||
if(def->wield_mesh == NULL)
|
||||
{
|
||||
infostream<<"ItemDefManager: WARNING: "
|
||||
<<"updateTexturesAndMeshes(): "
|
||||
<<"Unable to create extruded mesh for item "
|
||||
<<def->name<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if(need_node_mesh)
|
||||
{
|
||||
/*
|
||||
Get node properties
|
||||
*/
|
||||
content_t id = nodedef->getId(def->name);
|
||||
const ContentFeatures &f = nodedef->get(id);
|
||||
|
||||
/*
|
||||
Make a mesh from the node
|
||||
*/
|
||||
MeshMakeData mesh_make_data;
|
||||
MapNode mesh_make_node(
|
||||
id,
|
||||
(f.param_type == CPT_LIGHT) ? 0xee : 0,
|
||||
0);
|
||||
mesh_make_data.fillSingleNode(1000, &mesh_make_node);
|
||||
scene::IMesh *node_mesh =
|
||||
makeMapBlockMesh(&mesh_make_data, gamedef);
|
||||
setMeshColor(node_mesh, video::SColor(255, 255, 255, 255));
|
||||
|
||||
/*
|
||||
Scale and translate the mesh so it's a unit cube
|
||||
centered on the origin
|
||||
*/
|
||||
scaleMesh(node_mesh, v3f(1.0/BS, 1.0/BS, 1.0/BS));
|
||||
translateMesh(node_mesh, v3f(-1.0, -1.0, -1.0));
|
||||
|
||||
/*
|
||||
Draw node mesh into a render target texture
|
||||
*/
|
||||
if(def->inventory_texture == NULL && node_mesh != NULL)
|
||||
{
|
||||
core::dimension2d<u32> dim(64,64);
|
||||
std::string rtt_texture_name = "INVENTORY_"
|
||||
+ def->name + "_RTT";
|
||||
v3f camera_position(0, 1.0, -1.5);
|
||||
camera_position.rotateXZBy(45);
|
||||
v3f camera_lookat(0, 0, 0);
|
||||
core::CMatrix4<f32> camera_projection_matrix;
|
||||
// Set orthogonal projection
|
||||
camera_projection_matrix.buildProjectionMatrixOrthoLH(
|
||||
1.65, 1.65, 0, 100);
|
||||
|
||||
video::SColorf ambient_light(0.2,0.2,0.2);
|
||||
v3f light_position(10, 100, -50);
|
||||
video::SColorf light_color(0.5,0.5,0.5);
|
||||
f32 light_radius = 1000;
|
||||
|
||||
def->inventory_texture = generateTextureFromMesh(
|
||||
node_mesh, device, dim, rtt_texture_name,
|
||||
camera_position,
|
||||
camera_lookat,
|
||||
camera_projection_matrix,
|
||||
ambient_light,
|
||||
light_position,
|
||||
light_color,
|
||||
light_radius);
|
||||
// Note: might have returned NULL
|
||||
}
|
||||
|
||||
/*
|
||||
Use the node mesh as the wield mesh
|
||||
*/
|
||||
if(def->wield_mesh == NULL && node_mesh != NULL)
|
||||
{
|
||||
// Scale to proper wield mesh proportions
|
||||
scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0)
|
||||
* def->wield_scale);
|
||||
def->wield_mesh = node_mesh;
|
||||
def->wield_mesh->grab();
|
||||
}
|
||||
|
||||
|
||||
if(node_mesh != NULL)
|
||||
node_mesh->drop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
u16 count = m_item_definitions.size();
|
||||
writeU16(os, count);
|
||||
for(std::map<std::string, ItemDefinition*>::const_iterator
|
||||
i = m_item_definitions.begin();
|
||||
i != m_item_definitions.end(); i++)
|
||||
{
|
||||
ItemDefinition *def = i->second;
|
||||
// Serialize ItemDefinition and write wrapped in a string
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
def->serialize(tmp_os);
|
||||
os<<serializeString(tmp_os.str());
|
||||
}
|
||||
writeU16(os, m_aliases.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_aliases.begin(); i != m_aliases.end(); i++)
|
||||
{
|
||||
os<<serializeString(i->first);
|
||||
os<<serializeString(i->second);
|
||||
}
|
||||
}
|
||||
void deSerialize(std::istream &is)
|
||||
{
|
||||
// Clear everything
|
||||
clear();
|
||||
// Deserialize
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
throw SerializationError("unsupported ItemDefManager version");
|
||||
u16 count = readU16(is);
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
// Deserialize a string and grab an ItemDefinition from it
|
||||
std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
|
||||
ItemDefinition def;
|
||||
def.deSerialize(tmp_is);
|
||||
// Register
|
||||
registerItem(def);
|
||||
}
|
||||
u16 num_aliases = readU16(is);
|
||||
for(u16 i=0; i<num_aliases; i++)
|
||||
{
|
||||
std::string name = deSerializeString(is);
|
||||
std::string convert_to = deSerializeString(is);
|
||||
registerAlias(name, convert_to);
|
||||
}
|
||||
}
|
||||
private:
|
||||
// Key is name
|
||||
std::map<std::string, ItemDefinition*> m_item_definitions;
|
||||
// Aliases
|
||||
std::map<std::string, std::string> m_aliases;
|
||||
};
|
||||
|
||||
IWritableItemDefManager* createItemDefManager()
|
||||
{
|
||||
return new CItemDefManager();
|
||||
}
|
||||
|
147
src/itemdef.h
Normal file
147
src/itemdef.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2011 Kahrl <kahrl@gmx.net>
|
||||
|
||||
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 ITEMDEF_HEADER
|
||||
#define ITEMDEF_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
class IGameDef;
|
||||
struct ToolDiggingProperties;
|
||||
|
||||
/*
|
||||
Base item definition
|
||||
*/
|
||||
|
||||
enum ItemType
|
||||
{
|
||||
ITEM_NONE,
|
||||
ITEM_NODE,
|
||||
ITEM_CRAFT,
|
||||
ITEM_TOOL,
|
||||
};
|
||||
|
||||
struct ItemDefinition
|
||||
{
|
||||
/*
|
||||
Basic item properties
|
||||
*/
|
||||
ItemType type;
|
||||
std::string name; // "" = hand
|
||||
std::string description; // Shown in tooltip.
|
||||
|
||||
/*
|
||||
Visual properties
|
||||
*/
|
||||
std::string inventory_image; // Optional for nodes, mandatory for tools/craftitems
|
||||
std::string wield_image; // If empty, inventory_image or mesh (only nodes) is used
|
||||
v3f wield_scale;
|
||||
|
||||
/*
|
||||
Item stack and interaction properties
|
||||
*/
|
||||
s16 stack_max;
|
||||
bool usable;
|
||||
bool liquids_pointable;
|
||||
// May be NULL. If non-NULL, deleted by destructor
|
||||
ToolDiggingProperties *tool_digging_properties;
|
||||
|
||||
/*
|
||||
Cached stuff
|
||||
*/
|
||||
#ifndef SERVER
|
||||
video::ITexture *inventory_texture;
|
||||
scene::IMesh *wield_mesh;
|
||||
#endif
|
||||
|
||||
/*
|
||||
Some helpful methods
|
||||
*/
|
||||
ItemDefinition();
|
||||
ItemDefinition(const ItemDefinition &def);
|
||||
ItemDefinition& operator=(const ItemDefinition &def);
|
||||
~ItemDefinition();
|
||||
void reset();
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is);
|
||||
private:
|
||||
void resetInitial();
|
||||
};
|
||||
|
||||
class IItemDefManager
|
||||
{
|
||||
public:
|
||||
IItemDefManager(){}
|
||||
virtual ~IItemDefManager(){}
|
||||
|
||||
// Get item definition
|
||||
virtual const ItemDefinition& get(const std::string &name) const=0;
|
||||
// Get alias definition
|
||||
virtual std::string getAlias(const std::string &name) const=0;
|
||||
// Get set of all defined item names and aliases
|
||||
virtual std::set<std::string> getAll() const=0;
|
||||
// Check if item is known
|
||||
virtual bool isKnown(const std::string &name) const=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
};
|
||||
|
||||
class IWritableItemDefManager : public IItemDefManager
|
||||
{
|
||||
public:
|
||||
IWritableItemDefManager(){}
|
||||
virtual ~IWritableItemDefManager(){}
|
||||
|
||||
// Get item definition
|
||||
virtual const ItemDefinition& get(const std::string &name) const=0;
|
||||
// Get alias definition
|
||||
virtual std::string getAlias(const std::string &name) const=0;
|
||||
// Get set of all defined item names and aliases
|
||||
virtual std::set<std::string> getAll() const=0;
|
||||
// Check if item is known
|
||||
virtual bool isKnown(const std::string &name) const=0;
|
||||
|
||||
// Remove all registered item and node definitions and aliases
|
||||
// Then re-add the builtin item definitions
|
||||
virtual void clear()=0;
|
||||
// Register item definition
|
||||
virtual void registerItem(const ItemDefinition &def)=0;
|
||||
// Set an alias so that items named <name> will load as <convert_to>.
|
||||
// Alias is not set if <name> has already been defined.
|
||||
// Alias will be removed if <name> is defined at a later point of time.
|
||||
virtual void registerAlias(const std::string &name,
|
||||
const std::string &convert_to)=0;
|
||||
|
||||
/*
|
||||
Update inventory textures and wield meshes to latest
|
||||
return values of ITextureSource and INodeDefManager.
|
||||
Call after updating the texture atlas of a texture source.
|
||||
*/
|
||||
virtual void updateTexturesAndMeshes(IGameDef *gamedef)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
IWritableItemDefManager* createItemDefManager();
|
||||
|
||||
#endif
|
@ -30,6 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "log.h"
|
||||
#include "nameidmapping.h"
|
||||
#include "content_mapnode.h" // For legacy name-id mapping
|
||||
#ifndef SERVER
|
||||
#include "mapblock_mesh.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
MapBlock
|
||||
|
@ -32,9 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "voxel.h"
|
||||
#include "staticobject.h"
|
||||
#include "mapblock_nodemod.h"
|
||||
#ifndef SERVER
|
||||
#include "mapblock_mesh.h"
|
||||
#endif
|
||||
#include "modifiedstate.h"
|
||||
|
||||
class Map;
|
||||
|
@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "profiler.h"
|
||||
#include "nodedef.h"
|
||||
#include "tile.h"
|
||||
#include "gamedef.h"
|
||||
#include "content_mapblock.h"
|
||||
#include "mineral.h" // For mineral_block_texture
|
||||
@ -83,6 +82,39 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||
}
|
||||
}
|
||||
|
||||
void MeshMakeData::fillSingleNode(u32 daynight_ratio, MapNode *node)
|
||||
{
|
||||
m_daynight_ratio = daynight_ratio;
|
||||
m_blockpos = v3s16(0,0,0);
|
||||
m_temp_mods.clear();
|
||||
|
||||
v3s16 blockpos_nodes = v3s16(0,0,0);
|
||||
VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
|
||||
blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1));
|
||||
s32 volume = area.getVolume();
|
||||
s32 our_node_index = area.index(1,1,1);
|
||||
|
||||
// Allocate this block + neighbors
|
||||
m_vmanip.clear();
|
||||
m_vmanip.addArea(area);
|
||||
|
||||
// Fill in data
|
||||
MapNode *data = new MapNode[volume];
|
||||
for(s32 i = 0; i < volume; i++)
|
||||
{
|
||||
if(i == our_node_index)
|
||||
{
|
||||
data[i] = *node;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0);
|
||||
}
|
||||
}
|
||||
m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent());
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
/*
|
||||
vertex_dirs: v3s16[4]
|
||||
*/
|
||||
@ -207,8 +239,8 @@ static void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
|
||||
else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y;
|
||||
else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z;
|
||||
|
||||
v3f zerovector = v3f(0,0,0);
|
||||
|
||||
v3f normal(dir.X, dir.Y, dir.Z);
|
||||
|
||||
u8 alpha = tile.alpha;
|
||||
/*u8 alpha = 255;
|
||||
if(tile.id == TILE_WATER)
|
||||
@ -230,16 +262,16 @@ static void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
|
||||
face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), c,
|
||||
core::vector2d<f32>(x0+w*abs_scale, y0));*/
|
||||
|
||||
face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0),
|
||||
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
|
||||
MapBlock_LightColor(alpha, li0),
|
||||
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
||||
face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0),
|
||||
face.vertices[1] = video::S3DVertex(vertex_pos[1], normal,
|
||||
MapBlock_LightColor(alpha, li1),
|
||||
core::vector2d<f32>(x0, y0+h));
|
||||
face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0),
|
||||
face.vertices[2] = video::S3DVertex(vertex_pos[2], normal,
|
||||
MapBlock_LightColor(alpha, li2),
|
||||
core::vector2d<f32>(x0, y0));
|
||||
face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0),
|
||||
face.vertices[3] = video::S3DVertex(vertex_pos[3], normal,
|
||||
MapBlock_LightColor(alpha, li3),
|
||||
core::vector2d<f32>(x0+w*abs_scale, y0));
|
||||
|
||||
@ -309,8 +341,8 @@ static TileSpec getTile(const MapNode &node, v3s16 dir,
|
||||
Gets node tile from any place relative to block.
|
||||
Returns TILE_NODE if doesn't exist or should not be drawn.
|
||||
*/
|
||||
static TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
NodeModMap &temp_mods, ITextureSource *tsrc, INodeDefManager *ndef)
|
||||
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
NodeModMap *temp_mods, ITextureSource *tsrc, INodeDefManager *ndef)
|
||||
{
|
||||
TileSpec spec;
|
||||
spec = getTile(mn, face_dir, tsrc, ndef);
|
||||
@ -325,13 +357,15 @@ static TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
{
|
||||
struct NodeMod mod = n->getValue();*/
|
||||
NodeMod mod;
|
||||
if(temp_mods.get(p, &mod))
|
||||
if(temp_mods && temp_mods->get(p, &mod))
|
||||
{
|
||||
#if 0 // NODEMOD_CHANGECONTENT isn't used at the moment
|
||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||
{
|
||||
MapNode mn2(mod.param);
|
||||
spec = getTile(mn2, face_dir, tsrc, ndef);
|
||||
}
|
||||
#endif
|
||||
if(mod.type == NODEMOD_CRACK)
|
||||
{
|
||||
/*
|
||||
@ -361,19 +395,14 @@ static TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
return spec;
|
||||
}
|
||||
|
||||
static content_t getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
|
||||
static content_t getNodeContent(v3s16 p, MapNode mn, NodeModMap *temp_mods)
|
||||
{
|
||||
/*
|
||||
Check temporary modifications on this node
|
||||
*/
|
||||
/*core::map<v3s16, NodeMod>::Node *n;
|
||||
n = m_temp_mods.find(p);
|
||||
// If modified
|
||||
if(n != NULL)
|
||||
{
|
||||
struct NodeMod mod = n->getValue();*/
|
||||
#if 0 // NODEMOD_CHANGECONTENT isn't used at the moment
|
||||
NodeMod mod;
|
||||
if(temp_mods.get(p, &mod))
|
||||
if(temp_mods && temp_mods->get(p, &mod))
|
||||
{
|
||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||
{
|
||||
@ -395,6 +424,7 @@ static content_t getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return mn.getContent();
|
||||
}
|
||||
@ -469,7 +499,7 @@ static void getTileInfo(
|
||||
v3s16 face_dir,
|
||||
u32 daynight_ratio,
|
||||
VoxelManipulator &vmanip,
|
||||
NodeModMap &temp_mods,
|
||||
NodeModMap *temp_mods,
|
||||
bool smooth_lighting,
|
||||
IGameDef *gamedef,
|
||||
// Output:
|
||||
@ -553,7 +583,7 @@ static void updateFastFaceRow(
|
||||
v3s16 face_dir,
|
||||
v3f face_dir_f,
|
||||
core::array<FastFace> &dest,
|
||||
NodeModMap &temp_mods,
|
||||
NodeModMap *temp_mods,
|
||||
VoxelManipulator &vmanip,
|
||||
v3s16 blockpos_nodes,
|
||||
bool smooth_lighting,
|
||||
@ -749,7 +779,7 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data, IGameDef *gamedef)
|
||||
v3s16(0,1,0), //face dir
|
||||
v3f (0,1,0),
|
||||
fastfaces_new,
|
||||
data->m_temp_mods,
|
||||
&data->m_temp_mods,
|
||||
data->m_vmanip,
|
||||
blockpos_nodes,
|
||||
smooth_lighting,
|
||||
@ -768,7 +798,7 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data, IGameDef *gamedef)
|
||||
v3s16(1,0,0),
|
||||
v3f (1,0,0),
|
||||
fastfaces_new,
|
||||
data->m_temp_mods,
|
||||
&data->m_temp_mods,
|
||||
data->m_vmanip,
|
||||
blockpos_nodes,
|
||||
smooth_lighting,
|
||||
@ -787,7 +817,7 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data, IGameDef *gamedef)
|
||||
v3s16(0,0,1),
|
||||
v3f (0,0,1),
|
||||
fastfaces_new,
|
||||
data->m_temp_mods,
|
||||
&data->m_temp_mods,
|
||||
data->m_vmanip,
|
||||
blockpos_nodes,
|
||||
smooth_lighting,
|
||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "mapblock_nodemod.h"
|
||||
#include "tile.h"
|
||||
#include "voxel.h"
|
||||
|
||||
class IGameDef;
|
||||
@ -125,6 +126,8 @@ private:
|
||||
|
||||
// Helper functions
|
||||
video::SColor MapBlock_LightColor(u8 alpha, u8 light);
|
||||
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
NodeModMap *temp_mods, ITextureSource *tsrc, INodeDefManager *ndef);
|
||||
|
||||
class MapBlock;
|
||||
|
||||
@ -140,6 +143,11 @@ struct MeshMakeData
|
||||
parent of block.
|
||||
*/
|
||||
void fill(u32 daynight_ratio, MapBlock *block);
|
||||
|
||||
/*
|
||||
Set up with only a single node at (1,1,1)
|
||||
*/
|
||||
void fillSingleNode(u32 daynight_ratio, MapNode *node);
|
||||
};
|
||||
|
||||
// This is the highest-level function in here
|
||||
|
@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "materials.h"
|
||||
#include "mapnode.h"
|
||||
#include "nodedef.h"
|
||||
#include "tooldef.h"
|
||||
#include "utility.h"
|
||||
|
||||
void MaterialProperties::serialize(std::ostream &os)
|
||||
@ -49,6 +48,56 @@ void MaterialProperties::deSerialize(std::istream &is)
|
||||
flammability = readF1000(is);
|
||||
}
|
||||
|
||||
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),
|
||||
dt_crumbliness(d),
|
||||
dt_cuttability(e),
|
||||
basedurability(f),
|
||||
dd_weight(g),
|
||||
dd_crackiness(h),
|
||||
dd_crumbliness(i),
|
||||
dd_cuttability(j)
|
||||
{}
|
||||
|
||||
void ToolDiggingProperties::serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
writeF1000(os, full_punch_interval);
|
||||
writeF1000(os, basetime);
|
||||
writeF1000(os, dt_weight);
|
||||
writeF1000(os, dt_crackiness);
|
||||
writeF1000(os, dt_crumbliness);
|
||||
writeF1000(os, dt_cuttability);
|
||||
writeF1000(os, basedurability);
|
||||
writeF1000(os, dd_weight);
|
||||
writeF1000(os, dd_crackiness);
|
||||
writeF1000(os, dd_crumbliness);
|
||||
writeF1000(os, dd_cuttability);
|
||||
}
|
||||
|
||||
void ToolDiggingProperties::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
"unsupported ToolDiggingProperties version");
|
||||
full_punch_interval = readF1000(is);
|
||||
basetime = readF1000(is);
|
||||
dt_weight = readF1000(is);
|
||||
dt_crackiness = readF1000(is);
|
||||
dt_crumbliness = readF1000(is);
|
||||
dt_cuttability = readF1000(is);
|
||||
basedurability = readF1000(is);
|
||||
dd_weight = readF1000(is);
|
||||
dd_crackiness = readF1000(is);
|
||||
dd_crumbliness = readF1000(is);
|
||||
dd_cuttability = readF1000(is);
|
||||
}
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch)
|
||||
{
|
||||
|
@ -72,6 +72,29 @@ struct MaterialProperties
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
struct ToolDiggingProperties
|
||||
{
|
||||
// time = basetime + sum(feature here * feature in MaterialProperties)
|
||||
float full_punch_interval;
|
||||
float basetime;
|
||||
float dt_weight;
|
||||
float dt_crackiness;
|
||||
float dt_crumbliness;
|
||||
float dt_cuttability;
|
||||
float basedurability;
|
||||
float dd_weight;
|
||||
float dd_crackiness;
|
||||
float dd_crumbliness;
|
||||
float dd_cuttability;
|
||||
|
||||
ToolDiggingProperties(float full_punch_interval_=2.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);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
struct DiggingProperties
|
||||
{
|
||||
bool diggable;
|
||||
@ -87,7 +110,6 @@ struct DiggingProperties
|
||||
{}
|
||||
};
|
||||
|
||||
struct ToolDiggingProperties;
|
||||
class INodeDefManager;
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
|
117
src/mesh.cpp
117
src/mesh.cpp
@ -18,8 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "mesh.h"
|
||||
#include "log.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <IAnimatedMesh.h>
|
||||
#include <SAnimatedMesh.h>
|
||||
#include <ICameraSceneNode.h>
|
||||
|
||||
// In Irrlicht 1.8 the signature of ITexture::lock was changed from
|
||||
// (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
|
||||
@ -73,9 +77,15 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
// Set default material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add mesh buffer to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||
@ -280,6 +290,13 @@ scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||
}
|
||||
img1->drop();
|
||||
}
|
||||
|
||||
// Set default material
|
||||
mesh->getMeshBuffer(0)->getMaterial().setTexture(0, texture);
|
||||
mesh->getMeshBuffer(0)->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
mesh->getMeshBuffer(0)->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
mesh->getMeshBuffer(0)->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
scaleMesh(mesh, scale); // also recalculates bounding box
|
||||
return mesh;
|
||||
}
|
||||
@ -313,6 +330,35 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
|
||||
mesh->setBoundingBox(bbox);
|
||||
}
|
||||
|
||||
void translateMesh(scene::IMesh *mesh, v3f vec)
|
||||
{
|
||||
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 += vec;
|
||||
}
|
||||
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)
|
||||
@ -360,3 +406,74 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
video::ITexture *generateTextureFromMesh(scene::IMesh *mesh,
|
||||
IrrlichtDevice *device,
|
||||
core::dimension2d<u32> dim,
|
||||
std::string texture_name,
|
||||
v3f camera_position,
|
||||
v3f camera_lookat,
|
||||
core::CMatrix4<f32> camera_projection_matrix,
|
||||
video::SColorf ambient_light,
|
||||
v3f light_position,
|
||||
video::SColorf light_color,
|
||||
f32 light_radius)
|
||||
{
|
||||
video::IVideoDriver *driver = device->getVideoDriver();
|
||||
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
||||
{
|
||||
errorstream<<"generateTextureFromMesh(): EVDF_RENDER_TO_TARGET"
|
||||
" not supported."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create render target texture
|
||||
video::ITexture *rtt = driver->addRenderTargetTexture(
|
||||
dim, texture_name.c_str(), video::ECF_A8R8G8B8);
|
||||
if(rtt == NULL)
|
||||
{
|
||||
errorstream<<"generateTextureFromMesh(): addRenderTargetTexture"
|
||||
" returned NULL."<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set render target
|
||||
driver->setRenderTarget(rtt, true, true, video::SColor(0,0,0,0));
|
||||
|
||||
// Get a scene manager
|
||||
scene::ISceneManager *smgr_main = device->getSceneManager();
|
||||
assert(smgr_main);
|
||||
scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
|
||||
assert(smgr);
|
||||
|
||||
scene::IMeshSceneNode* meshnode = smgr->addMeshSceneNode(mesh, NULL, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
||||
meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||
meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
|
||||
meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
|
||||
|
||||
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
|
||||
camera_position, camera_lookat);
|
||||
// second parameter of setProjectionMatrix (isOrthogonal) is ignored
|
||||
camera->setProjectionMatrix(camera_projection_matrix, false);
|
||||
|
||||
smgr->setAmbientLight(ambient_light);
|
||||
smgr->addLightSceneNode(0, light_position, light_color, light_radius);
|
||||
|
||||
// Render scene
|
||||
driver->beginScene(true, true, video::SColor(0,0,0,0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
|
||||
// NOTE: The scene nodes should not be dropped, otherwise
|
||||
// smgr->drop() segfaults
|
||||
/*cube->drop();
|
||||
camera->drop();
|
||||
light->drop();*/
|
||||
// Drop scene manager
|
||||
smgr->drop();
|
||||
|
||||
// Unset render target
|
||||
driver->setRenderTarget(0, true, true, 0);
|
||||
|
||||
return rtt;
|
||||
}
|
||||
|
22
src/mesh.h
22
src/mesh.h
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MESH_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
Create a new cube mesh.
|
||||
@ -47,6 +48,11 @@ scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||
*/
|
||||
void scaleMesh(scene::IMesh *mesh, v3f scale);
|
||||
|
||||
/*
|
||||
Translate each vertex coordinate by the specified vector.
|
||||
*/
|
||||
void translateMesh(scene::IMesh *mesh, v3f vec);
|
||||
|
||||
/*
|
||||
Set a constant color for all vertices in the mesh
|
||||
*/
|
||||
@ -63,4 +69,20 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
|
||||
const video::SColor &colorY,
|
||||
const video::SColor &colorZ);
|
||||
|
||||
/*
|
||||
Render a mesh to a texture.
|
||||
Returns NULL if render-to-texture failed.
|
||||
*/
|
||||
video::ITexture *generateTextureFromMesh(scene::IMesh *mesh,
|
||||
IrrlichtDevice *device,
|
||||
core::dimension2d<u32> dim,
|
||||
std::string texture_name,
|
||||
v3f camera_position,
|
||||
v3f camera_lookat,
|
||||
core::CMatrix4<f32> camera_projection_matrix,
|
||||
video::SColorf ambient_light,
|
||||
v3f light_position,
|
||||
video::SColorf light_color,
|
||||
f32 light_radius);
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "mineral.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
|
||||
const char *mineral_filenames[MINERAL_COUNT] =
|
||||
@ -47,5 +48,15 @@ std::string mineral_block_texture(u8 mineral)
|
||||
return mineral_textures[mineral];
|
||||
}
|
||||
|
||||
ItemStack getDiggedMineralItem(u8 mineral, IGameDef *gamedef)
|
||||
{
|
||||
if(mineral == MINERAL_COAL)
|
||||
return ItemStack("default:coal_lump", 1, 0, "", gamedef->idef());
|
||||
else if(mineral == MINERAL_IRON)
|
||||
return ItemStack("default:iron_lump", 1, 0, "", gamedef->idef());
|
||||
else
|
||||
return ItemStack();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -38,19 +38,10 @@ void init_mineral();
|
||||
|
||||
#define MINERAL_COUNT 3
|
||||
|
||||
std::string mineral_block_texture(u8 mineral);
|
||||
|
||||
class IGameDef;
|
||||
|
||||
inline CraftItem * getDiggedMineralItem(u8 mineral, IGameDef *gamedef)
|
||||
{
|
||||
if(mineral == MINERAL_COAL)
|
||||
return new CraftItem(gamedef, "lump_of_coal", 1);
|
||||
else if(mineral == MINERAL_IRON)
|
||||
return new CraftItem(gamedef, "lump_of_iron", 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
std::string mineral_block_texture(u8 mineral);
|
||||
ItemStack getDiggedMineralItem(u8 mineral, IGameDef *gamedef);
|
||||
|
||||
#endif
|
||||
|
||||
|
199
src/nodedef.cpp
199
src/nodedef.cpp
@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
|
||||
#include "main.h" // For g_settings
|
||||
#include "nodemetadata.h"
|
||||
#include "itemdef.h"
|
||||
#ifndef SERVER
|
||||
#include "tile.h"
|
||||
#endif
|
||||
@ -103,8 +103,6 @@ void ContentFeatures::reset()
|
||||
Cached stuff
|
||||
*/
|
||||
#ifndef SERVER
|
||||
inventory_texture = NULL;
|
||||
|
||||
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
|
||||
special_materials[j] = NULL;
|
||||
special_aps[j] = NULL;
|
||||
@ -113,7 +111,6 @@ void ContentFeatures::reset()
|
||||
visual_solidness = 0;
|
||||
backface_culling = true;
|
||||
#endif
|
||||
used_texturenames.clear();
|
||||
/*
|
||||
Actual data
|
||||
|
||||
@ -127,7 +124,6 @@ void ContentFeatures::reset()
|
||||
tname_tiles[i] = "";
|
||||
for(u16 j=0; j<CF_SPECIAL_COUNT; j++)
|
||||
mspec_special[j] = MaterialSpec();
|
||||
tname_inventory = "";
|
||||
alpha = 255;
|
||||
post_effect_color = video::SColor(0, 0, 0, 0);
|
||||
param_type = CPT_NONE;
|
||||
@ -140,7 +136,6 @@ void ContentFeatures::reset()
|
||||
climbable = false;
|
||||
buildable_to = false;
|
||||
wall_mounted = false;
|
||||
often_contains_mineral = false;
|
||||
dug_item = "";
|
||||
extra_dug_item = "";
|
||||
extra_dug_item_rarity = 2;
|
||||
@ -153,21 +148,20 @@ void ContentFeatures::reset()
|
||||
damage_per_second = 0;
|
||||
selection_box = NodeBox();
|
||||
material = MaterialProperties();
|
||||
cookresult_item = ""; // Cannot be cooked
|
||||
furnace_cooktime = 3.0;
|
||||
furnace_burntime = -1.0; // Cannot be burned
|
||||
// Make unknown blocks diggable
|
||||
material.diggability = DIGGABLE_CONSTANT;
|
||||
material.constant_time = 0.5;
|
||||
}
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
writeU8(os, 1); // version
|
||||
os<<serializeString(name);
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
os<<serializeString(tname_tiles[i]);
|
||||
os<<serializeString(tname_inventory);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
mspec_special[i].serialize(os);
|
||||
@ -187,7 +181,6 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU8(os, climbable);
|
||||
writeU8(os, buildable_to);
|
||||
writeU8(os, wall_mounted);
|
||||
writeU8(os, often_contains_mineral);
|
||||
os<<serializeString(dug_item);
|
||||
os<<serializeString(extra_dug_item);
|
||||
writeS32(os, extra_dug_item_rarity);
|
||||
@ -200,15 +193,12 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU32(os, damage_per_second);
|
||||
selection_box.serialize(os);
|
||||
material.serialize(os);
|
||||
os<<serializeString(cookresult_item);
|
||||
writeF1000(os, furnace_cooktime);
|
||||
writeF1000(os, furnace_burntime);
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
if(version != 1)
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
name = deSerializeString(is);
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
@ -216,9 +206,7 @@ void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
if(readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i=0; i<6; i++)
|
||||
setTexture(i, deSerializeString(is));
|
||||
//tname_tiles[i] = deSerializeString(is);
|
||||
tname_inventory = deSerializeString(is);
|
||||
tname_tiles[i] = deSerializeString(is);
|
||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
@ -239,7 +227,6 @@ void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
climbable = readU8(is);
|
||||
buildable_to = readU8(is);
|
||||
wall_mounted = readU8(is);
|
||||
often_contains_mineral = readU8(is);
|
||||
dug_item = deSerializeString(is);
|
||||
extra_dug_item = deSerializeString(is);
|
||||
extra_dug_item_rarity = readS32(is);
|
||||
@ -252,53 +239,6 @@ void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
damage_per_second = readU32(is);
|
||||
selection_box.deSerialize(is);
|
||||
material.deSerialize(is);
|
||||
cookresult_item = deSerializeString(is);
|
||||
furnace_cooktime = readF1000(is);
|
||||
furnace_burntime = readF1000(is);
|
||||
}
|
||||
|
||||
void ContentFeatures::setTexture(u16 i, std::string name)
|
||||
{
|
||||
used_texturenames.insert(name);
|
||||
tname_tiles[i] = name;
|
||||
if(tname_inventory == "")
|
||||
tname_inventory = name;
|
||||
}
|
||||
|
||||
void ContentFeatures::setAllTextures(std::string name)
|
||||
{
|
||||
for(u16 i=0; i<6; i++)
|
||||
setTexture(i, name);
|
||||
// Force inventory texture too
|
||||
setInventoryTexture(name);
|
||||
}
|
||||
|
||||
void ContentFeatures::setSpecialMaterial(u16 i, const MaterialSpec &mspec)
|
||||
{
|
||||
assert(i < CF_SPECIAL_COUNT);
|
||||
mspec_special[i] = mspec;
|
||||
}
|
||||
|
||||
void ContentFeatures::setInventoryTexture(std::string imgname)
|
||||
{
|
||||
tname_inventory = imgname;
|
||||
}
|
||||
|
||||
void ContentFeatures::setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right)
|
||||
{
|
||||
str_replace_char(top, '^', '&');
|
||||
str_replace_char(left, '^', '&');
|
||||
str_replace_char(right, '^', '&');
|
||||
|
||||
std::string imgname_full;
|
||||
imgname_full += "[inventorycube{";
|
||||
imgname_full += top;
|
||||
imgname_full += "{";
|
||||
imgname_full += left;
|
||||
imgname_full += "{";
|
||||
imgname_full += right;
|
||||
tname_inventory = imgname_full;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -311,14 +251,12 @@ public:
|
||||
void clear()
|
||||
{
|
||||
m_name_id_mapping.clear();
|
||||
m_name_id_mapping_with_aliases.clear();
|
||||
|
||||
m_aliases.clear();
|
||||
|
||||
for(u16 i=0; i<=MAX_CONTENT; i++)
|
||||
{
|
||||
ContentFeatures &f = m_content_features[i];
|
||||
f.reset(); // Reset to defaults
|
||||
f.setAllTextures("unknown_block.png");
|
||||
}
|
||||
|
||||
// Set CONTENT_AIR
|
||||
@ -336,7 +274,7 @@ public:
|
||||
// Insert directly into containers
|
||||
content_t c = CONTENT_AIR;
|
||||
m_content_features[c] = f;
|
||||
m_name_id_mapping.set(c, f.name);
|
||||
addNameIdMapping(c, f.name);
|
||||
}
|
||||
// Set CONTENT_IGNORE
|
||||
{
|
||||
@ -354,7 +292,7 @@ public:
|
||||
// Insert directly into containers
|
||||
content_t c = CONTENT_IGNORE;
|
||||
m_content_features[c] = f;
|
||||
m_name_id_mapping.set(c, f.name);
|
||||
addNameIdMapping(c, f.name);
|
||||
}
|
||||
}
|
||||
// CONTENT_IGNORE = not found
|
||||
@ -401,12 +339,14 @@ public:
|
||||
{
|
||||
return get(n.getContent());
|
||||
}
|
||||
virtual bool getId(const std::string &name_, content_t &result) const
|
||||
virtual bool getId(const std::string &name, content_t &result) const
|
||||
{
|
||||
// Convert name according to possible alias
|
||||
std::string name = getAlias(name_);
|
||||
// Get id
|
||||
return m_name_id_mapping.getId(name, result);
|
||||
std::map<std::string, content_t>::const_iterator
|
||||
i = m_name_id_mapping_with_aliases.find(name);
|
||||
if(i == m_name_id_mapping_with_aliases.end())
|
||||
return false;
|
||||
result = i->second;
|
||||
return true;
|
||||
}
|
||||
virtual content_t getId(const std::string &name) const
|
||||
{
|
||||
@ -420,14 +360,6 @@ public:
|
||||
getId(name, id);
|
||||
return get(id);
|
||||
}
|
||||
virtual std::string getAlias(const std::string &name) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i;
|
||||
i = m_aliases.find(name);
|
||||
if(i != m_aliases.end())
|
||||
return i->second;
|
||||
return name;
|
||||
}
|
||||
// IWritableNodeDefManager
|
||||
virtual void set(content_t c, const ContentFeatures &def)
|
||||
{
|
||||
@ -451,20 +383,14 @@ public:
|
||||
}
|
||||
m_content_features[c] = def;
|
||||
if(def.name != "")
|
||||
m_name_id_mapping.set(c, def.name);
|
||||
|
||||
// Remove conflicting alias if it exists
|
||||
bool alias_removed = (m_aliases.erase(def.name) != 0);
|
||||
if(alias_removed)
|
||||
infostream<<"ndef: erased alias "<<def.name
|
||||
<<" because node was defined"<<std::endl;
|
||||
addNameIdMapping(c, def.name);
|
||||
}
|
||||
virtual content_t set(const std::string &name,
|
||||
const ContentFeatures &def)
|
||||
{
|
||||
assert(name == def.name);
|
||||
u16 id = CONTENT_IGNORE;
|
||||
bool found = m_name_id_mapping.getId(name, id);
|
||||
bool found = m_name_id_mapping.getId(name, id); // ignore aliases
|
||||
if(!found){
|
||||
// Determine if full param2 is required
|
||||
bool require_full_param2 = (
|
||||
@ -481,7 +407,7 @@ public:
|
||||
if(id == CONTENT_IGNORE)
|
||||
return CONTENT_IGNORE;
|
||||
if(name != "")
|
||||
m_name_id_mapping.set(id, name);
|
||||
addNameIdMapping(id, name);
|
||||
}
|
||||
set(id, def);
|
||||
return id;
|
||||
@ -491,23 +417,27 @@ public:
|
||||
assert(name != "");
|
||||
ContentFeatures f;
|
||||
f.name = name;
|
||||
f.setAllTextures("unknown_block.png");
|
||||
// Make unknown blocks diggable
|
||||
f.material.diggability = DIGGABLE_NORMAL;
|
||||
f.material.diggability = DIGGABLE_CONSTANT;
|
||||
f.material.constant_time = 0.5;
|
||||
return set(name, f);
|
||||
}
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)
|
||||
virtual void updateAliases(IItemDefManager *idef)
|
||||
{
|
||||
content_t id;
|
||||
if(getId(name, id)){
|
||||
infostream<<"ndef: not setting alias "<<name<<" -> "<<convert_to
|
||||
<<": "<<name<<" is already defined"<<std::endl;
|
||||
return;
|
||||
std::set<std::string> all = idef->getAll();
|
||||
m_name_id_mapping_with_aliases.clear();
|
||||
for(std::set<std::string>::iterator
|
||||
i = all.begin(); i != all.end(); i++)
|
||||
{
|
||||
std::string name = *i;
|
||||
std::string convert_to = idef->getAlias(name);
|
||||
content_t id;
|
||||
if(m_name_id_mapping.getId(convert_to, id))
|
||||
{
|
||||
m_name_id_mapping_with_aliases.insert(
|
||||
std::make_pair(name, id));
|
||||
}
|
||||
}
|
||||
infostream<<"ndef: setting alias "<<name<<" -> "<<convert_to
|
||||
<<std::endl;
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
virtual void updateTextures(ITextureSource *tsrc)
|
||||
{
|
||||
@ -523,6 +453,14 @@ public:
|
||||
{
|
||||
ContentFeatures *f = &m_content_features[i];
|
||||
|
||||
std::string tname_tiles[6];
|
||||
for(u32 j=0; j<6; j++)
|
||||
{
|
||||
tname_tiles[j] = f->tname_tiles[j];
|
||||
if(tname_tiles[j] == "")
|
||||
tname_tiles[j] = "unknown_block.png";
|
||||
}
|
||||
|
||||
switch(f->drawtype){
|
||||
default:
|
||||
case NDT_NORMAL:
|
||||
@ -567,8 +505,7 @@ public:
|
||||
f->drawtype = NDT_NORMAL;
|
||||
f->solidness = 2;
|
||||
for(u32 i=0; i<6; i++){
|
||||
f->setTexture(i, f->tname_tiles[i]
|
||||
+ std::string("^[noalpha"));
|
||||
tname_tiles[i] += std::string("^[noalpha");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -581,16 +518,9 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
// Inventory texture
|
||||
if(f->tname_inventory != "")
|
||||
f->inventory_texture = tsrc->getTextureRaw(f->tname_inventory);
|
||||
else
|
||||
f->inventory_texture = NULL;
|
||||
// Tile textures
|
||||
for(u16 j=0; j<6; j++){
|
||||
if(f->tname_tiles[j] == "")
|
||||
continue;
|
||||
f->tiles[j].texture = tsrc->getTexture(f->tname_tiles[j]);
|
||||
f->tiles[j].texture = tsrc->getTexture(tname_tiles[j]);
|
||||
f->tiles[j].alpha = f->alpha;
|
||||
if(f->alpha == 255)
|
||||
f->tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
||||
@ -649,16 +579,8 @@ public:
|
||||
}
|
||||
writeU16(os, count);
|
||||
os<<serializeLongString(tmp_os.str());
|
||||
|
||||
writeU16(os, m_aliases.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_aliases.begin(); i != m_aliases.end(); i++)
|
||||
{
|
||||
os<<serializeString(i->first);
|
||||
os<<serializeString(i->second);
|
||||
}
|
||||
}
|
||||
void deSerialize(std::istream &is, IGameDef *gamedef)
|
||||
void deSerialize(std::istream &is)
|
||||
{
|
||||
clear();
|
||||
u16 count = readU16(is);
|
||||
@ -674,27 +596,26 @@ public:
|
||||
if(i == CONTENT_IGNORE || i == CONTENT_AIR)
|
||||
continue;*/
|
||||
ContentFeatures *f = &m_content_features[i];
|
||||
f->deSerialize(tmp_is, gamedef);
|
||||
f->deSerialize(tmp_is);
|
||||
if(f->name != "")
|
||||
m_name_id_mapping.set(i, f->name);
|
||||
}
|
||||
|
||||
u16 num_aliases = readU16(is);
|
||||
if(!is.eof()){
|
||||
for(u16 i=0; i<num_aliases; i++){
|
||||
std::string name = deSerializeString(is);
|
||||
std::string convert_to = deSerializeString(is);
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
addNameIdMapping(i, f->name);
|
||||
}
|
||||
}
|
||||
private:
|
||||
void addNameIdMapping(content_t i, std::string name)
|
||||
{
|
||||
m_name_id_mapping.set(i, name);
|
||||
m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
|
||||
}
|
||||
private:
|
||||
// Features indexed by id
|
||||
ContentFeatures m_content_features[MAX_CONTENT+1];
|
||||
// A mapping for fast converting back and forth between names and ids
|
||||
NameIdMapping m_name_id_mapping;
|
||||
// Aliases
|
||||
std::map<std::string, std::string> m_aliases;
|
||||
// Like m_name_id_mapping, but only from names to ids, and includes
|
||||
// item aliases too. Updated by updateAliases()
|
||||
// Note: Not serialized.
|
||||
std::map<std::string, content_t> m_name_id_mapping_with_aliases;
|
||||
};
|
||||
|
||||
IWritableNodeDefManager* createNodeDefManager()
|
||||
|
@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "tile.h"
|
||||
#endif
|
||||
#include "materials.h" // MaterialProperties
|
||||
class IItemDefManager;
|
||||
class ITextureSource;
|
||||
class IGameDef;
|
||||
|
||||
@ -124,7 +125,6 @@ struct ContentFeatures
|
||||
// 0 1 2 3 4 5
|
||||
// up down right left back front
|
||||
TileSpec tiles[6];
|
||||
video::ITexture *inventory_texture;
|
||||
// Special material/texture
|
||||
// - Currently used for flowing liquids
|
||||
video::SMaterial *special_materials[CF_SPECIAL_COUNT];
|
||||
@ -133,11 +133,7 @@ struct ContentFeatures
|
||||
u8 visual_solidness; // When solidness=0, this tells how it looks like
|
||||
bool backface_culling;
|
||||
#endif
|
||||
|
||||
// List of textures that are used and are wanted to be included in
|
||||
// the texture atlas
|
||||
std::set<std::string> used_texturenames;
|
||||
|
||||
|
||||
/*
|
||||
Actual data
|
||||
*/
|
||||
@ -148,7 +144,6 @@ struct ContentFeatures
|
||||
enum NodeDrawType drawtype;
|
||||
float visual_scale; // Misc. scale parameter
|
||||
std::string tname_tiles[6];
|
||||
std::string tname_inventory;
|
||||
MaterialSpec mspec_special[CF_SPECIAL_COUNT]; // Use setter methods
|
||||
u8 alpha;
|
||||
|
||||
@ -174,10 +169,6 @@ struct ContentFeatures
|
||||
// If true, param2 is set to direction when placed. Used for torches.
|
||||
// NOTE: the direction format is quite inefficient and should be changed
|
||||
bool wall_mounted;
|
||||
// Whether this content type often contains mineral.
|
||||
// Used for texture atlas creation.
|
||||
// Currently only enabled for CONTENT_STONE.
|
||||
bool often_contains_mineral;
|
||||
// Inventory item string as which the node appears in inventory when dug.
|
||||
// Mineral overrides this.
|
||||
std::string dug_item;
|
||||
@ -202,9 +193,6 @@ struct ContentFeatures
|
||||
u32 damage_per_second;
|
||||
NodeBox selection_box;
|
||||
MaterialProperties material;
|
||||
std::string cookresult_item;
|
||||
float furnace_cooktime;
|
||||
float furnace_burntime;
|
||||
|
||||
/*
|
||||
Methods
|
||||
@ -214,22 +202,8 @@ struct ContentFeatures
|
||||
~ContentFeatures();
|
||||
void reset();
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is, IGameDef *gamedef);
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
/*
|
||||
Texture setters.
|
||||
|
||||
*/
|
||||
|
||||
// Texture setters. They also add stuff to used_texturenames.
|
||||
void setTexture(u16 i, std::string name);
|
||||
void setAllTextures(std::string name);
|
||||
void setSpecialMaterial(u16 i, const MaterialSpec &mspec);
|
||||
|
||||
void setInventoryTexture(std::string imgname);
|
||||
void setInventoryTextureCube(std::string top,
|
||||
std::string left, std::string right);
|
||||
|
||||
/*
|
||||
Some handy methods
|
||||
*/
|
||||
@ -253,7 +227,6 @@ public:
|
||||
virtual bool getId(const std::string &name, content_t &result) const=0;
|
||||
virtual content_t getId(const std::string &name) const=0;
|
||||
virtual const ContentFeatures& get(const std::string &name) const=0;
|
||||
virtual std::string getAlias(const std::string &name) const =0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
};
|
||||
@ -271,8 +244,7 @@ public:
|
||||
virtual content_t getId(const std::string &name) const=0;
|
||||
// If not found, returns the features of CONTENT_IGNORE
|
||||
virtual const ContentFeatures& get(const std::string &name) const=0;
|
||||
virtual std::string getAlias(const std::string &name) const =0;
|
||||
|
||||
|
||||
// Register node definition
|
||||
virtual void set(content_t c, const ContentFeatures &def)=0;
|
||||
// Register node definition by name (allocate an id)
|
||||
@ -281,11 +253,12 @@ public:
|
||||
const ContentFeatures &def)=0;
|
||||
// If returns CONTENT_IGNORE, could not allocate id
|
||||
virtual content_t allocateDummy(const std::string &name)=0;
|
||||
// Set an alias so that nodes named <name> will load as <convert_to>.
|
||||
// Alias is not set if <name> has already been defined.
|
||||
// Alias will be removed if <name> is defined at a later point of time.
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)=0;
|
||||
|
||||
/*
|
||||
Update item alias mapping.
|
||||
Call after updating item definitions.
|
||||
*/
|
||||
virtual void updateAliases(IItemDefManager *idef)=0;
|
||||
|
||||
/*
|
||||
Update tile textures to latest return values of TextueSource.
|
||||
@ -294,7 +267,7 @@ public:
|
||||
virtual void updateTextures(ITextureSource *tsrc)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void deSerialize(std::istream &is, IGameDef *gamedef)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
IWritableNodeDefManager* createNodeDefManager();
|
||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "main.h" // For g_settings
|
||||
#include "settings.h"
|
||||
#include "nodedef.h"
|
||||
#include "collision.h"
|
||||
#include "environment.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
@ -37,13 +38,13 @@ Player::Player(IGameDef *gamedef):
|
||||
in_water_stable(false),
|
||||
is_climbing(false),
|
||||
swimming_up(false),
|
||||
inventory(gamedef->idef()),
|
||||
inventory_backup(NULL),
|
||||
craftresult_is_preview(true),
|
||||
hp(20),
|
||||
peer_id(PEER_ID_INEXISTENT),
|
||||
// protected
|
||||
m_gamedef(gamedef),
|
||||
m_selected_item(0),
|
||||
m_pitch(0),
|
||||
m_yaw(0),
|
||||
m_speed(0,0,0),
|
||||
@ -58,11 +59,6 @@ Player::~Player()
|
||||
delete inventory_backup;
|
||||
}
|
||||
|
||||
void Player::wieldItem(u16 item)
|
||||
{
|
||||
m_selected_item = item;
|
||||
}
|
||||
|
||||
void Player::resetInventory()
|
||||
{
|
||||
inventory.clear();
|
||||
@ -172,7 +168,7 @@ void Player::deSerialize(std::istream &is)
|
||||
hp = 20;
|
||||
}
|
||||
|
||||
inventory.deSerialize(is, m_gamedef);
|
||||
inventory.deSerialize(is);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
|
14
src/player.h
14
src/player.h
@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include "inventory.h"
|
||||
#include "collision.h"
|
||||
|
||||
#define PLAYERNAME_SIZE 20
|
||||
|
||||
@ -31,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
class CollisionInfo;
|
||||
|
||||
class Player
|
||||
{
|
||||
@ -117,16 +117,7 @@ public:
|
||||
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
|
||||
}
|
||||
|
||||
virtual void wieldItem(u16 item);
|
||||
virtual const InventoryItem *getWieldItem() const
|
||||
{
|
||||
const InventoryList *list = inventory.getList("main");
|
||||
if (list)
|
||||
return list->getItem(m_selected_item);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * getName()
|
||||
const char * getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
@ -174,7 +165,6 @@ protected:
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
char m_name[PLAYERNAME_SIZE];
|
||||
u16 m_selected_item;
|
||||
f32 m_pitch;
|
||||
f32 m_yaw;
|
||||
v3f m_speed;
|
||||
|
2739
src/scriptapi.cpp
2739
src/scriptapi.cpp
File diff suppressed because it is too large
Load Diff
@ -27,11 +27,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
class ServerActiveObject;
|
||||
class ServerRemotePlayer;
|
||||
typedef struct lua_State lua_State;
|
||||
struct LuaEntityProperties;
|
||||
class ItemStack;
|
||||
struct PointedThing;
|
||||
//class IGameDef;
|
||||
class ServerRemotePlayer;
|
||||
|
||||
void scriptapi_export(lua_State *L, Server *server);
|
||||
bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
|
||||
@ -66,17 +67,13 @@ void scriptapi_on_dieplayer(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);
|
||||
bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
|
||||
ServerActiveObject *dropper, v3f pos,
|
||||
bool &callback_exists);
|
||||
bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
|
||||
ServerActiveObject *placer, v3f pos,
|
||||
bool &callback_exists);
|
||||
bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
|
||||
ServerActiveObject *user, const PointedThing& pointed,
|
||||
bool &callback_exists);
|
||||
/* item callbacks */
|
||||
bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *dropper, v3f pos);
|
||||
bool scriptapi_item_on_place(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *placer, const PointedThing &pointed);
|
||||
bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *user, const PointedThing &pointed);
|
||||
|
||||
/* luaentity */
|
||||
// Returns true if succesfully added into Lua; false otherwise.
|
||||
|
994
src/server.cpp
994
src/server.cpp
File diff suppressed because it is too large
Load Diff
28
src/server.h
28
src/server.h
@ -36,10 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "inventorymanager.h"
|
||||
struct LuaState;
|
||||
typedef struct lua_State lua_State;
|
||||
class IWritableToolDefManager;
|
||||
class IWritableItemDefManager;
|
||||
class IWritableNodeDefManager;
|
||||
class IWritableCraftDefManager;
|
||||
class IWritableCraftItemDefManager;
|
||||
|
||||
/*
|
||||
Some random functions
|
||||
@ -437,6 +436,7 @@ public:
|
||||
Shall be called with the environment and the connection locked.
|
||||
*/
|
||||
Inventory* getInventory(const InventoryLocation &loc);
|
||||
std::string getInventoryOwner(const InventoryLocation &loc);
|
||||
void setInventoryModified(const InventoryLocation &loc);
|
||||
|
||||
// Connection must be locked when called
|
||||
@ -514,17 +514,15 @@ public:
|
||||
|
||||
// IGameDef interface
|
||||
// Under envlock
|
||||
virtual IToolDefManager* getToolDefManager();
|
||||
virtual IItemDefManager* getItemDefManager();
|
||||
virtual INodeDefManager* getNodeDefManager();
|
||||
virtual ICraftDefManager* getCraftDefManager();
|
||||
virtual ICraftItemDefManager* getCraftItemDefManager();
|
||||
virtual ITextureSource* getTextureSource();
|
||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||
|
||||
IWritableToolDefManager* getWritableToolDefManager();
|
||||
IWritableItemDefManager* getWritableItemDefManager();
|
||||
IWritableNodeDefManager* getWritableNodeDefManager();
|
||||
IWritableCraftDefManager* getWritableCraftDefManager();
|
||||
IWritableCraftItemDefManager* getWritableCraftItemDefManager();
|
||||
|
||||
const ModSpec* getModSpec(const std::string &modname);
|
||||
|
||||
@ -545,12 +543,10 @@ private:
|
||||
const std::wstring &reason);
|
||||
static void SendDeathscreen(con::Connection &con, u16 peer_id,
|
||||
bool set_camera_point_target, v3f camera_point_target);
|
||||
static void SendToolDef(con::Connection &con, u16 peer_id,
|
||||
IToolDefManager *tooldef);
|
||||
static void SendItemDef(con::Connection &con, u16 peer_id,
|
||||
IItemDefManager *itemdef);
|
||||
static void SendNodeDef(con::Connection &con, u16 peer_id,
|
||||
INodeDefManager *nodedef);
|
||||
static void SendCraftItemDef(con::Connection &con, u16 peer_id,
|
||||
ICraftItemDefManager *nodedef);
|
||||
|
||||
/*
|
||||
Non-static send methods.
|
||||
@ -562,7 +558,7 @@ private:
|
||||
// Envlock and conlock should be locked when calling these
|
||||
void SendInventory(u16 peer_id);
|
||||
// send wielded item info about player to all
|
||||
void SendWieldedItem(const Player *player);
|
||||
void SendWieldedItem(const ServerRemotePlayer *srp);
|
||||
// send wielded item info about all players to all players
|
||||
void SendPlayerItems();
|
||||
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
||||
@ -599,6 +595,7 @@ private:
|
||||
void HandlePlayerHP(Player *player, s16 damage);
|
||||
void RespawnPlayer(Player *player);
|
||||
|
||||
bool GetCraftingResult(u16 peer_id, ItemStack &result, bool decrementInput);
|
||||
void UpdateCrafting(u16 peer_id);
|
||||
|
||||
// When called, connection mutex should be locked
|
||||
@ -664,8 +661,8 @@ private:
|
||||
// Envlock and conlock should be locked when using Lua
|
||||
lua_State *m_lua;
|
||||
|
||||
// Tool definition manager
|
||||
IWritableToolDefManager *m_toolmgr;
|
||||
// Item definition manager
|
||||
IWritableItemDefManager *m_itemdef;
|
||||
|
||||
// Node definition manager
|
||||
IWritableNodeDefManager *m_nodedef;
|
||||
@ -673,9 +670,6 @@ private:
|
||||
// Craft definition manager
|
||||
IWritableCraftDefManager *m_craftdef;
|
||||
|
||||
// CraftItem definition manager
|
||||
IWritableCraftItemDefManager *m_craftitemdef;
|
||||
|
||||
// Mods
|
||||
core::list<ModSpec> m_mods;
|
||||
|
||||
@ -740,7 +734,7 @@ private:
|
||||
core::list<std::string> m_modspaths;
|
||||
|
||||
bool m_shutdown_requested;
|
||||
|
||||
|
||||
/*
|
||||
Map edit event queue. Automatically receives all map edits.
|
||||
The constructor of this class registers us to receive them through
|
||||
|
@ -20,7 +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"
|
||||
#include "materials.h"
|
||||
|
||||
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
|
||||
ActiveObject(0),
|
||||
@ -67,10 +67,31 @@ void ServerActiveObject::registerType(u16 type, Factory f)
|
||||
m_types.insert(type, f);
|
||||
}
|
||||
|
||||
void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
|
||||
ItemStack ServerActiveObject::getWieldedItem() const
|
||||
{
|
||||
*dst = ToolDiggingProperties();
|
||||
const Inventory *inv = getInventory();
|
||||
if(inv)
|
||||
{
|
||||
const InventoryList *list = inv->getList(getWieldList());
|
||||
if(list)
|
||||
return list->getItem(getWieldIndex());
|
||||
}
|
||||
return ItemStack();
|
||||
}
|
||||
|
||||
|
||||
bool ServerActiveObject::setWieldedItem(const ItemStack &item)
|
||||
{
|
||||
Inventory *inv = getInventory();
|
||||
if(inv)
|
||||
{
|
||||
InventoryList *list = inv->getList(getWieldList());
|
||||
if (list)
|
||||
{
|
||||
list->changeItem(getWieldIndex(), item);
|
||||
setInventoryModified();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "irrlichttypes.h"
|
||||
#include "activeobject.h"
|
||||
#include "utility.h"
|
||||
#include "inventorymanager.h"
|
||||
|
||||
/*
|
||||
|
||||
@ -41,7 +42,7 @@ Some planning
|
||||
*/
|
||||
|
||||
class ServerEnvironment;
|
||||
class InventoryItem;
|
||||
class ItemStack;
|
||||
class Player;
|
||||
struct ToolDiggingProperties;
|
||||
|
||||
@ -138,19 +139,27 @@ public:
|
||||
{}
|
||||
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; }
|
||||
virtual void addToInventoryLater(InventoryItem *item)
|
||||
{}
|
||||
virtual void setHP(s16 hp)
|
||||
{}
|
||||
virtual s16 getHP()
|
||||
{ return 0; }
|
||||
|
||||
// Inventory and wielded item
|
||||
virtual Inventory* getInventory()
|
||||
{ return NULL; }
|
||||
virtual const Inventory* getInventory() const
|
||||
{ return NULL; }
|
||||
virtual InventoryLocation getInventoryLocation() const
|
||||
{ return InventoryLocation(); }
|
||||
virtual void setInventoryModified()
|
||||
{}
|
||||
virtual std::string getWieldList() const
|
||||
{ return ""; }
|
||||
virtual int getWieldIndex() const
|
||||
{ return 0; }
|
||||
virtual ItemStack getWieldedItem() const;
|
||||
virtual bool setWieldedItem(const ItemStack &item);
|
||||
|
||||
/*
|
||||
Number of players which know about this object. Object won't be
|
||||
deleted until this is 0 to keep the id preserved for the right
|
||||
|
@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
#include "gamedef.h"
|
||||
#include "tooldef.h"
|
||||
#include "inventory.h"
|
||||
#include "environment.h"
|
||||
#include "materials.h"
|
||||
|
||||
@ -31,6 +31,7 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
|
||||
ServerActiveObject(env, v3f(0,0,0)),
|
||||
m_last_good_position(0,0,0),
|
||||
m_last_good_position_age(0),
|
||||
m_wield_index(0),
|
||||
m_inventory_not_sent(false),
|
||||
m_hp_not_sent(false),
|
||||
m_respawn_active(false),
|
||||
@ -57,7 +58,6 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
|
||||
}
|
||||
ServerRemotePlayer::~ServerRemotePlayer()
|
||||
{
|
||||
clearAddToInventoryLater();
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::setPosition(const v3f &position)
|
||||
@ -67,12 +67,41 @@ void ServerRemotePlayer::setPosition(const v3f &position)
|
||||
m_position_not_sent = true;
|
||||
}
|
||||
|
||||
InventoryItem* ServerRemotePlayer::getWieldedItem()
|
||||
Inventory* ServerRemotePlayer::getInventory()
|
||||
{
|
||||
InventoryList *list = inventory.getList("main");
|
||||
if (list)
|
||||
return list->getItem(m_selected_item);
|
||||
return NULL;
|
||||
return &inventory;
|
||||
}
|
||||
|
||||
const Inventory* ServerRemotePlayer::getInventory() const
|
||||
{
|
||||
return &inventory;
|
||||
}
|
||||
|
||||
InventoryLocation ServerRemotePlayer::getInventoryLocation() const
|
||||
{
|
||||
InventoryLocation loc;
|
||||
loc.setPlayer(getName());
|
||||
return loc;
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::setInventoryModified()
|
||||
{
|
||||
m_inventory_not_sent = true;
|
||||
}
|
||||
|
||||
std::string ServerRemotePlayer::getWieldList() const
|
||||
{
|
||||
return "main";
|
||||
}
|
||||
|
||||
int ServerRemotePlayer::getWieldIndex() const
|
||||
{
|
||||
return m_wield_index;
|
||||
}
|
||||
|
||||
void ServerRemotePlayer::setWieldIndex(int i)
|
||||
{
|
||||
m_wield_index = i;
|
||||
}
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
@ -156,8 +185,10 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
|
||||
mp.crackiness = -0.5;
|
||||
mp.cuttability = 0.5;
|
||||
|
||||
ToolDiggingProperties tp;
|
||||
puncher->getWieldDiggingProperties(&tp);
|
||||
IItemDefManager *idef = m_env->getGameDef()->idef();
|
||||
ItemStack punchitem = puncher->getWieldedItem();
|
||||
ToolDiggingProperties tp =
|
||||
punchitem.getToolDiggingProperties(idef);
|
||||
|
||||
HittingProperties hitprop = getHittingProperties(&mp, &tp,
|
||||
time_from_last_punch);
|
||||
@ -167,7 +198,8 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
|
||||
<<" HP"<<std::endl;
|
||||
|
||||
setHP(getHP() - hitprop.hp);
|
||||
puncher->damageWieldedItem(hitprop.wear);
|
||||
punchitem.addWear(hitprop.wear, idef);
|
||||
puncher->setWieldedItem(punchitem);
|
||||
|
||||
if(hitprop.hp != 0)
|
||||
{
|
||||
@ -201,109 +233,6 @@ void ServerRemotePlayer::moveTo(v3f pos, bool continuous)
|
||||
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;
|
||||
|
@ -46,9 +46,6 @@ public:
|
||||
|
||||
virtual void setPosition(const v3f &position);
|
||||
|
||||
// Returns a reference
|
||||
virtual InventoryItem* getWieldedItem();
|
||||
|
||||
/* ServerActiveObject interface */
|
||||
|
||||
u8 getType() const
|
||||
@ -77,19 +74,20 @@ public:
|
||||
virtual std::string getDescription()
|
||||
{return std::string("player ")+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 Inventory* getInventory();
|
||||
virtual const Inventory* getInventory() const;
|
||||
virtual InventoryLocation getInventoryLocation() const;
|
||||
virtual void setInventoryModified();
|
||||
virtual std::string getWieldList() const;
|
||||
virtual int getWieldIndex() const;
|
||||
virtual void setWieldIndex(int i);
|
||||
|
||||
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;
|
||||
int m_wield_index;
|
||||
bool m_inventory_not_sent;
|
||||
bool m_hp_not_sent;
|
||||
bool m_respawn_active;
|
||||
|
198
src/test.cpp
198
src/test.cpp
@ -47,6 +47,75 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
assert(exception_thrown);\
|
||||
}
|
||||
|
||||
/*
|
||||
A few item and node definitions for those tests that need them
|
||||
*/
|
||||
|
||||
#define CONTENT_STONE 0
|
||||
#define CONTENT_GRASS 0x800
|
||||
|
||||
void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *ndef)
|
||||
{
|
||||
content_t i;
|
||||
ItemDefinition itemdef;
|
||||
ContentFeatures f;
|
||||
|
||||
/*
|
||||
Stone
|
||||
*/
|
||||
i = CONTENT_STONE;
|
||||
itemdef = ItemDefinition();
|
||||
itemdef.type = ITEM_NODE;
|
||||
itemdef.name = "default:stone";
|
||||
itemdef.description = "Stone";
|
||||
itemdef.inventory_image = "[inventorycube"
|
||||
"{default_stone.png"
|
||||
"{default_stone.png"
|
||||
"{default_stone.png";
|
||||
f = ContentFeatures();
|
||||
f.name = itemdef.name;
|
||||
for(int i = 0; i < 6; i++)
|
||||
f.tname_tiles[i] = "default_stone.png";
|
||||
f.param_type = CPT_MINERAL;
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = itemdef.name;
|
||||
f.material.diggability = DIGGABLE_NORMAL;
|
||||
f.material.weight = 5.0;
|
||||
f.material.crackiness = 1.0;
|
||||
f.material.crumbliness = -0.1;
|
||||
f.material.cuttability = -0.2;
|
||||
idef->registerItem(itemdef);
|
||||
ndef->set(i, f);
|
||||
|
||||
/*
|
||||
Grass
|
||||
*/
|
||||
i = CONTENT_GRASS;
|
||||
itemdef = ItemDefinition();
|
||||
itemdef.type = ITEM_NODE;
|
||||
itemdef.name = "default:dirt_with_grass";
|
||||
itemdef.description = "Dirt with grass";
|
||||
itemdef.inventory_image = "[inventorycube"
|
||||
"{default_grass.png"
|
||||
"{default_dirt.png&default_grass_side.png"
|
||||
"{default_dirt.png&default_grass_side.png";
|
||||
f = ContentFeatures();
|
||||
f.name = itemdef.name;
|
||||
f.tname_tiles[0] = "default_grass.png";
|
||||
f.tname_tiles[1] = "default_dirt.png";
|
||||
for(int i = 2; i < 6; i++)
|
||||
f.tname_tiles[i] = "default_dirt.png^default_grass_side.png";
|
||||
f.is_ground_content = true;
|
||||
f.dug_item = itemdef.name;
|
||||
f.material.diggability = DIGGABLE_NORMAL;
|
||||
f.material.weight = 1.2;
|
||||
f.material.crackiness = 0.0;
|
||||
f.material.crumbliness = 1.2;
|
||||
f.material.cuttability = -0.4;
|
||||
idef->registerItem(itemdef);
|
||||
ndef->set(i, f);
|
||||
}
|
||||
|
||||
struct TestUtilities
|
||||
{
|
||||
void Run()
|
||||
@ -96,7 +165,118 @@ struct TestSettings
|
||||
assert(fabs(s.getV3F("coord2").Z - 3.3) < 0.001);
|
||||
}
|
||||
};
|
||||
|
||||
struct TestSerialization
|
||||
{
|
||||
// To be used like this:
|
||||
// mkstr("Some\0string\0with\0embedded\0nuls")
|
||||
// since std::string("...") doesn't work as expected in that case.
|
||||
template<size_t N> std::string mkstr(const char (&s)[N])
|
||||
{
|
||||
return std::string(s, N - 1);
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
// Tests some serialization primitives
|
||||
|
||||
assert(serializeString("") == mkstr("\0\0"));
|
||||
assert(serializeWideString(L"") == mkstr("\0\0"));
|
||||
assert(serializeLongString("") == mkstr("\0\0\0\0"));
|
||||
assert(serializeJsonString("") == "\"\"");
|
||||
|
||||
std::string teststring = "Hello world!";
|
||||
assert(serializeString(teststring) ==
|
||||
mkstr("\0\14Hello world!"));
|
||||
assert(serializeWideString(narrow_to_wide(teststring)) ==
|
||||
mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"));
|
||||
assert(serializeLongString(teststring) ==
|
||||
mkstr("\0\0\0\14Hello world!"));
|
||||
assert(serializeJsonString(teststring) ==
|
||||
"\"Hello world!\"");
|
||||
|
||||
std::string teststring2;
|
||||
std::wstring teststring2_w;
|
||||
std::string teststring2_w_encoded;
|
||||
{
|
||||
std::ostringstream tmp_os;
|
||||
std::wostringstream tmp_os_w;
|
||||
std::ostringstream tmp_os_w_encoded;
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
tmp_os<<(char)i;
|
||||
tmp_os_w<<(wchar_t)i;
|
||||
tmp_os_w_encoded<<(char)0<<(char)i;
|
||||
}
|
||||
teststring2 = tmp_os.str();
|
||||
teststring2_w = tmp_os_w.str();
|
||||
teststring2_w_encoded = tmp_os_w_encoded.str();
|
||||
}
|
||||
assert(serializeString(teststring2) ==
|
||||
mkstr("\1\0") + teststring2);
|
||||
assert(serializeWideString(teststring2_w) ==
|
||||
mkstr("\1\0") + teststring2_w_encoded);
|
||||
assert(serializeLongString(teststring2) ==
|
||||
mkstr("\0\0\1\0") + teststring2);
|
||||
assert(serializeJsonString(teststring2) ==
|
||||
mkstr("\"") +
|
||||
"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007" +
|
||||
"\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f" +
|
||||
"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017" +
|
||||
"\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f" +
|
||||
" !\\\"" + teststring2.substr(0x23, 0x2f-0x23) +
|
||||
"\\/" + teststring2.substr(0x30, 0x5c-0x30) +
|
||||
"\\\\" + teststring2.substr(0x5d, 0x7f-0x5d) + "\\u007f" +
|
||||
"\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085\\u0086\\u0087" +
|
||||
"\\u0088\\u0089\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f" +
|
||||
"\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097" +
|
||||
"\\u0098\\u0099\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" +
|
||||
"\\u00a0\\u00a1\\u00a2\\u00a3\\u00a4\\u00a5\\u00a6\\u00a7" +
|
||||
"\\u00a8\\u00a9\\u00aa\\u00ab\\u00ac\\u00ad\\u00ae\\u00af" +
|
||||
"\\u00b0\\u00b1\\u00b2\\u00b3\\u00b4\\u00b5\\u00b6\\u00b7" +
|
||||
"\\u00b8\\u00b9\\u00ba\\u00bb\\u00bc\\u00bd\\u00be\\u00bf" +
|
||||
"\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u00c6\\u00c7" +
|
||||
"\\u00c8\\u00c9\\u00ca\\u00cb\\u00cc\\u00cd\\u00ce\\u00cf" +
|
||||
"\\u00d0\\u00d1\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6\\u00d7" +
|
||||
"\\u00d8\\u00d9\\u00da\\u00db\\u00dc\\u00dd\\u00de\\u00df" +
|
||||
"\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u00e6\\u00e7" +
|
||||
"\\u00e8\\u00e9\\u00ea\\u00eb\\u00ec\\u00ed\\u00ee\\u00ef" +
|
||||
"\\u00f0\\u00f1\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6\\u00f7" +
|
||||
"\\u00f8\\u00f9\\u00fa\\u00fb\\u00fc\\u00fd\\u00fe\\u00ff" +
|
||||
"\"");
|
||||
|
||||
{
|
||||
std::istringstream is(serializeString(teststring2), std::ios::binary);
|
||||
assert(deSerializeString(is) == teststring2);
|
||||
assert(!is.eof());
|
||||
is.get();
|
||||
assert(is.eof());
|
||||
}
|
||||
{
|
||||
std::istringstream is(serializeWideString(teststring2_w), std::ios::binary);
|
||||
assert(deSerializeWideString(is) == teststring2_w);
|
||||
assert(!is.eof());
|
||||
is.get();
|
||||
assert(is.eof());
|
||||
}
|
||||
{
|
||||
std::istringstream is(serializeLongString(teststring2), std::ios::binary);
|
||||
assert(deSerializeLongString(is) == teststring2);
|
||||
assert(!is.eof());
|
||||
is.get();
|
||||
assert(is.eof());
|
||||
}
|
||||
{
|
||||
std::istringstream is(serializeJsonString(teststring2), std::ios::binary);
|
||||
//dstream<<serializeJsonString(deSerializeJsonString(is));
|
||||
assert(deSerializeJsonString(is) == teststring2);
|
||||
assert(!is.eof());
|
||||
is.get();
|
||||
assert(is.eof());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TestCompress
|
||||
{
|
||||
void Run()
|
||||
@ -283,11 +463,11 @@ struct TestVoxelManipulator
|
||||
|
||||
infostream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
|
||||
|
||||
v.setNodeNoRef(v3s16(-1,0,-1), MapNode(2));
|
||||
v.setNodeNoRef(v3s16(-1,0,-1), MapNode(CONTENT_GRASS));
|
||||
|
||||
v.print(infostream, nodedef);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == CONTENT_GRASS);
|
||||
|
||||
infostream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
|
||||
|
||||
@ -301,7 +481,7 @@ struct TestVoxelManipulator
|
||||
|
||||
v.print(infostream, nodedef);
|
||||
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
|
||||
assert(v.getNode(v3s16(-1,0,-1)).getContent() == CONTENT_GRASS);
|
||||
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
|
||||
}
|
||||
};
|
||||
@ -1086,16 +1266,18 @@ void run_tests()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
// Create node definitions
|
||||
IWritableNodeDefManager *nodedef = createNodeDefManager();
|
||||
content_mapnode_init(nodedef);
|
||||
// Create item and node definitions
|
||||
IWritableItemDefManager *idef = createItemDefManager();
|
||||
IWritableNodeDefManager *ndef = createNodeDefManager();
|
||||
define_some_nodes(idef, ndef);
|
||||
|
||||
infostream<<"run_tests() started"<<std::endl;
|
||||
TEST(TestUtilities);
|
||||
TEST(TestSettings);
|
||||
TEST(TestCompress);
|
||||
TESTPARAMS(TestMapNode, nodedef);
|
||||
TESTPARAMS(TestVoxelManipulator, nodedef);
|
||||
TEST(TestSerialization);
|
||||
TESTPARAMS(TestMapNode, ndef);
|
||||
TESTPARAMS(TestVoxelManipulator, ndef);
|
||||
//TEST(TestMapBlock);
|
||||
//TEST(TestMapSector);
|
||||
if(INTERNET_SIMULATOR == false){
|
||||
|
182
src/tile.cpp
182
src/tile.cpp
@ -337,6 +337,12 @@ public:
|
||||
return ap.atlas;
|
||||
}
|
||||
|
||||
// Returns a pointer to the irrlicht device
|
||||
virtual IrrlichtDevice* getDevice()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
// Update new texture pointer and texture coordinates to an
|
||||
// AtlasPointer based on it's texture id
|
||||
void updateAP(AtlasPointer &ap);
|
||||
@ -469,8 +475,6 @@ u32 TextureSource::getTextureId(const std::string &name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Draw a progress bar on the image
|
||||
void make_progressbar(float value, video::IImage *image);
|
||||
// Brighten image
|
||||
void brighten(video::IImage *image);
|
||||
|
||||
@ -816,14 +820,12 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
|
||||
if(j == CONTENT_IGNORE || j == CONTENT_AIR)
|
||||
continue;
|
||||
const ContentFeatures &f = ndef->get(j);
|
||||
for(std::set<std::string>::const_iterator
|
||||
i = f.used_texturenames.begin();
|
||||
i != f.used_texturenames.end(); i++)
|
||||
for(u32 i=0; i<6; i++)
|
||||
{
|
||||
std::string name = *i;
|
||||
std::string name = f.tname_tiles[i];
|
||||
sourcelist[name] = true;
|
||||
|
||||
if(f.often_contains_mineral){
|
||||
if(f.param_type == CPT_MINERAL){
|
||||
for(int k=1; k<MINERAL_COUNT; k++){
|
||||
std::string mineraltexture = mineral_block_texture(k);
|
||||
std::string fulltexture = name + "^" + mineraltexture;
|
||||
@ -1316,23 +1318,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
[progressbarN
|
||||
Adds a progress bar, 0.0 <= N <= 1.0
|
||||
*/
|
||||
else if(part_of_name.substr(0,12) == "[progressbar")
|
||||
{
|
||||
if(baseimg == NULL)
|
||||
{
|
||||
errorstream<<"generate_image(): baseimg==NULL "
|
||||
<<"for part_of_name=\""<<part_of_name
|
||||
<<"\", cancelling."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
float value = stof(part_of_name.substr(12));
|
||||
make_progressbar(value, baseimg);
|
||||
}
|
||||
/*
|
||||
"[brighten"
|
||||
*/
|
||||
@ -1442,23 +1427,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
std::string imagename_left = sf.next("{");
|
||||
std::string imagename_right = sf.next("{");
|
||||
|
||||
#if 1
|
||||
// TODO: Create cube with different textures on different sides
|
||||
|
||||
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
||||
{
|
||||
errorstream<<"generate_image(): EVDF_RENDER_TO_TARGET"
|
||||
" not supported. Creating fallback image"<<std::endl;
|
||||
baseimg = generate_image_from_scratch(
|
||||
imagename_top, device, sourcecache);
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 w0 = 64;
|
||||
u32 h0 = 64;
|
||||
//infostream<<"inventorycube w="<<w0<<" h="<<h0<<std::endl;
|
||||
core::dimension2d<u32> dim(w0,h0);
|
||||
|
||||
// Generate images for the faces of the cube
|
||||
video::IImage *img_top = generate_image_from_scratch(
|
||||
imagename_top, device, sourcecache);
|
||||
@ -1482,84 +1450,65 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
img_left->drop();
|
||||
img_right->drop();
|
||||
|
||||
// Create render target texture
|
||||
video::ITexture *rtt = NULL;
|
||||
std::string rtt_name = part_of_name + "_RTT";
|
||||
rtt = driver->addRenderTargetTexture(dim, rtt_name.c_str(),
|
||||
video::ECF_A8R8G8B8);
|
||||
assert(rtt);
|
||||
|
||||
// Set render target
|
||||
driver->setRenderTarget(rtt, true, true,
|
||||
video::SColor(0,0,0,0));
|
||||
|
||||
// Get a scene manager
|
||||
scene::ISceneManager *smgr_main = device->getSceneManager();
|
||||
assert(smgr_main);
|
||||
scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
|
||||
assert(smgr);
|
||||
|
||||
/*
|
||||
Create scene:
|
||||
- An unit cube is centered at 0,0,0
|
||||
- Camera looks at cube from Y+, Z- towards Y-, Z+
|
||||
Draw a cube mesh into a render target texture
|
||||
*/
|
||||
|
||||
scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1));
|
||||
setMeshColor(cube, video::SColor(255, 255, 255, 255));
|
||||
cube->getMeshBuffer(0)->getMaterial().setTexture(0, texture_top);
|
||||
cube->getMeshBuffer(1)->getMaterial().setTexture(0, texture_top);
|
||||
cube->getMeshBuffer(2)->getMaterial().setTexture(0, texture_right);
|
||||
cube->getMeshBuffer(3)->getMaterial().setTexture(0, texture_right);
|
||||
cube->getMeshBuffer(4)->getMaterial().setTexture(0, texture_left);
|
||||
cube->getMeshBuffer(5)->getMaterial().setTexture(0, texture_left);
|
||||
|
||||
scene::IMeshSceneNode* cubenode = smgr->addMeshSceneNode(cube, NULL, -1, v3f(0,0,0), v3f(0,45,0), v3f(1,1,1), true);
|
||||
cube->drop();
|
||||
core::dimension2d<u32> dim(64,64);
|
||||
std::string rtt_texture_name = part_of_name + "_RTT";
|
||||
|
||||
// Set texture of cube
|
||||
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));
|
||||
v3f camera_position(0, 1.0, -1.5);
|
||||
camera_position.rotateXZBy(45);
|
||||
v3f camera_lookat(0, 0, 0);
|
||||
core::CMatrix4<f32> camera_projection_matrix;
|
||||
// Set orthogonal projection
|
||||
core::CMatrix4<f32> pm;
|
||||
pm.buildProjectionMatrixOrthoLH(1.65, 1.65, 0, 100);
|
||||
camera->setProjectionMatrix(pm, true);
|
||||
camera_projection_matrix.buildProjectionMatrixOrthoLH(
|
||||
1.65, 1.65, 0, 100);
|
||||
|
||||
/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
|
||||
v3f(-50, 100, -75), video::SColorf(0.5,0.5,0.5), 1000);
|
||||
video::SColorf ambient_light(0.2,0.2,0.2);
|
||||
v3f light_position(10, 100, -50);
|
||||
video::SColorf light_color(0.5,0.5,0.5);
|
||||
f32 light_radius = 1000;
|
||||
|
||||
smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));
|
||||
|
||||
// Render scene
|
||||
driver->beginScene(true, true, video::SColor(0,0,0,0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
video::ITexture *rtt = generateTextureFromMesh(
|
||||
cube, device, dim, rtt_texture_name,
|
||||
camera_position,
|
||||
camera_lookat,
|
||||
camera_projection_matrix,
|
||||
ambient_light,
|
||||
light_position,
|
||||
light_color,
|
||||
light_radius);
|
||||
|
||||
// NOTE: The scene nodes should not be dropped, otherwise
|
||||
// smgr->drop() segfaults
|
||||
/*cube->drop();
|
||||
camera->drop();
|
||||
light->drop();*/
|
||||
// Drop scene manager
|
||||
smgr->drop();
|
||||
|
||||
// Unset render target
|
||||
driver->setRenderTarget(0, true, true, 0);
|
||||
// Drop mesh
|
||||
cube->drop();
|
||||
|
||||
// Free textures of images
|
||||
driver->removeTexture(texture_top);
|
||||
driver->removeTexture(texture_left);
|
||||
driver->removeTexture(texture_right);
|
||||
|
||||
if(rtt == NULL)
|
||||
{
|
||||
errorstream<<"generate_image(): render to texture failed."
|
||||
" Creating fallback image"<<std::endl;
|
||||
baseimg = generate_image_from_scratch(
|
||||
imagename_top, device, sourcecache);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create image of render target
|
||||
video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);
|
||||
|
||||
assert(image);
|
||||
|
||||
|
||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
if(image)
|
||||
@ -1567,7 +1516,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
image->copyTo(baseimg);
|
||||
image->drop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1579,38 +1527,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||
return true;
|
||||
}
|
||||
|
||||
void make_progressbar(float value, video::IImage *image)
|
||||
{
|
||||
if(image == NULL)
|
||||
return;
|
||||
|
||||
core::dimension2d<u32> size = image->getDimension();
|
||||
|
||||
u32 barheight = size.Height/16;
|
||||
u32 barpad_x = size.Width/16;
|
||||
u32 barpad_y = size.Height/16;
|
||||
u32 barwidth = size.Width - barpad_x*2;
|
||||
v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
|
||||
|
||||
u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
|
||||
|
||||
video::SColor active(255,255,0,0);
|
||||
video::SColor inactive(255,0,0,0);
|
||||
for(u32 x0=0; x0<barwidth; x0++)
|
||||
{
|
||||
video::SColor *c;
|
||||
if(x0 < barvalue_i)
|
||||
c = &active;
|
||||
else
|
||||
c = &inactive;
|
||||
u32 x = x0 + barpos.X;
|
||||
for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
|
||||
{
|
||||
image->setPixel(x,y, *c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void brighten(video::IImage *image)
|
||||
{
|
||||
if(image == NULL)
|
||||
|
@ -110,6 +110,8 @@ public:
|
||||
{return AtlasPointer(0);}
|
||||
virtual video::ITexture* getTextureRaw(const std::string &name)
|
||||
{return NULL;}
|
||||
virtual IrrlichtDevice* getDevice()
|
||||
{return NULL;}
|
||||
virtual void updateAP(AtlasPointer &ap){};
|
||||
};
|
||||
|
||||
@ -126,6 +128,8 @@ public:
|
||||
{return AtlasPointer(0);}
|
||||
virtual video::ITexture* getTextureRaw(const std::string &name)
|
||||
{return NULL;}
|
||||
virtual IrrlichtDevice* getDevice()
|
||||
{return NULL;}
|
||||
virtual void updateAP(AtlasPointer &ap){};
|
||||
|
||||
virtual void processQueue()=0;
|
||||
|
238
src/tooldef.cpp
238
src/tooldef.cpp
@ -1,238 +0,0 @@
|
||||
/*
|
||||
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 "tooldef.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include "utility.h"
|
||||
#include <map>
|
||||
|
||||
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),
|
||||
dt_crumbliness(d),
|
||||
dt_cuttability(e),
|
||||
basedurability(f),
|
||||
dd_weight(g),
|
||||
dd_crackiness(h),
|
||||
dd_crumbliness(i),
|
||||
dd_cuttability(j)
|
||||
{}
|
||||
|
||||
std::string ToolDefinition::dump()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"[ToolDefinition::dump() not implemented due to lazyness]"
|
||||
<<std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void ToolDefinition::serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(imagename);
|
||||
writeF1000(os, properties.basetime);
|
||||
writeF1000(os, properties.dt_weight);
|
||||
writeF1000(os, properties.dt_crackiness);
|
||||
writeF1000(os, properties.dt_crumbliness);
|
||||
writeF1000(os, properties.dt_cuttability);
|
||||
writeF1000(os, properties.basedurability);
|
||||
writeF1000(os, properties.dd_weight);
|
||||
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)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
"unsupported ToolDefinition version");
|
||||
imagename = deSerializeString(is);
|
||||
properties.basetime = readF1000(is);
|
||||
properties.dt_weight = readF1000(is);
|
||||
properties.dt_crackiness = readF1000(is);
|
||||
properties.dt_crumbliness = readF1000(is);
|
||||
properties.dt_cuttability = readF1000(is);
|
||||
properties.basedurability = readF1000(is);
|
||||
properties.dd_weight = readF1000(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
|
||||
{
|
||||
public:
|
||||
virtual ~CToolDefManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
virtual const ToolDefinition* getToolDefinition(const std::string &toolname_) const
|
||||
{
|
||||
// Convert name according to possible alias
|
||||
std::string toolname = getAlias(toolname_);
|
||||
// Get the definition
|
||||
core::map<std::string, ToolDefinition*>::Node *n;
|
||||
n = m_tool_definitions.find(toolname);
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
return n->getValue();
|
||||
}
|
||||
virtual std::string getImagename(const std::string &toolname) const
|
||||
{
|
||||
const ToolDefinition *def = getToolDefinition(toolname);
|
||||
if(def == NULL)
|
||||
return "";
|
||||
return def->imagename;
|
||||
}
|
||||
virtual ToolDiggingProperties getDiggingProperties(
|
||||
const std::string &toolname) const
|
||||
{
|
||||
const ToolDefinition *def = getToolDefinition(toolname);
|
||||
// If tool does not exist, just return an impossible
|
||||
if(def == NULL){
|
||||
// If tool does not exist, try empty name
|
||||
const ToolDefinition *def = getToolDefinition("");
|
||||
if(def == NULL) // If that doesn't exist either, return default
|
||||
return ToolDiggingProperties();
|
||||
return def->properties;
|
||||
}
|
||||
return def->properties;
|
||||
}
|
||||
virtual std::string getAlias(const std::string &name) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i;
|
||||
i = m_aliases.find(name);
|
||||
if(i != m_aliases.end())
|
||||
return i->second;
|
||||
return name;
|
||||
}
|
||||
// IWritableToolDefManager
|
||||
virtual bool registerTool(std::string toolname, const ToolDefinition &def)
|
||||
{
|
||||
infostream<<"registerTool: registering tool \""<<toolname<<"\""<<std::endl;
|
||||
m_tool_definitions[toolname] = new ToolDefinition(def);
|
||||
|
||||
// Remove conflicting alias if it exists
|
||||
bool alias_removed = (m_aliases.erase(toolname) != 0);
|
||||
if(alias_removed)
|
||||
infostream<<"tdef: erased alias "<<toolname
|
||||
<<" because tool was defined"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
virtual void clear()
|
||||
{
|
||||
for(core::map<std::string, ToolDefinition*>::Iterator
|
||||
i = m_tool_definitions.getIterator();
|
||||
i.atEnd() == false; i++){
|
||||
delete i.getNode()->getValue();
|
||||
}
|
||||
m_tool_definitions.clear();
|
||||
m_aliases.clear();
|
||||
}
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)
|
||||
{
|
||||
if(getToolDefinition(name) != NULL){
|
||||
infostream<<"tdef: not setting alias "<<name<<" -> "<<convert_to
|
||||
<<": "<<name<<" is already defined"<<std::endl;
|
||||
return;
|
||||
}
|
||||
infostream<<"tdef: setting alias "<<name<<" -> "<<convert_to
|
||||
<<std::endl;
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
virtual void serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
u16 count = m_tool_definitions.size();
|
||||
writeU16(os, count);
|
||||
for(core::map<std::string, ToolDefinition*>::Iterator
|
||||
i = m_tool_definitions.getIterator();
|
||||
i.atEnd() == false; i++){
|
||||
std::string name = i.getNode()->getKey();
|
||||
ToolDefinition *def = i.getNode()->getValue();
|
||||
// Serialize name
|
||||
os<<serializeString(name);
|
||||
// Serialize ToolDefinition and write wrapped in a string
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
def->serialize(tmp_os);
|
||||
os<<serializeString(tmp_os.str());
|
||||
}
|
||||
|
||||
writeU16(os, m_aliases.size());
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_aliases.begin(); i != m_aliases.end(); i++)
|
||||
{
|
||||
os<<serializeString(i->first);
|
||||
os<<serializeString(i->second);
|
||||
}
|
||||
}
|
||||
virtual void deSerialize(std::istream &is)
|
||||
{
|
||||
// Clear everything
|
||||
clear();
|
||||
// Deserialize
|
||||
int version = readU8(is);
|
||||
if(version != 0) throw SerializationError(
|
||||
"unsupported ToolDefManager version");
|
||||
u16 count = readU16(is);
|
||||
for(u16 i=0; i<count; i++){
|
||||
// Deserialize name
|
||||
std::string name = deSerializeString(is);
|
||||
// Deserialize a string and grab a ToolDefinition from it
|
||||
std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
|
||||
ToolDefinition def;
|
||||
def.deSerialize(tmp_is);
|
||||
// Register
|
||||
registerTool(name, def);
|
||||
}
|
||||
|
||||
u16 num_aliases = readU16(is);
|
||||
if(!is.eof()){
|
||||
for(u16 i=0; i<num_aliases; i++){
|
||||
std::string name = deSerializeString(is);
|
||||
std::string convert_to = deSerializeString(is);
|
||||
m_aliases[name] = convert_to;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
// Key is name
|
||||
core::map<std::string, ToolDefinition*> m_tool_definitions;
|
||||
// Aliases
|
||||
std::map<std::string, std::string> m_aliases;
|
||||
};
|
||||
|
||||
IWritableToolDefManager* createToolDefManager()
|
||||
{
|
||||
return new CToolDefManager();
|
||||
}
|
||||
|
103
src/tooldef.h
103
src/tooldef.h
@ -1,103 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef TOOLDEF_HEADER
|
||||
#define TOOLDEF_HEADER
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
struct ToolDiggingProperties
|
||||
{
|
||||
// time = basetime + sum(feature here * feature in MaterialProperties)
|
||||
float full_punch_interval;
|
||||
float basetime;
|
||||
float dt_weight;
|
||||
float dt_crackiness;
|
||||
float dt_crumbliness;
|
||||
float dt_cuttability;
|
||||
float basedurability;
|
||||
float dd_weight;
|
||||
float dd_crackiness;
|
||||
float dd_crumbliness;
|
||||
float dd_cuttability;
|
||||
|
||||
ToolDiggingProperties(float full_punch_interval_=2.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);
|
||||
};
|
||||
|
||||
struct ToolDefinition
|
||||
{
|
||||
std::string imagename;
|
||||
ToolDiggingProperties properties;
|
||||
|
||||
ToolDefinition(){}
|
||||
ToolDefinition(const std::string &imagename_,
|
||||
ToolDiggingProperties properties_):
|
||||
imagename(imagename_),
|
||||
properties(properties_)
|
||||
{}
|
||||
|
||||
std::string dump();
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
||||
class IToolDefManager
|
||||
{
|
||||
public:
|
||||
IToolDefManager(){}
|
||||
virtual ~IToolDefManager(){}
|
||||
virtual const ToolDefinition* getToolDefinition(const std::string &toolname) const=0;
|
||||
virtual std::string getImagename(const std::string &toolname) const =0;
|
||||
virtual ToolDiggingProperties getDiggingProperties(
|
||||
const std::string &toolname) const =0;
|
||||
virtual std::string getAlias(const std::string &name) const =0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
};
|
||||
|
||||
class IWritableToolDefManager : public IToolDefManager
|
||||
{
|
||||
public:
|
||||
IWritableToolDefManager(){}
|
||||
virtual ~IWritableToolDefManager(){}
|
||||
virtual const ToolDefinition* getToolDefinition(const std::string &toolname) const=0;
|
||||
virtual std::string getImagename(const std::string &toolname) const =0;
|
||||
virtual ToolDiggingProperties getDiggingProperties(
|
||||
const std::string &toolname) const =0;
|
||||
virtual std::string getAlias(const std::string &name) const =0;
|
||||
|
||||
virtual bool registerTool(std::string toolname, const ToolDefinition &def)=0;
|
||||
virtual void clear()=0;
|
||||
// Set an alias so that entries named <name> will load as <convert_to>.
|
||||
// Alias is not set if <name> has already been defined.
|
||||
// Alias will be removed if <name> is defined at a later point of time.
|
||||
virtual void setAlias(const std::string &name,
|
||||
const std::string &convert_to)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
IWritableToolDefManager* createToolDefManager();
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
#include "log.h"
|
||||
#include <iomanip>
|
||||
|
||||
TimeTaker::TimeTaker(const char *name, u32 *result)
|
||||
{
|
||||
@ -234,6 +235,100 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates a string encoded in JSON format (almost equivalent to a C string literal)
|
||||
std::string serializeJsonString(const std::string &plain)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os<<"\"";
|
||||
for(size_t i = 0; i < plain.size(); i++)
|
||||
{
|
||||
char c = plain[i];
|
||||
switch(c)
|
||||
{
|
||||
case '"': os<<"\\\""; break;
|
||||
case '\\': os<<"\\\\"; break;
|
||||
case '/': os<<"\\/"; break;
|
||||
case '\b': os<<"\\b"; break;
|
||||
case '\f': os<<"\\f"; break;
|
||||
case '\n': os<<"\\n"; break;
|
||||
case '\r': os<<"\\r"; break;
|
||||
case '\t': os<<"\\t"; break;
|
||||
default:
|
||||
{
|
||||
if(c >= 32 && c <= 126)
|
||||
{
|
||||
os<<c;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 cnum = (u32) (u8) c;
|
||||
os<<"\\u"<<std::hex<<std::setw(4)<<std::setfill('0')<<cnum;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
os<<"\"";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// Reads a string encoded in JSON format
|
||||
std::string deSerializeJsonString(std::istream &is)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
char c, c2;
|
||||
|
||||
// Parse initial doublequote
|
||||
is >> c;
|
||||
if(c != '"')
|
||||
throw SerializationError("JSON string must start with doublequote");
|
||||
|
||||
// Parse characters
|
||||
for(;;)
|
||||
{
|
||||
c = is.get();
|
||||
if(is.eof())
|
||||
throw SerializationError("JSON string ended prematurely");
|
||||
if(c == '"')
|
||||
{
|
||||
return os.str();
|
||||
}
|
||||
else if(c == '\\')
|
||||
{
|
||||
c2 = is.get();
|
||||
if(is.eof())
|
||||
throw SerializationError("JSON string ended prematurely");
|
||||
switch(c2)
|
||||
{
|
||||
default: os<<c2; break;
|
||||
case 'b': os<<'\b'; break;
|
||||
case 'f': os<<'\f'; break;
|
||||
case 'n': os<<'\n'; break;
|
||||
case 'r': os<<'\r'; break;
|
||||
case 't': os<<'\t'; break;
|
||||
case 'u':
|
||||
{
|
||||
char hexdigits[4+1];
|
||||
is.read(hexdigits, 4);
|
||||
if(is.eof())
|
||||
throw SerializationError("JSON string ended prematurely");
|
||||
hexdigits[4] = 0;
|
||||
std::istringstream tmp_is(hexdigits, std::ios::binary);
|
||||
int hexnumber;
|
||||
tmp_is >> std::hex >> hexnumber;
|
||||
os<<((char)hexnumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<c;
|
||||
}
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// Get an sha-1 hash of the player's name combined with
|
||||
// the password entered. That's what the server uses as
|
||||
// their password. (Exception : if the password field is
|
||||
|
@ -1694,6 +1694,12 @@ inline std::string deSerializeLongString(std::istream &is)
|
||||
return s;
|
||||
}
|
||||
|
||||
// Creates a string encoded in JSON format (almost equivalent to a C string literal)
|
||||
std::string serializeJsonString(const std::string &plain);
|
||||
|
||||
// Reads a string encoded in JSON format
|
||||
std::string deSerializeJsonString(std::istream &is);
|
||||
|
||||
//
|
||||
|
||||
inline u32 time_to_daynight_ratio(u32 time_of_day)
|
||||
|
Loading…
Reference in New Issue
Block a user