Players are more like objects + related stuff

This commit is contained in:
Perttu Ahola 2011-12-01 23:33:48 +02:00
parent ee0d3bacbc
commit af32240545
15 changed files with 622 additions and 599 deletions

@ -7,13 +7,32 @@
-- name "foomod", a texture could be called "foomod_superfurnace.png" -- name "foomod", a texture could be called "foomod_superfurnace.png"
-- Due to historical reasons, the default mod does not follow this rule. -- 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: -- Global functions:
-- minetest.register_entity(name, prototype_table) -- minetest.register_entity(name, prototype table)
-- minetest.register_tool(name, {lots of stuff}) -- minetest.register_tool(name, tool definition)
-- minetest.register_node(name, {lots of stuff}) -- minetest.register_node(name, node definition)
-- minetest.register_craftitem(name, {lots of stuff}) -- minetest.register_craftitem(name, craftitem definition)
-- minetest.register_craft({output=item, recipe={...}) -- minetest.register_craft(recipe)
-- minetest.register_globalstep(func) -- minetest.register_globalstep(func(dtime))
-- minetest.register_on_placenode(func(pos, newnode, placer)) -- minetest.register_on_placenode(func(pos, newnode, placer))
-- minetest.register_on_dignode(func(pos, oldnode, digger)) -- minetest.register_on_dignode(func(pos, oldnode, digger))
-- minetest.register_on_punchnode(func(pos, node, puncher)) -- minetest.register_on_punchnode(func(pos, node, puncher))
@ -22,11 +41,14 @@
-- minetest.register_on_respawnplayer(func(ObjectRef)) -- minetest.register_on_respawnplayer(func(ObjectRef))
-- ^ return true in func to disable regular player placement -- ^ return true in func to disable regular player placement
-- minetest.register_on_chat_message(func(name, message)) -- minetest.register_on_chat_message(func(name, message))
-- minetest.setting_get(name) -- minetest.setting_get(name) -> string or nil
-- minetest.setting_getbool(name) -- minetest.setting_getbool(name) -> boolean value or nil
-- minetest.chat_send_all(text) -- minetest.chat_send_all(text)
-- minetest.chat_send_player(name, 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: -- Global objects:
-- minetest.env - environment reference -- minetest.env - environment reference
@ -79,29 +101,28 @@
-- ObjectRef is basically ServerActiveObject. -- ObjectRef is basically ServerActiveObject.
-- ObjectRef methods: -- ObjectRef methods:
-- - remove(): remove object (after returning from Lua) -- - 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} -- - setpos(pos); pos={x=num, y=num, z=num}
-- - moveto(pos, continuous=false): interpolated move -- - moveto(pos, continuous=false): interpolated move
-- - punch(puncher); puncher = an another ObjectRef -- - punch(puncher); puncher = an another ObjectRef
-- - right_click(clicker); clicker = an another ObjectRef -- - right_click(clicker); clicker = an another ObjectRef
-- - get_wielded_itemstring() -- - get_wield_digging_properties() -> digging property table
-- - get_wielded_item()
-- - damage_wielded_item(num) (item damage/wear range is 0-65535)
-- - add_to_inventory(itemstring): add an item to object inventory
-- - add_to_inventory_later(itemstring): like above, but after callback returns (only allowed for craftitem callbacks) -- - 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) -- - get_hp(): returns number of hitpoints (2 * number of hearts)
-- - set_hp(hp): set number of hitpoints (2 * number of hearts) -- - set_hp(hp): set number of hitpoints (2 * number of hearts)
-- LuaEntitySAO-only: -- LuaEntitySAO-only:
-- - setvelocity({x=num, y=num, z=num}) -- - setvelocity({x=num, y=num, z=num})
-- - setacceleration({x=num, y=num, z=num}) -- - setacceleration({x=num, y=num, z=num})
-- - getacceleration() -- - getacceleration() -> {x=num, y=num, z=num}
-- - settexturemod(mod) -- - settexturemod(mod)
-- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2, -- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
-- - select_horiz_by_yawpitch=false) -- - select_horiz_by_yawpitch=false)
-- Player-only: -- Player-only:
-- - get_player_name(): will return nil if is not a player -- - get_player_name(): will return nil if is not a player
-- - inventory_set_list(name, {item1, item2, ...}) -- - 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: -- Registered entities:
-- - Functions receive a "luaentity" as self: -- - Functions receive a "luaentity" as self:
@ -112,13 +133,113 @@
-- - on_step(self, dtime) -- - on_step(self, dtime)
-- - on_punch(self, hitter) -- - on_punch(self, hitter)
-- - on_rightclick(self, clicker) -- - 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: -- Entity prototype table:
-- {name="name", param1=num, param2=num} -- {
-- 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: -- Tool definition:
-- {x=num, y=num, z=num} -- {
-- 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)) -- print("minetest dump: "..dump(minetest))

