Node placement / mineral / serialization / iron freq / node_dig callback
authorKahrl <kahrl@gmx.net>
Fri, 20 Jan 2012 23:11:44 +0000 (00:11 +0100)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 22 Jan 2012 15:24:50 +0000 (17:24 +0200)
- 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.

38 files changed:
data/builtin.lua
data/mods/default/init.lua
data/mods/default/textures/default_mineral_coal.png [new file with mode: 0644]
data/mods/default/textures/default_mineral_iron.png [new file with mode: 0644]
data/mods/legacy/init.lua
data/mods/legacy/textures/mineral_coal.png [deleted file]
data/mods/legacy/textures/mineral_iron.png [deleted file]
src/CMakeLists.txt
src/client.cpp
src/content_mapblock.cpp
src/content_mapnode.cpp
src/environment.cpp
src/game.cpp
src/gamedef.h
src/light.h
src/main.cpp
src/map.cpp
src/map.h
src/mapblock.cpp
src/mapblock.h
src/mapblock_mesh.cpp
src/mapgen.cpp
src/mapnode.cpp
src/mapnode.h
src/materials.cpp
src/materials.h
src/mineral.cpp [deleted file]
src/mineral.h [deleted file]
src/nameidmapping.h
src/nodedef.cpp
src/nodedef.h
src/scriptapi.cpp
src/scriptapi.h
src/serialization.h
src/server.cpp
src/servermain.cpp
src/test.cpp
src/tile.cpp

index 1926d88b4991d3a4cdc71cfad9742c35e0dfc45d..2e31c43b86b3c13591486e3e0532f1acfe3862a2 100644 (file)
@@ -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
index 8093e99d5dd4e8e16695ea34fb99b111f8cb89a5..7c6cccd44761d6efb45aa633dd6912687483a4ff 100644 (file)
 -- - 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
 --     myvariable = whatever,
 -- }
 --
--- Item definition:
+-- Item definition options (register_node, register_craftitem, register_tool)
 -- {
 --     description = "Steel Axe",
 --     inventory_image = "default_tool_steelaxe.png",
 --     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"},
 --     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,
 --     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 = "",
 --         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", {
diff --git a/data/mods/default/textures/default_mineral_coal.png b/data/mods/default/textures/default_mineral_coal.png
new file mode 100644 (file)
index 0000000..3ff9692
Binary files /dev/null and b/data/mods/default/textures/default_mineral_coal.png differ
diff --git a/data/mods/default/textures/default_mineral_iron.png b/data/mods/default/textures/default_mineral_iron.png
new file mode 100644 (file)
index 0000000..51b15d9
Binary files /dev/null and b/data/mods/default/textures/default_mineral_iron.png differ
index 127b0e17fb825478805dfcf8c7e1fa5ccfd549cf..7f9088ce092078318f34ea7ea62d085c2c4af5d2 100644 (file)
@@ -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")
diff --git a/data/mods/legacy/textures/mineral_coal.png b/data/mods/legacy/textures/mineral_coal.png
deleted file mode 100644 (file)
index 3ff9692..0000000
Binary files a/data/mods/legacy/textures/mineral_coal.png and /dev/null differ
diff --git a/data/mods/legacy/textures/mineral_iron.png b/data/mods/legacy/textures/mineral_iron.png
deleted file mode 100644 (file)
index 51b15d9..0000000
Binary files a/data/mods/legacy/textures/mineral_iron.png and /dev/null differ
index e82e26dc7a2fa09e2979c72dd815b2ddf63fca8d..ee02d66f0acefdd658c4e3948020c07e80e99bae 100644 (file)
@@ -115,7 +115,6 @@ set(common_SRCS
        nodemetadata.cpp
        serverobject.cpp
        noise.cpp
-       mineral.cpp
        porting.cpp
        materials.cpp
        defaultsettings.cpp
index feb8a3a1ed30d7abe85363dce1f361035d2aef15..602f0cf84abf44b4c444e681e2615c5724f21be5 100644 (file)
@@ -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)
        {}
index 79f49cbf814f588f7129e1e8f115400d6028f9a8..dc1e1daed1e5045d74eed5ccb8877337f8e74161 100644 (file)
@@ -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++)
                        {
index 4701736cfd79849f8ada6eca4b039547967241b8..ce7ee593f12cd1811f37fa4f1509a8678ab6ef73 100644 (file)
@@ -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
index 3a294086c8ac78a6ee19b9bce7cff7a17868a76c..7c2aef27208df1d1b439b7c366b23bfcbd0e0a5f 100644 (file)
@@ -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();
index 7bd5d958736f2ee3b969c42578a9c5fb0ee70761..055320a8e4423902ab226e144a7b34947804d7da 100644 (file)
@@ -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;
 
index 8df6988ad2a8a866924df46cb422021de6823fb4..10ab0b0bcfb57e4ecd9cc71516366ca81302d950 100644 (file)
@@ -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;
 
 /*
index c1af7fa62dcee09929b013a3cc2da3d21e9ca52f..238acce43d2d73c52e0762f395e244c68a4ccb16 100644 (file)
@@ -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
 
index b7c3ceffe3dfdd57409ba5e4a28a2ce464e43872..6cb9cf98419744493a2b017e440f5925d4dcabd3 100644 (file)
@@ -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
        */
index 8bdc2ad4c97f341e8bffd3faa737cfccdcad97de..31c0c958b955346be7dbe0ab62cee91f454497f4 100644 (file)
@@ -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)
index 2bd2c0eb860b5d01c753b83ea3c78b4f2d4f2d04..90255c1d9cf289564f95581d4263d428d92fa955 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -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);
 
