mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 21:14:15 +02:00
Node placement / mineral / serialization / iron freq / node_dig callback
- Node placement code moved to Lua - Mineral system removed (added default:stone_with_coal and default:stone_with_iron). - MapBlock and MapNode serialization updated. - Mapgen: Frequency of iron increased. - node_dig callback and related changes.
This commit is contained in:
parent
f22c73f501
commit
157a4cf18c
265
data/builtin.lua
265
data/builtin.lua
@ -83,7 +83,7 @@ end
|
||||
-- Item definition helpers
|
||||
--
|
||||
|
||||
minetest.inventorycube = function(img1, img2, img3)
|
||||
function minetest.inventorycube(img1, img2, img3)
|
||||
img2 = img2 or img1
|
||||
img3 = img3 or img1
|
||||
return "[inventorycube"
|
||||
@ -92,7 +92,11 @@ minetest.inventorycube = function(img1, img2, img3)
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
minetest.get_pointed_thing_position = function(pointed_thing, above)
|
||||
function minetest.pos_to_string(pos)
|
||||
return "(" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ")"
|
||||
end
|
||||
|
||||
function minetest.get_pointed_thing_position(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
@ -113,31 +117,240 @@ minetest.get_pointed_thing_position = function(pointed_thing, above)
|
||||
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)
|
||||
function minetest.dir_to_facedir(dir)
|
||||
if math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 1
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.dir_to_wallmounted(dir)
|
||||
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
|
||||
if dir.y < 0 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
elseif math.abs(dir.x) > math.abs(dir.z) then
|
||||
if dir.x < 0 then
|
||||
return 3
|
||||
else
|
||||
return 2
|
||||
end
|
||||
else
|
||||
if dir.z < 0 then
|
||||
return 5
|
||||
else
|
||||
return 4
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.get_node_drops(nodename, toolname)
|
||||
local drop = ItemStack({name=nodename}):get_definition().drop
|
||||
if drop == nil then
|
||||
-- default drop
|
||||
print("default drop: " .. nodename)
|
||||
return {ItemStack({name=nodename})}
|
||||
elseif type(drop) == "string" then
|
||||
-- itemstring drop
|
||||
return {ItemStack(drop)}
|
||||
elseif drop.items == nil then
|
||||
-- drop = {} to disable default drop
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Extended drop table
|
||||
local got_items = {}
|
||||
local got_count = 0
|
||||
local _, item, tool
|
||||
for _, item in ipairs(drop.items) do
|
||||
local good_rarity = true
|
||||
local good_tool = true
|
||||
if item.rarity ~= nil then
|
||||
good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
|
||||
end
|
||||
if item.tools ~= nil then
|
||||
good_tool = false
|
||||
for _, tool in ipairs(item.tools) do
|
||||
if tool:sub(1, 1) == '~' then
|
||||
good_tool = toolname:find(tool:sub(2)) ~= nil
|
||||
else
|
||||
good_tool = toolname == tool
|
||||
end
|
||||
if good_tool then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if good_rarity and good_tool then
|
||||
got_count = got_count + 1
|
||||
for _, add_item in ipairs(item.items) do
|
||||
got_items[#got_items+1] = add_item
|
||||
end
|
||||
if drop.max_items ~= nil and got_count == drop.max_items then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return got_items
|
||||
end
|
||||
|
||||
function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
local item = itemstack:peek_item()
|
||||
local def = itemstack:get_definition()
|
||||
if def.type == "node" and pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local oldnode = minetest.env:get_node(pos)
|
||||
local olddef = ItemStack({name=oldnode.name}):get_definition()
|
||||
|
||||
if not olddef.buildable_to then
|
||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||
.. " node in invalid position " .. minetest.pos_to_string(pos)
|
||||
.. ", replacing " .. oldnode.name)
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action", placer:get_player_name() .. " places node "
|
||||
.. def.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
local newnode = {name = def.name, param1 = 0, param2 = 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.paramtype2 == 'wallmounted' then
|
||||
local under = pointed_thing.under
|
||||
local above = pointed_thing.above
|
||||
local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif def.paramtype2 == 'facedir' then
|
||||
local playerpos = placer:getpos()
|
||||
local dir = {x = pos.x - playerpos.x, y = pos.y - playerpos.y, z = pos.z - playerpos.z}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
end
|
||||
|
||||
-- Add node and update
|
||||
minetest.env:add_node(pos, newnode)
|
||||
|
||||
-- Set metadata owner
|
||||
if def.metadata_name ~= "" then
|
||||
minetest.env:get_meta(pos):set_owner(placer:get_player_name())
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||
callback(pos, newnode, placer)
|
||||
end
|
||||
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
|
||||
if pos ~= nil then
|
||||
local item = itemstack:take_item()
|
||||
minetest.env:add_item(pos, item)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function minetest.item_place(itemstack, placer, pointed_thing)
|
||||
if itemstack:get_definition().type == "node" then
|
||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
else
|
||||
return minetest.item_place_object(itemstack, placer, pointed_thing)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.item_drop(itemstack, dropper, pos)
|
||||
minetest.env:add_item(pos, itemstack)
|
||||
return ""
|
||||
end
|
||||
|
||||
function minetest.item_eat(hp_change)
|
||||
function minetest.item_eat(hp_change, replace_with_item)
|
||||
return function(itemstack, user, pointed_thing) -- closure
|
||||
if itemstack:take_item() ~= nil then
|
||||
user:set_hp(user:get_hp() + hp_change)
|
||||
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.node_punch(pos, node, puncher)
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_punchnodes) do
|
||||
callback(pos, node, puncher)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function minetest.node_dig(pos, node, digger)
|
||||
minetest.debug("node_dig")
|
||||
|
||||
local def = ItemStack({name=node.name}):get_definition()
|
||||
if not def.diggable then
|
||||
minetest.debug("not diggable")
|
||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||
.. node.name .. " which is not diggable "
|
||||
.. minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.env:get_meta(pos)
|
||||
if meta ~= nil and not meta:get_allow_removal() then
|
||||
minetest.debug("dig prevented by metadata")
|
||||
minetest.log("info", digger:get_player_name() .. " tried to dig "
|
||||
.. node.name .. ", but removal is disabled by metadata "
|
||||
.. minetest.pos_to_string(pos))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log('action', digger:get_player_name() .. " digs "
|
||||
.. node.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
local wielded = digger:get_wielded_item()
|
||||
local drops = minetest.get_node_drops(node.name, wielded:get_name())
|
||||
|
||||
-- Wear out tool
|
||||
mp = def.material
|
||||
tp = wielded:get_tool_digging_properties()
|
||||
dp = minetest.get_digging_properties(mp, tp)
|
||||
wielded:add_wear(dp.wear)
|
||||
digger:set_wielded_item(wielded)
|
||||
|
||||
-- Add dropped items
|
||||
local _, dropped_item
|
||||
for _, dropped_item in ipairs(drops) do
|
||||
digger:get_inventory():add_item("main", dropped_item)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove node and update
|
||||
minetest.env:remove_node(pos)
|
||||
|
||||
-- Run script hook
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_dignodes) do
|
||||
callback(pos, node, digger)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Item definition defaults
|
||||
--
|
||||
@ -151,16 +364,18 @@ minetest.nodedef_default = {
|
||||
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_place = minetest.item_place,
|
||||
on_drop = minetest.item_drop,
|
||||
on_use = nil,
|
||||
|
||||
on_punch = minetest.node_punch,
|
||||
on_dig = minetest.node_dig,
|
||||
|
||||
-- Node properties
|
||||
drawtype = "normal",
|
||||
visual_scale = 1.0,
|
||||
@ -172,6 +387,7 @@ minetest.nodedef_default = {
|
||||
alpha = 255,
|
||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
paramtype = "none",
|
||||
paramtype2 = "none",
|
||||
is_ground_content = false,
|
||||
sunlight_propagates = false,
|
||||
walkable = true,
|
||||
@ -179,10 +395,6 @@ minetest.nodedef_default = {
|
||||
diggable = true,
|
||||
climbable = false,
|
||||
buildable_to = false,
|
||||
wall_mounted = false,
|
||||
--dug_item intentionally not defined here
|
||||
extra_dug_item = "",
|
||||
extra_dug_item_rarity = 2,
|
||||
metadata_name = "",
|
||||
liquidtype = "none",
|
||||
liquid_alternative_flowing = "",
|
||||
@ -199,6 +411,8 @@ minetest.nodedef_default = {
|
||||
cuttability = 0,
|
||||
flammability = 0,
|
||||
},
|
||||
legacy_facedir_simple = false,
|
||||
legacy_wallmounted = false,
|
||||
}
|
||||
|
||||
minetest.craftitemdef_default = {
|
||||
@ -369,12 +583,12 @@ function minetest.register_item(name, itemdef)
|
||||
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()
|
||||
-- Flowing liquid uses param2
|
||||
if itemdef.type == "node" and itemdef.liquidtype == "flowing" then
|
||||
itemdef.paramtype2 = "flowingliquid"
|
||||
end
|
||||
|
||||
-- Legacy stuff
|
||||
-- BEGIN Legacy stuff
|
||||
if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
|
||||
minetest.register_craft({
|
||||
type="cooking",
|
||||
@ -390,6 +604,7 @@ function minetest.register_item(name, itemdef)
|
||||
burntime=itemdef.furnace_burntime
|
||||
})
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
-- Disable all further modifications
|
||||
getmetatable(itemdef).__newindex = {}
|
||||
@ -408,10 +623,11 @@ end
|
||||
function minetest.register_craftitem(name, craftitemdef)
|
||||
craftitemdef.type = "craft"
|
||||
|
||||
-- Legacy stuff
|
||||
-- BEGIN Legacy stuff
|
||||
if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
|
||||
craftitemdef.inventory_image = craftitemdef.image
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, craftitemdef)
|
||||
end
|
||||
@ -420,7 +636,7 @@ function minetest.register_tool(name, tooldef)
|
||||
tooldef.type = "tool"
|
||||
tooldef.stack_max = 1
|
||||
|
||||
-- Legacy stuff
|
||||
-- BEGIN Legacy stuff
|
||||
if tooldef.inventory_image == nil and tooldef.image ~= nil then
|
||||
tooldef.inventory_image = tooldef.image
|
||||
end
|
||||
@ -450,6 +666,7 @@ function minetest.register_tool(name, tooldef)
|
||||
dd_cuttability = tooldef.dd_cuttability,
|
||||
}
|
||||
end
|
||||
-- END Legacy stuff
|
||||
|
||||
minetest.register_item(name, tooldef)
|
||||
end
|
||||
@ -643,4 +860,10 @@ minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registr
|
||||
minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
|
||||
minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
|
||||
|
||||
--
|
||||
-- Set random seed
|
||||
--
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
-- END
|
||||
|
@ -176,6 +176,7 @@
|
||||
-- - set_text(text) -- eg. set the text of a sign
|
||||
-- - get_text()
|
||||
-- - get_owner()
|
||||
-- - set_owner(string)
|
||||
-- Generic node metadata specific:
|
||||
-- - set_infotext(infotext)
|
||||
-- - get_inventory() -> InvRef
|
||||
@ -302,7 +303,7 @@
|
||||
-- myvariable = whatever,
|
||||
-- }
|
||||
--
|
||||
-- Item definition:
|
||||
-- Item definition options (register_node, register_craftitem, register_tool)
|
||||
-- {
|
||||
-- description = "Steel Axe",
|
||||
-- inventory_image = "default_tool_steelaxe.png",
|
||||
@ -328,9 +329,9 @@
|
||||
-- on_use = func(item, user, pointed_thing),
|
||||
-- }
|
||||
--
|
||||
-- Node definition options:
|
||||
-- Node definition options (register_node):
|
||||
-- {
|
||||
-- <all fields from item definitions>,
|
||||
-- <all fields allowed in item definitions>,
|
||||
-- drawtype = "normal",
|
||||
-- visual_scale = 1.0,
|
||||
-- tile_images = {"default_unknown_block.png"},
|
||||
@ -341,6 +342,7 @@
|
||||
-- alpha = 255,
|
||||
-- post_effect_color = {a=0, r=0, g=0, b=0},
|
||||
-- paramtype = "none",
|
||||
-- paramtype2 = "none",
|
||||
-- is_ground_content = false,
|
||||
-- sunlight_propagates = false,
|
||||
-- walkable = true,
|
||||
@ -348,10 +350,8 @@
|
||||
-- diggable = true,
|
||||
-- climbable = false,
|
||||
-- buildable_to = false,
|
||||
-- wall_mounted = false,
|
||||
-- dug_item = "",
|
||||
-- extra_dug_item = "",
|
||||
-- extra_dug_item_rarity = 2,
|
||||
-- drop = "",
|
||||
-- -- alternatively drop = { max_items = ..., items = { ... } }
|
||||
-- metadata_name = "",
|
||||
-- liquidtype = "none",
|
||||
-- liquid_alternative_flowing = "",
|
||||
@ -368,23 +368,10 @@
|
||||
-- cuttability = 0,
|
||||
-- flammability = 0,
|
||||
-- },
|
||||
-- on_drop = func(item, dropper),
|
||||
-- on_place = func(item, placer, pointed_thing),
|
||||
-- on_use = func(item, user, pointed_thing),
|
||||
-- legacy_facedir_simple = false, -- Support maps made in and before January 2012
|
||||
-- legacy_wallmounted = false, -- Support maps made in and before January 2012
|
||||
-- }
|
||||
--
|
||||
-- Craftitem definition options:
|
||||
-- {
|
||||
-- description = <tooltip text>,
|
||||
-- inventory_image = "default_unknown_block.png",
|
||||
-- wield_image = "",
|
||||
-- stack_max = <maximum number of items in stack>,
|
||||
-- liquids_pointable = <whether can point liquids>,
|
||||
-- on_drop = func(item, dropper),
|
||||
-- on_place = func(item, placer, pointed_thing),
|
||||
-- on_use = func(item, user, pointed_thing),
|
||||
-- }
|
||||
--
|
||||
-- Recipe:
|
||||
-- {
|
||||
-- output = 'default:pick_stone',
|
||||
@ -1111,10 +1098,26 @@ minetest.register_craft({
|
||||
minetest.register_node("default:stone", {
|
||||
description = "Stone",
|
||||
tile_images = {"default_stone.png"},
|
||||
paramtype = "mineral",
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_stonelike(1.0),
|
||||
dug_item = 'node "default:cobble" 1',
|
||||
drop = 'default:cobble',
|
||||
legacy_mineral = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:stone_with_coal", {
|
||||
description = "Stone with coal",
|
||||
tile_images = {"default_stone.png^default_mineral_coal.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_stonelike(1.0),
|
||||
drop = 'default:coal_lump',
|
||||
})
|
||||
|
||||
minetest.register_node("default:stone_with_iron", {
|
||||
description = "Stone with iron",
|
||||
tile_images = {"default_stone.png^default_mineral_iron.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_stonelike(1.0),
|
||||
drop = 'default:iron_lump',
|
||||
})
|
||||
|
||||
minetest.register_node("default:dirt_with_grass", {
|
||||
@ -1122,7 +1125,7 @@ minetest.register_node("default:dirt_with_grass", {
|
||||
tile_images = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_dirtlike(1.0),
|
||||
dug_item = 'node "default:dirt" 1',
|
||||
drop = 'default:dirt',
|
||||
})
|
||||
|
||||
minetest.register_node("default:dirt_with_grass_footsteps", {
|
||||
@ -1130,7 +1133,7 @@ minetest.register_node("default:dirt_with_grass_footsteps", {
|
||||
tile_images = {"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_dirtlike(1.0),
|
||||
dug_item = 'node "default:dirt" 1',
|
||||
drop = 'default:dirt',
|
||||
})
|
||||
|
||||
minetest.register_node("default:dirt", {
|
||||
@ -1159,7 +1162,7 @@ minetest.register_node("default:sandstone", {
|
||||
tile_images = {"default_sandstone.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_dirtlike(1.0), -- FIXME should this be stonelike?
|
||||
dug_item = 'node "default:sand" 1', -- FIXME is this intentional?
|
||||
drop = 'default:sand',
|
||||
})
|
||||
|
||||
minetest.register_node("default:clay", {
|
||||
@ -1167,7 +1170,7 @@ minetest.register_node("default:clay", {
|
||||
tile_images = {"default_clay.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_dirtlike(1.0),
|
||||
dug_item = 'craft "default:clay_lump" 4',
|
||||
drop = 'default:clay_lump 4',
|
||||
})
|
||||
|
||||
minetest.register_node("default:brick", {
|
||||
@ -1175,7 +1178,7 @@ minetest.register_node("default:brick", {
|
||||
tile_images = {"default_brick.png"},
|
||||
is_ground_content = true,
|
||||
material = minetest.digprop_stonelike(1.0),
|
||||
dug_item = 'craft "default:clay_brick" 4',
|
||||
drop = 'default:clay_brick 4',
|
||||
})
|
||||
|
||||
minetest.register_node("default:tree", {
|
||||
@ -1211,8 +1214,21 @@ minetest.register_node("default:leaves", {
|
||||
tile_images = {"default_leaves.png"},
|
||||
paramtype = "light",
|
||||
material = minetest.digprop_leaveslike(1.0),
|
||||
extra_dug_item = 'node "default:sapling" 1',
|
||||
extra_dug_item_rarity = 20,
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
{
|
||||
-- player will get sapling with 1/20 chance
|
||||
items = {'default:sapling'},
|
||||
rarity = 20,
|
||||
},
|
||||
{
|
||||
-- player will get leaves only if he get no saplings,
|
||||
-- this is because max_items is 1
|
||||
items = {'default:leaves'},
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("default:cactus", {
|
||||
@ -1290,8 +1306,8 @@ minetest.register_node("default:ladder", {
|
||||
inventory_image = "default_ladder.png",
|
||||
wield_image = "default_ladder.png",
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
is_ground_content = true,
|
||||
wall_mounted = true,
|
||||
walkable = false,
|
||||
climbable = true,
|
||||
selection_box = {
|
||||
@ -1301,6 +1317,7 @@ minetest.register_node("default:ladder", {
|
||||
--wall_side = = <default>
|
||||
},
|
||||
material = minetest.digprop_woodlike(0.5),
|
||||
legacy_wallmounted = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:wood", {
|
||||
@ -1420,9 +1437,9 @@ minetest.register_node("default:torch", {
|
||||
inventory_image = "default_torch_on_floor.png",
|
||||
wield_image = "default_torch_on_floor.png",
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
wall_mounted = true,
|
||||
light_source = LIGHT_MAX-1,
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
@ -1431,6 +1448,7 @@ minetest.register_node("default:torch", {
|
||||
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
|
||||
},
|
||||
material = minetest.digprop_constanttime(0.0),
|
||||
legacy_wallmounted = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:sign_wall", {
|
||||
@ -1440,9 +1458,9 @@ minetest.register_node("default:sign_wall", {
|
||||
inventory_image = "default_sign_wall.png",
|
||||
wield_image = "default_sign_wall.png",
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
wall_mounted = true,
|
||||
metadata_name = "sign",
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
@ -1451,33 +1469,37 @@ minetest.register_node("default:sign_wall", {
|
||||
--wall_side = <default>
|
||||
},
|
||||
material = minetest.digprop_constanttime(0.5),
|
||||
legacy_wallmounted = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:chest", {
|
||||
description = "Chest",
|
||||
tile_images = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
|
||||
paramtype = "facedir_simple",
|
||||
paramtype2 = "facedir",
|
||||
metadata_name = "chest",
|
||||
material = minetest.digprop_woodlike(1.0),
|
||||
legacy_facedir_simple = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:chest_locked", {
|
||||
description = "Locked Chest",
|
||||
tile_images = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"},
|
||||
paramtype = "facedir_simple",
|
||||
paramtype2 = "facedir",
|
||||
metadata_name = "locked_chest",
|
||||
material = minetest.digprop_woodlike(1.0),
|
||||
legacy_facedir_simple = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:furnace", {
|
||||
description = "Furnace",
|
||||
tile_images = {"default_furnace_side.png", "default_furnace_side.png", "default_furnace_side.png",
|
||||
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"},
|
||||
paramtype = "facedir_simple",
|
||||
paramtype2 = "facedir",
|
||||
metadata_name = "furnace",
|
||||
material = minetest.digprop_stonelike(3.0),
|
||||
legacy_facedir_simple = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:cobble", {
|
||||
@ -1506,8 +1528,9 @@ minetest.register_node("default:nyancat", {
|
||||
tile_images = {"default_nc_side.png", "default_nc_side.png", "default_nc_side.png",
|
||||
"default_nc_side.png", "default_nc_back.png", "default_nc_front.png"},
|
||||
inventory_image = "default_nc_front.png",
|
||||
paramtype = "facedir_simple",
|
||||
paramtype2 = "facedir",
|
||||
material = minetest.digprop_stonelike(3.0),
|
||||
legacy_facedir_simple = true,
|
||||
})
|
||||
|
||||
minetest.register_node("default:nyancat_rainbow", {
|
||||
|
Before Width: | Height: | Size: 952 B After Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@ -6,6 +6,8 @@
|
||||
--
|
||||
|
||||
minetest.register_alias("stone", "default:stone")
|
||||
minetest.register_alias("stone_with_coal", "default:stone_with_coal")
|
||||
minetest.register_alias("stone_with_iron", "default:stone_with_iron")
|
||||
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")
|
||||
|
@ -115,7 +115,6 @@ set(common_SRCS
|
||||
nodemetadata.cpp
|
||||
serverobject.cpp
|
||||
noise.cpp
|
||||
mineral.cpp
|
||||
porting.cpp
|
||||
materials.cpp
|
||||
defaultsettings.cpp
|
||||
|
@ -899,7 +899,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
Update an existing block
|
||||
*/
|
||||
//infostream<<"Updating"<<std::endl;
|
||||
block->deSerialize(istr, ser_version);
|
||||
block->deSerialize(istr, ser_version, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -908,7 +908,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
*/
|
||||
//infostream<<"Creating new"<<std::endl;
|
||||
block = new MapBlock(&m_env.getMap(), p, this);
|
||||
block->deSerialize(istr, ser_version);
|
||||
block->deSerialize(istr, ser_version, false);
|
||||
sector->insertBlock(block);
|
||||
}
|
||||
|
||||
@ -1816,8 +1816,7 @@ void Client::addNode(v3s16 p, MapNode n)
|
||||
try
|
||||
{
|
||||
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
|
||||
std::string st = std::string("");
|
||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, st);
|
||||
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{}
|
||||
|
@ -85,15 +85,15 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||
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]),
|
||||
video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]),
|
||||
video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]),
|
||||
video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]),
|
||||
video::S3DVertex(max.X,min.Y,max.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]),
|
||||
video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]),
|
||||
video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]),
|
||||
video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]),
|
||||
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
|
||||
};
|
||||
|
||||
for(s32 j=0; j<24; j++)
|
||||
@ -602,7 +602,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
break;
|
||||
case NDT_TORCHLIKE:
|
||||
{
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
|
||||
AtlasPointer ap(0);
|
||||
if(dir == v3s16(0,-1,0)){
|
||||
@ -694,7 +694,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
ap.x0(), ap.y1()),
|
||||
};
|
||||
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
|
||||
for(s32 i=0; i<4; i++)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
Ranges:
|
||||
0x000...0x07f (0...127): param2 is fully usable
|
||||
126 and 127 are reserved (CONTENT_AIR and CONTENT_IGNORE).
|
||||
0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable
|
||||
0x800...0xfff (2048...4095): higher 4 bits of param2 are not usable
|
||||
*/
|
||||
#define CONTENT_STONE 0
|
||||
#define CONTENT_WATER 2
|
||||
|
@ -2057,7 +2057,9 @@ void ClientEnvironment::step(float dtime)
|
||||
MapNode n = m_map->getNode(p);
|
||||
light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
catch(InvalidPositionException &e){
|
||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
player->updateLight(light);
|
||||
|
||||
/*
|
||||
@ -2104,7 +2106,6 @@ void ClientEnvironment::step(float dtime)
|
||||
if(m_active_object_light_update_interval.step(dtime, 0.21))
|
||||
{
|
||||
// Update lighting
|
||||
//u8 light = LIGHT_MAX;
|
||||
u8 light = 0;
|
||||
try{
|
||||
// Get node at head
|
||||
@ -2112,7 +2113,9 @@ void ClientEnvironment::step(float dtime)
|
||||
MapNode n = m_map->getNode(p);
|
||||
light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
catch(InvalidPositionException &e){
|
||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
obj->updateLight(light);
|
||||
}
|
||||
}
|
||||
@ -2203,7 +2206,9 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||
MapNode n = m_map->getNode(p);
|
||||
light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e) {}
|
||||
catch(InvalidPositionException &e){
|
||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
object->updateLight(light);
|
||||
}
|
||||
return object->getId();
|
||||
|
11
src/game.cpp
11
src/game.cpp
@ -303,6 +303,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
should_show_hilightbox = false;
|
||||
selected_object = NULL;
|
||||
|
||||
INodeDefManager *nodedef = client->getNodeDefManager();
|
||||
|
||||
// First try to find a pointed at active object
|
||||
if(look_for_object)
|
||||
{
|
||||
@ -378,7 +380,7 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
v3s16(-1,0,0), // left
|
||||
};
|
||||
|
||||
const ContentFeatures &f = client->getNodeDefManager()->get(n);
|
||||
const ContentFeatures &f = nodedef->get(n);
|
||||
|
||||
if(f.selection_box.type == NODEBOX_FIXED)
|
||||
{
|
||||
@ -447,7 +449,7 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
}
|
||||
else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS/2 - BS/6 - BS/20;
|
||||
v3f cpf = npf + dir_f;
|
||||
@ -1827,11 +1829,10 @@ void the_game(
|
||||
MapNode n = client.getNode(nodepos);
|
||||
|
||||
// Get digging properties for material and tool
|
||||
content_t material = n.getContent();
|
||||
MaterialProperties mp = nodedef->get(n.getContent()).material;
|
||||
ToolDiggingProperties tp =
|
||||
playeritem.getToolDiggingProperties(itemdef);
|
||||
DiggingProperties prop =
|
||||
getDiggingProperties(material, &tp, nodedef);
|
||||
DiggingProperties prop = getDiggingProperties(&mp, &tp);
|
||||
|
||||
float dig_time_complete = 0.0;
|
||||
|
||||
|
@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
class IItemDefManager;
|
||||
class INodeDefManager;
|
||||
class ICraftDefManager;
|
||||
// Mineral too?
|
||||
class ITextureSource;
|
||||
|
||||
/*
|
||||
|
17
src/light.h
17
src/light.h
@ -75,16 +75,27 @@ inline u8 undiminish_light(u8 light)
|
||||
|
||||
extern u8 light_decode_table[LIGHT_MAX+1];
|
||||
|
||||
// 0 <= light <= LIGHT_SUN
|
||||
// 0 <= return value <= 255
|
||||
inline u8 decode_light(u8 light)
|
||||
{
|
||||
if(light == LIGHT_SUN)
|
||||
return light_decode_table[LIGHT_MAX];
|
||||
|
||||
if(light > LIGHT_MAX)
|
||||
light = LIGHT_MAX;
|
||||
|
||||
return light_decode_table[light];
|
||||
}
|
||||
|
||||
// 0 <= daylight_factor <= 1000
|
||||
// 0 <= lightday, lightnight <= LIGHT_SUN
|
||||
// 0 <= return value <= LIGHT_SUN
|
||||
inline u8 blend_light(u32 daylight_factor, u8 lightday, u8 lightnight)
|
||||
{
|
||||
u32 c = 1000;
|
||||
u32 l = ((daylight_factor * lightday + (c-daylight_factor) * lightnight))/c;
|
||||
if(l > LIGHT_SUN)
|
||||
l = LIGHT_SUN;
|
||||
return l;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
31
src/main.cpp
31
src/main.cpp
@ -54,24 +54,6 @@ A list of "active blocks" in which stuff happens. (+=done)
|
||||
+ This was left to be done by the old system and it sends only the
|
||||
nearest ones.
|
||||
|
||||
Vim conversion regexpes for moving to extended content type storage:
|
||||
%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g
|
||||
%s/content_features(\([^.]*\)\.d)/content_features(\1)/g
|
||||
%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g
|
||||
%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g
|
||||
%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g
|
||||
%s/\.d;/.getContent();/g
|
||||
%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g
|
||||
Other things to note:
|
||||
- node.d = node.param0 (only in raw serialization; use getContent() otherwise)
|
||||
- node.param = node.param1
|
||||
- node.dir = node.param2
|
||||
- content_walkable(node.d) etc should be changed to
|
||||
content_features(node).walkable etc
|
||||
- Also check for lines that store the result of getContent to a 8-bit
|
||||
variable and fix them (result of getContent() must be stored in
|
||||
content_t, which is 16-bit)
|
||||
|
||||
NOTE: Seeds in 1260:6c77e7dbfd29:
|
||||
5721858502589302589:
|
||||
Spawns you on a small sand island with a surface dungeon
|
||||
@ -351,8 +333,6 @@ TODO: Block cube placement around player's head
|
||||
TODO: Protocol version field
|
||||
TODO: Think about using same bits for material for fences and doors, for
|
||||
example
|
||||
TODO: Move mineral to param2, increment map serialization version, add
|
||||
conversion
|
||||
|
||||
SUGG: Restart irrlicht completely when coming back to main menu from game.
|
||||
- This gets rid of everything that is stored in irrlicht's caches.
|
||||
@ -419,7 +399,6 @@ Doing currently:
|
||||
#include "filesys.h"
|
||||
#include "config.h"
|
||||
#include "guiMainMenu.h"
|
||||
#include "mineral.h"
|
||||
#include "materials.h"
|
||||
#include "game.h"
|
||||
#include "keycode.h"
|
||||
@ -1260,16 +1239,6 @@ int main(int argc, char *argv[])
|
||||
srand(time(0));
|
||||
mysrand(time(0));
|
||||
|
||||
/*
|
||||
Pre-initialize some stuff with a dummy irrlicht wrapper.
|
||||
|
||||
These are needed for unit tests at least.
|
||||
*/
|
||||
|
||||
// Must be called before texturesource is created
|
||||
// (for texture atlas making)
|
||||
init_mineral();
|
||||
|
||||
/*
|
||||
Run unit tests
|
||||
*/
|
||||
|
23
src/map.cpp
23
src/map.cpp
@ -915,7 +915,7 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
|
||||
/*
|
||||
*/
|
||||
void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name)
|
||||
core::map<v3s16, MapBlock*> &modified_blocks)
|
||||
{
|
||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||
|
||||
@ -1010,9 +1010,6 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
if(!meta){
|
||||
errorstream<<"Failed to create node metadata \""
|
||||
<<metadata_name<<"\""<<std::endl;
|
||||
} else {
|
||||
meta->setOwner(player_name);
|
||||
setNodeMetadata(p, meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1291,8 +1288,7 @@ bool Map::addNodeWithEvent(v3s16 p, MapNode n)
|
||||
bool succeeded = true;
|
||||
try{
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
std::string st = std::string("");
|
||||
addNodeAndUpdate(p, n, modified_blocks, st);
|
||||
addNodeAndUpdate(p, n, modified_blocks);
|
||||
|
||||
// Copy modified_blocks to event
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
@ -3271,10 +3267,7 @@ void ServerMap::saveBlock(MapBlock *block)
|
||||
o.write((char*)&version, 1);
|
||||
|
||||
// Write basic data
|
||||
block->serialize(o, version);
|
||||
|
||||
// Write extra data stored on disk
|
||||
block->serializeDiskExtra(o, version);
|
||||
block->serialize(o, version, true);
|
||||
|
||||
// Write block to database
|
||||
|
||||
@ -3336,11 +3329,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
||||
}
|
||||
|
||||
// Read basic data
|
||||
block->deSerialize(is, version);
|
||||
block->deSerialize(is, version, true);
|
||||
|
||||
// Read extra data stored on disk
|
||||
block->deSerializeDiskExtra(is, version);
|
||||
|
||||
// If it's a new block, insert it to the map
|
||||
if(created_new)
|
||||
sector->insertBlock(block);
|
||||
@ -3406,10 +3396,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
|
||||
}
|
||||
|
||||
// Read basic data
|
||||
block->deSerialize(is, version);
|
||||
|
||||
// Read extra data stored on disk
|
||||
block->deSerializeDiskExtra(is, version);
|
||||
block->deSerialize(is, version, true);
|
||||
|
||||
// If it's a new block, insert it to the map
|
||||
if(created_new)
|
||||
|
@ -212,7 +212,7 @@ public:
|
||||
These handle lighting but not faces.
|
||||
*/
|
||||
void addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name);
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
void removeNodeAndUpdate(v3s16 p,
|
||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||
|
||||
|
543
src/mapblock.cpp
543
src/mapblock.cpp
@ -507,25 +507,41 @@ s16 MapBlock::getGroundLevel(v2s16 p2d)
|
||||
/*
|
||||
Serialization
|
||||
*/
|
||||
|
||||
// List relevant id-name pairs for ids in the block using nodedef
|
||||
static void getBlockNodeIdMapping(NameIdMapping *nimap, MapBlock *block,
|
||||
// Renumbers the content IDs (starting at 0 and incrementing
|
||||
static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
|
||||
INodeDefManager *nodedef)
|
||||
{
|
||||
std::map<content_t, content_t> mapping;
|
||||
std::set<content_t> unknown_contents;
|
||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
|
||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||
content_t id_counter = 0;
|
||||
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
|
||||
{
|
||||
v3s16 p(x0,y0,z0);
|
||||
MapNode n = block->getNode(p);
|
||||
content_t id = n.getContent();
|
||||
const ContentFeatures &f = nodedef->get(id);
|
||||
const std::string &name = f.name;
|
||||
if(name == "")
|
||||
unknown_contents.insert(id);
|
||||
content_t global_id = nodes[i].getContent();
|
||||
content_t id = CONTENT_IGNORE;
|
||||
|
||||
// Try to find an existing mapping
|
||||
std::map<content_t, content_t>::iterator j = mapping.find(global_id);
|
||||
if(j != mapping.end())
|
||||
{
|
||||
id = j->second;
|
||||
}
|
||||
else
|
||||
nimap->set(id, name);
|
||||
{
|
||||
// We have to assign a new mapping
|
||||
id = id_counter++;
|
||||
mapping.insert(std::make_pair(global_id, id));
|
||||
|
||||
const ContentFeatures &f = nodedef->get(global_id);
|
||||
const std::string &name = f.name;
|
||||
if(name == "")
|
||||
unknown_contents.insert(global_id);
|
||||
else
|
||||
nimap->set(id, name);
|
||||
}
|
||||
|
||||
// Update the MapNode
|
||||
nodes[i].setContent(id);
|
||||
}
|
||||
for(std::set<content_t>::const_iterator
|
||||
i = unknown_contents.begin();
|
||||
@ -537,7 +553,7 @@ static void getBlockNodeIdMapping(NameIdMapping *nimap, MapBlock *block,
|
||||
// Correct ids in the block to match nodedef based on names.
|
||||
// Unknown ones are added to nodedef.
|
||||
// Will not update itself to match id-name pairs in nodedef.
|
||||
void correctBlockNodeIds(const NameIdMapping *nimap, MapBlock *block,
|
||||
static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
|
||||
IGameDef *gamedef)
|
||||
{
|
||||
INodeDefManager *nodedef = gamedef->ndef();
|
||||
@ -547,13 +563,9 @@ void correctBlockNodeIds(const NameIdMapping *nimap, MapBlock *block,
|
||||
// correct ids.
|
||||
std::set<content_t> unnamed_contents;
|
||||
std::set<std::string> unallocatable_contents;
|
||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
|
||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
|
||||
{
|
||||
v3s16 p(x0,y0,z0);
|
||||
MapNode n = block->getNode(p);
|
||||
content_t local_id = n.getContent();
|
||||
content_t local_id = nodes[i].getContent();
|
||||
std::string name;
|
||||
bool found = nimap->getName(local_id, name);
|
||||
if(!found){
|
||||
@ -569,8 +581,7 @@ void correctBlockNodeIds(const NameIdMapping *nimap, MapBlock *block,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
n.setContent(global_id);
|
||||
block->setNode(p, n);
|
||||
nodes[i].setContent(global_id);
|
||||
}
|
||||
for(std::set<content_t>::const_iterator
|
||||
i = unnamed_contents.begin();
|
||||
@ -588,7 +599,7 @@ void correctBlockNodeIds(const NameIdMapping *nimap, MapBlock *block,
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapBlock format not supported");
|
||||
@ -598,22 +609,226 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
throw SerializationError("ERROR: Not writing dummy block.");
|
||||
}
|
||||
|
||||
if(version <= 21)
|
||||
{
|
||||
serialize_pre22(os, version, disk);
|
||||
return;
|
||||
}
|
||||
|
||||
// First byte
|
||||
u8 flags = 0;
|
||||
if(is_underground)
|
||||
flags |= 0x01;
|
||||
if(m_day_night_differs)
|
||||
flags |= 0x02;
|
||||
if(m_lighting_expired)
|
||||
flags |= 0x04;
|
||||
if(m_generated == false)
|
||||
flags |= 0x08;
|
||||
writeU8(os, flags);
|
||||
|
||||
/*
|
||||
Bulk node data
|
||||
*/
|
||||
NameIdMapping nimap;
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
if(disk)
|
||||
{
|
||||
MapNode *tmp_nodes = new MapNode[nodecount];
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
tmp_nodes[i] = data[i];
|
||||
getBlockNodeIdMapping(&nimap, tmp_nodes, m_gamedef->ndef());
|
||||
|
||||
u8 content_width = 1;
|
||||
/*u8 content_width = (nimap.size() <= 255) ? 1 : 2;*/
|
||||
u8 params_width = 2;
|
||||
writeU8(os, content_width);
|
||||
writeU8(os, params_width);
|
||||
MapNode::serializeBulk(os, version, tmp_nodes, nodecount,
|
||||
content_width, params_width, true);
|
||||
delete[] tmp_nodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 content_width = 1;
|
||||
/*u8 content_width = 2;*/
|
||||
u8 params_width = 2;
|
||||
writeU8(os, content_width);
|
||||
writeU8(os, params_width);
|
||||
MapNode::serializeBulk(os, version, data, nodecount,
|
||||
content_width, params_width, true);
|
||||
}
|
||||
|
||||
/*
|
||||
Node metadata
|
||||
*/
|
||||
std::ostringstream oss(std::ios_base::binary);
|
||||
m_node_metadata->serialize(oss);
|
||||
compressZlib(oss.str(), os);
|
||||
|
||||
/*
|
||||
Data that goes to disk, but not the network
|
||||
*/
|
||||
if(disk)
|
||||
{
|
||||
// Static objects
|
||||
m_static_objects.serialize(os);
|
||||
|
||||
// Timestamp
|
||||
writeU32(os, getTimestamp());
|
||||
|
||||
// Write block-specific node definition id mapping
|
||||
nimap.serialize(os);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapBlock format not supported");
|
||||
|
||||
if(version <= 21)
|
||||
{
|
||||
deSerialize_pre22(is, version, disk);
|
||||
return;
|
||||
}
|
||||
|
||||
u8 flags = readU8(is);
|
||||
is_underground = (flags & 0x01) ? true : false;
|
||||
m_day_night_differs = (flags & 0x02) ? true : false;
|
||||
m_lighting_expired = (flags & 0x04) ? true : false;
|
||||
m_generated = (flags & 0x08) ? false : true;
|
||||
|
||||
/*
|
||||
Bulk node data
|
||||
*/
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
u8 content_width = readU8(is);
|
||||
u8 params_width = readU8(is);
|
||||
if(content_width != 1)
|
||||
throw SerializationError("MapBlock::deSerialize(): invalid content_width");
|
||||
if(params_width != 2)
|
||||
throw SerializationError("MapBlock::deSerialize(): invalid params_width");
|
||||
MapNode::deSerializeBulk(is, version, data, nodecount,
|
||||
content_width, params_width, true);
|
||||
|
||||
/*
|
||||
NodeMetadata
|
||||
*/
|
||||
// Ignore errors
|
||||
try{
|
||||
std::ostringstream oss(std::ios_base::binary);
|
||||
decompressZlib(is, oss);
|
||||
std::istringstream iss(oss.str(), std::ios_base::binary);
|
||||
m_node_metadata->deSerialize(iss, m_gamedef);
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
|
||||
<<" while deserializing node metadata"<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Data that is only on disk
|
||||
*/
|
||||
if(disk)
|
||||
{
|
||||
// Static objects
|
||||
m_static_objects.deSerialize(is);
|
||||
|
||||
// Timestamp
|
||||
setTimestamp(readU32(is));
|
||||
m_disk_timestamp = m_timestamp;
|
||||
|
||||
// Dynamically re-set ids based on node names
|
||||
NameIdMapping nimap;
|
||||
nimap.deSerialize(is);
|
||||
correctBlockNodeIds(&nimap, data, m_gamedef);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Legacy serialization
|
||||
*/
|
||||
|
||||
// List relevant id-name pairs for ids in the block using nodedef
|
||||
// Before serialization version 22
|
||||
static void getBlockNodeIdMapping_pre22(NameIdMapping *nimap, MapNode *nodes,
|
||||
INodeDefManager *nodedef)
|
||||
{
|
||||
std::set<content_t> unknown_contents;
|
||||
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
|
||||
{
|
||||
content_t id = nodes[i].getContent();
|
||||
const ContentFeatures &f = nodedef->get(id);
|
||||
const std::string &name = f.name;
|
||||
if(name == "")
|
||||
unknown_contents.insert(id);
|
||||
else
|
||||
nimap->set(id, name);
|
||||
}
|
||||
for(std::set<content_t>::const_iterator
|
||||
i = unknown_contents.begin();
|
||||
i != unknown_contents.end(); i++){
|
||||
errorstream<<"getBlockNodeIdMapping_pre22(): IGNORING ERROR: "
|
||||
<<"Name for node id "<<(*i)<<" not known"<<std::endl;
|
||||
}
|
||||
}
|
||||
void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk)
|
||||
{
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
MapNode *tmp_data = new MapNode[nodecount];
|
||||
|
||||
// Legacy data changes
|
||||
// This code has to change from post-22 to pre-22 format.
|
||||
INodeDefManager *nodedef = m_gamedef->ndef();
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
const ContentFeatures &f = nodedef->get(tmp_data[i].getContent());
|
||||
// Mineral
|
||||
if(nodedef->getId("default:stone_with_coal") == tmp_data[i].getContent())
|
||||
{
|
||||
tmp_data[i].setContent(nodedef->getId("default:stone"));
|
||||
tmp_data[i].setParam1(1); // MINERAL_COAL
|
||||
}
|
||||
else if(nodedef->getId("default:stone_with_iron") == tmp_data[i].getContent())
|
||||
{
|
||||
tmp_data[i].setContent(nodedef->getId("default:stone"));
|
||||
tmp_data[i].setParam1(2); // MINERAL_IRON
|
||||
}
|
||||
// facedir_simple
|
||||
if(f.legacy_facedir_simple)
|
||||
{
|
||||
tmp_data[i].setParam1(tmp_data[i].getParam2());
|
||||
tmp_data[i].setParam2(0);
|
||||
}
|
||||
// wall_mounted
|
||||
if(f.legacy_wallmounted)
|
||||
{
|
||||
u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0};
|
||||
u8 dir_new_format = tmp_data[i].getParam2() & 7; // lowest 3 bits
|
||||
u8 dir_old_format = wallmounted_new_to_old[dir_new_format];
|
||||
tmp_data[i].setParam2(dir_old_format);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize nodes
|
||||
u32 ser_length = MapNode::serializedLength(version);
|
||||
SharedBuffer<u8> databuf_nodelist(nodecount * ser_length);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
tmp_data[i].serialize(&databuf_nodelist[i*ser_length], version);
|
||||
}
|
||||
|
||||
delete[] tmp_data;
|
||||
|
||||
// These have no compression
|
||||
if(version <= 3 || version == 5 || version == 6)
|
||||
{
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
u32 buflen = 1 + nodecount * MapNode::serializedLength(version);
|
||||
SharedBuffer<u8> dest(buflen);
|
||||
|
||||
dest[0] = is_underground;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
u32 s = 1 + i * MapNode::serializedLength(version);
|
||||
data[i].serialize(&dest[s], version);
|
||||
}
|
||||
|
||||
os.write((char*)*dest, dest.getSize());
|
||||
writeU8(os, is_underground);
|
||||
os.write((char*)*databuf_nodelist, databuf_nodelist.getSize());
|
||||
}
|
||||
else if(version <= 10)
|
||||
{
|
||||
@ -623,15 +838,13 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
*/
|
||||
|
||||
// First byte
|
||||
os.write((char*)&is_underground, 1);
|
||||
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
writeU8(os, is_underground);
|
||||
|
||||
// Get and compress materials
|
||||
SharedBuffer<u8> materialdata(nodecount);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
materialdata[i] = data[i].param0;
|
||||
materialdata[i] = databuf_nodelist[i*ser_length];
|
||||
}
|
||||
compress(materialdata, os, version);
|
||||
|
||||
@ -639,7 +852,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
SharedBuffer<u8> lightdata(nodecount);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
lightdata[i] = data[i].param1;
|
||||
lightdata[i] = databuf_nodelist[i*ser_length+1];
|
||||
}
|
||||
compress(lightdata, os, version);
|
||||
|
||||
@ -649,7 +862,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
SharedBuffer<u8> param2data(nodecount);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
param2data[i] = data[i].param2;
|
||||
param2data[i] = databuf_nodelist[i*ser_length+2];
|
||||
}
|
||||
compress(param2data, os, version);
|
||||
}
|
||||
@ -670,28 +883,19 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
if(m_generated == false)
|
||||
flags |= 0x08;
|
||||
}
|
||||
os.write((char*)&flags, 1);
|
||||
writeU8(os, flags);
|
||||
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
/*
|
||||
Get data
|
||||
*/
|
||||
|
||||
// Serialize nodes
|
||||
SharedBuffer<u8> databuf_nodelist(nodecount*3);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
data[i].serialize(&databuf_nodelist[i*3], version);
|
||||
}
|
||||
|
||||
// Create buffer with different parameters sorted
|
||||
SharedBuffer<u8> databuf(nodecount*3);
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
databuf[i] = databuf_nodelist[i*3];
|
||||
databuf[i+nodecount] = databuf_nodelist[i*3+1];
|
||||
databuf[i+nodecount*2] = databuf_nodelist[i*3+2];
|
||||
databuf[i] = databuf_nodelist[i*ser_length];
|
||||
databuf[i+nodecount] = databuf_nodelist[i*ser_length+1];
|
||||
databuf[i+nodecount*2] = databuf_nodelist[i*ser_length+2];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -728,50 +932,69 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(disk)
|
||||
{
|
||||
// Versions up from 9 have block objects. (DEPRECATED)
|
||||
if(version >= 9)
|
||||
{
|
||||
// count=0
|
||||
writeU16(os, 0);
|
||||
}
|
||||
|
||||
// Versions up from 15 have static objects.
|
||||
if(version >= 15)
|
||||
{
|
||||
m_static_objects.serialize(os);
|
||||
}
|
||||
|
||||
// Timestamp
|
||||
if(version >= 17)
|
||||
{
|
||||
writeU32(os, getTimestamp());
|
||||
}
|
||||
|
||||
// Scan and write node definition id mapping
|
||||
if(version >= 21)
|
||||
{
|
||||
NameIdMapping nimap;
|
||||
getBlockNodeIdMapping_pre22(&nimap, data, m_gamedef->ndef());
|
||||
nimap.serialize(os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapBlock format not supported");
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
// These have no lighting info
|
||||
if(version <= 1)
|
||||
{
|
||||
setLightingExpired(true);
|
||||
}
|
||||
// Initialize default flags
|
||||
is_underground = false;
|
||||
m_day_night_differs = false;
|
||||
m_lighting_expired = false;
|
||||
m_generated = true;
|
||||
|
||||
// These have no "generated" field
|
||||
if(version < 18)
|
||||
{
|
||||
m_generated = true;
|
||||
}
|
||||
// Make a temporary buffer
|
||||
u32 ser_length = MapNode::serializedLength(version);
|
||||
SharedBuffer<u8> databuf_nodelist(nodecount * ser_length);
|
||||
|
||||
// These have no compression
|
||||
if(version <= 3 || version == 5 || version == 6)
|
||||
{
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
char tmp;
|
||||
is.read(&tmp, 1);
|
||||
if(is.gcount() != 1)
|
||||
throw SerializationError
|
||||
("MapBlock::deSerialize: no enough input data");
|
||||
is_underground = tmp;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
s32 len = MapNode::serializedLength(version);
|
||||
SharedBuffer<u8> d(len);
|
||||
is.read((char*)*d, len);
|
||||
if(is.gcount() != len)
|
||||
throw SerializationError
|
||||
("MapBlock::deSerialize: no enough input data");
|
||||
data[i].deSerialize(*d, version);
|
||||
}
|
||||
is.read((char*)*databuf_nodelist, nodecount * ser_length);
|
||||
if(is.gcount() != nodecount * ser_length)
|
||||
throw SerializationError
|
||||
("MapBlock::deSerialize: no enough input data");
|
||||
}
|
||||
else if(version <= 10)
|
||||
{
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
u8 t8;
|
||||
is.read((char*)&t8, 1);
|
||||
is_underground = t8;
|
||||
@ -786,7 +1009,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
("MapBlock::deSerialize: invalid format");
|
||||
for(u32 i=0; i<s.size(); i++)
|
||||
{
|
||||
data[i].param0 = s[i];
|
||||
databuf_nodelist[i*ser_length] = s[i];
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -799,7 +1022,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
("MapBlock::deSerialize: invalid format");
|
||||
for(u32 i=0; i<s.size(); i++)
|
||||
{
|
||||
data[i].param1 = s[i];
|
||||
databuf_nodelist[i*ser_length + 1] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -814,15 +1037,13 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
("MapBlock::deSerialize: invalid format");
|
||||
for(u32 i=0; i<s.size(); i++)
|
||||
{
|
||||
data[i].param2 = s[i];
|
||||
databuf_nodelist[i*ser_length + 2] = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// All other versions (newest)
|
||||
else
|
||||
{
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
||||
u8 flags;
|
||||
is.read((char*)&flags, 1);
|
||||
is_underground = (flags & 0x01) ? true : false;
|
||||
@ -843,11 +1064,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
// deserialize nodes from buffer
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
u8 buf[3];
|
||||
buf[0] = s[i];
|
||||
buf[1] = s[i+nodecount];
|
||||
buf[2] = s[i+nodecount*2];
|
||||
data[i].deSerialize(buf, version);
|
||||
databuf_nodelist[i*ser_length] = s[i];
|
||||
databuf_nodelist[i*ser_length + 1] = s[i+nodecount];
|
||||
databuf_nodelist[i*ser_length + 2] = s[i+nodecount*2];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -879,76 +1098,102 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
|
||||
{
|
||||
// Versions up from 9 have block objects. (DEPRECATED)
|
||||
if(version >= 9)
|
||||
// Deserialize node data
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
// count=0
|
||||
writeU16(os, 0);
|
||||
}
|
||||
|
||||
// Versions up from 15 have static objects.
|
||||
if(version >= 15)
|
||||
{
|
||||
m_static_objects.serialize(os);
|
||||
data[i].deSerialize(&databuf_nodelist[i*ser_length], version);
|
||||
}
|
||||
|
||||
// Timestamp
|
||||
if(version >= 17)
|
||||
if(disk)
|
||||
{
|
||||
writeU32(os, getTimestamp());
|
||||
}
|
||||
/*
|
||||
Versions up from 9 have block objects. (DEPRECATED)
|
||||
*/
|
||||
if(version >= 9){
|
||||
u16 count = readU16(is);
|
||||
// Not supported and length not known if count is not 0
|
||||
if(count != 0){
|
||||
errorstream<<"WARNING: MapBlock::deSerialize_pre22(): "
|
||||
<<"Ignoring stuff coming at and after MBOs"<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan and write node definition id mapping
|
||||
if(version >= 21){
|
||||
/*
|
||||
Versions up from 15 have static objects.
|
||||
*/
|
||||
if(version >= 15)
|
||||
m_static_objects.deSerialize(is);
|
||||
|
||||
// Timestamp
|
||||
if(version >= 17){
|
||||
setTimestamp(readU32(is));
|
||||
m_disk_timestamp = m_timestamp;
|
||||
} else {
|
||||
setTimestamp(BLOCK_TIMESTAMP_UNDEFINED);
|
||||
}
|
||||
|
||||
// Dynamically re-set ids based on node names
|
||||
NameIdMapping nimap;
|
||||
getBlockNodeIdMapping(&nimap, this, m_gamedef->ndef());
|
||||
nimap.serialize(os);
|
||||
// If supported, read node definition id mapping
|
||||
if(version >= 21){
|
||||
nimap.deSerialize(is);
|
||||
// Else set the legacy mapping
|
||||
} else {
|
||||
content_mapnode_get_name_id_mapping(&nimap);
|
||||
}
|
||||
correctBlockNodeIds(&nimap, data, m_gamedef);
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
|
||||
{
|
||||
/*
|
||||
Versions up from 9 have block objects. (DEPRECATED)
|
||||
*/
|
||||
if(version >= 9){
|
||||
u16 count = readU16(is);
|
||||
// Not supported and length not known if count is not 0
|
||||
if(count != 0){
|
||||
errorstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
|
||||
<<"Ignoring stuff coming at and after MBOs"<<std::endl;
|
||||
return;
|
||||
|
||||
// Legacy data changes
|
||||
// This code has to convert from pre-22 to post-22 format.
|
||||
INodeDefManager *nodedef = m_gamedef->ndef();
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
{
|
||||
const ContentFeatures &f = nodedef->get(data[i].getContent());
|
||||
// Mineral
|
||||
if(nodedef->getId("default:stone") == data[i].getContent()
|
||||
&& data[i].getParam1() == 1)
|
||||
{
|
||||
//dstream << "legacy coal\n";
|
||||
data[i].setContent(nodedef->getId("default:stone_with_coal"));
|
||||
data[i].setParam1(0);
|
||||
}
|
||||
else if(nodedef->getId("default:stone") == data[i].getContent()
|
||||
&& data[i].getParam1() == 2)
|
||||
{
|
||||
//dstream << "legacy iron\n";
|
||||
data[i].setContent(nodedef->getId("default:stone_with_iron"));
|
||||
data[i].setParam1(0);
|
||||
}
|
||||
// facedir_simple
|
||||
if(f.legacy_facedir_simple)
|
||||
{
|
||||
dstream << "legacy_facedir_simple\n";
|
||||
data[i].setParam2(data[i].getParam1());
|
||||
data[i].setParam1(0);
|
||||
}
|
||||
// wall_mounted
|
||||
if(f.legacy_wallmounted)
|
||||
{
|
||||
dstream << "legacy_wallmounted\n";
|
||||
u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0};
|
||||
u8 dir_old_format = data[i].getParam2();
|
||||
u8 dir_new_format = 0;
|
||||
for(u8 j=0; j<8; j++)
|
||||
{
|
||||
if((dir_old_format & wallmounted_new_to_old[j]) != 0)
|
||||
{
|
||||
dir_new_format = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
data[i].setParam2(dir_new_format);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Versions up from 15 have static objects.
|
||||
*/
|
||||
if(version >= 15)
|
||||
m_static_objects.deSerialize(is);
|
||||
|
||||
// Timestamp
|
||||
if(version >= 17){
|
||||
setTimestamp(readU32(is));
|
||||
m_disk_timestamp = m_timestamp;
|
||||
} else {
|
||||
setTimestamp(BLOCK_TIMESTAMP_UNDEFINED);
|
||||
}
|
||||
|
||||
// Dynamically re-set ids based on node names
|
||||
NameIdMapping nimap;
|
||||
// If supported, read node definition id mapping
|
||||
if(version >= 21){
|
||||
nimap.deSerialize(is);
|
||||
// Else set the legacy mapping
|
||||
} else {
|
||||
content_mapnode_get_name_id_mapping(&nimap);
|
||||
}
|
||||
correctBlockNodeIds(&nimap, this, m_gamedef);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -363,17 +363,8 @@ public:
|
||||
Graphics-related methods
|
||||
*/
|
||||
|
||||
/*// A quick version with nodes passed as parameters
|
||||
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||
v3s16 face_dir);*/
|
||||
/*// A more convenient version
|
||||
u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
|
||||
{
|
||||
return getFaceLight(daynight_ratio,
|
||||
getNodeParentNoEx(p),
|
||||
getNodeParentNoEx(p + face_dir),
|
||||
face_dir);
|
||||
}*/
|
||||
#ifndef SERVER // Only on client
|
||||
|
||||
u8 getFaceLight2(u32 daynight_ratio, v3s16 p, v3s16 face_dir,
|
||||
INodeDefManager *nodemgr)
|
||||
{
|
||||
@ -383,8 +374,6 @@ public:
|
||||
face_dir, nodemgr);
|
||||
}
|
||||
|
||||
#ifndef SERVER // Only on client
|
||||
|
||||
#if 1
|
||||
/*
|
||||
Thread-safely updates the whole mesh of the mapblock.
|
||||
@ -524,20 +513,20 @@ public:
|
||||
*/
|
||||
|
||||
// These don't write or read version by itself
|
||||
void serialize(std::ostream &os, u8 version);
|
||||
void deSerialize(std::istream &is, u8 version);
|
||||
|
||||
// Used after the basic ones when writing on disk (serverside)
|
||||
void serializeDiskExtra(std::ostream &os, u8 version);
|
||||
// In addition to doing other things, will add unknown blocks from
|
||||
// id-name mapping to wndef
|
||||
void deSerializeDiskExtra(std::istream &is, u8 version);
|
||||
// Set disk to true for on-disk format, false for over-the-network format
|
||||
void serialize(std::ostream &os, u8 version, bool disk);
|
||||
// If disk == true: In addition to doing other things, will add
|
||||
// unknown blocks from id-name mapping to wndef
|
||||
void deSerialize(std::istream &is, u8 version, bool disk);
|
||||
|
||||
private:
|
||||
/*
|
||||
Private methods
|
||||
*/
|
||||
|
||||
void serialize_pre22(std::ostream &os, u8 version, bool disk);
|
||||
void deSerialize_pre22(std::istream &is, u8 version, bool disk);
|
||||
|
||||
/*
|
||||
Used only internally, because changes can't be tracked
|
||||
*/
|
||||
|
@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "content_mapblock.h"
|
||||
#include "mineral.h" // For mineral_block_texture
|
||||
|
||||
void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block)
|
||||
{
|
||||
@ -282,59 +281,37 @@ static void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
|
||||
dest.push_back(face);
|
||||
}
|
||||
|
||||
static TileSpec getTile(const MapNode &node, v3s16 dir,
|
||||
ITextureSource *tsrc, INodeDefManager *nodemgr)
|
||||
static TileSpec getTile(const MapNode &node, v3s16 dir, INodeDefManager *nodemgr)
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(node);
|
||||
|
||||
if(f.param_type == CPT_FACEDIR_SIMPLE)
|
||||
dir = facedir_rotate(node.param1, dir);
|
||||
|
||||
TileSpec spec;
|
||||
|
||||
s32 dir_i = -1;
|
||||
|
||||
if(dir == v3s16(0,0,0))
|
||||
dir_i = -1;
|
||||
else if(dir == v3s16(0,1,0))
|
||||
dir_i = 0;
|
||||
else if(dir == v3s16(0,-1,0))
|
||||
dir_i = 1;
|
||||
else if(dir == v3s16(1,0,0))
|
||||
dir_i = 2;
|
||||
else if(dir == v3s16(-1,0,0))
|
||||
dir_i = 3;
|
||||
else if(dir == v3s16(0,0,1))
|
||||
dir_i = 4;
|
||||
else if(dir == v3s16(0,0,-1))
|
||||
dir_i = 5;
|
||||
|
||||
if(dir_i == -1)
|
||||
// Non-directional
|
||||
spec = f.tiles[0];
|
||||
else
|
||||
spec = f.tiles[dir_i];
|
||||
|
||||
/*
|
||||
If it contains some mineral, change texture id
|
||||
*/
|
||||
if(f.param_type == CPT_MINERAL && tsrc)
|
||||
{
|
||||
u8 mineral = node.getMineral(nodemgr);
|
||||
std::string mineral_texture_name = mineral_block_texture(mineral);
|
||||
if(mineral_texture_name != "")
|
||||
{
|
||||
u32 orig_id = spec.texture.id;
|
||||
std::string texture_name = tsrc->getTextureName(orig_id);
|
||||
//texture_name += "^blit:";
|
||||
texture_name += "^";
|
||||
texture_name += mineral_texture_name;
|
||||
u32 new_id = tsrc->getTextureId(texture_name);
|
||||
spec.texture = tsrc->getTexture(new_id);
|
||||
}
|
||||
}
|
||||
// Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0),
|
||||
// (0,0,1), (0,0,-1) or (0,0,0)
|
||||
assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z <= 1);
|
||||
|
||||
return spec;
|
||||
// Convert direction to single integer for table lookup
|
||||
// 0 = (0,0,0)
|
||||
// 1 = (1,0,0)
|
||||
// 2 = (0,1,0)
|
||||
// 3 = (0,0,1)
|
||||
// 4 = invalid, treat as (0,0,0)
|
||||
// 5 = (0,0,-1)
|
||||
// 6 = (0,-1,0)
|
||||
// 7 = (-1,0,0)
|
||||
u8 dir_i = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7;
|
||||
|
||||
// Get rotation for things like chests
|
||||
u8 facedir = node.getFaceDir(nodemgr);
|
||||
assert(facedir <= 3);
|
||||
|
||||
static const u8 dir_to_tile[4 * 8] =
|
||||
{
|
||||
// 0 +X +Y +Z 0 -Z -Y -X
|
||||
0, 2, 0, 4, 0, 5, 1, 3, // facedir = 0
|
||||
0, 4, 0, 3, 0, 2, 1, 5, // facedir = 1
|
||||
0, 3, 0, 5, 0, 4, 1, 2, // facedir = 2
|
||||
0, 5, 0, 2, 0, 3, 1, 4, // facedir = 3
|
||||
};
|
||||
|
||||
return nodemgr->get(node).tiles[dir_to_tile[facedir*8 + dir_i]];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -345,7 +322,7 @@ 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);
|
||||
spec = getTile(mn, face_dir, ndef);
|
||||
|
||||
/*
|
||||
Check temporary modifications on this node
|
||||
@ -363,7 +340,7 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||
{
|
||||
MapNode mn2(mod.param);
|
||||
spec = getTile(mn2, face_dir, tsrc, ndef);
|
||||
spec = getTile(mn2, face_dir, ndef);
|
||||
}
|
||||
#endif
|
||||
if(mod.type == NODEMOD_CRACK)
|
||||
|
300
src/mapgen.cpp
300
src/mapgen.cpp
@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "noise.h"
|
||||
#include "mapblock.h"
|
||||
#include "map.h"
|
||||
#include "mineral.h"
|
||||
//#include "serverobject.h"
|
||||
#include "content_sao.h"
|
||||
#include "nodedef.h"
|
||||
@ -1652,15 +1651,20 @@ void make_block(BlockMakeData *data)
|
||||
MapNode n_##name(c_##name);
|
||||
|
||||
CONTENT_VARIABLE(ndef, stone);
|
||||
CONTENT_VARIABLE(ndef, water_source);
|
||||
CONTENT_VARIABLE(ndef, air);
|
||||
CONTENT_VARIABLE(ndef, water_source);
|
||||
CONTENT_VARIABLE(ndef, dirt);
|
||||
CONTENT_VARIABLE(ndef, sand);
|
||||
CONTENT_VARIABLE(ndef, gravel);
|
||||
CONTENT_VARIABLE(ndef, clay);
|
||||
CONTENT_VARIABLE(ndef, lava_source);
|
||||
CONTENT_VARIABLE(ndef, cobble);
|
||||
CONTENT_VARIABLE(ndef, mossycobble);
|
||||
CONTENT_VARIABLE(ndef, dirt_with_grass);
|
||||
CONTENT_VARIABLE(ndef, junglegrass);
|
||||
CONTENT_VARIABLE(ndef, stone_with_coal);
|
||||
CONTENT_VARIABLE(ndef, stone_with_iron);
|
||||
CONTENT_VARIABLE(ndef, mese);
|
||||
|
||||
/*
|
||||
Make base ground level
|
||||
@ -1702,139 +1706,6 @@ void make_block(BlockMakeData *data)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Add minerals
|
||||
*/
|
||||
|
||||
{
|
||||
PseudoRandom mineralrandom(blockseed);
|
||||
|
||||
/*
|
||||
Add meseblocks
|
||||
*/
|
||||
for(s16 i=0; i<approx_ground_depth/4; i++)
|
||||
{
|
||||
if(mineralrandom.next()%50 == 0)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(LEGN(ndef, "CONTENT_MESE"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add others
|
||||
*/
|
||||
{
|
||||
u16 a = mineralrandom.range(0,15);
|
||||
a = a*a*a;
|
||||
u16 amount = 20 * a/1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
|
||||
u8 base_content = LEGN(ndef, "CONTENT_STONE");
|
||||
MapNode new_content(CONTENT_IGNORE);
|
||||
u32 sparseness = 6;
|
||||
|
||||
if(noisebuf_ground_crumbleness.get(x,y+5,z) < -0.1)
|
||||
{
|
||||
new_content = MapNode(LEGN(ndef, "CONTENT_STONE"), MINERAL_COAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(noisebuf_ground_wetness.get(x,y+5,z) > 0.0)
|
||||
new_content = MapNode(LEGN(ndef, "CONTENT_STONE"), MINERAL_IRON);
|
||||
/*if(noisebuf_ground_wetness.get(x,y,z) > 0.0)
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_MUD"));
|
||||
else
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_SAND"));*/
|
||||
}
|
||||
/*else if(noisebuf_ground_crumbleness.get(x,y,z) > 0.1)
|
||||
{
|
||||
}*/
|
||||
|
||||
if(new_content.getContent() != CONTENT_IGNORE)
|
||||
{
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == base_content)
|
||||
{
|
||||
if(mineralrandom.next()%sparseness == 0)
|
||||
vmanip.m_data[vi] = new_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add coal
|
||||
*/
|
||||
//for(s16 i=0; i < MYMAX(0, 50 - abs(node_min.Y+8 - (-30))); i++)
|
||||
//for(s16 i=0; i<50; i++)
|
||||
u16 coal_amount = 30;
|
||||
u16 coal_rareness = 60 / coal_amount;
|
||||
if(coal_rareness == 0)
|
||||
coal_rareness = 1;
|
||||
if(mineralrandom.next()%coal_rareness == 0)
|
||||
{
|
||||
u16 a = mineralrandom.next() % 16;
|
||||
u16 amount = coal_amount * a*a*a / 1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(LEGN(ndef, "CONTENT_STONE"), MINERAL_COAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add iron
|
||||
*/
|
||||
u16 iron_amount = 8;
|
||||
u16 iron_rareness = 60 / iron_amount;
|
||||
if(iron_rareness == 0)
|
||||
iron_rareness = 1;
|
||||
if(mineralrandom.next()%iron_rareness == 0)
|
||||
{
|
||||
u16 a = mineralrandom.next() % 16;
|
||||
u16 amount = iron_amount * a*a*a / 1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(LEGN(ndef, "CONTENT_STONE"), MINERAL_IRON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Add mud and sand and others underground (in place of stone)
|
||||
*/
|
||||
@ -1955,7 +1826,7 @@ void make_block(BlockMakeData *data)
|
||||
/*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE)
|
||||
{
|
||||
if(wetness > 1.2)
|
||||
vmanip.m_data[i].setContent(LEGN(ndef, "CONTENT_MUD"));
|
||||
vmanip.m_data[i].setContent(c_dirt);
|
||||
}*/
|
||||
data->vmanip->m_area.add_y(em, i, -1);
|
||||
}
|
||||
@ -2077,23 +1948,23 @@ void make_block(BlockMakeData *data)
|
||||
((claynoise > 0) && (claynoise < 0.12) && (current_depth == 1))
|
||||
);
|
||||
if (have_clay)
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_CLAY"));
|
||||
vmanip.m_data[i] = MapNode(c_clay);
|
||||
else
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_SAND"));
|
||||
vmanip.m_data[i] = MapNode(c_sand);
|
||||
}
|
||||
#if 1
|
||||
else if(current_depth==0 && !water_detected
|
||||
&& y >= WATER_LEVEL && air_detected)
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_GRASS"));
|
||||
vmanip.m_data[i] = MapNode(c_dirt_with_grass);
|
||||
#endif
|
||||
else
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_MUD"));
|
||||
vmanip.m_data[i] = MapNode(c_dirt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vmanip.m_data[i].getContent() == LEGN(ndef, "CONTENT_MUD")
|
||||
|| vmanip.m_data[i].getContent() == LEGN(ndef, "CONTENT_GRASS"))
|
||||
vmanip.m_data[i] = MapNode(LEGN(ndef, "CONTENT_STONE"));
|
||||
if(vmanip.m_data[i].getContent() == c_dirt
|
||||
|| vmanip.m_data[i].getContent() == c_dirt_with_grass)
|
||||
vmanip.m_data[i] = MapNode(c_stone);
|
||||
}
|
||||
|
||||
current_depth++;
|
||||
@ -2171,7 +2042,7 @@ void make_block(BlockMakeData *data)
|
||||
make_papyrus(vmanip, p, ndef);
|
||||
}
|
||||
// Trees grow only on mud and grass, on land
|
||||
else if((n->getContent() == c_dirt || n->getContent() == LEGN(ndef, "CONTENT_GRASS")) && y > WATER_LEVEL + 2)
|
||||
else if((n->getContent() == c_dirt || n->getContent() == c_dirt_with_grass) && y > WATER_LEVEL + 2)
|
||||
{
|
||||
p.Y++;
|
||||
//if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5)
|
||||
@ -2238,10 +2109,10 @@ void make_block(BlockMakeData *data)
|
||||
continue;
|
||||
/*p.Y--;
|
||||
if(vmanip.m_area.contains(p))
|
||||
vmanip.m_data[vmanip.m_area.index(p)] = LEGN(ndef, "CONTENT_MUD");
|
||||
vmanip.m_data[vmanip.m_area.index(p)] = c_dirt;
|
||||
p.Y++;*/
|
||||
if(vmanip.m_area.contains(p))
|
||||
vmanip.m_data[vmanip.m_area.index(p)] = LEGN(ndef, "CONTENT_JUNGLEGRASS");
|
||||
vmanip.m_data[vmanip.m_area.index(p)] = c_junglegrass;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2269,7 +2140,7 @@ void make_block(BlockMakeData *data)
|
||||
/*{
|
||||
u32 i = data->vmanip->m_area.index(v3s16(p));
|
||||
MapNode *n = &data->vmanip->m_data[i];
|
||||
if(n->getContent() != LEGN(ndef, "CONTENT_MUD") && n->getContent() != LEGN(ndef, "CONTENT_GRASS"))
|
||||
if(n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass)
|
||||
continue;
|
||||
}*/
|
||||
// Will be placed one higher
|
||||
@ -2304,7 +2175,7 @@ void make_block(BlockMakeData *data)
|
||||
/*{
|
||||
u32 i = data->vmanip->m_area.index(v3s16(p));
|
||||
MapNode *n = &data->vmanip->m_data[i];
|
||||
if(n->getContent() != LEGN(ndef, "CONTENT_MUD") && n->getContent() != LEGN(ndef, "CONTENT_GRASS"))
|
||||
if(n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass)
|
||||
continue;
|
||||
}*/
|
||||
// Will be placed one lower
|
||||
@ -2315,6 +2186,139 @@ void make_block(BlockMakeData *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
Add minerals
|
||||
*/
|
||||
|
||||
{
|
||||
PseudoRandom mineralrandom(blockseed);
|
||||
|
||||
/*
|
||||
Add meseblocks
|
||||
*/
|
||||
for(s16 i=0; i<approx_ground_depth/4; i++)
|
||||
{
|
||||
if(mineralrandom.next()%50 == 0)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(c_mese);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add others
|
||||
*/
|
||||
{
|
||||
u16 a = mineralrandom.range(0,15);
|
||||
a = a*a*a;
|
||||
u16 amount = 20 * a/1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
|
||||
u8 base_content = c_stone;
|
||||
MapNode new_content(CONTENT_IGNORE);
|
||||
u32 sparseness = 6;
|
||||
|
||||
if(noisebuf_ground_crumbleness.get(x,y+5,z) < -0.1)
|
||||
{
|
||||
new_content = MapNode(c_stone_with_coal);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(noisebuf_ground_wetness.get(x,y+5,z) > 0.0)
|
||||
new_content = MapNode(c_stone_with_iron);
|
||||
/*if(noisebuf_ground_wetness.get(x,y,z) > 0.0)
|
||||
vmanip.m_data[i] = MapNode(c_dirt);
|
||||
else
|
||||
vmanip.m_data[i] = MapNode(c_sand);*/
|
||||
}
|
||||
/*else if(noisebuf_ground_crumbleness.get(x,y,z) > 0.1)
|
||||
{
|
||||
}*/
|
||||
|
||||
if(new_content.getContent() != CONTENT_IGNORE)
|
||||
{
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == base_content)
|
||||
{
|
||||
if(mineralrandom.next()%sparseness == 0)
|
||||
vmanip.m_data[vi] = new_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add coal
|
||||
*/
|
||||
//for(s16 i=0; i < MYMAX(0, 50 - abs(node_min.Y+8 - (-30))); i++)
|
||||
//for(s16 i=0; i<50; i++)
|
||||
u16 coal_amount = 30;
|
||||
u16 coal_rareness = 60 / coal_amount;
|
||||
if(coal_rareness == 0)
|
||||
coal_rareness = 1;
|
||||
if(mineralrandom.next()%coal_rareness == 0)
|
||||
{
|
||||
u16 a = mineralrandom.next() % 16;
|
||||
u16 amount = coal_amount * a*a*a / 1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(c_stone_with_coal);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Add iron
|
||||
*/
|
||||
u16 iron_amount = 8;
|
||||
u16 iron_rareness = 60 / iron_amount;
|
||||
if(iron_rareness == 0)
|
||||
iron_rareness = 1;
|
||||
if(mineralrandom.next()%iron_rareness == 0)
|
||||
{
|
||||
u16 a = mineralrandom.next() % 16;
|
||||
u16 amount = iron_amount * a*a*a / 1000;
|
||||
for(s16 i=0; i<amount; i++)
|
||||
{
|
||||
s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
|
||||
s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
|
||||
s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
|
||||
for(u16 i=0; i<27; i++)
|
||||
{
|
||||
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() == c_stone)
|
||||
if(mineralrandom.next()%8 == 0)
|
||||
vmanip.m_data[vi] = MapNode(c_stone_with_iron);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BlockMakeData::BlockMakeData():
|
||||
|
578
src/mapnode.cpp
578
src/mapnode.cpp
@ -21,13 +21,342 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapnode.h"
|
||||
#include "porting.h"
|
||||
#include <string>
|
||||
#include "mineral.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "nodedef.h"
|
||||
#include "content_mapnode.h" // For mapnode_translate_*_internal
|
||||
#include "serialization.h" // For ser_ver_supported
|
||||
|
||||
/*
|
||||
MapNode
|
||||
*/
|
||||
|
||||
// Create directly from a nodename
|
||||
// If name is unknown, sets CONTENT_IGNORE
|
||||
MapNode::MapNode(INodeDefManager *ndef, const std::string &name,
|
||||
u8 a_param1, u8 a_param2)
|
||||
{
|
||||
content_t id = CONTENT_IGNORE;
|
||||
ndef->getId(name, id);
|
||||
param1 = a_param1;
|
||||
param2 = a_param2;
|
||||
// Set content (param0 and (param2&0xf0)) after other params
|
||||
// because this needs to override part of param2
|
||||
setContent(id);
|
||||
}
|
||||
|
||||
void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr)
|
||||
{
|
||||
// If node doesn't contain light data, ignore this
|
||||
if(nodemgr->get(*this).param_type != CPT_LIGHT)
|
||||
return;
|
||||
if(bank == LIGHTBANK_DAY)
|
||||
{
|
||||
param1 &= 0xf0;
|
||||
param1 |= a_light & 0x0f;
|
||||
}
|
||||
else if(bank == LIGHTBANK_NIGHT)
|
||||
{
|
||||
param1 &= 0x0f;
|
||||
param1 |= (a_light & 0x0f)<<4;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
|
||||
{
|
||||
// Select the brightest of [light source, propagated light]
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
u8 light = 0;
|
||||
if(f.param_type == CPT_LIGHT)
|
||||
{
|
||||
if(bank == LIGHTBANK_DAY)
|
||||
light = param1 & 0x0f;
|
||||
else if(bank == LIGHTBANK_NIGHT)
|
||||
light = (param1>>4)&0x0f;
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
if(f.light_source > light)
|
||||
light = f.light_source;
|
||||
return light;
|
||||
}
|
||||
|
||||
bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const
|
||||
{
|
||||
// Select the brightest of [light source, propagated light]
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
if(f.param_type == CPT_LIGHT)
|
||||
{
|
||||
lightday = param1 & 0x0f;
|
||||
lightnight = (param1>>4)&0x0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightday = 0;
|
||||
lightnight = 0;
|
||||
}
|
||||
if(f.light_source > lightday)
|
||||
lightday = f.light_source;
|
||||
if(f.light_source > lightnight)
|
||||
lightnight = f.light_source;
|
||||
return f.param_type == CPT_LIGHT || f.light_source != 0;
|
||||
}
|
||||
|
||||
u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
if(f.param_type_2 == CPT2_FACEDIR)
|
||||
return getParam2() & 0x03;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 MapNode::getWallMounted(INodeDefManager *nodemgr) const
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
if(f.param_type_2 == CPT2_WALLMOUNTED)
|
||||
return getParam2() & 0x07;
|
||||
return 0;
|
||||
}
|
||||
|
||||
v3s16 MapNode::getWallMountedDir(INodeDefManager *nodemgr) const
|
||||
{
|
||||
switch(getWallMounted(nodemgr))
|
||||
{
|
||||
case 0: default: return v3s16(0,1,0);
|
||||
case 1: return v3s16(0,-1,0);
|
||||
case 2: return v3s16(1,0,0);
|
||||
case 3: return v3s16(-1,0,0);
|
||||
case 4: return v3s16(0,0,1);
|
||||
case 5: return v3s16(0,0,-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
u32 MapNode::serializedLength(u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
if(version == 0)
|
||||
return 1;
|
||||
else if(version <= 9)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
}
|
||||
void MapNode::serialize(u8 *dest, u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
if(version <= 21)
|
||||
{
|
||||
serialize_pre22(dest, version);
|
||||
return;
|
||||
}
|
||||
|
||||
writeU8(dest+0, param0);
|
||||
writeU8(dest+1, param1);
|
||||
writeU8(dest+2, param2);
|
||||
}
|
||||
void MapNode::deSerialize(u8 *source, u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
if(version <= 21)
|
||||
{
|
||||
deSerialize_pre22(source, version);
|
||||
return;
|
||||
}
|
||||
|
||||
param0 = readU8(source+0);
|
||||
param1 = readU8(source+1);
|
||||
param2 = readU8(source+2);
|
||||
}
|
||||
void MapNode::serializeBulk(std::ostream &os, int version,
|
||||
const MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
assert(version >= 22);
|
||||
assert(content_width == 1);
|
||||
assert(params_width == 2);
|
||||
|
||||
SharedBuffer<u8> databuf(nodecount * (content_width + params_width));
|
||||
|
||||
// Serialize content
|
||||
if(content_width == 1)
|
||||
{
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
writeU8(&databuf[i], nodes[i].param0);
|
||||
}
|
||||
/* If param0 is extended to two bytes, use something like this: */
|
||||
/*else if(content_width == 2)
|
||||
{
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
writeU16(&databuf[i*2], nodes[i].param0);
|
||||
}*/
|
||||
|
||||
// Serialize param1
|
||||
u32 start1 = content_width * nodecount;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
writeU8(&databuf[start1 + i], nodes[i].param1);
|
||||
|
||||
// Serialize param2
|
||||
u32 start2 = (content_width + 1) * nodecount;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
writeU8(&databuf[start2 + i], nodes[i].param2);
|
||||
|
||||
/*
|
||||
Compress data to output stream
|
||||
*/
|
||||
|
||||
if(compressed)
|
||||
{
|
||||
compressZlib(databuf, os);
|
||||
}
|
||||
else
|
||||
{
|
||||
os.write((const char*) &databuf[0], databuf.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
// Deserialize bulk node data
|
||||
void MapNode::deSerializeBulk(std::istream &is, int version,
|
||||
MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
assert(version >= 22);
|
||||
assert(content_width == 1);
|
||||
assert(params_width == 2);
|
||||
|
||||
// Uncompress or read data
|
||||
u32 len = nodecount * (content_width + params_width);
|
||||
SharedBuffer<u8> databuf(len);
|
||||
if(compressed)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
decompressZlib(is, os);
|
||||
std::string s = os.str();
|
||||
if(s.size() != len)
|
||||
throw SerializationError("deSerializeBulkNodes: "
|
||||
"decompress resulted in invalid size");
|
||||
memcpy(&databuf[0], s.c_str(), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
is.read((char*) &databuf[0], len);
|
||||
if(is.eof() || is.fail())
|
||||
throw SerializationError("deSerializeBulkNodes: "
|
||||
"failed to read bulk node data");
|
||||
}
|
||||
|
||||
// Deserialize content
|
||||
if(content_width == 1)
|
||||
{
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
nodes[i].param0 = readU8(&databuf[i]);
|
||||
}
|
||||
/* If param0 is extended to two bytes, use something like this: */
|
||||
/*else if(content_width == 2)
|
||||
{
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
nodes[i].param0 = readU16(&databuf[i*2]);
|
||||
}*/
|
||||
|
||||
// Deserialize param1
|
||||
u32 start1 = content_width * nodecount;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
nodes[i].param1 = readU8(&databuf[start1 + i]);
|
||||
|
||||
// Deserialize param2
|
||||
u32 start2 = (content_width + 1) * nodecount;
|
||||
for(u32 i=0; i<nodecount; i++)
|
||||
nodes[i].param2 = readU8(&databuf[start2 + i]);
|
||||
}
|
||||
|
||||
/*
|
||||
Legacy serialization
|
||||
*/
|
||||
void MapNode::serialize_pre22(u8 *dest, u8 version)
|
||||
{
|
||||
// Translate to wanted version
|
||||
MapNode n_foreign = mapnode_translate_from_internal(*this, version);
|
||||
|
||||
u16 actual_content = n_foreign.param0;
|
||||
|
||||
// Convert special values from new version to old
|
||||
if(version <= 18)
|
||||
{
|
||||
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||
// are 255 and 254
|
||||
if(actual_content == CONTENT_IGNORE)
|
||||
actual_content = 255;
|
||||
else if(actual_content == CONTENT_AIR)
|
||||
actual_content = 254;
|
||||
}
|
||||
|
||||
if(version == 0)
|
||||
{
|
||||
dest[0] = actual_content;
|
||||
}
|
||||
else if(version <= 9)
|
||||
{
|
||||
dest[0] = actual_content;
|
||||
dest[1] = n_foreign.param1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = actual_content;
|
||||
dest[1] = n_foreign.param1;
|
||||
dest[2] = n_foreign.param2;
|
||||
}
|
||||
}
|
||||
void MapNode::deSerialize_pre22(u8 *source, u8 version)
|
||||
{
|
||||
if(version <= 1)
|
||||
{
|
||||
param0 = source[0];
|
||||
}
|
||||
else if(version <= 9)
|
||||
{
|
||||
param0 = source[0];
|
||||
param1 = source[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
param0 = source[0];
|
||||
param1 = source[1];
|
||||
param2 = source[2];
|
||||
}
|
||||
|
||||
// Convert special values from old version to new
|
||||
if(version <= 19)
|
||||
{
|
||||
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||
// are 255 and 254
|
||||
// Version 19 is fucked up with sometimes the old values and sometimes not
|
||||
if(param0 == 255)
|
||||
param0 = CONTENT_IGNORE;
|
||||
else if(param0 == 254)
|
||||
param0 = CONTENT_AIR;
|
||||
}
|
||||
|
||||
// Translate to our known version
|
||||
*this = mapnode_translate_to_internal(*this, version);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
/*
|
||||
Nodes make a face if contents differ and solidness differs.
|
||||
Return value:
|
||||
@ -83,252 +412,6 @@ u8 face_contents(content_t m1, content_t m2, bool *equivalent,
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
v3s16 facedir_rotate(u8 facedir, v3s16 dir)
|
||||
{
|
||||
/*
|
||||
Face 2 (normally Z-) direction:
|
||||
facedir=0: Z-
|
||||
facedir=1: X-
|
||||
facedir=2: Z+
|
||||
facedir=3: X+
|
||||
*/
|
||||
v3s16 newdir;
|
||||
if(facedir==0) // Same
|
||||
newdir = v3s16(dir.X, dir.Y, dir.Z);
|
||||
else if(facedir == 1) // Face is taken from rotXZccv(-90)
|
||||
newdir = v3s16(-dir.Z, dir.Y, dir.X);
|
||||
else if(facedir == 2) // Face is taken from rotXZccv(180)
|
||||
newdir = v3s16(-dir.X, dir.Y, -dir.Z);
|
||||
else if(facedir == 3) // Face is taken from rotXZccv(90)
|
||||
newdir = v3s16(dir.Z, dir.Y, -dir.X);
|
||||
else
|
||||
newdir = dir;
|
||||
return newdir;
|
||||
}
|
||||
|
||||
u8 packDir(v3s16 dir)
|
||||
{
|
||||
u8 b = 0;
|
||||
|
||||
if(dir.X > 0)
|
||||
b |= (1<<0);
|
||||
else if(dir.X < 0)
|
||||
b |= (1<<1);
|
||||
|
||||
if(dir.Y > 0)
|
||||
b |= (1<<2);
|
||||
else if(dir.Y < 0)
|
||||
b |= (1<<3);
|
||||
|
||||
if(dir.Z > 0)
|
||||
b |= (1<<4);
|
||||
else if(dir.Z < 0)
|
||||
b |= (1<<5);
|
||||
|
||||
return b;
|
||||
}
|
||||
v3s16 unpackDir(u8 b)
|
||||
{
|
||||
v3s16 d(0,0,0);
|
||||
|
||||
if(b & (1<<0))
|
||||
d.X = 1;
|
||||
else if(b & (1<<1))
|
||||
d.X = -1;
|
||||
|
||||
if(b & (1<<2))
|
||||
d.Y = 1;
|
||||
else if(b & (1<<3))
|
||||
d.Y = -1;
|
||||
|
||||
if(b & (1<<4))
|
||||
d.Z = 1;
|
||||
else if(b & (1<<5))
|
||||
d.Z = -1;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
MapNode
|
||||
*/
|
||||
|
||||
// Create directly from a nodename
|
||||
// If name is unknown, sets CONTENT_IGNORE
|
||||
MapNode::MapNode(INodeDefManager *ndef, const std::string &name,
|
||||
u8 a_param1, u8 a_param2)
|
||||
{
|
||||
content_t id = CONTENT_IGNORE;
|
||||
ndef->getId(name, id);
|
||||
param1 = a_param1;
|
||||
param2 = a_param2;
|
||||
// Set content (param0 and (param2&0xf0)) after other params
|
||||
// because this needs to override part of param2
|
||||
setContent(id);
|
||||
}
|
||||
|
||||
void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr)
|
||||
{
|
||||
// If node doesn't contain light data, ignore this
|
||||
if(nodemgr->get(*this).param_type != CPT_LIGHT)
|
||||
return;
|
||||
if(bank == LIGHTBANK_DAY)
|
||||
{
|
||||
param1 &= 0xf0;
|
||||
param1 |= a_light & 0x0f;
|
||||
}
|
||||
else if(bank == LIGHTBANK_NIGHT)
|
||||
{
|
||||
param1 &= 0x0f;
|
||||
param1 |= (a_light & 0x0f)<<4;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
|
||||
{
|
||||
// Select the brightest of [light source, propagated light]
|
||||
u8 light = 0;
|
||||
if(nodemgr->get(*this).param_type == CPT_LIGHT)
|
||||
{
|
||||
if(bank == LIGHTBANK_DAY)
|
||||
light = param1 & 0x0f;
|
||||
else if(bank == LIGHTBANK_NIGHT)
|
||||
light = (param1>>4)&0x0f;
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
if(nodemgr->get(*this).light_source > light)
|
||||
light = nodemgr->get(*this).light_source;
|
||||
return light;
|
||||
}
|
||||
|
||||
u8 MapNode::getLightBanksWithSource(INodeDefManager *nodemgr) const
|
||||
{
|
||||
// Select the brightest of [light source, propagated light]
|
||||
u8 lightday = 0;
|
||||
u8 lightnight = 0;
|
||||
if(nodemgr->get(*this).param_type == CPT_LIGHT)
|
||||
{
|
||||
lightday = param1 & 0x0f;
|
||||
lightnight = (param1>>4)&0x0f;
|
||||
}
|
||||
if(nodemgr->get(*this).light_source > lightday)
|
||||
lightday = nodemgr->get(*this).light_source;
|
||||
if(nodemgr->get(*this).light_source > lightnight)
|
||||
lightnight = nodemgr->get(*this).light_source;
|
||||
return (lightday&0x0f) | ((lightnight<<4)&0xf0);
|
||||
}
|
||||
|
||||
u8 MapNode::getMineral(INodeDefManager *nodemgr) const
|
||||
{
|
||||
if(nodemgr->get(*this).param_type == CPT_MINERAL)
|
||||
{
|
||||
return param1 & 0x0f;
|
||||
}
|
||||
|
||||
return MINERAL_NONE;
|
||||
}
|
||||
|
||||
u32 MapNode::serializedLength(u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
if(version == 0)
|
||||
return 1;
|
||||
else if(version <= 9)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
}
|
||||
void MapNode::serialize(u8 *dest, u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
// Translate to wanted version
|
||||
MapNode n_foreign = mapnode_translate_from_internal(*this, version);
|
||||
|
||||
u8 actual_param0 = n_foreign.param0;
|
||||
|
||||
// Convert special values from new version to old
|
||||
if(version <= 18)
|
||||
{
|
||||
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||
// are 255 and 254
|
||||
if(actual_param0 == CONTENT_IGNORE)
|
||||
actual_param0 = 255;
|
||||
else if(actual_param0 == CONTENT_AIR)
|
||||
actual_param0 = 254;
|
||||
}
|
||||
|
||||
if(version == 0)
|
||||
{
|
||||
dest[0] = actual_param0;
|
||||
}
|
||||
else if(version <= 9)
|
||||
{
|
||||
dest[0] = actual_param0;
|
||||
dest[1] = n_foreign.param1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = actual_param0;
|
||||
dest[1] = n_foreign.param1;
|
||||
dest[2] = n_foreign.param2;
|
||||
}
|
||||
}
|
||||
void MapNode::deSerialize(u8 *source, u8 version)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapNode format not supported");
|
||||
|
||||
if(version == 0)
|
||||
{
|
||||
param0 = source[0];
|
||||
}
|
||||
else if(version == 1)
|
||||
{
|
||||
param0 = source[0];
|
||||
}
|
||||
else if(version <= 9)
|
||||
{
|
||||
param0 = source[0];
|
||||
param1 = source[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
param0 = source[0];
|
||||
param1 = source[1];
|
||||
param2 = source[2];
|
||||
}
|
||||
|
||||
// Convert special values from old version to new
|
||||
if(version <= 18)
|
||||
{
|
||||
// In these versions, CONTENT_IGNORE and CONTENT_AIR
|
||||
// are 255 and 254
|
||||
if(param0 == 255)
|
||||
param0 = CONTENT_IGNORE;
|
||||
else if(param0 == 254)
|
||||
param0 = CONTENT_AIR;
|
||||
}
|
||||
// version 19 is fucked up with sometimes the old values and sometimes not
|
||||
if(version == 19)
|
||||
{
|
||||
if(param0 == 255)
|
||||
param0 = CONTENT_IGNORE;
|
||||
else if(param0 == 254)
|
||||
param0 = CONTENT_AIR;
|
||||
}
|
||||
|
||||
// Translate to our known version
|
||||
*this = mapnode_translate_to_internal(*this, version);
|
||||
}
|
||||
|
||||
/*
|
||||
Gets lighting value at face of node
|
||||
@ -380,4 +463,5 @@ u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
112
src/mapnode.h
112
src/mapnode.h
@ -32,8 +32,8 @@ class INodeDefManager;
|
||||
- Tile = TileSpec at some side of a node of some content type
|
||||
|
||||
Content ranges:
|
||||
0x000...0x07f: param2 is fully usable
|
||||
0x800...0xfff: param2 lower 4 bytes are free
|
||||
0x000...0x07f: param2 is fully usable
|
||||
0x800...0xfff: param2 lower 4 bits are free
|
||||
*/
|
||||
typedef u16 content_t;
|
||||
#define MAX_CONTENT 0xfff
|
||||
@ -56,36 +56,6 @@ typedef u16 content_t;
|
||||
*/
|
||||
#define CONTENT_AIR 126
|
||||
|
||||
#ifndef SERVER
|
||||
/*
|
||||
Nodes make a face if contents differ and solidness differs.
|
||||
Return value:
|
||||
0: No face
|
||||
1: Face uses m1's content
|
||||
2: Face uses m2's content
|
||||
equivalent: Whether the blocks share the same face (eg. water and glass)
|
||||
*/
|
||||
u8 face_contents(content_t m1, content_t m2, bool *equivalent,
|
||||
INodeDefManager *nodemgr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Packs directions like (1,0,0), (1,-1,0) in six bits.
|
||||
NOTE: This wastes way too much space for most purposes.
|
||||
*/
|
||||
u8 packDir(v3s16 dir);
|
||||
v3s16 unpackDir(u8 b);
|
||||
|
||||
/*
|
||||
facedir: CPT_FACEDIR_SIMPLE param1 value
|
||||
dir: The face for which stuff is wanted
|
||||
return value: The face from which the stuff is actually found
|
||||
|
||||
NOTE: Currently this uses 2 bits for Z-,X-,Z+,X+, should there be Y+
|
||||
and Y- too?
|
||||
*/
|
||||
v3s16 facedir_rotate(u8 facedir, v3s16 dir);
|
||||
|
||||
enum LightBank
|
||||
{
|
||||
LIGHTBANK_DAY,
|
||||
@ -122,7 +92,6 @@ struct MapNode
|
||||
stored logarithmically from 0 to LIGHT_MAX.
|
||||
Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
|
||||
- Contains 2 values, day- and night lighting. Each takes 4 bits.
|
||||
- Mineral content (should be removed from here)
|
||||
- Uhh... well, most blocks have light or nothing in here.
|
||||
*/
|
||||
u8 param1;
|
||||
@ -143,7 +112,7 @@ struct MapNode
|
||||
{
|
||||
param1 = a_param1;
|
||||
param2 = a_param2;
|
||||
// Set content (param0 and (param2&0xf0)) after other params
|
||||
// Set content (param0 and param2&0xf0)) after other params
|
||||
// because this needs to override part of param2
|
||||
setContent(content);
|
||||
}
|
||||
@ -210,40 +179,22 @@ struct MapNode
|
||||
|
||||
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
|
||||
u8 getLight(enum LightBank bank, INodeDefManager *nodemgr) const;
|
||||
u8 getLightBanksWithSource(INodeDefManager *nodemgr) const;
|
||||
bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const;
|
||||
|
||||
// 0 <= daylight_factor <= 1000
|
||||
// 0 <= return value <= LIGHT_SUN
|
||||
u8 getLightBlend(u32 daylight_factor, INodeDefManager *nodemgr) const
|
||||
{
|
||||
u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY, nodemgr)
|
||||
+ (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT, nodemgr))
|
||||
)/1000;
|
||||
u8 max = LIGHT_MAX;
|
||||
if(getLight(LIGHTBANK_DAY, nodemgr) == LIGHT_SUN)
|
||||
max = LIGHT_SUN;
|
||||
if(l > max)
|
||||
l = max;
|
||||
return l;
|
||||
u8 lightday = 0;
|
||||
u8 lightnight = 0;
|
||||
getLightBanks(lightday, lightnight, nodemgr);
|
||||
return blend_light(daylight_factor, lightday, lightnight);
|
||||
}
|
||||
/*// 0 <= daylight_factor <= 1000
|
||||
// 0 <= return value <= 255
|
||||
u8 getLightBlend(u32 daylight_factor, INodeDefManager *nodemgr)
|
||||
{
|
||||
u8 daylight = decode_light(getLight(LIGHTBANK_DAY, nodemgr));
|
||||
u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT, nodemgr));
|
||||
u8 mix = ((daylight_factor * daylight
|
||||
+ (1000-daylight_factor) * nightlight)
|
||||
)/1000;
|
||||
return mix;
|
||||
}*/
|
||||
|
||||
/*
|
||||
Gets mineral content of node, if there is any.
|
||||
MINERAL_NONE if doesn't contain or isn't able to contain mineral.
|
||||
*/
|
||||
u8 getMineral(INodeDefManager *nodemgr) const;
|
||||
|
||||
u8 getFaceDir(INodeDefManager *nodemgr) const;
|
||||
u8 getWallMounted(INodeDefManager *nodemgr) const;
|
||||
v3s16 getWallMountedDir(INodeDefManager *nodemgr) const;
|
||||
|
||||
/*
|
||||
Serialization functions
|
||||
*/
|
||||
@ -252,8 +203,44 @@ struct MapNode
|
||||
void serialize(u8 *dest, u8 version);
|
||||
void deSerialize(u8 *source, u8 version);
|
||||
|
||||
// Serializes or deserializes a list of nodes in bulk format (first the
|
||||
// content of all nodes, then the param1 of all nodes, then the param2
|
||||
// of all nodes).
|
||||
// version = serialization version. Must be >= 22
|
||||
// content_width = the number of bytes of content per node
|
||||
// params_width = the number of bytes of params per node
|
||||
// compressed = true to zlib-compress output
|
||||
static void serializeBulk(std::ostream &os, int version,
|
||||
const MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed);
|
||||
static void deSerializeBulk(std::istream &is, int version,
|
||||
MapNode *nodes, u32 nodecount,
|
||||
u8 content_width, u8 params_width, bool compressed);
|
||||
|
||||
private:
|
||||
// Deprecated serialization methods
|
||||
void serialize_pre22(u8 *dest, u8 version);
|
||||
void deSerialize_pre22(u8 *source, u8 version);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
MapNode helpers for mesh making stuff
|
||||
*/
|
||||
|
||||
#ifndef SERVER
|
||||
|
||||
/*
|
||||
Nodes make a face if contents differ and solidness differs.
|
||||
Return value:
|
||||
0: No face
|
||||
1: Face uses m1's content
|
||||
2: Face uses m2's content
|
||||
equivalent: Whether the blocks share the same face (eg. water and glass)
|
||||
*/
|
||||
u8 face_contents(content_t m1, content_t m2, bool *equivalent,
|
||||
INodeDefManager *nodemgr);
|
||||
|
||||
/*
|
||||
Gets lighting value at face of node
|
||||
|
||||
@ -275,3 +262,6 @@ u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -18,8 +18,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "materials.h"
|
||||
#include "mapnode.h"
|
||||
#include "nodedef.h"
|
||||
#include "utility.h"
|
||||
|
||||
void MaterialProperties::serialize(std::ostream &os)
|
||||
@ -139,13 +137,6 @@ DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
return getDiggingProperties(mp, tp, 1000000);
|
||||
}
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content,
|
||||
const ToolDiggingProperties *tp, INodeDefManager *nodemgr)
|
||||
{
|
||||
const MaterialProperties &mp = nodemgr->get(content).material;
|
||||
return getDiggingProperties(&mp, tp);
|
||||
}
|
||||
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch)
|
||||
{
|
||||
@ -160,3 +151,9 @@ HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
return HittingProperties(hp, wear);
|
||||
}
|
||||
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp)
|
||||
{
|
||||
return getHittingProperties(mp, tp, 1000000);
|
||||
}
|
||||
|
||||
|
@ -110,17 +110,12 @@ struct DiggingProperties
|
||||
{}
|
||||
};
|
||||
|
||||
class INodeDefManager;
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch);
|
||||
|
||||
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp);
|
||||
|
||||
DiggingProperties getDiggingProperties(u16 content,
|
||||
const ToolDiggingProperties *tp, INodeDefManager *nodemgr);
|
||||
|
||||
struct HittingProperties
|
||||
{
|
||||
s16 hp;
|
||||
@ -135,5 +130,8 @@ struct HittingProperties
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp, float time_from_last_punch);
|
||||
|
||||
HittingProperties getHittingProperties(const MaterialProperties *mp,
|
||||
const ToolDiggingProperties *tp);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 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 "mineral.h"
|
||||
#include "gamedef.h"
|
||||
|
||||
|
||||
const char *mineral_filenames[MINERAL_COUNT] =
|
||||
{
|
||||
NULL,
|
||||
"mineral_coal.png",
|
||||
"mineral_iron.png"
|
||||
};
|
||||
|
||||
std::string mineral_textures[MINERAL_COUNT];
|
||||
|
||||
void init_mineral()
|
||||
{
|
||||
for(u32 i=0; i<MINERAL_COUNT; i++)
|
||||
{
|
||||
if(mineral_filenames[i] == NULL)
|
||||
continue;
|
||||
mineral_textures[i] = mineral_filenames[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string mineral_block_texture(u8 mineral)
|
||||
{
|
||||
if(mineral >= MINERAL_COUNT)
|
||||
return "";
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 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 MINERAL_HEADER
|
||||
#define MINERAL_HEADER
|
||||
|
||||
#include "inventory.h"
|
||||
|
||||
/*
|
||||
Minerals
|
||||
|
||||
Value is stored in the lowest 5 bits of a MapNode's CPT_MINERAL
|
||||
type param.
|
||||
*/
|
||||
|
||||
// Caches textures
|
||||
void init_mineral();
|
||||
|
||||
#define MINERAL_NONE 0
|
||||
#define MINERAL_COAL 1
|
||||
#define MINERAL_IRON 2
|
||||
|
||||
#define MINERAL_COUNT 3
|
||||
|
||||
class IGameDef;
|
||||
|
||||
std::string mineral_block_texture(u8 mineral);
|
||||
ItemStack getDiggedMineralItem(u8 mineral, IGameDef *gamedef);
|
||||
|
||||
#endif
|
||||
|
@ -70,6 +70,9 @@ public:
|
||||
result = i->second;
|
||||
return true;
|
||||
}
|
||||
u16 size() const{
|
||||
return m_id_to_name.size();
|
||||
}
|
||||
private:
|
||||
std::map<u16, std::string> m_id_to_name;
|
||||
std::map<std::string, u16> m_name_to_id;
|
||||
|
@ -127,6 +127,7 @@ void ContentFeatures::reset()
|
||||
alpha = 255;
|
||||
post_effect_color = video::SColor(0, 0, 0, 0);
|
||||
param_type = CPT_NONE;
|
||||
param_type_2 = CPT2_NONE;
|
||||
is_ground_content = false;
|
||||
light_propagates = false;
|
||||
sunlight_propagates = false;
|
||||
@ -135,10 +136,6 @@ void ContentFeatures::reset()
|
||||
diggable = true;
|
||||
climbable = false;
|
||||
buildable_to = false;
|
||||
wall_mounted = false;
|
||||
dug_item = "";
|
||||
extra_dug_item = "";
|
||||
extra_dug_item_rarity = 2;
|
||||
metadata_name = "";
|
||||
liquid_type = LIQUID_NONE;
|
||||
liquid_alternative_flowing = "";
|
||||
@ -151,6 +148,8 @@ void ContentFeatures::reset()
|
||||
// Make unknown blocks diggable
|
||||
material.diggability = DIGGABLE_CONSTANT;
|
||||
material.constant_time = 0.5;
|
||||
legacy_facedir_simple = false;
|
||||
legacy_wallmounted = false;
|
||||
}
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os)
|
||||
@ -172,6 +171,7 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU8(os, post_effect_color.getGreen());
|
||||
writeU8(os, post_effect_color.getBlue());
|
||||
writeU8(os, param_type);
|
||||
writeU8(os, param_type_2);
|
||||
writeU8(os, is_ground_content);
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
@ -180,10 +180,6 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU8(os, diggable);
|
||||
writeU8(os, climbable);
|
||||
writeU8(os, buildable_to);
|
||||
writeU8(os, wall_mounted);
|
||||
os<<serializeString(dug_item);
|
||||
os<<serializeString(extra_dug_item);
|
||||
writeS32(os, extra_dug_item_rarity);
|
||||
os<<serializeString(metadata_name);
|
||||
writeU8(os, liquid_type);
|
||||
os<<serializeString(liquid_alternative_flowing);
|
||||
@ -193,6 +189,8 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU32(os, damage_per_second);
|
||||
selection_box.serialize(os);
|
||||
material.serialize(os);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
@ -218,6 +216,7 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||
post_effect_color.setGreen(readU8(is));
|
||||
post_effect_color.setBlue(readU8(is));
|
||||
param_type = (enum ContentParamType)readU8(is);
|
||||
param_type_2 = (enum ContentParamType2)readU8(is);
|
||||
is_ground_content = readU8(is);
|
||||
light_propagates = readU8(is);
|
||||
sunlight_propagates = readU8(is);
|
||||
@ -226,10 +225,6 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||
diggable = readU8(is);
|
||||
climbable = readU8(is);
|
||||
buildable_to = readU8(is);
|
||||
wall_mounted = readU8(is);
|
||||
dug_item = deSerializeString(is);
|
||||
extra_dug_item = deSerializeString(is);
|
||||
extra_dug_item_rarity = readS32(is);
|
||||
metadata_name = deSerializeString(is);
|
||||
liquid_type = (enum LiquidType)readU8(is);
|
||||
liquid_alternative_flowing = deSerializeString(is);
|
||||
@ -239,6 +234,8 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||
damage_per_second = readU32(is);
|
||||
selection_box.deSerialize(is);
|
||||
material.deSerialize(is);
|
||||
legacy_facedir_simple = readU8(is);
|
||||
legacy_wallmounted = readU8(is);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -298,7 +295,7 @@ public:
|
||||
// CONTENT_IGNORE = not found
|
||||
content_t getFreeId(bool require_full_param2)
|
||||
{
|
||||
// If allowed, first search in the large 4-byte-param2 pool
|
||||
// If allowed, first search in the large 4-bit-param2 pool
|
||||
if(!require_full_param2){
|
||||
for(u16 i=0x800; i<=0xfff; i++){
|
||||
const ContentFeatures &f = m_content_features[i];
|
||||
@ -306,7 +303,7 @@ public:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// Then search from the small 8-byte-param2 pool
|
||||
// Then search from the small 8-bit-param2 pool
|
||||
for(u16 i=0; i<=125; i++){
|
||||
const ContentFeatures &f = m_content_features[i];
|
||||
if(f.name == "")
|
||||
@ -394,13 +391,9 @@ public:
|
||||
if(!found){
|
||||
// Determine if full param2 is required
|
||||
bool require_full_param2 = (
|
||||
def.liquid_type == LIQUID_FLOWING
|
||||
def.param_type_2 == CPT2_FULL
|
||||
||
|
||||
def.drawtype == NDT_FLOWINGLIQUID
|
||||
||
|
||||
def.drawtype == NDT_TORCHLIKE
|
||||
||
|
||||
def.drawtype == NDT_SIGNLIKE
|
||||
def.param_type_2 == CPT2_FLOWINGLIQUID
|
||||
);
|
||||
// Get some id
|
||||
id = getFreeId(require_full_param2);
|
||||
|
@ -37,9 +37,19 @@ enum ContentParamType
|
||||
{
|
||||
CPT_NONE,
|
||||
CPT_LIGHT,
|
||||
CPT_MINERAL,
|
||||
};
|
||||
|
||||
enum ContentParamType2
|
||||
{
|
||||
CPT2_NONE,
|
||||
// Need 8-bit param2
|
||||
CPT2_FULL,
|
||||
// Flowing liquid properties
|
||||
CPT2_FLOWINGLIQUID,
|
||||
// Direction for chests and furnaces and such
|
||||
CPT_FACEDIR_SIMPLE
|
||||
CPT2_FACEDIR,
|
||||
// Direction for signs, torches and such
|
||||
CPT2_WALLMOUNTED,
|
||||
};
|
||||
|
||||
enum LiquidType
|
||||
@ -53,7 +63,7 @@ enum NodeBoxType
|
||||
{
|
||||
NODEBOX_REGULAR, // Regular block; allows buildable_to
|
||||
NODEBOX_FIXED, // Static separately defined box
|
||||
NODEBOX_WALLMOUNTED, // Box for wall_mounted nodes; (top, bottom, side)
|
||||
NODEBOX_WALLMOUNTED, // Box for wall mounted nodes; (top, bottom, side)
|
||||
};
|
||||
|
||||
struct NodeBox
|
||||
@ -151,6 +161,8 @@ struct ContentFeatures
|
||||
video::SColor post_effect_color;
|
||||
// Type of MapNode::param1
|
||||
ContentParamType param_type;
|
||||
// Type of MapNode::param2
|
||||
ContentParamType2 param_type_2;
|
||||
// True for all ground-like things like stone and mud, false for eg. trees
|
||||
bool is_ground_content;
|
||||
bool light_propagates;
|
||||
@ -166,16 +178,6 @@ struct ContentFeatures
|
||||
bool climbable;
|
||||
// Player can build on these
|
||||
bool buildable_to;
|
||||
// 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;
|
||||
// Inventory item string as which the node appears in inventory when dug.
|
||||
// Mineral overrides this.
|
||||
std::string dug_item;
|
||||
// Extra dug item and its rarity
|
||||
std::string extra_dug_item;
|
||||
// Usual get interval for extra dug item
|
||||
s32 extra_dug_item_rarity;
|
||||
// Metadata name of node (eg. "furnace")
|
||||
std::string metadata_name;
|
||||
// Whether the node is non-liquid, source liquid or flowing liquid
|
||||
@ -193,6 +195,11 @@ struct ContentFeatures
|
||||
u32 damage_per_second;
|
||||
NodeBox selection_box;
|
||||
MaterialProperties material;
|
||||
// Compatibility with old maps
|
||||
// Set to true if paramtype used to be 'facedir_simple'
|
||||
bool legacy_facedir_simple;
|
||||
// Set to true if wall_mounted used to be set to true
|
||||
bool legacy_wallmounted;
|
||||
|
||||
/*
|
||||
Methods
|
||||
|
@ -314,6 +314,15 @@ static int getenumfield(lua_State *L, int table,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setintfield(lua_State *L, int table,
|
||||
const char *fieldname, int value)
|
||||
{
|
||||
lua_pushinteger(L, value);
|
||||
if(table < 0)
|
||||
table -= 1;
|
||||
lua_setfield(L, table, fieldname);
|
||||
}
|
||||
|
||||
static void setfloatfield(lua_State *L, int table,
|
||||
const char *fieldname, float value)
|
||||
{
|
||||
@ -323,6 +332,15 @@ static void setfloatfield(lua_State *L, int table,
|
||||
lua_setfield(L, table, fieldname);
|
||||
}
|
||||
|
||||
static void setboolfield(lua_State *L, int table,
|
||||
const char *fieldname, bool value)
|
||||
{
|
||||
lua_pushboolean(L, value);
|
||||
if(table < 0)
|
||||
table -= 1;
|
||||
lua_setfield(L, table, fieldname);
|
||||
}
|
||||
|
||||
static void warn_if_field_exists(lua_State *L, int table,
|
||||
const char *fieldname, const std::string &message)
|
||||
{
|
||||
@ -369,8 +387,16 @@ struct EnumString es_ContentParamType[] =
|
||||
{
|
||||
{CPT_NONE, "none"},
|
||||
{CPT_LIGHT, "light"},
|
||||
{CPT_MINERAL, "mineral"},
|
||||
{CPT_FACEDIR_SIMPLE, "facedir_simple"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
struct EnumString es_ContentParamType2[] =
|
||||
{
|
||||
{CPT2_NONE, "none"},
|
||||
{CPT2_FULL, "full"},
|
||||
{CPT2_FLOWINGLIQUID, "flowingliquid"},
|
||||
{CPT2_FACEDIR, "facedir"},
|
||||
{CPT2_WALLMOUNTED, "wallmounted"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
@ -586,6 +612,25 @@ static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
|
||||
return box;
|
||||
}
|
||||
|
||||
/*
|
||||
MaterialProperties
|
||||
*/
|
||||
|
||||
static MaterialProperties read_material_properties(
|
||||
lua_State *L, int table)
|
||||
{
|
||||
MaterialProperties prop;
|
||||
prop.diggability = (Diggability)getenumfield(L, -1, "diggability",
|
||||
es_Diggability, DIGGABLE_NORMAL);
|
||||
getfloatfield(L, -1, "constant_time", prop.constant_time);
|
||||
getfloatfield(L, -1, "weight", prop.weight);
|
||||
getfloatfield(L, -1, "crackiness", prop.crackiness);
|
||||
getfloatfield(L, -1, "crumbliness", prop.crumbliness);
|
||||
getfloatfield(L, -1, "cuttability", prop.cuttability);
|
||||
getfloatfield(L, -1, "flammability", prop.flammability);
|
||||
return prop;
|
||||
}
|
||||
|
||||
/*
|
||||
ToolDiggingProperties
|
||||
*/
|
||||
@ -631,6 +676,43 @@ static void push_tool_digging_properties(lua_State *L,
|
||||
set_tool_digging_properties(L, -1, prop);
|
||||
}
|
||||
|
||||
/*
|
||||
DiggingProperties
|
||||
*/
|
||||
|
||||
static void set_digging_properties(lua_State *L, int table,
|
||||
const DiggingProperties &prop)
|
||||
{
|
||||
setboolfield(L, table, "diggable", prop.diggable);
|
||||
setfloatfield(L, table, "time", prop.time);
|
||||
setintfield(L, table, "wear", prop.wear);
|
||||
}
|
||||
|
||||
static void push_digging_properties(lua_State *L,
|
||||
const DiggingProperties &prop)
|
||||
{
|
||||
lua_newtable(L);
|
||||
set_digging_properties(L, -1, prop);
|
||||
}
|
||||
|
||||
/*
|
||||
HittingProperties
|
||||
*/
|
||||
|
||||
static void set_hitting_properties(lua_State *L, int table,
|
||||
const HittingProperties &prop)
|
||||
{
|
||||
setintfield(L, table, "hp", prop.hp);
|
||||
setintfield(L, table, "wear", prop.wear);
|
||||
}
|
||||
|
||||
static void push_hitting_properties(lua_State *L,
|
||||
const HittingProperties &prop)
|
||||
{
|
||||
lua_newtable(L);
|
||||
set_hitting_properties(L, -1, prop);
|
||||
}
|
||||
|
||||
/*
|
||||
PointedThing
|
||||
*/
|
||||
@ -797,12 +879,24 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||
|
||||
f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
|
||||
es_ContentParamType, CPT_NONE);
|
||||
f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
|
||||
es_ContentParamType2, CPT2_NONE);
|
||||
|
||||
// Warn about some deprecated fields
|
||||
warn_if_field_exists(L, index, "wall_mounted",
|
||||
"deprecated: use paramtype2 = 'wallmounted'");
|
||||
warn_if_field_exists(L, index, "light_propagates",
|
||||
"deprecated: determined from paramtype");
|
||||
warn_if_field_exists(L, index, "dug_item",
|
||||
"deprecated: use 'drops' field");
|
||||
warn_if_field_exists(L, index, "extra_dug_item",
|
||||
"deprecated: use 'drops' field");
|
||||
warn_if_field_exists(L, index, "extra_dug_item_rarity",
|
||||
"deprecated: use 'drops' field");
|
||||
|
||||
// True for all ground-like things like stone and mud, false for eg. trees
|
||||
getboolfield(L, index, "is_ground_content", f.is_ground_content);
|
||||
f.light_propagates = (f.param_type == CPT_LIGHT);
|
||||
warn_if_field_exists(L, index, "light_propagates",
|
||||
"deprecated: determined from paramtype");
|
||||
getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
|
||||
// This is used for collision detection.
|
||||
// Also for general solidness queries.
|
||||
@ -815,16 +909,6 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||
getboolfield(L, index, "climbable", f.climbable);
|
||||
// Player can build on these
|
||||
getboolfield(L, index, "buildable_to", f.buildable_to);
|
||||
// If true, param2 is set to direction when placed. Used for torches.
|
||||
// NOTE: the direction format is quite inefficient and should be changed
|
||||
getboolfield(L, index, "wall_mounted", f.wall_mounted);
|
||||
// Inventory item string as which the node appears in inventory when dug.
|
||||
// Mineral overrides this.
|
||||
getstringfield(L, index, "dug_item", f.dug_item);
|
||||
// Extra dug item and its rarity
|
||||
getstringfield(L, index, "extra_dug_item", f.extra_dug_item);
|
||||
// Usual get interval for extra dug item
|
||||
getintfield(L, index, "extra_dug_item_rarity", f.extra_dug_item_rarity);
|
||||
// Metadata name of node (eg. "furnace")
|
||||
getstringfield(L, index, "metadata_name", f.metadata_name);
|
||||
// Whether the node is non-liquid, source liquid or flowing liquid
|
||||
@ -876,18 +960,15 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||
|
||||
lua_getfield(L, index, "material");
|
||||
if(lua_istable(L, -1)){
|
||||
f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
|
||||
es_Diggability, DIGGABLE_NORMAL);
|
||||
|
||||
getfloatfield(L, -1, "constant_time", f.material.constant_time);
|
||||
getfloatfield(L, -1, "weight", f.material.weight);
|
||||
getfloatfield(L, -1, "crackiness", f.material.crackiness);
|
||||
getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
|
||||
getfloatfield(L, -1, "cuttability", f.material.cuttability);
|
||||
getfloatfield(L, -1, "flammability", f.material.flammability);
|
||||
f.material = read_material_properties(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Set to true if paramtype used to be 'facedir_simple'
|
||||
getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
|
||||
// Set to true if wall_mounted used to be set to true
|
||||
getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -1774,6 +1855,33 @@ private:
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_owner(self, string)
|
||||
static int l_set_owner(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
NodeMetadata *meta = getmeta(ref);
|
||||
if(meta == NULL) return 0;
|
||||
// Do it
|
||||
std::string owner = luaL_checkstring(L, 2);
|
||||
meta->setOwner(owner);
|
||||
reportMetadataChange(ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_allow_removal(self)
|
||||
static int l_get_allow_removal(lua_State *L)
|
||||
{
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
NodeMetadata *meta = getmeta(ref);
|
||||
if(meta == NULL){
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
// Do it
|
||||
lua_pushboolean(L, !meta->nodeRemovalDisabled());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* IGenericNodeMetadata interface */
|
||||
|
||||
// set_infotext(self, text)
|
||||
@ -1984,6 +2092,8 @@ const luaL_reg NodeMetaRef::methods[] = {
|
||||
method(NodeMetaRef, set_text),
|
||||
method(NodeMetaRef, get_text),
|
||||
method(NodeMetaRef, get_owner),
|
||||
method(NodeMetaRef, set_owner),
|
||||
method(NodeMetaRef, get_allow_removal),
|
||||
method(NodeMetaRef, set_infotext),
|
||||
method(NodeMetaRef, get_inventory),
|
||||
method(NodeMetaRef, set_inventory_draw_spec),
|
||||
@ -3369,6 +3479,32 @@ static int l_get_inventory(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_digging_properties(material_properties, tool_digging_properties[, time_from_last_punch])
|
||||
static int l_get_digging_properties(lua_State *L)
|
||||
{
|
||||
MaterialProperties mp = read_material_properties(L, 1);
|
||||
ToolDiggingProperties tp = read_tool_digging_properties(L, 2);
|
||||
if(lua_isnoneornil(L, 3))
|
||||
push_digging_properties(L, getDiggingProperties(&mp, &tp));
|
||||
else
|
||||
push_digging_properties(L, getDiggingProperties(&mp, &tp,
|
||||
luaL_checknumber(L, 3)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_hitting_properties(material_properties, tool_digging_properties[, time_from_last_punch])
|
||||
static int l_get_hitting_properties(lua_State *L)
|
||||
{
|
||||
MaterialProperties mp = read_material_properties(L, 1);
|
||||
ToolDiggingProperties tp = read_tool_digging_properties(L, 2);
|
||||
if(lua_isnoneornil(L, 3))
|
||||
push_hitting_properties(L, getHittingProperties(&mp, &tp));
|
||||
else
|
||||
push_hitting_properties(L, getHittingProperties(&mp, &tp,
|
||||
luaL_checknumber(L, 3)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_current_modname()
|
||||
static int l_get_current_modname(lua_State *L)
|
||||
{
|
||||
@ -3402,6 +3538,8 @@ static const struct luaL_Reg minetest_f [] = {
|
||||
{"chat_send_player", l_chat_send_player},
|
||||
{"get_player_privs", l_get_player_privs},
|
||||
{"get_inventory", l_get_inventory},
|
||||
{"get_digging_properties", l_get_digging_properties},
|
||||
{"get_hitting_properties", l_get_hitting_properties},
|
||||
{"get_current_modname", l_get_current_modname},
|
||||
{"get_modpath", l_get_modpath},
|
||||
{NULL, NULL}
|
||||
@ -3719,6 +3857,8 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
dstream<<"player: "<<player<<" id: "<<player->getId()<<std::endl;
|
||||
|
||||
bool positioning_handled_by_some = false;
|
||||
|
||||
// Get minetest.registered_on_respawnplayers
|
||||
@ -3754,7 +3894,7 @@ void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
|
||||
}
|
||||
|
||||
/*
|
||||
item callbacks
|
||||
item callbacks and node callbacks
|
||||
*/
|
||||
|
||||
// Retrieves minetest.registered_items[name][callbackname]
|
||||
@ -3864,6 +4004,50 @@ bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool scriptapi_node_on_punch(lua_State *L, v3s16 pos, MapNode node,
|
||||
ServerActiveObject *puncher)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
INodeDefManager *ndef = get_server(L)->ndef();
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_punch"))
|
||||
return false;
|
||||
|
||||
// Call function
|
||||
push_v3s16(L, pos);
|
||||
pushnode(L, node, ndef);
|
||||
objectref_get_or_create(L, puncher);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool scriptapi_node_on_dig(lua_State *L, v3s16 pos, MapNode node,
|
||||
ServerActiveObject *digger)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
INodeDefManager *ndef = get_server(L)->ndef();
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_dig"))
|
||||
return false;
|
||||
|
||||
// Call function
|
||||
push_v3s16(L, pos);
|
||||
pushnode(L, node, ndef);
|
||||
objectref_get_or_create(L, digger);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
environment
|
||||
*/
|
||||
@ -3893,102 +4077,6 @@ void scriptapi_environment_step(lua_State *L, float dtime)
|
||||
}
|
||||
}
|
||||
|
||||
void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
|
||||
ServerActiveObject *placer)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
//infostream<<"scriptapi_environment_on_placenode"<<std::endl;
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Get the writable node definition manager from the server
|
||||
IWritableNodeDefManager *ndef =
|
||||
get_server(L)->getWritableNodeDefManager();
|
||||
|
||||
// Get minetest.registered_on_placenodes
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "registered_on_placenodes");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int table = lua_gettop(L);
|
||||
// Foreach
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
// Call function
|
||||
push_v3s16(L, p);
|
||||
pushnode(L, newnode, ndef);
|
||||
objectref_get_or_create(L, placer);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
|
||||
void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
|
||||
ServerActiveObject *digger)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
//infostream<<"scriptapi_environment_on_dignode"<<std::endl;
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Get the writable node definition manager from the server
|
||||
IWritableNodeDefManager *ndef =
|
||||
get_server(L)->getWritableNodeDefManager();
|
||||
|
||||
// Get minetest.registered_on_dignodes
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "registered_on_dignodes");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int table = lua_gettop(L);
|
||||
// Foreach
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
// Call function
|
||||
push_v3s16(L, p);
|
||||
pushnode(L, oldnode, ndef);
|
||||
objectref_get_or_create(L, digger);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
|
||||
void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *puncher)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
//infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Get the writable node definition manager from the server
|
||||
IWritableNodeDefManager *ndef =
|
||||
get_server(L)->getWritableNodeDefManager();
|
||||
|
||||
// Get minetest.registered_on_punchnodes
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "registered_on_punchnodes");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int table = lua_gettop(L);
|
||||
// Foreach
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
// Call function
|
||||
push_v3s16(L, p);
|
||||
pushnode(L, node, ndef);
|
||||
objectref_get_or_create(L, puncher);
|
||||
if(lua_pcall(L, 3, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
// value removed, keep key for next iteration
|
||||
}
|
||||
}
|
||||
|
||||
void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
|
||||
{
|
||||
realitycheck(L);
|
||||
|
@ -49,15 +49,6 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
|
||||
/* environment */
|
||||
// On environment step
|
||||
void scriptapi_environment_step(lua_State *L, float dtime);
|
||||
// After adding node
|
||||
void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
|
||||
ServerActiveObject *placer);
|
||||
// After removing node
|
||||
void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
|
||||
ServerActiveObject *digger);
|
||||
// When punching node
|
||||
void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *puncher);
|
||||
// After generating a piece of map
|
||||
void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp);
|
||||
|
||||
@ -75,6 +66,12 @@ bool scriptapi_item_on_place(lua_State *L, ItemStack &item,
|
||||
bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
|
||||
ServerActiveObject *user, const PointedThing &pointed);
|
||||
|
||||
/* node callbacks */
|
||||
bool scriptapi_node_on_punch(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *puncher);
|
||||
bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
|
||||
ServerActiveObject *digger);
|
||||
|
||||
/* luaentity */
|
||||
// Returns true if succesfully added into Lua; false otherwise.
|
||||
bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
|
||||
|
@ -57,11 +57,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
19: new content type handling
|
||||
20: many existing content types translated to extended ones
|
||||
21: dynamic content type allocation
|
||||
22: full 16-bit content types, minerals removed, facedir & wallmounted changed
|
||||
*/
|
||||
// This represents an uninitialized or invalid format
|
||||
#define SER_FMT_VER_INVALID 255
|
||||
// Highest supported serialization version
|
||||
#define SER_FMT_VER_HIGHEST 21
|
||||
#define SER_FMT_VER_HIGHEST 22
|
||||
// Lowest supported serialization version
|
||||
#define SER_FMT_VER_LOWEST 0
|
||||
|
||||
|
353
src/server.cpp
353
src/server.cpp
@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "constants.h"
|
||||
#include "voxel.h"
|
||||
#include "materials.h"
|
||||
#include "mineral.h"
|
||||
#include "config.h"
|
||||
#include "servercommand.h"
|
||||
#include "filesys.h"
|
||||
@ -2899,13 +2898,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
/*
|
||||
Make sure the player is allowed to do it
|
||||
*/
|
||||
bool interact_priv = (getPlayerPrivs(player) & PRIV_INTERACT) != 0;
|
||||
if(!interact_priv)
|
||||
if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
|
||||
{
|
||||
infostream<<"Ignoring interaction from player "<<player->getName()
|
||||
<<" because privileges are "<<getPlayerPrivs(player)
|
||||
<<std::endl;
|
||||
// NOTE: no return; here, fall through
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2919,10 +2917,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
NOTE: This can be used in the future to check if
|
||||
somebody is cheating, by checking the timing.
|
||||
*/
|
||||
bool cannot_punch_node = !interact_priv;
|
||||
|
||||
MapNode n(CONTENT_IGNORE);
|
||||
|
||||
try
|
||||
{
|
||||
n = m_env->getMap().getNode(p_under);
|
||||
@ -2934,22 +2929,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
<<std::endl;
|
||||
m_emerge_queue.addBlock(peer_id,
|
||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||
cannot_punch_node = true;
|
||||
}
|
||||
|
||||
if(cannot_punch_node)
|
||||
return;
|
||||
|
||||
/*
|
||||
Run script hook
|
||||
*/
|
||||
scriptapi_environment_on_punchnode(m_lua, p_under, n, srp);
|
||||
if(n.getContent() != CONTENT_IGNORE)
|
||||
scriptapi_node_on_punch(m_lua, p_under, n, srp);
|
||||
}
|
||||
else if(pointed.type == POINTEDTHING_OBJECT)
|
||||
{
|
||||
if(!interact_priv)
|
||||
return;
|
||||
|
||||
// Skip if object has been removed
|
||||
if(pointed_object->m_removed)
|
||||
return;
|
||||
@ -2977,190 +2962,24 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
else if(action == 2)
|
||||
{
|
||||
// Only complete digging of nodes
|
||||
if(pointed.type != POINTEDTHING_NODE)
|
||||
return;
|
||||
|
||||
// Mandatory parameter; actually used for nothing
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
|
||||
content_t material = CONTENT_IGNORE;
|
||||
u8 mineral = MINERAL_NONE;
|
||||
|
||||
bool cannot_remove_node = !interact_priv;
|
||||
|
||||
MapNode n(CONTENT_IGNORE);
|
||||
try
|
||||
if(pointed.type == POINTEDTHING_NODE)
|
||||
{
|
||||
n = m_env->getMap().getNode(p_under);
|
||||
// Get mineral
|
||||
mineral = n.getMineral(m_nodedef);
|
||||
// Get material at position
|
||||
material = n.getContent();
|
||||
// If not yet cancelled
|
||||
if(cannot_remove_node == false)
|
||||
MapNode n(CONTENT_IGNORE);
|
||||
try
|
||||
{
|
||||
// If it's not diggable, do nothing
|
||||
if(m_nodedef->get(material).diggable == false)
|
||||
{
|
||||
infostream<<"Server: Not finishing digging: "
|
||||
<<"Node not diggable"
|
||||
<<std::endl;
|
||||
cannot_remove_node = true;
|
||||
}
|
||||
n = m_env->getMap().getNode(p_under);
|
||||
}
|
||||
// If not yet cancelled
|
||||
if(cannot_remove_node == false)
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Get node metadata
|
||||
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p_under);
|
||||
if(meta && meta->nodeRemovalDisabled() == true)
|
||||
{
|
||||
infostream<<"Server: Not finishing digging: "
|
||||
<<"Node metadata disables removal"
|
||||
<<std::endl;
|
||||
cannot_remove_node = true;
|
||||
}
|
||||
infostream<<"Server: Not finishing digging: Node not found."
|
||||
<<" Adding block to emerge queue."
|
||||
<<std::endl;
|
||||
m_emerge_queue.addBlock(peer_id,
|
||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||
}
|
||||
if(n.getContent() != CONTENT_IGNORE)
|
||||
scriptapi_node_on_dig(m_lua, p_under, n, srp);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
infostream<<"Server: Not finishing digging: Node not found."
|
||||
<<" Adding block to emerge queue."
|
||||
<<std::endl;
|
||||
m_emerge_queue.addBlock(peer_id,
|
||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||
cannot_remove_node = true;
|
||||
}
|
||||
|
||||
/*
|
||||
If node can't be removed, set block to be re-sent to
|
||||
client and quit.
|
||||
*/
|
||||
if(cannot_remove_node)
|
||||
{
|
||||
infostream<<"Server: Not finishing digging."<<std::endl;
|
||||
|
||||
// Client probably has wrong data.
|
||||
// Set block not sent, so that client will get
|
||||
// a valid one.
|
||||
infostream<<"Client "<<peer_id<<" tried to dig "
|
||||
<<"node; but node cannot be removed."
|
||||
<<" setting MapBlock not sent."<<std::endl;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
v3s16 blockpos = getNodeBlockPos(p_under);
|
||||
client->SetBlockNotSent(blockpos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
actionstream<<player->getName()<<" digs "<<PP(p_under)
|
||||
<<", gets material "<<(int)material<<", mineral "
|
||||
<<(int)mineral<<std::endl;
|
||||
|
||||
/*
|
||||
Send the removal to all close-by players.
|
||||
- If other player is close, send REMOVENODE
|
||||
- Otherwise set blocks not sent
|
||||
*/
|
||||
core::list<u16> far_players;
|
||||
sendRemoveNode(p_under, peer_id, &far_players, 30);
|
||||
|
||||
/*
|
||||
Update and send inventory
|
||||
*/
|
||||
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
{
|
||||
/*
|
||||
Wear out tool
|
||||
*/
|
||||
InventoryList *mlist = player->inventory.getList("main");
|
||||
if(mlist != NULL)
|
||||
{
|
||||
ItemStack &item = mlist->getItem(item_i);
|
||||
|
||||
// Get digging properties for material and tool
|
||||
ToolDiggingProperties tp =
|
||||
item.getToolDiggingProperties(m_itemdef);
|
||||
DiggingProperties prop =
|
||||
getDiggingProperties(material, &tp, m_nodedef);
|
||||
item.addWear(prop.wear, m_itemdef);
|
||||
srp->m_inventory_not_sent = true;
|
||||
}
|
||||
|
||||
/*
|
||||
Add dug item to inventory
|
||||
*/
|
||||
|
||||
ItemStack item;
|
||||
|
||||
if(mineral != MINERAL_NONE)
|
||||
item = getDiggedMineralItem(mineral, this);
|
||||
|
||||
// If not mineral
|
||||
if(item.empty())
|
||||
{
|
||||
const std::string &dug_s = m_nodedef->get(material).dug_item;
|
||||
if(dug_s != "")
|
||||
{
|
||||
item.deSerialize(dug_s, m_itemdef);
|
||||
}
|
||||
}
|
||||
|
||||
if(!item.empty())
|
||||
{
|
||||
// Add a item to inventory
|
||||
player->inventory.addItem("main", item);
|
||||
srp->m_inventory_not_sent = true;
|
||||
}
|
||||
|
||||
item.clear();
|
||||
|
||||
{
|
||||
const std::string &extra_dug_s = m_nodedef->get(material).extra_dug_item;
|
||||
s32 extra_rarity = m_nodedef->get(material).extra_dug_item_rarity;
|
||||
if(extra_dug_s != "" && extra_rarity != 0
|
||||
&& myrand() % extra_rarity == 0)
|
||||
{
|
||||
item.deSerialize(extra_dug_s, m_itemdef);
|
||||
}
|
||||
}
|
||||
|
||||
if(!item.empty())
|
||||
{
|
||||
// Add a item to inventory
|
||||
player->inventory.addItem("main", item);
|
||||
srp->m_inventory_not_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Remove the node
|
||||
(this takes some time so it is done after the quick stuff)
|
||||
*/
|
||||
{
|
||||
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
|
||||
|
||||
m_env->getMap().removeNodeAndUpdate(p_under, modified_blocks);
|
||||
}
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
for(core::list<u16>::Iterator
|
||||
i = far_players.begin();
|
||||
i != far_players.end(); i++)
|
||||
{
|
||||
u16 peer_id = *i;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
if(client==NULL)
|
||||
continue;
|
||||
client->SetBlocksNotSent(modified_blocks);
|
||||
}
|
||||
|
||||
/*
|
||||
Run script hook
|
||||
*/
|
||||
scriptapi_environment_on_dignode(m_lua, p_under, n, srp);
|
||||
} // action == 2
|
||||
|
||||
/*
|
||||
@ -3168,16 +2987,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
*/
|
||||
else if(action == 3)
|
||||
{
|
||||
if(!interact_priv)
|
||||
{
|
||||
infostream<<"Not allowing player "
|
||||
<<player->getName()<<" to place item: "
|
||||
<<"no interact privileges"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = srp->getWieldedItem();
|
||||
|
||||
// Reset build time counter
|
||||
if(pointed.type == POINTEDTHING_NODE &&
|
||||
item.getDefinition(m_itemdef).type == ITEM_NODE)
|
||||
getClient(peer_id)->m_time_from_building = 0.0;
|
||||
|
||||
if(pointed.type == POINTEDTHING_OBJECT)
|
||||
{
|
||||
// Right click object
|
||||
@ -3201,123 +3017,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
srp->setWieldedItem(item);
|
||||
}
|
||||
else if(pointed.type == POINTEDTHING_NODE &&
|
||||
item.getDefinition(m_itemdef).type == ITEM_NODE)
|
||||
{
|
||||
bool cannot_place_node = !interact_priv;
|
||||
|
||||
try{
|
||||
// Don't add a node if this is not a free space
|
||||
MapNode n2 = m_env->getMap().getNode(p_above);
|
||||
if(m_nodedef->get(n2).buildable_to == false)
|
||||
{
|
||||
infostream<<"Client "<<peer_id<<" tried to place"
|
||||
<<" node in invalid position."<<std::endl;
|
||||
cannot_place_node = true;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
infostream<<"Server: Ignoring ADDNODE: Node not found"
|
||||
<<" Adding block to emerge queue."
|
||||
<<std::endl;
|
||||
m_emerge_queue.addBlock(peer_id,
|
||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||
cannot_place_node = true;
|
||||
}
|
||||
|
||||
if(cannot_place_node)
|
||||
{
|
||||
// Client probably has wrong data.
|
||||
// Set block not sent, so that client will get
|
||||
// a valid one.
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
v3s16 blockpos = getNodeBlockPos(p_above);
|
||||
client->SetBlockNotSent(blockpos);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset build time counter
|
||||
getClient(peer_id)->m_time_from_building = 0.0;
|
||||
|
||||
// Create node data
|
||||
MapNode n(m_nodedef, item.name, 0, 0);
|
||||
|
||||
actionstream<<player->getName()<<" places material "
|
||||
<<item.name
|
||||
<<" at "<<PP(p_under)<<std::endl;
|
||||
|
||||
// Calculate direction for wall mounted stuff
|
||||
if(m_nodedef->get(n).wall_mounted)
|
||||
n.param2 = packDir(p_under - p_above);
|
||||
|
||||
// Calculate the direction for furnaces and chests and stuff
|
||||
if(m_nodedef->get(n).param_type == CPT_FACEDIR_SIMPLE)
|
||||
{
|
||||
v3f playerpos = player->getPosition();
|
||||
v3f blockpos = intToFloat(p_above, BS) - playerpos;
|
||||
blockpos = blockpos.normalize();
|
||||
n.param1 = 0;
|
||||
if (fabs(blockpos.X) > fabs(blockpos.Z)) {
|
||||
if (blockpos.X < 0)
|
||||
n.param1 = 3;
|
||||
else
|
||||
n.param1 = 1;
|
||||
} else {
|
||||
if (blockpos.Z < 0)
|
||||
n.param1 = 2;
|
||||
else
|
||||
n.param1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Send to all close-by players
|
||||
*/
|
||||
core::list<u16> far_players;
|
||||
sendAddNode(p_above, n, 0, &far_players, 30);
|
||||
|
||||
/*
|
||||
Handle inventory
|
||||
*/
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
{
|
||||
// Remove from inventory and send inventory
|
||||
item.remove(1);
|
||||
srp->setWieldedItem(item);
|
||||
}
|
||||
|
||||
/*
|
||||
Add node.
|
||||
|
||||
This takes some time so it is done after the quick stuff
|
||||
*/
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
{
|
||||
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
|
||||
|
||||
std::string p_name = std::string(player->getName());
|
||||
m_env->getMap().addNodeAndUpdate(p_above, n, modified_blocks, p_name);
|
||||
}
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
for(core::list<u16>::Iterator
|
||||
i = far_players.begin();
|
||||
i != far_players.end(); i++)
|
||||
{
|
||||
u16 peer_id = *i;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
if(client==NULL)
|
||||
continue;
|
||||
client->SetBlocksNotSent(modified_blocks);
|
||||
}
|
||||
|
||||
/*
|
||||
Run script hook
|
||||
*/
|
||||
scriptapi_environment_on_placenode(m_lua, p_above, n, srp);
|
||||
}
|
||||
|
||||
} // action == 3
|
||||
|
||||
@ -3326,14 +3025,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
*/
|
||||
else if(action == 4)
|
||||
{
|
||||
// Requires interact privs
|
||||
if(!interact_priv)
|
||||
{
|
||||
infostream<<"Not allowing player to use item: "
|
||||
"no interact privileges"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = srp->getWieldedItem();
|
||||
|
||||
actionstream<<player->getName()<<" uses "<<item.name
|
||||
@ -3949,7 +3640,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
|
||||
*/
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
block->serialize(os, ver);
|
||||
block->serialize(os, ver, false);
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
|
||||
|
||||
|
@ -68,7 +68,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "porting.h"
|
||||
#include "materials.h"
|
||||
#include "config.h"
|
||||
#include "mineral.h"
|
||||
#include "filesys.h"
|
||||
#include "defaultsettings.h"
|
||||
#include "settings.h"
|
||||
@ -301,10 +300,6 @@ int main(int argc, char *argv[])
|
||||
srand(time(0));
|
||||
mysrand(time(0));
|
||||
|
||||
// Initialize stuff
|
||||
|
||||
init_mineral();
|
||||
|
||||
/*
|
||||
Run unit tests
|
||||
*/
|
||||
|
@ -76,9 +76,7 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
|
||||
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;
|
||||
@ -106,7 +104,6 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
|
||||
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;
|
||||
|
13
src/tile.cpp
13
src/tile.cpp
@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "log.h"
|
||||
#include "mapnode.h" // For texture atlas making
|
||||
#include "mineral.h" // For texture atlas making
|
||||
#include "nodedef.h" // For texture atlas making
|
||||
#include "gamedef.h"
|
||||
|
||||
@ -299,8 +298,8 @@ public:
|
||||
Example names:
|
||||
"stone.png"
|
||||
"stone.png^crack2"
|
||||
"stone.png^blit:mineral_coal.png"
|
||||
"stone.png^blit:mineral_coal.png^crack1"
|
||||
"stone.png^mineral_coal.png"
|
||||
"stone.png^mineral_coal.png^crack1"
|
||||
|
||||
- If texture specified by name is found from cache, return the
|
||||
cached id.
|
||||
@ -824,14 +823,6 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
|
||||
{
|
||||
std::string name = f.tname_tiles[i];
|
||||
sourcelist[name] = true;
|
||||
|
||||
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;
|
||||
sourcelist[fulltexture] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user