@ -2126,6 +2126,8 @@ public:
if(player && player->isLocal()) if(player && player->isLocal())
m_is_local_player = true; m_is_local_player = true;
pos_translator.init(m_position);
updateNodePos(); updateNodePos();
} }

@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" // For g_profiler #include "main.h" // For g_profiler
#include "profiler.h" #include "profiler.h"
#include "serialization.h" // For compressZlib #include "serialization.h" // For compressZlib
#include "materials.h" // For MaterialProperties
#include "tooldef.h" // ToolDiggingProperties
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; 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(); InventoryItem *item = createInventoryItem();
bool fits = puncher->addToInventory(item); bool fits = puncher->addToInventory(item);
@ -432,7 +434,7 @@ std::string RatSAO::getStaticData()
return os.str(); 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); std::istringstream is("CraftItem rat 1", std::ios_base::binary);
IGameDef *gamedef = m_env->getGameDef(); IGameDef *gamedef = m_env->getGameDef();
@ -687,36 +689,28 @@ std::string Oerkki1SAO::getStaticData()
return os.str(); 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(); v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
std::string toolname = "";
InventoryItem *item = puncher->getWieldedItem();
if(item && (std::string)item->getName() == "ToolItem"){
ToolItem *titem = (ToolItem*)item;
toolname = titem->getToolName();
}
m_speed_f += dir*12*BS; m_speed_f += dir*12*BS;
u16 amount = 5; // "Material" properties of an oerkki
/* See tool names in inventory.h */ MaterialProperties mp;
if(toolname == "WSword") mp.diggability = DIGGABLE_NORMAL;
amount = 10; mp.crackiness = -1.0;
if(toolname == "STSword") mp.cuttability = 1.0;
amount = 12;
if(toolname == "SteelSword") ToolDiggingProperties tp;
amount = 16; puncher->getWieldDiggingProperties(&tp);
if(toolname == "STAxe")
amount = 7; HittingProperties hitprop = getHittingProperties(&mp, &tp,
if(toolname == "SteelAxe") time_from_last_punch);
amount = 9;
if(toolname == "SteelPick") doDamage(hitprop.hp);
amount = 7; puncher->damageWieldedItem(hitprop.wear);
doDamage(amount);
puncher->damageWieldedItem(65536/100);
} }
void Oerkki1SAO::doDamage(u16 d) 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(); 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 // A quick hack; SAO description is player name for player
std::string playername = puncher->getDescription(); std::string playername = puncher->getDescription();
Map *map = &m_env->getMap(); Map *map = &m_env->getMap();
actionstream<<playername<<" punches mob id="<<m_id actionstream<<playername<<" punches mob id="<<m_id
<<" with a \""<<toolname<<"\" at " <<" at "<<PP(m_base_position/BS)<<std::endl;
<<PP(m_base_position/BS)<<std::endl;
m_disturb_timer = 0; m_disturb_timer = 0;
m_disturbing_player = playername; m_disturbing_player = playername;
@ -1405,23 +1394,21 @@ void MobV2SAO::punch(ServerActiveObject *puncher)
} }
sendPosition(); sendPosition();
u16 amount = 2;
/* See tool names in inventory.h */ // "Material" properties of the MobV2
if(toolname == "WSword") MaterialProperties mp;
amount = 4; mp.diggability = DIGGABLE_NORMAL;
if(toolname == "STSword") mp.crackiness = -1.0;
amount = 6; mp.cuttability = 1.0;
if(toolname == "SteelSword")
amount = 8; ToolDiggingProperties tp;
if(toolname == "STAxe") puncher->getWieldDiggingProperties(&tp);
amount = 3;
if(toolname == "SteelAxe") HittingProperties hitprop = getHittingProperties(&mp, &tp,
amount = 4; time_from_last_punch);
if(toolname == "SteelPick")
amount = 3; doDamage(hitprop.hp);
doDamage(amount); puncher->damageWieldedItem(hitprop.wear);
puncher->damageWieldedItem(65536/100);
} }
bool MobV2SAO::isPeaceful() bool MobV2SAO::isPeaceful()
@ -1686,7 +1673,7 @@ InventoryItem* LuaEntitySAO::createPickedUpItem()
return item; return item;
} }
void LuaEntitySAO::punch(ServerActiveObject *puncher) void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
{ {
if(!m_registered) if(!m_registered)
return; return;
@ -1799,96 +1786,3 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
m_messages_out.push_back(aom); 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;
}

@ -50,7 +50,7 @@ public:
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
InventoryItem* createInventoryItem(); InventoryItem* createInventoryItem();
void punch(ServerActiveObject *puncher); void punch(ServerActiveObject *puncher, float time_from_last_punch);
float getMinimumSavedMovement(){ return 0.1*BS; } float getMinimumSavedMovement(){ return 0.1*BS; }
private: private:
std::string m_inventorystring; std::string m_inventorystring;
@ -70,7 +70,7 @@ public:
void step(float dtime, bool send_recommended); void step(float dtime, bool send_recommended);
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
void punch(ServerActiveObject *puncher); void punch(ServerActiveObject *puncher, float time_from_last_punch);
private: private:
bool m_is_active; bool m_is_active;
IntervalLimiter m_inactive_interval; IntervalLimiter m_inactive_interval;
@ -96,7 +96,7 @@ public:
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
InventoryItem* createPickedUpItem(){return NULL;} InventoryItem* createPickedUpItem(){return NULL;}
void punch(ServerActiveObject *puncher); void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful(){return false;} bool isPeaceful(){return false;}
private: private:
void doDamage(u16 d); void doDamage(u16 d);
@ -156,7 +156,7 @@ public:
std::string getClientInitializationData(); std::string getClientInitializationData();
void step(float dtime, bool send_recommended); void step(float dtime, bool send_recommended);
InventoryItem* createPickedUpItem(){return NULL;} InventoryItem* createPickedUpItem(){return NULL;}
void punch(ServerActiveObject *puncher); void punch(ServerActiveObject *puncher, float time_from_last_punch);
bool isPeaceful(); bool isPeaceful();
private: private:
void sendPosition(); void sendPosition();
@ -210,7 +210,7 @@ public:
std::string getClientInitializationData(); std::string getClientInitializationData();
std::string getStaticData(); std::string getStaticData();
InventoryItem* createPickedUpItem(); InventoryItem* createPickedUpItem();
void punch(ServerActiveObject *puncher); void punch(ServerActiveObject *puncher, float time_from_last_punch);
void rightClick(ServerActiveObject *clicker); void rightClick(ServerActiveObject *clicker);
void setPos(v3f pos); void setPos(v3f pos);
void moveTo(v3f pos, bool continuous); void moveTo(v3f pos, bool continuous);
@ -240,30 +240,5 @@ private:
float m_last_sent_move_precision; 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 #endif

@ -750,7 +750,8 @@ void ServerEnvironment::clearAllObjects()
scriptapi_rm_object_reference(m_lua, obj); scriptapi_rm_object_reference(m_lua, obj);
// Delete active object // Delete active object
delete obj; if(obj->environmentDeletes())
delete obj;
// Id to be removed from m_active_objects // Id to be removed from m_active_objects
objects_to_remove.push_back(id); objects_to_remove.push_back(id);
} }
@ -1181,7 +1182,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
succeeded = false; succeeded = false;
} }
delete obj; if(obj->environmentDeletes())
delete obj;
return succeeded; return succeeded;
} }
@ -1296,7 +1298,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
{ {
errorstream<<"ServerEnvironment::addActiveObjectRaw(): " errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"no free ids available"<<std::endl; <<"no free ids available"<<std::endl;
delete object; if(object->environmentDeletes())
delete object;
return 0; return 0;
} }
object->setId(new_id); object->setId(new_id);
@ -1309,7 +1312,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
{ {
errorstream<<"ServerEnvironment::addActiveObjectRaw(): " errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"id is not free ("<<object->getId()<<")"<<std::endl; <<"id is not free ("<<object->getId()<<")"<<std::endl;
delete object; if(object->environmentDeletes())
delete object;
return 0; return 0;
} }
/*infostream<<"ServerEnvironment::addActiveObjectRaw(): " /*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
@ -1411,7 +1415,8 @@ void ServerEnvironment::removeRemovedObjects()
scriptapi_rm_object_reference(m_lua, obj); scriptapi_rm_object_reference(m_lua, obj);
// Delete // Delete
delete obj; if(obj->environmentDeletes())
delete obj;
// Id to be removed from m_active_objects // Id to be removed from m_active_objects
objects_to_remove.push_back(id); objects_to_remove.push_back(id);
} }
@ -1699,7 +1704,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
scriptapi_rm_object_reference(m_lua, obj); scriptapi_rm_object_reference(m_lua, obj);
// Delete active object // Delete active object
delete obj; if(obj->environmentDeletes())
delete obj;
// Id to be removed from m_active_objects // Id to be removed from m_active_objects
objects_to_remove.push_back(id); objects_to_remove.push_back(id);
} }

@ -49,34 +49,65 @@ void MaterialProperties::deSerialize(std::istream &is)
flammability = readF1000(is); flammability = readF1000(is);
} }
DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp, DiggingProperties getDiggingProperties(const MaterialProperties *mp,
INodeDefManager *nodemgr) const ToolDiggingProperties *tp, float time_from_last_punch)
{ {
assert(tp); if(mp->diggability == DIGGABLE_NOT)
const MaterialProperties &mp = nodemgr->get(content).material;
if(mp.diggability == DIGGABLE_NOT)
return DiggingProperties(false, 0, 0); return DiggingProperties(false, 0, 0);
if(mp.diggability == DIGGABLE_CONSTANT) if(mp->diggability == DIGGABLE_CONSTANT)
return DiggingProperties(true, mp.constant_time, 0); return DiggingProperties(true, mp->constant_time, 0);
float time = tp->basetime; float time = tp->basetime;
time += tp->dt_weight * mp.weight; time += tp->dt_weight * mp->weight;
time += tp->dt_crackiness * mp.crackiness; time += tp->dt_crackiness * mp->crackiness;
time += tp->dt_crumbliness * mp.crumbliness; time += tp->dt_crumbliness * mp->crumbliness;
time += tp->dt_cuttability * mp.cuttability; time += tp->dt_cuttability * mp->cuttability;
if(time < 0.2) if(time < 0.2)
time = 0.2; time = 0.2;
float durability = tp->basedurability; float durability = tp->basedurability;
durability += tp->dd_weight * mp.weight; durability += tp->dd_weight * mp->weight;
durability += tp->dd_crackiness * mp.crackiness; durability += tp->dd_crackiness * mp->crackiness;
durability += tp->dd_crumbliness * mp.crumbliness; durability += tp->dd_crumbliness * mp->crumbliness;
durability += tp->dd_cuttability * mp.cuttability; durability += tp->dd_cuttability * mp->cuttability;
if(durability < 1) if(durability < 1)
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; float wear = 1.0 / durability;
u16 wear_i = 65535.*wear; u16 wear_i = 65535.*wear;
return DiggingProperties(true, time, wear_i); return DiggingProperties(true, time, wear_i);
} }
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp)
{
return getDiggingProperties(mp, tp, 1000000);
}
DiggingProperties getDiggingProperties(u16 content,
const ToolDiggingProperties *tp, INodeDefManager *nodemgr)
{
const MaterialProperties &mp = nodemgr->get(content).material;
return getDiggingProperties(&mp, tp);
}
HittingProperties getHittingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp, float time_from_last_punch)
{
DiggingProperties digprop = getDiggingProperties(mp, tp,
time_from_last_punch);
// If digging time would be 1 second, 2 hearts go in 1 second.
s16 hp = 2.0 * 2.0 / digprop.time + 0.5;
// Wear is the same as for digging a single node
s16 wear = (float)digprop.wear + 0.5;
return HittingProperties(hp, wear);
}

@ -74,30 +74,44 @@ struct MaterialProperties
struct DiggingProperties 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; bool diggable;
// Digging time in seconds // Digging time in seconds
float time; float time;
// Caused wear // Caused wear
u16 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; struct ToolDiggingProperties;
class INodeDefManager; class INodeDefManager;
DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp, DiggingProperties getDiggingProperties(const MaterialProperties *mp,
INodeDefManager *nodemgr); 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 #endif

@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h" #include "environment.h"
#include "gamedef.h" #include "gamedef.h"
#include "content_sao.h" #include "content_sao.h"
#include "tooldef.h"
#include "materials.h"
Player::Player(IGameDef *gamedef): Player::Player(IGameDef *gamedef):
touching_ground(false), touching_ground(false),
@ -188,7 +190,9 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
m_additional_items(), m_additional_items(),
m_inventory_not_sent(false), m_inventory_not_sent(false),
m_hp_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_, ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
@ -197,7 +201,8 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
ServerActiveObject(env, pos_), ServerActiveObject(env, pos_),
m_inventory_not_sent(false), m_inventory_not_sent(false),
m_hp_not_sent(false), m_hp_not_sent(false),
m_sao(NULL) m_is_in_environment(false),
m_position_not_sent(false)
{ {
setPosition(pos_); setPosition(pos_);
peer_id = peer_id_; peer_id = peer_id_;
@ -206,32 +211,15 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
ServerRemotePlayer::~ServerRemotePlayer() ServerRemotePlayer::~ServerRemotePlayer()
{ {
clearAddToInventoryLater(); clearAddToInventoryLater();
if(m_sao)
m_sao->setPlayer(NULL);
} }
void ServerRemotePlayer::setPosition(const v3f &position) void ServerRemotePlayer::setPosition(const v3f &position)
{ {
Player::setPosition(position); Player::setPosition(position);
ServerActiveObject::setBasePosition(position); ServerActiveObject::setBasePosition(position);
if(m_sao) m_position_not_sent = true;
m_sao->positionUpdated();
} }
void ServerRemotePlayer::setSAO(PlayerSAO *sao)
{
infostream<<"ServerRemotePlayer \""<<getName()
<<"\" got sao="<<sao<<std::endl;
m_sao = sao;
}
PlayerSAO* ServerRemotePlayer::getSAO()
{
return m_sao;
}
/* ServerActiveObject interface */
InventoryItem* ServerRemotePlayer::getWieldedItem() InventoryItem* ServerRemotePlayer::getWieldedItem()
{ {
InventoryList *list = inventory.getList("main"); InventoryList *list = inventory.getList("main");
@ -239,6 +227,120 @@ InventoryItem* ServerRemotePlayer::getWieldedItem()
return list->getItem(m_selected_item); return list->getItem(m_selected_item);
return NULL; return NULL;
} }
/* ServerActiveObject interface */
void ServerRemotePlayer::addedToEnvironment()
{
assert(!m_is_in_environment);
m_is_in_environment = true;
}
void ServerRemotePlayer::removingFromEnvironment()
{
assert(m_is_in_environment);
m_is_in_environment = false;
}
void ServerRemotePlayer::step(float dtime, bool send_recommended)
{
if(send_recommended == false)
return;
if(m_position_not_sent)
{
m_position_not_sent = false;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, getPosition());
// yaw
writeF1000(os, getYaw());
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string ServerRemotePlayer::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// name
os<<serializeString(getName());
// pos
writeV3F1000(os, getPosition());
// yaw
writeF1000(os, getYaw());
return os.str();
}
std::string ServerRemotePlayer::getStaticData()
{
assert(0);
return "";
}
void ServerRemotePlayer::punch(ServerActiveObject *puncher,
float time_from_last_punch)
{
if(!puncher)
return;
// "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) void ServerRemotePlayer::damageWieldedItem(u16 amount)
{ {
infostream<<"Damaging "<<getName()<<"'s wielded item for amount=" infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
@ -332,13 +434,12 @@ void ServerRemotePlayer::setHP(s16 hp_)
{ {
s16 oldhp = hp; s16 oldhp = hp;
hp = hp_;
// FIXME: don't hardcode maximum HP, make configurable per object // FIXME: don't hardcode maximum HP, make configurable per object
if(hp < 0) if(hp_ < 0)
hp = 0; hp_ = 0;
else if(hp > 20) else if(hp_ > 20)
hp = 20; hp_ = 20;
hp = hp_;
if(hp != oldhp) if(hp != oldhp)
m_hp_not_sent = true; m_hp_not_sent = true;
@ -348,129 +449,6 @@ s16 ServerRemotePlayer::getHP()
return hp; 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 #ifndef SERVER
/* /*
LocalPlayer LocalPlayer

@ -201,32 +201,34 @@ public:
virtual void setPosition(const v3f &position); virtual void setPosition(const v3f &position);
void setSAO(PlayerSAO *sao); // Returns a reference
PlayerSAO* getSAO(); virtual InventoryItem* getWieldedItem();
/* ServerActiveObject interface */ /* ServerActiveObject interface */
u8 getType() const u8 getType() const
{return ACTIVEOBJECT_TYPE_PLAYER;} {return ACTIVEOBJECT_TYPE_PLAYER;}
virtual void setPos(v3f pos) // Called after id has been set and has been inserted in environment
{ void addedToEnvironment();
setPosition(pos); // Called before removing from environment
// Movement caused by this command is always valid void removingFromEnvironment();
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;
}
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();} virtual std::string getDescription(){return getName();}
// Returns a reference
virtual InventoryItem* getWieldedItem(); virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
virtual void damageWieldedItem(u16 amount); virtual void damageWieldedItem(u16 amount);
// If all fits, eats item and returns true. Otherwise returns false. // If all fits, eats item and returns true. Otherwise returns false.
virtual bool addToInventory(InventoryItem *item); virtual bool addToInventory(InventoryItem *item);
@ -241,110 +243,13 @@ public:
std::vector<InventoryItem*> m_additional_items; std::vector<InventoryItem*> m_additional_items;
bool m_inventory_not_sent; bool m_inventory_not_sent;
bool m_hp_not_sent; bool m_hp_not_sent;
bool m_respawn_active;
private: private:
bool m_is_in_environment;
PlayerSAO *m_sao; 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 #ifndef SERVER
struct PlayerControl struct PlayerControl
{ {

@ -386,6 +386,15 @@ static int getenumfield(lua_State *L, int table,
return result; 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 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 EnumString definitions
*/ */
@ -672,19 +746,7 @@ static int l_register_tool(lua_State *L)
IWritableToolDefManager *tooldef = IWritableToolDefManager *tooldef =
server->getWritableToolDefManager(); server->getWritableToolDefManager();
ToolDefinition def; ToolDefinition def = read_tool_definition(L, table);
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);
tooldef->registerTool(name, def); tooldef->registerTool(name, def);
return 0; /* number of results */ return 0; /* number of results */
@ -1588,9 +1650,7 @@ private:
return NULL; return NULL;
if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
return NULL; return NULL;
PlayerSAO *player_sao = static_cast<PlayerSAO*>(obj); return static_cast<ServerRemotePlayer*>(obj);
return player_sao->getPlayer();
//return static_cast<ServerRemotePlayer*>(obj);
} }
// Exported functions // Exported functions
@ -1690,65 +1750,16 @@ private:
return 0; return 0;
} }
// get_wielded_itemstring(self) // get_wield_digging_properties(self)
static int l_get_wielded_itemstring(lua_State *L) static int l_get_wield_digging_properties(lua_State *L)
{ {
ObjectRef *ref = checkobject(L, 1); ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref); ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0; if(co == NULL) return 0;
// Do it // Do it
InventoryItem *item = co->getWieldedItem(); ToolDiggingProperties prop;
if(item == NULL){ co->getWieldDiggingProperties(&prop);
lua_pushnil(L); push_tool_digging_properties(L, prop);
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);
}
return 1; return 1;
} }
@ -1976,6 +1987,68 @@ private:
return 1; 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: public:
ObjectRef(ServerActiveObject *object): ObjectRef(ServerActiveObject *object):
m_object(object) m_object(object)
@ -2046,8 +2119,7 @@ const luaL_reg ObjectRef::methods[] = {
method(ObjectRef, moveto), method(ObjectRef, moveto),
method(ObjectRef, punch), method(ObjectRef, punch),
method(ObjectRef, right_click), method(ObjectRef, right_click),
method(ObjectRef, get_wielded_itemstring), method(ObjectRef, get_wield_digging_properties),
method(ObjectRef, get_wielded_item),
method(ObjectRef, damage_wielded_item), method(ObjectRef, damage_wielded_item),
method(ObjectRef, add_to_inventory), method(ObjectRef, add_to_inventory),
method(ObjectRef, add_to_inventory_later), method(ObjectRef, add_to_inventory_later),
@ -2063,6 +2135,8 @@ const luaL_reg ObjectRef::methods[] = {
method(ObjectRef, get_player_name), method(ObjectRef, get_player_name),
method(ObjectRef, inventory_set_list), method(ObjectRef, inventory_set_list),
method(ObjectRef, inventory_get_list), method(ObjectRef, inventory_get_list),
method(ObjectRef, get_wielded_itemstring),
method(ObjectRef, get_wielded_item),
{0,0} {0,0}
}; };

