-- 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))
if(player && player->isLocal())
m_is_local_player = true;
+ pos_translator.init(m_position);
+
updateNodePos();
}
#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;
}
}
-void ItemSAO::punch(ServerActiveObject *puncher)
+void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
{
InventoryItem *item = createInventoryItem();
bool fits = puncher->addToInventory(item);
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();
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)
}
}
-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;
}
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()
return item;
}
-void LuaEntitySAO::punch(ServerActiveObject *puncher)
+void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
{
if(!m_registered)
return;
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;
-}
-
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;
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;
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);
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();
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);
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
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);
}
succeeded = false;
}
- delete obj;
+ if(obj->environmentDeletes())
+ delete obj;
return succeeded;
}
{
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"no free ids available"<<std::endl;
- delete object;
+ if(object->environmentDeletes())
+ delete object;
return 0;
}
object->setId(new_id);
{
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"id is not free ("<<object->getId()<<")"<<std::endl;
- delete object;
+ if(object->environmentDeletes())
+ delete object;
return 0;
}
/*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
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);
}
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);
}
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);
+}
+
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
#include "environment.h"
#include "gamedef.h"
#include "content_sao.h"
+#include "tooldef.h"
+#include "materials.h"
Player::Player(IGameDef *gamedef):
touching_ground(false),
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_,
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_;
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="
{
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;
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
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);
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
{
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
*/
}
}
+/*
+ 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
*/
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 */
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
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;
}
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)
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),
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}
};
player->m_last_good_position_age = 0;
}
+ /*
+ Handle player HPs
+ */
+ HandlePlayerHP(player, 0);
+
/*
Send player inventories and HPs if necessary
*/
}
// 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
actionstream<<player->getName()<<" respawns at "
<<PP(player->getPosition()/BS)<<std::endl;
+
+ srp->m_removed = false;
+ m_env->addActiveObject(srp);
}
else if(command == TOSERVER_INTERACT)
{
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;
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
{
{
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());
}
}
- // 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)
#include "serverobject.h"
#include <fstream>
#include "inventory.h"
+#include "tooldef.h"
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
ActiveObject(0),
m_types.insert(type, f);
}
+void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst)
+{
+ *dst = ToolDiggingProperties();
+}
+
class ServerEnvironment;
class InventoryItem;
class Player;
+struct ToolDiggingProperties;
class ServerActiveObject : public ActiveObject
{
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
#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),
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)
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
struct ToolDiggingProperties
{
// time = basetime + sum(feature here * feature in MaterialProperties)
+ float full_punch_interval;
float basetime;
float dt_weight;
float dt_crackiness;
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);
};