Players are more like objects + related stuff
authorPerttu Ahola <celeron55@gmail.com>
Thu, 1 Dec 2011 21:33:48 +0000 (23:33 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Thu, 1 Dec 2011 21:33:48 +0000 (23:33 +0200)
15 files changed:
data/mods/default/init.lua
src/content_cao.cpp
src/content_sao.cpp
src/content_sao.h
src/environment.cpp
src/materials.cpp
src/materials.h
src/player.cpp
src/player.h
src/scriptapi.cpp
src/server.cpp
src/serverobject.cpp
src/serverobject.h
src/tooldef.cpp
src/tooldef.h

index 0333ae0136c6b3e5f221991c2c1e6d85a1dac870..79976f2c4373e394159f180ac3c9d2c367d15881 100644 (file)
@@ -7,13 +7,32 @@
 -- name "foomod", a texture could be called "foomod_superfurnace.png"
 -- Due to historical reasons, the default mod does not follow this rule.
 --
+-- MapNode representation:
+-- {name="name", param1=num, param2=num}
+--
+-- Position representation:
+-- {x=num, y=num, z=num}
+--
+-- stackstring/itemstring: A stack of items in serialized format.
+-- eg. 'NodeItem "dirt" 5'
+-- eg. 'ToolItem "WPick" 21323'
+-- eg. 'CraftItem "apple" 2'
+--
+-- item: A single item in Lua table format.
+-- eg. {type="NodeItem", name="dirt"} 
+--     ^ a single dirt node
+-- eg. {type="ToolItem", name="WPick", wear=21323}
+--     ^ a wooden pick about 1/3 weared out
+-- eg. {type="CraftItem", name="apple"}
+--     ^ an apple.
+--
 -- Global functions:
--- minetest.register_entity(name, prototype_table)
--- minetest.register_tool(name, {lots of stuff})
--- minetest.register_node(name, {lots of stuff})
--- minetest.register_craftitem(name, {lots of stuff})
--- minetest.register_craft({output=item, recipe={...})
--- minetest.register_globalstep(func)
+-- minetest.register_entity(name, prototype table)
+-- minetest.register_tool(name, tool definition)
+-- minetest.register_node(name, node definition)
+-- minetest.register_craftitem(name, craftitem definition)
+-- minetest.register_craft(recipe)
+-- minetest.register_globalstep(func(dtime))
 -- minetest.register_on_placenode(func(pos, newnode, placer))
 -- minetest.register_on_dignode(func(pos, oldnode, digger))
 -- minetest.register_on_punchnode(func(pos, node, puncher))
 -- minetest.register_on_respawnplayer(func(ObjectRef))
 -- ^ return true in func to disable regular player placement
 -- minetest.register_on_chat_message(func(name, message))
--- minetest.setting_get(name)
--- minetest.setting_getbool(name)
+-- minetest.setting_get(name) -> string or nil
+-- minetest.setting_getbool(name) -> boolean value or nil
 -- minetest.chat_send_all(text)
 -- minetest.chat_send_player(name, text)
--- minetest.get_player_privs(name)
+-- minetest.get_player_privs(name) -> set of privs
+-- stackstring_take_item(stackstring) -> stackstring, item
+-- stackstring_put_item(stackstring, item) -> stackstring, success
+-- stackstring_put_stackstring(stackstring, stackstring) -> stackstring, success
 --
 -- Global objects:
 -- minetest.env - environment reference
 -- ObjectRef is basically ServerActiveObject.
 -- ObjectRef methods:
 -- - remove(): remove object (after returning from Lua)
--- - getpos(): returns {x=num, y=num, z=num}
+-- - getpos() -> {x=num, y=num, z=num}
 -- - setpos(pos); pos={x=num, y=num, z=num}
 -- - moveto(pos, continuous=false): interpolated move
 -- - punch(puncher); puncher = an another ObjectRef
 -- - right_click(clicker); clicker = an another ObjectRef
--- - get_wielded_itemstring()
--- - get_wielded_item()
--- - damage_wielded_item(num) (item damage/wear range is 0-65535)
--- - add_to_inventory(itemstring): add an item to object inventory
+-- - get_wield_digging_properties() -> digging property table
 -- - add_to_inventory_later(itemstring): like above, but after callback returns (only allowed for craftitem callbacks)
 -- - get_hp(): returns number of hitpoints (2 * number of hearts)
 -- - set_hp(hp): set number of hitpoints (2 * number of hearts)
 -- LuaEntitySAO-only:
 -- - setvelocity({x=num, y=num, z=num})
 -- - setacceleration({x=num, y=num, z=num})
--- - getacceleration()
+-- - getacceleration() -> {x=num, y=num, z=num}
 -- - settexturemod(mod)
 -- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
 -- -           select_horiz_by_yawpitch=false)
 -- Player-only:
 -- - get_player_name(): will return nil if is not a player
 -- - inventory_set_list(name, {item1, item2, ...})
--- - inventory_get_list(name)
+-- - inventory_get_list(name) -> {item1, item2, ...}
+-- - damage_wielded_item(num) (item damage/wear range is 0-65535)
+-- - add_to_inventory(itemstring): add an item to object inventory
 --
 -- Registered entities:
 -- - Functions receive a "luaentity" as self:
 --   - on_step(self, dtime)
 --   - on_punch(self, hitter)
 --   - on_rightclick(self, clicker)
---   - get_staticdata(self): return string
+--   - get_staticdata(self)
+--     ^ return string that will be passed to on_activate when the object
+--       is created next time
 --
--- MapNode representation:
--- {name="name", param1=num, param2=num}
+-- Entity prototype table:
+-- {
+--     physical = true,
+--     collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
+--     visual = "cube",
+--     textures = {texture,texture,texture,texture,texture,texture},
+--     on_activate = function(self, staticdata),
+--     on_step = function(self, dtime),
+--     on_punch = function(self, hitter),
+--     on_rightclick = function(self, clicker),
+--     get_staticdata = function(self),
+--     # Also you can define arbitrary member variables here
+--     myvariable = whatever,
+-- }
 --
--- Position representation:
--- {x=num, y=num, z=num}
+-- Tool definition:
+-- {
+--     image = "tool_steelaxe.png",
+--     full_punch_interval = 1.0,
+--     basetime = 1.0,
+--     dt_weight = 0.5,
+--     dt_crackiness = -0.2,
+--     dt_crumbliness = 1,
+--     dt_cuttability = -0.5,
+--     basedurability = 330,
+--     dd_weight = 0,
+--     dd_crackiness = 0,
+--     dd_crumbliness = 0,
+--     dd_cuttability = 0,
+-- }
+--
+-- Node definition options:
+-- {
+--     name = "somenode",
+--     drawtype = "normal",
+--     visual_scale = 1.0,
+--     tile_images = {"unknown_block.png"},
+--     inventory_image = "unknown_block.png",
+--     special_materials = {
+--         {image="", backface_culling=true},
+--         {image="", backface_culling=true},
+--     },
+--     alpha = 255,
+--     post_effect_color = {a=0, r=0, g=0, b=0},
+--     paramtype = "none",
+--     is_ground_content = false,
+--     light_propagates = false,
+--     sunlight_propagates = false,
+--     walkable = true,
+--     pointable = true,
+--     diggable = true,
+--     climbable = false,
+--     buildable_to = false,
+--     wall_mounted = false,
+--     often_contains_mineral = false,
+--     dug_item = "",
+--     extra_dug_item = "",
+--     extra_dug_item_rarity = 2,
+--     metadata_name = "",
+--     liquidtype = "none",
+--     liquid_alternative_flowing = "",
+--     liquid_alternative_source = "",
+--     liquid_viscosity = 0,
+--     light_source = 0,
+--     damage_per_second = 0,
+--     selection_box = {type="regular"},
+--     material = {
+--         diggablity = "normal",
+--         weight = 0,
+--         crackiness = 0,
+--         crumbliness = 0,
+--         cuttability = 0,
+--         flammability = 0,
+--     },
+--     cookresult_item = "", -- Cannot be cooked
+--     furnace_cooktime = 3.0,
+--     furnace_burntime = -1, -- Cannot be used as fuel
+-- }
+--
+-- Craftitem definition options:
+-- minetest.register_craftitem("name", {
+--     image = "image.png",
+--     stack_max = <maximum number of items in stack>,
+--     cookresult_item = itemstring (result of cooking),
+--     furnace_cooktime = <cooking time>,
+--     furnace_burntime = <time to burn as fuel in furnace>,
+--     usable = <uh... some boolean value>,
+--     dropcount = <amount of items to drop using drop action>
+--     liquids_pointable = <whether can point liquids>,
+--     on_drop = func(item, dropper, pos),
+--     on_place_on_ground = func(item, placer, pos),
+--     on_use = func(item, player, pointed_thing),
+-- })
+-- 
+-- Recipe:
+-- {
+--     output = 'ToolItem "STPick"',
+--     recipe = {
+--         {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
+--         {'', 'CraftItem "Stick"', ''},
+--         {'', 'CraftItem "Stick"', ''},
+--     }
+-- }
 --
 
 -- print("minetest dump: "..dump(minetest))
index 011a3f408ae75ef72112797e1ac35b73b4887a0f..20eb3cf1b2aaaf82d05021e91869fca3af9b4452 100644 (file)
@@ -2126,6 +2126,8 @@ public:
                if(player && player->isLocal())
                        m_is_local_player = true;
                
+               pos_translator.init(m_position);
+
                updateNodePos();
        }
 
index a4c9c59f8b70acd09e60f682fb7991a3916224c1..e0f230bbcae1dc2286e55d37afa1037b7fbf95e5 100644 (file)
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "main.h" // For g_profiler
 #include "profiler.h"
 #include "serialization.h" // For compressZlib
+#include "materials.h" // For MaterialProperties
+#include "tooldef.h" // ToolDiggingProperties
 
 core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
 
@@ -241,7 +243,7 @@ InventoryItem * ItemSAO::createInventoryItem()
        }
 }
 