index 73c13caca258d11572e53819b84c430688b31b46..fb3bbf7a7fb466c8316ed791132befc537714b15 100644 (file)
@@ -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.");
        }
        
-       // These have no compression
-       if(version <= 3 || version == 5 || version == 6)
+       if(version <= 21)
        {
-               u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
-               
-               u32 buflen = 1 + nodecount * MapNode::serializedLength(version);
-               SharedBuffer<u8> dest(buflen);
+               serialize_pre22(os, version, disk);
+               return;
+       }
 
-               dest[0] = is_underground;
+       // 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)
                {
-                       u32 s = 1 + i * MapNode::serializedLength(version);
-                       data[i].serialize(&dest[s], version);
+                       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;
                
-               os.write((char*)*dest, dest.getSize());
+       // These have no compression
+       if(version <= 3 || version == 5 || version == 6)
+       {
+               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)
                        }
                }
        }
-}
 
-void MapBlock::deSerialize(std::istream &is, u8 version)
-{
-       if(!ser_ver_supported(version))
-               throw VersionMismatchException("ERROR: MapBlock format not supported");
 
-       // These have no lighting info
-       if(version <= 1)
+       if(disk)
        {
-               setLightingExpired(true);
-       }
+               // Versions up from 9 have block objects. (DEPRECATED)
+               if(version >= 9)
+               {
+                       // count=0
+                       writeU16(os, 0);
+               }
 
-       // These have no "generated" field
-       if(version < 18)
-       {
-               m_generated = true;
+               // 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_pre22(std::istream &is, u8 version, bool disk)
+{
+       u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
+
+       // Initialize default flags
+       is_underground = false;
+       m_day_night_differs = false;
+       m_lighting_expired = false;
+       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;
+                       }
+               }
+
+               /*
+                       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);
+               }
 
-       // Scan and write node definition id mapping
-       if(version >= 21){
+               // 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);
 }
 
 /*
index f2d94753c9fba586f5f8bff26d6fe20220acfc4f..c9ff366794911526817fe2db5cebbae2df25db87 100644 (file)
@@ -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
        */
index db9057e193ecf217618bde45d1dd72c4a5173ed9..b843448c484c1cb70461d80593d4d27f433f6b1e 100644 (file)
@@ -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);
+       // 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);
+
+       // 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);
        