@ -1431,6 +1431,11 @@ void Server::AsyncRunStep()
player->m_last_good_position_age = 0; player->m_last_good_position_age = 0;
} }
/*
Handle player HPs
*/
HandlePlayerHP(player, 0);
/* /*
Send player inventories and HPs if necessary Send player inventories and HPs if necessary
*/ */
@ -2230,8 +2235,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
} }
// Add PlayerSAO // Add PlayerSAO
PlayerSAO *sao = new PlayerSAO(m_env, player->getPosition(), player); player->m_removed = false;
m_env->addActiveObject(sao); m_env->addActiveObject(player);
/* /*
Answer with a TOCLIENT_INIT Answer with a TOCLIENT_INIT
@ -2983,6 +2988,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
actionstream<<player->getName()<<" respawns at " actionstream<<player->getName()<<" respawns at "
<<PP(player->getPosition()/BS)<<std::endl; <<PP(player->getPosition()/BS)<<std::endl;
srp->m_removed = false;
m_env->addActiveObject(srp);
} }
else if(command == TOSERVER_INTERACT) else if(command == TOSERVER_INTERACT)
{ {
@ -4523,6 +4531,11 @@ void Server::SendTextures(u16 peer_id)
void Server::HandlePlayerHP(Player *player, s16 damage) void Server::HandlePlayerHP(Player *player, s16 damage)
{ {
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
if(srp->m_respawn_active)
return;
if(player->hp > damage) if(player->hp > damage)
{ {
player->hp -= damage; player->hp -= damage;
@ -4549,6 +4562,8 @@ void Server::HandlePlayerHP(Player *player, s16 damage)
if(client->net_proto_version >= 3) if(client->net_proto_version >= 3)
{ {
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0)); SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
srp->m_removed = true;
srp->m_respawn_active = true;
} }
else else
{ {
@ -4561,6 +4576,7 @@ void Server::RespawnPlayer(Player *player)
{ {
player->hp = 20; player->hp = 20;
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player); ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
srp->m_respawn_active = false;
bool repositioned = scriptapi_on_respawnplayer(m_lua, srp); bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
if(!repositioned){ if(!repositioned){
v3f pos = findSpawnPos(m_env->getServerMap()); v3f pos = findSpawnPos(m_env->getServerMap());
@ -4983,16 +4999,9 @@ void Server::handlePeerChange(PeerChange &c)
} }
} }
// Remove PlayerSAO // Remove from environment
if(player != NULL) if(player != NULL)
{ player->m_removed = true;
PlayerSAO *sao = player->getSAO();
if(sao){
sao->setPlayer(NULL);
sao->m_removed = true;
}
player->setSAO(NULL);
}
// Set player client disconnected // Set player client disconnected
if(player != NULL) if(player != NULL)

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h" #include "serverobject.h"
#include <fstream> #include <fstream>
#include "inventory.h" #include "inventory.h"
#include "tooldef.h"
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos): ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
ActiveObject(0), ActiveObject(0),
@ -66,5 +67,10 @@ void ServerActiveObject::registerType(u16 type, Factory f)
m_types.insert(type, f); m_types.insert(type, f);
} }
void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
{
*dst = ToolDiggingProperties();
}

@ -43,6 +43,7 @@ Some planning
class ServerEnvironment; class ServerEnvironment;
class InventoryItem; class InventoryItem;
class Player; class Player;
struct ToolDiggingProperties;
class ServerActiveObject : public ActiveObject class ServerActiveObject : public ActiveObject
{ {
@ -128,23 +129,24 @@ public:
virtual bool isStaticAllowed() const virtual bool isStaticAllowed() const
{return true;} {return true;}
virtual void punch(ServerActiveObject *puncher){} // time_from_last_punch is used for lessening damage if punching fast
virtual void rightClick(ServerActiveObject *clicker){} virtual void punch(ServerActiveObject *puncher,
float time_from_last_punch=1000000)
// Returns a reference {}
virtual InventoryItem* getWieldedItem() virtual void rightClick(ServerActiveObject *clicker)
{ return NULL; } {}
virtual void getWieldDiggingProperties(ToolDiggingProperties *dst);
virtual void damageWieldedItem(u16 amount) virtual void damageWieldedItem(u16 amount)
{} {}
// If all fits, eats item and returns true. Otherwise returns false. // If all fits, eats item and returns true. Otherwise returns false.
virtual bool addToInventory(InventoryItem *item) virtual bool addToInventory(InventoryItem *item)
{return false;} { return false; }
virtual void addToInventoryLater(InventoryItem *item) virtual void addToInventoryLater(InventoryItem *item)
{} {}
virtual void setHP(s16 hp) virtual void setHP(s16 hp)
{} {}
virtual s16 getHP() virtual s16 getHP()
{return 0;} { return 0; }
/* /*
Number of players which know about this object. Object won't be Number of players which know about this object. Object won't be

@ -23,9 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <sstream> #include <sstream>
#include "utility.h" #include "utility.h"
ToolDiggingProperties::ToolDiggingProperties( ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_,
float a, float b, float c, float d, float e, float a, float b, float c, float d, float e,
float f, float g, float h, float i, float j): float f, float g, float h, float i, float j):
full_punch_interval(full_punch_interval_),
basetime(a), basetime(a),
dt_weight(b), dt_weight(b),
dt_crackiness(c), dt_crackiness(c),
@ -60,6 +61,7 @@ void ToolDefinition::serialize(std::ostream &os)
writeF1000(os, properties.dd_crackiness); writeF1000(os, properties.dd_crackiness);
writeF1000(os, properties.dd_crumbliness); writeF1000(os, properties.dd_crumbliness);
writeF1000(os, properties.dd_cuttability); writeF1000(os, properties.dd_cuttability);
writeF1000(os, properties.full_punch_interval);
} }
void ToolDefinition::deSerialize(std::istream &is) void ToolDefinition::deSerialize(std::istream &is)
@ -78,6 +80,9 @@ void ToolDefinition::deSerialize(std::istream &is)
properties.dd_crackiness = readF1000(is); properties.dd_crackiness = readF1000(is);
properties.dd_crumbliness = readF1000(is); properties.dd_crumbliness = readF1000(is);
properties.dd_cuttability = 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 class CToolDefManager: public IWritableToolDefManager

@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct ToolDiggingProperties struct ToolDiggingProperties
{ {
// time = basetime + sum(feature here * feature in MaterialProperties) // time = basetime + sum(feature here * feature in MaterialProperties)
float full_punch_interval;
float basetime; float basetime;
float dt_weight; float dt_weight;
float dt_crackiness; float dt_crackiness;
@ -37,7 +38,7 @@ struct ToolDiggingProperties
float dd_crumbliness; float dd_crumbliness;
float dd_cuttability; 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 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); float f=50, float g=0, float h=0, float i=0, float j=0);
}; };