-void ItemSAO::punch(ServerActiveObject *puncher)
+void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
 {
        InventoryItem *item = createInventoryItem();
        bool fits = puncher->addToInventory(item);
@@ -432,7 +434,7 @@ std::string RatSAO::getStaticData()
        return os.str();
 }
 
-void RatSAO::punch(ServerActiveObject *puncher)
+void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
 {
        std::istringstream is("CraftItem rat 1", std::ios_base::binary);
        IGameDef *gamedef = m_env->getGameDef();
@@ -687,36 +689,28 @@ std::string Oerkki1SAO::getStaticData()
        return os.str();
 }
 
-void Oerkki1SAO::punch(ServerActiveObject *puncher)
+void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
 {
+       if(!puncher)
+               return;
+       
        v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
+       m_speed_f += dir*12*BS;
 
-       std::string toolname = "";
-       InventoryItem *item = puncher->getWieldedItem();
-       if(item && (std::string)item->getName() == "ToolItem"){
-               ToolItem *titem = (ToolItem*)item;
-               toolname = titem->getToolName();
-       }
+       // "Material" properties of an oerkki
+       MaterialProperties mp;
+       mp.diggability = DIGGABLE_NORMAL;
+       mp.crackiness = -1.0;
+       mp.cuttability = 1.0;
 
-       m_speed_f += dir*12*BS;
+       ToolDiggingProperties tp;
+       puncher->getWieldDiggingProperties(&tp);
 
-       u16 amount = 5;
-       /* See tool names in inventory.h */
-       if(toolname == "WSword")
-               amount = 10;
-       if(toolname == "STSword")
-               amount = 12;
-       if(toolname == "SteelSword")
-               amount = 16;
-       if(toolname == "STAxe")
-               amount = 7;
-       if(toolname == "SteelAxe")
-               amount = 9;
-       if(toolname == "SteelPick")
-               amount = 7;
-       doDamage(amount);
-       
-       puncher->damageWieldedItem(65536/100);
+       HittingProperties hitprop = getHittingProperties(&mp, &tp,
+                       time_from_last_punch);
+
+       doDamage(hitprop.hp);
+       puncher->damageWieldedItem(hitprop.wear);
 }
 
 void Oerkki1SAO::doDamage(u16 d)
@@ -1365,25 +1359,20 @@ void MobV2SAO::step(float dtime, bool send_recommended)
        }
 }
 
-void MobV2SAO::punch(ServerActiveObject *puncher)
+void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
 {
+       if(!puncher)
+               return;
+       
        v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
 
-       std::string toolname = "";
-       InventoryItem *item = puncher->getWieldedItem();
-       if(item && (std::string)item->getName() == "ToolItem"){
-               ToolItem *titem = (ToolItem*)item;
-               toolname = titem->getToolName();
-       }
-       
        // A quick hack; SAO description is player name for player
        std::string playername = puncher->getDescription();
 
        Map *map = &m_env->getMap();
        
        actionstream<<playername<<" punches mob id="<<m_id
-                       <<" with a \""<<toolname<<"\" at "
-                       <<PP(m_base_position/BS)<<std::endl;
+                       <<" at "<<PP(m_base_position/BS)<<std::endl;
 
        m_disturb_timer = 0;
        m_disturbing_player = playername;
@@ -1405,23 +1394,21 @@ void MobV2SAO::punch(ServerActiveObject *puncher)
        }
        sendPosition();
        
-       u16 amount = 2;
-       /* See tool names in inventory.h */
-       if(toolname == "WSword")
-               amount = 4;
-       if(toolname == "STSword")
-               amount = 6;
-       if(toolname == "SteelSword")
-               amount = 8;
-       if(toolname == "STAxe")
-               amount = 3;
-       if(toolname == "SteelAxe")
-               amount = 4;
-       if(toolname == "SteelPick")
-               amount = 3;
-       doDamage(amount);
-       
-       puncher->damageWieldedItem(65536/100);
+
+       // "Material" properties of the MobV2
+       MaterialProperties mp;
+       mp.diggability = DIGGABLE_NORMAL;
+       mp.crackiness = -1.0;
+       mp.cuttability = 1.0;
+
+       ToolDiggingProperties tp;
+       puncher->getWieldDiggingProperties(&tp);
+
+       HittingProperties hitprop = getHittingProperties(&mp, &tp,
+                       time_from_last_punch);
+
+       doDamage(hitprop.hp);
+       puncher->damageWieldedItem(hitprop.wear);
 }
 
 bool MobV2SAO::isPeaceful()