-       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)
+       static const u8 dir_to_tile[4 * 8] =
        {
-               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);
-               }
-       }
-
-       return spec;
+               // 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)
index c2256cedbe5d1e1856ef64664a92a4c000974079..fe2ce13f58540cea813525e7e5c7976dbf9e1882 100644 (file)
@@ -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():
index a757149b10612925093837750b52a9a0d43f5599..bfadbeac5ddbe919dac889322be71e23d62426b3 100644 (file)
@@ -21,136 +21,11 @@ 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
 
-#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)
-
-       TODO: Add 3: Both faces drawn with backface culling, remove equivalent
-*/
-u8 face_contents(content_t m1, content_t m2, bool *equivalent,
-               INodeDefManager *nodemgr)
-{
-       *equivalent = false;
-
-       if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
-               return 0;
-       
-       bool contents_differ = (m1 != m2);
-       
-       const ContentFeatures &f1 = nodemgr->get(m1);
-       const ContentFeatures &f2 = nodemgr->get(m2);
-
-       // Contents don't differ for different forms of same liquid
-       if(f1.sameLiquid(f2))
-               contents_differ = false;
-       
-       u8 c1 = f1.solidness;
-       u8 c2 = f2.solidness;
-
-       bool solidness_differs = (c1 != c2);
-       bool makes_face = contents_differ && solidness_differs;
-
-       if(makes_face == false)
-               return 0;
-       
-       if(c1 == 0)
-               c1 = f1.visual_solidness;
-       if(c2 == 0)
-               c2 = f2.visual_solidness;
-       
-       if(c1 == c2){
-               *equivalent = true;
-               // If same solidness, liquid takes precense
-               if(f1.isLiquid())
-                       return 1;
-               if(f2.isLiquid())
-                       return 2;
-       }
-       
-       if(c1 > c2)
-               return 1;
-       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
 */
@@ -191,8 +66,9 @@ void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr
 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(nodemgr->get(*this).param_type == CPT_LIGHT)
+       if(f.param_type == CPT_LIGHT)
        {
                if(bank == LIGHTBANK_DAY)
                        light = param1 & 0x0f;
@@ -201,38 +77,63 @@ u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
                else
                        assert(0);
        }
-       if(nodemgr->get(*this).light_source > light)
-               light = nodemgr->get(*this).light_source;
+       if(f.light_source > light)
+               light = f.light_source;
        return light;
 }
 
-u8 MapNode::getLightBanksWithSource(INodeDefManager *nodemgr) const
+bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight, 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)
+       const ContentFeatures &f = nodemgr->get(*this);
+       if(f.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);
+       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::getMineral(INodeDefManager *nodemgr) const
+u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const
 {
-       if(nodemgr->get(*this).param_type == CPT_MINERAL)
+       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))
        {
-               return param1 & 0x0f;
+       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);
        }
-
-       return MINERAL_NONE;
 }
 
+
+
 u32 MapNode::serializedLength(u8 version)
 {
        if(!ser_ver_supported(version))
@@ -246,52 +147,182 @@ u32 MapNode::serializedLength(u8 version)
                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);
 
-       u8 actual_param0 = n_foreign.param0;
+       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_param0 == CONTENT_IGNORE)
-                       actual_param0 = 255;
-               else if(actual_param0 == CONTENT_AIR)
-                       actual_param0 = 254;
+               if(actual_content == CONTENT_IGNORE)
+                       actual_content = 255;
+               else if(actual_content == CONTENT_AIR)
+                       actual_content = 254;
        }
 
        if(version == 0)
        {
-               dest[0] = actual_param0;
+               dest[0] = actual_content;
        }
        else if(version <= 9)
        {
-               dest[0] = actual_param0;
+               dest[0] = actual_content;
                dest[1] = n_foreign.param1;
        }
        else
        {
-               dest[0] = actual_param0;
+               dest[0] = actual_content;
                dest[1] = n_foreign.param1;
                dest[2] = n_foreign.param2;
        }
 }