@@ -1686,7 +1673,7 @@ InventoryItem* LuaEntitySAO::createPickedUpItem()
        return item;
 }
 
-void LuaEntitySAO::punch(ServerActiveObject *puncher)
+void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
 {
        if(!m_registered)
                return;
@@ -1799,96 +1786,3 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
        m_messages_out.push_back(aom);
 }
 
-/*
-       PlayerSAO
-*/
-
-// Prototype
-PlayerSAO proto_PlayerSAO(NULL, v3f(0,0,0), NULL);
-
-PlayerSAO::PlayerSAO(ServerEnvironment *env, v3f pos,
-               ServerRemotePlayer *player):
-       ServerActiveObject(env, pos),
-       m_player(player),
-       m_position_updated(true)
-{
-       if(m_player)
-               m_player->setSAO(this);
-}
-
-PlayerSAO::~PlayerSAO()
-{
-       if(m_player)
-               m_player->setSAO(NULL);
-}
-
-void PlayerSAO::step(float dtime, bool send_recommended)
-{
-       if(!m_player)
-               return;
-       
-       if(send_recommended == false)
-               return;
-       
-       if(m_position_updated)
-       {
-               m_position_updated = false;
-
-               std::ostringstream os(std::ios::binary);
-               // command (0 = update position)
-               writeU8(os, 0);
-               // pos
-               writeV3F1000(os, m_player->getPosition());
-               // yaw
-               writeF1000(os, m_player->getYaw());
-               // create message and add to list
-               ActiveObjectMessage aom(getId(), false, os.str());
-               m_messages_out.push_back(aom);
-       }
-}
-
-std::string PlayerSAO::getClientInitializationData()
-{
-       if(!m_player)
-               return "";
-       
-       std::ostringstream os(std::ios::binary);
-       // version
-       writeU8(os, 0);
-       // name
-       os<<serializeString(m_player->getName());
-       // pos
-       writeV3F1000(os, m_player->getPosition());
-       // yaw
-       writeF1000(os, m_player->getYaw());
-       return os.str();
-}
-
-std::string PlayerSAO::getStaticData()
-{
-       assert(0);
-       return "";
-}
-
-void PlayerSAO::punch(ServerActiveObject *puncher)
-{
-       infostream<<"TODO: PlayerSAO::punch()"<<std::endl;
-}
-       
-void PlayerSAO::setPlayer(ServerRemotePlayer *player)
-{
-       infostream<<"PlayerSAO id="<<getId()<<" got player \""
-                       <<(player?player->getName():"(NULL)")<<"\""<<std::endl;
-       m_player = player;
-}
-
-ServerRemotePlayer* PlayerSAO::getPlayer()
-{
-       return m_player;
-}
-
-void PlayerSAO::positionUpdated()
-{
-       m_position_updated = true;
-}
-
index 19b0e74ba48e39438bb793d46345700324b0877e..51461bc957fce95cbfa45b74958739e6aefa09fc 100644 (file)
@@ -50,7 +50,7 @@ public:
        std::string getClientInitializationData();
        std::string getStaticData();
        InventoryItem* createInventoryItem();
-       void punch(ServerActiveObject *puncher);
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
        float getMinimumSavedMovement(){ return 0.1*BS; }
 private:
        std::string m_inventorystring;
@@ -70,7 +70,7 @@ public:
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData();
        std::string getStaticData();
-       void punch(ServerActiveObject *puncher);
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
 private:
        bool m_is_active;
        IntervalLimiter m_inactive_interval;
@@ -96,7 +96,7 @@ public:
        std::string getClientInitializationData();
        std::string getStaticData();
        InventoryItem* createPickedUpItem(){return NULL;}
-       void punch(ServerActiveObject *puncher);
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
        bool isPeaceful(){return false;}
 private:
        void doDamage(u16 d);
@@ -156,7 +156,7 @@ public:
        std::string getClientInitializationData();
        void step(float dtime, bool send_recommended);
        InventoryItem* createPickedUpItem(){return NULL;}
-       void punch(ServerActiveObject *puncher);
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
        bool isPeaceful();
 private:
        void sendPosition();
@@ -210,7 +210,7 @@ public:
        std::string getClientInitializationData();
        std::string getStaticData();
        InventoryItem* createPickedUpItem();
-       void punch(ServerActiveObject *puncher);
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
        void rightClick(ServerActiveObject *clicker);
        void setPos(v3f pos);
        void moveTo(v3f pos, bool continuous);
@@ -240,30 +240,5 @@ private:
        float m_last_sent_move_precision;
 };
 
-class ServerRemotePlayer;
-
-class PlayerSAO : public ServerActiveObject
-{
-public:
-       PlayerSAO(ServerEnvironment *env, v3f pos,
-                       ServerRemotePlayer *player);
-       ~PlayerSAO();
-       u8 getType() const
-               {return ACTIVEOBJECT_TYPE_PLAYER;}
-       void step(float dtime, bool send_recommended);
-       std::string getClientInitializationData();
-       std::string getStaticData();
-       bool isStaticAllowed() const
-       { return false; }
-       void punch(ServerActiveObject *puncher);
-       /* PlayerSAO-specific */
-       void setPlayer(ServerRemotePlayer *player);
-       ServerRemotePlayer* getPlayer();
-       void positionUpdated();
-private:
-       ServerRemotePlayer *m_player;
-       bool m_position_updated;
-};
-
 #endif
 
index 833ed93c2d566bf4f4ea55493a67d52418ad0097..17c9ecfffc69755ca4b5094f4143aeaf105741d6 100644 (file)
@@ -750,7 +750,8 @@ void ServerEnvironment::clearAllObjects()
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete active object
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
@@ -1181,7 +1182,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
                succeeded = false;
        }
 
-       delete obj;
+       if(obj->environmentDeletes())
+               delete obj;
 
        return succeeded;
 }
@@ -1296,7 +1298,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                {
                        errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
                                        <<"no free ids available"<<std::endl;
-                       delete object;
+                       if(object->environmentDeletes())
+                               delete object;
                        return 0;
                }
                object->setId(new_id);
@@ -1309,7 +1312,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
        {
                errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
                                <<"id is not free ("<<object->getId()<<")"<<std::endl;
-               delete object;
+               if(object->environmentDeletes())
+                       delete object;
                return 0;
        }
        /*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
@@ -1411,7 +1415,8 @@ void ServerEnvironment::removeRemovedObjects()
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
@@ -1699,7 +1704,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete active object
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
index ed0b00925ef5edfd2911aa70a8ba0ef45f8662c7..3f88f9d455ab0f3b4b5c6d5a65b7e88fa83eaade 100644 (file)
@@ -49,34 +49,65 @@ void MaterialProperties::deSerialize(std::istream &is)
        flammability = readF1000(is);
 }
 
-DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp,
-               INodeDefManager *nodemgr)
+DiggingProperties getDiggingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp, float time_from_last_punch)
 {
-       assert(tp);
-       const MaterialProperties &mp = nodemgr->get(content).material;
-       if(mp.diggability == DIGGABLE_NOT)
+       if(mp->diggability == DIGGABLE_NOT)
                return DiggingProperties(false, 0, 0);
-       if(mp.diggability == DIGGABLE_CONSTANT)
-               return DiggingProperties(true, mp.constant_time, 0);
+       if(mp->diggability == DIGGABLE_CONSTANT)
+               return DiggingProperties(true, mp->constant_time, 0);
 
        float time = tp->basetime;
-       time += tp->dt_weight * mp.weight;
-       time += tp->dt_crackiness * mp.crackiness;
-       time += tp->dt_crumbliness * mp.crumbliness;
-       time += tp->dt_cuttability * mp.cuttability;
+       time += tp->dt_weight * mp->weight;
+       time += tp->dt_crackiness * mp->crackiness;
+       time += tp->dt_crumbliness * mp->crumbliness;
+       time += tp->dt_cuttability * mp->cuttability;
        if(time < 0.2)
                time = 0.2;
 
        float durability = tp->basedurability;
-       durability += tp->dd_weight * mp.weight;
-       durability += tp->dd_crackiness * mp.crackiness;
-       durability += tp->dd_crumbliness * mp.crumbliness;
-       durability += tp->dd_cuttability * mp.cuttability;
+       durability += tp->dd_weight * mp->weight;
+       durability += tp->dd_crackiness * mp->crackiness;
+       durability += tp->dd_crumbliness * mp->crumbliness;
+       durability += tp->dd_cuttability * mp->cuttability;
        if(durability < 1)
                durability = 1;
+       
+       if(time_from_last_punch < tp->full_punch_interval){
+               float f = time_from_last_punch / tp->full_punch_interval;
+               time /= f;
+               durability /= f;
+       }
 
        float wear = 1.0 / durability;
        u16 wear_i = 65535.*wear;
        return DiggingProperties(true, time, wear_i);
 }
 
+DiggingProperties getDiggingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp)
+{
+       return getDiggingProperties(mp, tp, 1000000);
+}
+
+DiggingProperties getDiggingProperties(u16 content,
+               const ToolDiggingProperties *tp, INodeDefManager *nodemgr)
+{
+       const MaterialProperties &mp = nodemgr->get(content).material;
+       return getDiggingProperties(&mp, tp);
+}
+
+HittingProperties getHittingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp, float time_from_last_punch)
+{
+       DiggingProperties digprop = getDiggingProperties(mp, tp,
+                       time_from_last_punch);
+       
+       // If digging time would be 1 second, 2 hearts go in 1 second.
+       s16 hp = 2.0 * 2.0 / digprop.time + 0.5;
+       // Wear is the same as for digging a single node
+       s16 wear = (float)digprop.wear + 0.5;
+
+       return HittingProperties(hp, wear);
+}
+
index bcf9305811468bf92d65a19c8d7abf7bd5405b7a..b25d047beb9831060268d46a7e6a78d7d9a34d70 100644 (file)
@@ -74,30 +74,44 @@ struct MaterialProperties
 
 struct DiggingProperties
 {
-       DiggingProperties():
-               diggable(false),
-               time(0.0),
-               wear(0)
-       {
-       }
-       DiggingProperties(bool a_diggable, float a_time, u16 a_wear):
-               diggable(a_diggable),
-               time(a_time),
-               wear(a_wear)
-       {
-       }
        bool diggable;
        // Digging time in seconds
        float time;
        // Caused wear
        u16 wear;
+
+       DiggingProperties(bool a_diggable=false, float a_time=0, u16 a_wear=0):
+               diggable(a_diggable),
+               time(a_time),
+               wear(a_wear)
+       {}
 };
 
 struct ToolDiggingProperties;
 class INodeDefManager;
 
-DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp,
-               INodeDefManager *nodemgr);
+DiggingProperties getDiggingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp, float time_from_last_punch);
+
+DiggingProperties getDiggingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp);
+
+DiggingProperties getDiggingProperties(u16 content,
+               const ToolDiggingProperties *tp, INodeDefManager *nodemgr);
+
+struct HittingProperties
+{
+       s16 hp;
+       s16 wear;
+
+       HittingProperties(s16 hp_=0, s16 wear_=0):
+               hp(hp_),
+               wear(wear_)
+       {}
+};
+
+HittingProperties getHittingProperties(const MaterialProperties *mp,
+               const ToolDiggingProperties *tp, float time_from_last_punch);
 
 #endif
 
index 937ca9a3ff9f1ea3dea18129813071e78e04eeb6..8825668968c0fe510911d35c6687f22f688905ee 100644 (file)
@@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "environment.h"
 #include "gamedef.h"
 #include "content_sao.h"
+#include "tooldef.h"
+#include "materials.h"
 
 Player::Player(IGameDef *gamedef):
        touching_ground(false),
@@ -188,7 +190,9 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
        m_additional_items(),
        m_inventory_not_sent(false),
        m_hp_not_sent(false),
-       m_sao(NULL)
+       m_respawn_active(false),
+       m_is_in_environment(false),
+       m_position_not_sent(false)
 {
 }
 ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
@@ -197,7 +201,8 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
        ServerActiveObject(env, pos_),
        m_inventory_not_sent(false),
        m_hp_not_sent(false),
-       m_sao(NULL)
+       m_is_in_environment(false),
+       m_position_not_sent(false)
 {
        setPosition(pos_);
        peer_id = peer_id_;
@@ -206,39 +211,136 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
 ServerRemotePlayer::~ServerRemotePlayer()
 {
        clearAddToInventoryLater();
-       if(m_sao)
-               m_sao->setPlayer(NULL);
 }
 
 void ServerRemotePlayer::setPosition(const v3f &position)
 {
        Player::setPosition(position);
        ServerActiveObject::setBasePosition(position);
-       if(m_sao)
-               m_sao->positionUpdated();
+       m_position_not_sent = true;
 }
 
-void ServerRemotePlayer::setSAO(PlayerSAO *sao)
+InventoryItem* ServerRemotePlayer::getWieldedItem()
 {
-       infostream<<"ServerRemotePlayer \""<<getName()
-                       <<"\" got sao="<<sao<<std::endl;
-       m_sao = sao;
+       InventoryList *list = inventory.getList("main");
+       if (list)
+               return list->getItem(m_selected_item);
+       return NULL;
 }
 
-PlayerSAO* ServerRemotePlayer::getSAO()
+/* ServerActiveObject interface */
+
+void ServerRemotePlayer::addedToEnvironment()
 {
-       return m_sao;
+       assert(!m_is_in_environment);
+       m_is_in_environment = true;
 }
 