-void MapNode::deSerialize(u8 *source, u8 version)
+void MapNode::deSerialize_pre22(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)
+       if(version <= 1)
        {
                param0 = source[0];
        }
@@ -308,18 +339,11 @@ void MapNode::deSerialize(u8 *source, u8 version)
        }
        
        // Convert special values from old version to new
-       if(version <= 18)
+       if(version <= 19)
        {
                // 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)
-       {
+               // Version 19 is fucked up with sometimes the old values and sometimes not
                if(param0 == 255)
                        param0 = CONTENT_IGNORE;
                else if(param0 == 254)
@@ -330,6 +354,65 @@ void MapNode::deSerialize(u8 *source, u8 version)
        *this = mapnode_translate_to_internal(*this, version);
 }
 
+
+#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)
+
+       TODO: Add 3: Both faces drawn with backface culling, remove equivalent
+*/
+u8 face_contents(content_t m1, content_t m2, bool *equivalent,
+               INodeDefManager *nodemgr)
+{
+       *equivalent = false;
+
+       if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
+               return 0;
+       
+       bool contents_differ = (m1 != m2);
+       
+       const ContentFeatures &f1 = nodemgr->get(m1);
+       const ContentFeatures &f2 = nodemgr->get(m2);
+
+       // Contents don't differ for different forms of same liquid
+       if(f1.sameLiquid(f2))
+               contents_differ = false;
+       
+       u8 c1 = f1.solidness;
+       u8 c2 = f2.solidness;
+
+       bool solidness_differs = (c1 != c2);
+       bool makes_face = contents_differ && solidness_differs;
+
+       if(makes_face == false)
+               return 0;
+       
+       if(c1 == 0)
+               c1 = f1.visual_solidness;
+       if(c2 == 0)
+               c2 = f2.visual_solidness;
+       
+       if(c1 == c2){
+               *equivalent = true;
+               // If same solidness, liquid takes precense
+               if(f1.isLiquid())
+                       return 1;
+               if(f2.isLiquid())
+                       return 2;
+       }
+       
+       if(c1 > c2)
+               return 1;
+       else
+               return 2;
+}
+
 /*
        Gets lighting value at face of node
        
@@ -380,4 +463,5 @@ u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
        }
 }
 
+#endif
 
index 65fc3b3e29566394a31c58fa75d3be6bde212f7e..1c75f39c57e6361bfcd855e2f4f93907963ce6f9 100644 (file)
@@ -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
+
index 146209d5881cd5489d4c9b487a21ef31f04815e6..c37b7c5053736d85674dbca4c61606f6765f21f1 100644 (file)
@@ -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);
+}
+
index face7d5df7277784bc6337a4b66147cd45424c91..058b2ab8525b59c4a431fa8ea249370431c84d83 100644 (file)
@@ -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
 
diff --git a/src/mineral.cpp b/src/mineral.cpp
deleted file mode 100644 (file)
index 4e495fc..0000000
+++ /dev/null
@@ -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();
-}
-
-
-
diff --git a/src/mineral.h b/src/mineral.h
deleted file mode 100644 (file)
index a945d0e..0000000
+++ /dev/null
@@ -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
-
index 071599e109db0d00557df4582bab011efa0edb5f..238deb451514ef12abeeb5792db93e1c844eb332 100644 (file)
@@ -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;
index 87469bfb52726dc87524c2bd4b3e166a3cf3980a..3d85bdbd92a557f032151f7a081d3b5b6fd3876d 100644 (file)
@@ -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);
index 598ad7fb391555eeac7f122189caf479e0fc89b4..9524385cf075d6e8618b0ac65f6f83863fff7fc4 100644 (file)
@@ -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
index 187d1a894146cf3b8a0f5aabbef63c86d61f9180..173e5a827dfae22f1d978fb91e9b030c2ecd3ca7 100644 (file)
@@ -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,114 +4004,64 @@ bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
        return true;
 }
 
-/*
-       environment
-*/
-
-void scriptapi_environment_step(lua_State *L, float dtime)
+bool scriptapi_node_on_punch(lua_State *L, v3s16 pos, MapNode node,
+               ServerActiveObject *puncher)
 {
        realitycheck(L);
        assert(lua_checkstack(L, 20));
-       //infostream<<"scriptapi_environment_step"<<std::endl;
        StackUnroller stack_unroller(L);
 
-       // Get minetest.registered_globalsteps
-       lua_getglobal(L, "minetest");
-       lua_getfield(L, -1, "registered_globalsteps");
-       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
-               lua_pushnumber(L, dtime);
-               if(lua_pcall(L, 1, 0, 0))
-                       script_error(L, "error: %s", lua_tostring(L, -1));
-               // value removed, keep key for next iteration
-       }
-}
+       INodeDefManager *ndef = get_server(L)->ndef();
 