-/* ServerActiveObject interface */
+void ServerRemotePlayer::removingFromEnvironment()
+{
+       assert(m_is_in_environment);
+       m_is_in_environment = false;
+}
 
-InventoryItem* ServerRemotePlayer::getWieldedItem()
+void ServerRemotePlayer::step(float dtime, bool send_recommended)
 {
-       InventoryList *list = inventory.getList("main");
-       if (list)
-               return list->getItem(m_selected_item);
-       return NULL;
+       if(send_recommended == false)
+               return;
+       
+       if(m_position_not_sent)
+       {
+               m_position_not_sent = false;
+
+               std::ostringstream os(std::ios::binary);
+               // command (0 = update position)
+               writeU8(os, 0);
+               // pos
+               writeV3F1000(os, getPosition());
+               // yaw
+               writeF1000(os, getYaw());
+               // create message and add to list
+               ActiveObjectMessage aom(getId(), false, os.str());
+               m_messages_out.push_back(aom);
+       }
+}
+
+std::string ServerRemotePlayer::getClientInitializationData()
+{
+       std::ostringstream os(std::ios::binary);
+       // version
+       writeU8(os, 0);
+       // name
+       os<<serializeString(getName());
+       // pos
+       writeV3F1000(os, getPosition());
+       // yaw
+       writeF1000(os, getYaw());
+       return os.str();
+}
+
+std::string ServerRemotePlayer::getStaticData()
+{
+       assert(0);
+       return "";
+}
+
+void ServerRemotePlayer::punch(ServerActiveObject *puncher,
+               float time_from_last_punch)
+{
+       if(!puncher)
+               return;
+       
+       // "Material" properties of a player
+       MaterialProperties mp;
+       mp.diggability = DIGGABLE_NORMAL;
+       mp.crackiness = -1.0;
+       mp.cuttability = 1.0;
+
+       ToolDiggingProperties tp;
+       puncher->getWieldDiggingProperties(&tp);
+
+       HittingProperties hitprop = getHittingProperties(&mp, &tp,
+                       time_from_last_punch);
+       
+       infostream<<"1. getHP()="<<getHP()<<std::endl;
+       setHP(getHP() - hitprop.hp);
+       infostream<<"2. getHP()="<<getHP()<<std::endl;
+       puncher->damageWieldedItem(hitprop.wear);
+}
+
+void ServerRemotePlayer::rightClick(ServerActiveObject *clicker)
+{
+}
+
+void ServerRemotePlayer::setPos(v3f pos)
+{
+       setPosition(pos);
+       // Movement caused by this command is always valid
+       m_last_good_position = pos;
+       m_last_good_position_age = 0;
+}
+void ServerRemotePlayer::moveTo(v3f pos, bool continuous)
+{
+       setPosition(pos);
+       // Movement caused by this command is always valid
+       m_last_good_position = pos;
+       m_last_good_position_age = 0;
+}
+
+void ServerRemotePlayer::getWieldDiggingProperties(ToolDiggingProperties *dst)
+{
+       IGameDef *gamedef = m_env->getGameDef();
+       IToolDefManager *tdef = gamedef->tdef();
+
+       InventoryItem *item = getWieldedItem();
+       if(item == NULL || std::string(item->getName()) != "ToolItem"){
+               *dst = ToolDiggingProperties();
+               return;
+       }
+       ToolItem *titem = (ToolItem*)item;
+       *dst = tdef->getDiggingProperties(titem->getToolName());
 }
+
 void ServerRemotePlayer::damageWieldedItem(u16 amount)
 {
        infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
@@ -332,13 +434,12 @@ void ServerRemotePlayer::setHP(s16 hp_)
 {
        s16 oldhp = hp;
 
-       hp = hp_;
-
        // FIXME: don't hardcode maximum HP, make configurable per object
-       if(hp < 0)
-               hp = 0;
-       else if(hp > 20)
-               hp = 20;
+       if(hp_ < 0)
+               hp_ = 0;
+       else if(hp_ > 20)
+               hp_ = 20;
+       hp = hp_;
 
        if(hp != oldhp)
                m_hp_not_sent = true;
@@ -348,129 +449,6 @@ s16 ServerRemotePlayer::getHP()
        return hp;
 }
 
-/*
-       RemotePlayer
-*/
-
-#ifndef SERVER
-
-#if 0
-RemotePlayer::RemotePlayer(
-               IGameDef *gamedef,
-               scene::ISceneNode* parent,
-               IrrlichtDevice *device,
-               s32 id):
-       Player(gamedef),
-       scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id),
-       m_text(NULL)
-{
-       m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2);
-
-       if(parent != NULL && device != NULL)
-       {
-               // ISceneNode stores a member called SceneManager
-               scene::ISceneManager* mgr = SceneManager;
-               video::IVideoDriver* driver = mgr->getVideoDriver();
-               gui::IGUIEnvironment* gui = device->getGUIEnvironment();
-
-               // Add a text node for showing the name
-               wchar_t wname[1] = {0};
-               m_text = mgr->addTextSceneNode(gui->getBuiltInFont(),
-                               wname, video::SColor(255,255,255,255), this);
-               m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
-
-               // Attach a simple mesh to the player for showing an image
-               scene::SMesh *mesh = new scene::SMesh();
-               { // Front
-               scene::IMeshBuffer *buf = new scene::SMeshBuffer();
-               video::SColor c(255,255,255,255);
-               video::S3DVertex vertices[4] =
-               {
-                       video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
-                       video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
-                       video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
-                       video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
-               };
-               u16 indices[] = {0,1,2,2,3,0};
-               buf->append(vertices, 4, indices, 6);
-               // Set material
-               buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
-               //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
-               buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
-               buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
-               buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
-               //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
-               buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-               // Add to mesh
-               mesh->addMeshBuffer(buf);
-               buf->drop();
-               }
-               { // Back
-               scene::IMeshBuffer *buf = new scene::SMeshBuffer();
-               video::SColor c(255,255,255,255);
-               video::S3DVertex vertices[4] =
-               {
-                       video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
-                       video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
-                       video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
-                       video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
-               };
-               u16 indices[] = {0,1,2,2,3,0};
-               buf->append(vertices, 4, indices, 6);
-               // Set material
-               buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
-               //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
-               buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
-               buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
-               buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
-               buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-               // Add to mesh
-               mesh->addMeshBuffer(buf);
-               buf->drop();
-               }
-               m_node = mgr->addMeshSceneNode(mesh, this);
-               mesh->drop();
-               m_node->setPosition(v3f(0,0,0));
-       }
-}
-
-RemotePlayer::~RemotePlayer()
-{
-       if(SceneManager != NULL)
-               ISceneNode::remove();
-}
-
-void RemotePlayer::updateName(const char *name)
-{
-       Player::updateName(name);
-       if(m_text != NULL)
-       {
-               wchar_t wname[PLAYERNAME_SIZE];
-               mbstowcs(wname, m_name, strlen(m_name)+1);
-               m_text->setText(wname);
-       }
-}
-
-void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d)
-{
-       m_pos_animation_time_counter += dtime;
-       m_pos_animation_counter += dtime;
-       v3f movevector = m_position - m_oldpos;
-       f32 moveratio;
-       if(m_pos_animation_time < 0.001)
-               moveratio = 1.0;
-       else
-               moveratio = m_pos_animation_counter / m_pos_animation_time;
-       if(moveratio > 1.5)
-               moveratio = 1.5;
-       m_showpos = m_oldpos + movevector * moveratio;
-       
-       ISceneNode::setPosition(m_showpos);
-}
-#endif
-
-#endif
-
 #ifndef SERVER
 /*
        LocalPlayer
index 34fb5128cd36ff50b4997cd84f0b077a00b1f6d2..c9dbe76bb93858f6b7f14b54aa4a547387076f31 100644 (file)
@@ -201,32 +201,34 @@ public:
        
        virtual void setPosition(const v3f &position);
        
-       void setSAO(PlayerSAO *sao);
-       PlayerSAO* getSAO();
-
+       // Returns a reference
+       virtual InventoryItem* getWieldedItem();
+       
        /* ServerActiveObject interface */
 
        u8 getType() const
        {return ACTIVEOBJECT_TYPE_PLAYER;}
        
-       virtual void setPos(v3f pos)
-       {
-               setPosition(pos);
-               // Movement caused by this command is always valid
-               m_last_good_position = pos;
-               m_last_good_position_age = 0;
-       }
-       virtual void moveTo(v3f pos, bool continuous)
-       {
-               setPosition(pos);
-               // Movement caused by this command is always valid
-               m_last_good_position = pos;
-               m_last_good_position_age = 0;
-       }
+       // Called after id has been set and has been inserted in environment
+       void addedToEnvironment();
+       // Called before removing from environment
+       void removingFromEnvironment();
        
+       bool environmentDeletes() const
+       { return false; }
+       bool isStaticAllowed() const
+       { return false; }
+
+       void step(float dtime, bool send_recommended);
+       std::string getClientInitializationData();
+       std::string getStaticData();
+       void punch(ServerActiveObject *puncher, float time_from_last_punch);
+       void rightClick(ServerActiveObject *clicker);
+       void setPos(v3f pos);
+       void moveTo(v3f pos, bool continuous);
        virtual std::string getDescription(){return getName();}
-       // Returns a reference
-       virtual InventoryItem* getWieldedItem();
+
+       virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
        virtual void damageWieldedItem(u16 amount);
        // If all fits, eats item and returns true. Otherwise returns false.
        virtual bool addToInventory(InventoryItem *item);
@@ -241,110 +243,13 @@ public:
        std::vector<InventoryItem*> m_additional_items;
        bool m_inventory_not_sent;
        bool m_hp_not_sent;
+       bool m_respawn_active;
        
 private:
-
-       PlayerSAO *m_sao;
+       bool m_is_in_environment;
+       bool m_position_not_sent;
 };
 
-#ifndef SERVER
-
-#if 0
-/*
-       All the other players on the client are these
-*/
-
-class RemotePlayer : public Player, public scene::ISceneNode
-{
-public:
-       RemotePlayer(
-               IGameDef *gamedef,
-               scene::ISceneNode* parent=NULL,
-               IrrlichtDevice *device=NULL,
-               s32 id=0);
-       
-       virtual ~RemotePlayer();
-
-       /*
-               ISceneNode methods
-       */
-
-       virtual void OnRegisterSceneNode()
-       {
-               if (IsVisible)
-                       SceneManager->registerNodeForRendering(this);
-
-               ISceneNode::OnRegisterSceneNode();
-       }
-
-       virtual void render()
-       {
-               // Do nothing
-       }
-       
-       virtual const core::aabbox3d<f32>& getBoundingBox() const
-       {
-               return m_box;
-       }
-
-       void setPosition(const v3f &position)
-       {
-               m_oldpos = m_showpos;
-               
-               if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
-                       m_pos_animation_time = m_pos_animation_time_counter;
-               else
-                       m_pos_animation_time = m_pos_animation_time * 0.9
-                                       + m_pos_animation_time_counter * 0.1;
-               m_pos_animation_time_counter = 0;
-               m_pos_animation_counter = 0;
-               
-               Player::setPosition(position);
-               //ISceneNode::setPosition(position);
-       }
-
-       virtual void setYaw(f32 yaw)
-       {
-               Player::setYaw(yaw);
-               ISceneNode::setRotation(v3f(0, -yaw, 0));
-       }
-
-       bool isLocal() const
-       {
-               return false;
-       }
-
-       void updateName(const char *name);
-
-       virtual void updateLight(u8 light_at_pos)
-       {
-               Player::updateLight(light_at_pos);
-
-               if(m_node == NULL)
-                       return;
-
-               u8 li = decode_light(light_at_pos);
-               video::SColor color(255,li,li,li);
-               setMeshVerticesColor(m_node->getMesh(), color);
-       }
-       
-       void move(f32 dtime, Map &map, f32 pos_max_d);
-
-private:
-       scene::IMeshSceneNode *m_node;
-       scene::ITextSceneNode* m_text;
-       core::aabbox3d<f32> m_box;
-
-       v3f m_oldpos;
-       f32 m_pos_animation_counter;
-       f32 m_pos_animation_time;
-       f32 m_pos_animation_time_counter;
-       v3f m_showpos;
-};
-#endif
-
-#endif // !SERVER
-
 #ifndef SERVER
 struct PlayerControl
 {
index a87e7eabf8a2b576166e051eea87400492d2d698..40e31bb9f654968a8da3851e15df9b96070893c5 100644 (file)
@@ -386,6 +386,15 @@ static int getenumfield(lua_State *L, int table,
        return result;
 }
 
+static void setfloatfield(lua_State *L, int table,
+               const char *fieldname, float value)
+{
+       lua_pushnumber(L, value);
+       if(table < 0)
+               table -= 1;
+       lua_setfield(L, table, fieldname);
+}
+
 /*
        Inventory stuff
 */
@@ -455,6 +464,71 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name,
        }
 }
 
+/*
+       ToolDiggingProperties
+*/
+
+static ToolDiggingProperties read_tool_digging_properties(
+               lua_State *L, int table)
+{
+       ToolDiggingProperties prop;
+       getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
+       getfloatfield(L, table, "basetime", prop.basetime);
+       getfloatfield(L, table, "dt_weight", prop.dt_weight);
+       getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
+       getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
+       getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
+       getfloatfield(L, table, "basedurability", prop.basedurability);
+       getfloatfield(L, table, "dd_weight", prop.dd_weight);
+       getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
+       getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
+       getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
+       return prop;
+}
+
+static void set_tool_digging_properties(lua_State *L, int table,
+               const ToolDiggingProperties &prop)
+{
+       setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
+       setfloatfield(L, table, "basetime", prop.basetime);
+       setfloatfield(L, table, "dt_weight", prop.dt_weight);
+       setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
+       setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
+       setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
+       setfloatfield(L, table, "basedurability", prop.basedurability);
+       setfloatfield(L, table, "dd_weight", prop.dd_weight);
+       setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
+       setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
+       setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
+}
+
+static void push_tool_digging_properties(lua_State *L,
+               const ToolDiggingProperties &prop)
+{
+       lua_newtable(L);
+       set_tool_digging_properties(L, -1, prop);
+}
+
+/*
+       ToolDefinition
+*/
+
+static ToolDefinition read_tool_definition(lua_State *L, int table)
+{
+       ToolDefinition def;
+       getstringfield(L, table, "image", def.imagename);
+       def.properties = read_tool_digging_properties(L, table);
+       return def;
+}
+
+static void push_tool_definition(lua_State *L, const ToolDefinition &def)
+{
+       lua_newtable(L);
+       lua_pushstring(L, def.imagename.c_str());
+       lua_setfield(L, -2, "image");
+       set_tool_digging_properties(L, -1, def.properties);
+}
+
 /*
        EnumString definitions
 */