-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);
+       // Push callback function on stack
+       if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_punch"))
+               return false;
 
-       // 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
-       }
+       // 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;
 }
 
-void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
+bool scriptapi_node_on_dig(lua_State *L, v3s16 pos, MapNode node,
                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
-       }
+       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;
 }
 
-void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
-               ServerActiveObject *puncher)
+/*
+       environment
+*/
+
+void scriptapi_environment_step(lua_State *L, float dtime)
 {
        realitycheck(L);
        assert(lua_checkstack(L, 20));
-       //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
+       //infostream<<"scriptapi_environment_step"<<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
+       // Get minetest.registered_globalsteps
        lua_getglobal(L, "minetest");
-       lua_getfield(L, -1, "registered_on_punchnodes");
+       lua_getfield(L, -1, "registered_globalsteps");
        luaL_checktype(L, -1, LUA_TTABLE);
        int table = lua_gettop(L);
        // Foreach
@@ -3980,10 +4070,8 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
                // 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))
+               lua_pushnumber(L, dtime);
+               if(lua_pcall(L, 1, 0, 0))
                        script_error(L, "error: %s", lua_tostring(L, -1));
                // value removed, keep key for next iteration
        }
index 198f6052559fac7ef507a824fa1db8f20528ae6f..500a9ab99471f236242319802ff94add6ca0324c 100644 (file)
@@ -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,
index cc43811551ef6b35065cb76bdca92929e3d85865..bcfea451a0c26421d0bc2903cedf76a2138f6264 100644 (file)
@@ -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
 
index 3c0cab2a914308b7bdafe971d1ee7aaba7caf321..9f3db34d96e9789793fbc31f9a2520517d747436 100644 (file)
@@ -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
-                       {
-                               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)
-                               {
-                                       // 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;
-                                       }
-                               }
-                               // If not yet cancelled
-                               if(cannot_remove_node == false)
-                               {
-                                       // 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;
-                                       }
-                               }
-                       }
-                       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)
+                       if(pointed.type == POINTEDTHING_NODE)
                        {
-                               /*
-                                       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();
-                               
+                               MapNode n(CONTENT_IGNORE);
+                               try
                                {
-                                       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);
-                                       }
+                                       n = m_env->getMap().getNode(p_under);
                                }
-                       
-                               if(!item.empty())
+                               catch(InvalidPositionException &e)
                                {
-                                       // Add a item to inventory
-                                       player->inventory.addItem("main", item);
-                                       srp->m_inventory_not_sent = 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);
                        }
-
-                       /*
-                               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());
 
index e8a54512ec29ddce54d5d5c411abe3392db668c2..3ef1d9479a75788ac70c6a6753322b4eb59d1633 100644 (file)
@@ -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
        */
index caf31d1af9d2e823372e18852b0b583f2ce928ed..2d5c86e640650fe8d0f95a0d2a54fbed3e7d5b44 100644 (file)
@@ -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;
index 1d5f4d8338c97ec1d4237c5a3c5e09de7dfbddb7..bc4c49cb1717a548babd6a5204f67c58cdd8e43d 100644 (file)
@@ -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;
-                               }
-                       }
                }
        }