@@ -672,19 +746,7 @@ static int l_register_tool(lua_State *L)
        IWritableToolDefManager *tooldef =
                        server->getWritableToolDefManager();
        
-       ToolDefinition def;
-       
-       getstringfield(L, table, "image", def.imagename);
-       getfloatfield(L, table, "basetime", def.properties.basetime);
-       getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
-       getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
-       getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
-       getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
-       getfloatfield(L, table, "basedurability", def.properties.basedurability);
-       getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
-       getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
-       getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
-       getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
+       ToolDefinition def = read_tool_definition(L, table);
 
        tooldef->registerTool(name, def);
        return 0; /* number of results */
@@ -1588,9 +1650,7 @@ private:
                        return NULL;
                if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
                        return NULL;
-               PlayerSAO *player_sao = static_cast<PlayerSAO*>(obj);
-               return player_sao->getPlayer();
-               //return static_cast<ServerRemotePlayer*>(obj);
+               return static_cast<ServerRemotePlayer*>(obj);
        }
        
        // Exported functions
@@ -1690,65 +1750,16 @@ private:
                return 0;
        }
 
-       // get_wielded_itemstring(self)
-       static int l_get_wielded_itemstring(lua_State *L)
+       // get_wield_digging_properties(self)
+       static int l_get_wield_digging_properties(lua_State *L)
        {
                ObjectRef *ref = checkobject(L, 1);
                ServerActiveObject *co = getobject(ref);
                if(co == NULL) return 0;
                // Do it
-               InventoryItem *item = co->getWieldedItem();
-               if(item == NULL){
-                       lua_pushnil(L);
-                       return 1;
-               }
-               lua_pushstring(L, item->getItemString().c_str());
-               return 1;
-       }
-
-       // get_wielded_item(self)
-       static int l_get_wielded_item(lua_State *L)
-       {
-               ObjectRef *ref = checkobject(L, 1);
-               ServerActiveObject *co = getobject(ref);
-               if(co == NULL) return 0;
-               // Do it
-               InventoryItem *item0 = co->getWieldedItem();
-               if(item0 == NULL){
-                       lua_pushnil(L);
-                       return 1;
-               }
-               if(std::string("MaterialItem") == item0->getName()){
-                       MaterialItem *item = (MaterialItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "NodeItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getNodeName().c_str());
-                       lua_setfield(L, -2, "name");
-               }
-               else if(std::string("CraftItem") == item0->getName()){
-                       CraftItem *item = (CraftItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "CraftItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getSubName().c_str());
-                       lua_setfield(L, -2, "name");
-               }
-               else if(std::string("ToolItem") == item0->getName()){
-                       ToolItem *item = (ToolItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "ToolItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getToolName().c_str());
-                       lua_setfield(L, -2, "name");
-                       lua_pushstring(L, itos(item->getWear()).c_str());
-                       lua_setfield(L, -2, "wear");
-               }
-               else{
-                       errorstream<<"l_get_wielded_item: Unknown item name: \""
-                                       <<item0->getName()<<"\""<<std::endl;
-                       lua_pushnil(L);
-               }
+               ToolDiggingProperties prop;
+               co->getWieldDiggingProperties(&prop);
+               push_tool_digging_properties(L, prop);
                return 1;
        }
 
@@ -1976,6 +1987,68 @@ private:
                return 1;
        }
 
+       // get_wielded_itemstring(self)
+       static int l_get_wielded_itemstring(lua_State *L)
+       {
+               ObjectRef *ref = checkobject(L, 1);
+               ServerRemotePlayer *player = getplayer(ref);
+               if(player == NULL) return 0;
+               // Do it
+               InventoryItem *item = player->getWieldedItem();
+               if(item == NULL){
+                       lua_pushnil(L);
+                       return 1;
+               }
+               lua_pushstring(L, item->getItemString().c_str());
+               return 1;
+       }
+
+       // get_wielded_item(self)
+       static int l_get_wielded_item(lua_State *L)
+       {
+               ObjectRef *ref = checkobject(L, 1);
+               ServerRemotePlayer *player = getplayer(ref);
+               if(player == NULL) return 0;
+               // Do it
+               InventoryItem *item0 = player->getWieldedItem();
+               if(item0 == NULL){
+                       lua_pushnil(L);
+                       return 1;
+               }
+               if(std::string("MaterialItem") == item0->getName()){
+                       MaterialItem *item = (MaterialItem*)item0;
+                       lua_newtable(L);
+                       lua_pushstring(L, "NodeItem");
+                       lua_setfield(L, -2, "type");
+                       lua_pushstring(L, item->getNodeName().c_str());
+                       lua_setfield(L, -2, "name");
+               }
+               else if(std::string("CraftItem") == item0->getName()){
+                       CraftItem *item = (CraftItem*)item0;
+                       lua_newtable(L);
+                       lua_pushstring(L, "CraftItem");
+                       lua_setfield(L, -2, "type");
+                       lua_pushstring(L, item->getSubName().c_str());
+                       lua_setfield(L, -2, "name");
+               }
+               else if(std::string("ToolItem") == item0->getName()){
+                       ToolItem *item = (ToolItem*)item0;
+                       lua_newtable(L);
+                       lua_pushstring(L, "ToolItem");
+                       lua_setfield(L, -2, "type");
+                       lua_pushstring(L, item->getToolName().c_str());
+                       lua_setfield(L, -2, "name");
+                       lua_pushstring(L, itos(item->getWear()).c_str());
+                       lua_setfield(L, -2, "wear");
+               }
+               else{
+                       errorstream<<"l_get_wielded_item: Unknown item name: \""
+                                       <<item0->getName()<<"\""<<std::endl;
+                       lua_pushnil(L);
+               }
+               return 1;
+       }
+
 public:
        ObjectRef(ServerActiveObject *object):
                m_object(object)
@@ -2046,8 +2119,7 @@ const luaL_reg ObjectRef::methods[] = {
        method(ObjectRef, moveto),
        method(ObjectRef, punch),
        method(ObjectRef, right_click),
-       method(ObjectRef, get_wielded_itemstring),
-       method(ObjectRef, get_wielded_item),
+       method(ObjectRef, get_wield_digging_properties),
        method(ObjectRef, damage_wielded_item),
        method(ObjectRef, add_to_inventory),
        method(ObjectRef, add_to_inventory_later),
@@ -2063,6 +2135,8 @@ const luaL_reg ObjectRef::methods[] = {
        method(ObjectRef, get_player_name),
        method(ObjectRef, inventory_set_list),
        method(ObjectRef, inventory_get_list),
+       method(ObjectRef, get_wielded_itemstring),
+       method(ObjectRef, get_wielded_item),
        {0,0}
 };
 
index eebf96901001901903ae1e0dea56fa2e20945f51..2dceb805ba2259effa93f0c94a36709b91e01165 100644 (file)
@@ -1431,6 +1431,11 @@ void Server::AsyncRunStep()
                                player->m_last_good_position_age = 0;
                        }
 
+                       /*
+                               Handle player HPs
+                       */
+                       HandlePlayerHP(player, 0);
+
                        /*
                                Send player inventories and HPs if necessary
                        */
@@ -2230,8 +2235,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                }
 
                // Add PlayerSAO
-               PlayerSAO *sao = new PlayerSAO(m_env, player->getPosition(), player);
-               m_env->addActiveObject(sao);
+               player->m_removed = false;
+               m_env->addActiveObject(player);
 
                /*
                        Answer with a TOCLIENT_INIT
@@ -2983,6 +2988,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                
                actionstream<<player->getName()<<" respawns at "
                                <<PP(player->getPosition()/BS)<<std::endl;
+               
+               srp->m_removed = false;
+               m_env->addActiveObject(srp);
        }
        else if(command == TOSERVER_INTERACT)
        {
@@ -4523,6 +4531,11 @@ void Server::SendTextures(u16 peer_id)
 
 void Server::HandlePlayerHP(Player *player, s16 damage)
 {
+       ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
+
+       if(srp->m_respawn_active)
+               return;
+       
        if(player->hp > damage)
        {
                player->hp -= damage;
@@ -4549,6 +4562,8 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
                if(client->net_proto_version >= 3)
                {
                        SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
+                       srp->m_removed = true;
+                       srp->m_respawn_active = true;
                }
                else
                {
@@ -4561,6 +4576,7 @@ void Server::RespawnPlayer(Player *player)
 {
        player->hp = 20;
        ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
+       srp->m_respawn_active = false;
        bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
        if(!repositioned){
                v3f pos = findSpawnPos(m_env->getServerMap());
@@ -4983,16 +4999,9 @@ void Server::handlePeerChange(PeerChange &c)
                        }
                }
                
-               // Remove PlayerSAO
+               // Remove from environment
                if(player != NULL)
-               {
-                       PlayerSAO *sao = player->getSAO();
-                       if(sao){
-                               sao->setPlayer(NULL);
-                               sao->m_removed = true;
-                       }
-                       player->setSAO(NULL);
-               }
+                       player->m_removed = true;
                
                // Set player client disconnected
                if(player != NULL)
index 344ae406aedd61c3f3329746ae716e7f881e3758..ca3d2c3b98d2790de87d64905446a6fb0e273e99 100644 (file)
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "serverobject.h"
 #include <fstream>
 #include "inventory.h"
+#include "tooldef.h"
 
 ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
        ActiveObject(0),
@@ -66,5 +67,10 @@ void ServerActiveObject::registerType(u16 type, Factory f)
        m_types.insert(type, f);
 }
 
+void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
+{
+       *dst = ToolDiggingProperties();
+}
+
 
 
index 4dac4686368fc8bf77bcd465ee795d5ac46d1681..1386136cebdb6a7551476727a17cfe73c55df533 100644 (file)
@@ -43,6 +43,7 @@ Some planning
 class ServerEnvironment;
 class InventoryItem;
 class Player;
+struct ToolDiggingProperties;
 
 class ServerActiveObject : public ActiveObject
 {
@@ -128,23 +129,24 @@ public:
        virtual bool isStaticAllowed() const
        {return true;}
        
-       virtual void punch(ServerActiveObject *puncher){}
-       virtual void rightClick(ServerActiveObject *clicker){}
-       
-       // Returns a reference
-       virtual InventoryItem* getWieldedItem()
-               { return NULL; }
+       // time_from_last_punch is used for lessening damage if punching fast
+       virtual void punch(ServerActiveObject *puncher,
+                       float time_from_last_punch=1000000)
+       {}
+       virtual void rightClick(ServerActiveObject *clicker)
+       {}
+       virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
        virtual void damageWieldedItem(u16 amount)
-               {}
+       {}
        // If all fits, eats item and returns true. Otherwise returns false.
        virtual bool addToInventory(InventoryItem *item)
-               {return false;}
+       { return false; }
        virtual void addToInventoryLater(InventoryItem *item)
-               {}
+       {}
        virtual void setHP(s16 hp)
-               {}
+       {}
        virtual s16 getHP()
-               {return 0;}
+       { return 0; }
 
        /*
                Number of players which know about this object. Object won't be
index 1284a52abed0c867de9ef393d0f9e46c8510d212..45193f46bf770a27d94877c2f972703f58b19f57 100644 (file)
@@ -23,9 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <sstream>
 #include "utility.h"
 
-ToolDiggingProperties::ToolDiggingProperties(
+ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_,
                float a, float b, float c, float d, float e,
                float f, float g, float h, float i, float j):
+       full_punch_interval(full_punch_interval_),
        basetime(a),
        dt_weight(b),
        dt_crackiness(c),
@@ -60,6 +61,7 @@ void ToolDefinition::serialize(std::ostream &os)
        writeF1000(os, properties.dd_crackiness);
        writeF1000(os, properties.dd_crumbliness);
        writeF1000(os, properties.dd_cuttability);
+       writeF1000(os, properties.full_punch_interval);
 }
 
 void ToolDefinition::deSerialize(std::istream &is)
@@ -78,6 +80,9 @@ void ToolDefinition::deSerialize(std::istream &is)
        properties.dd_crackiness = readF1000(is);
        properties.dd_crumbliness = readF1000(is);
        properties.dd_cuttability = readF1000(is);
+       try{
+               properties.full_punch_interval = readF1000(is);
+       }catch(SerializationError &e){} // Temporary for 0.4.dev
 }
 
 class CToolDefManager: public IWritableToolDefManager
index 9741d7088719e22400851b11c5e3874d71f354f5..aa4cb6931ae3e912bb7f714fbb0340c220eb561a 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 struct ToolDiggingProperties
 {
        // time = basetime + sum(feature here * feature in MaterialProperties)
+       float full_punch_interval;
        float basetime;
        float dt_weight;
        float dt_crackiness;
@@ -37,7 +38,7 @@ struct ToolDiggingProperties
        float dd_crumbliness;
        float dd_cuttability;
 
-       ToolDiggingProperties(
+       ToolDiggingProperties(float full_punch_interval_=1.0,
                        float a=0.75, float b=0, float c=0, float d=0, float e=0,
                        float f=50, float g=0, float h=0, float i=0, float j=0);
 };