diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/content_cao.cpp | 2 | ||||
-rw-r--r-- | src/content_sao.cpp | 190 | ||||
-rw-r--r-- | src/content_sao.h | 35 | ||||
-rw-r--r-- | src/environment.cpp | 18 | ||||
-rw-r--r-- | src/materials.cpp | 61 | ||||
-rw-r--r-- | src/materials.h | 42 | ||||
-rw-r--r-- | src/player.cpp | 272 | ||||
-rw-r--r-- | src/player.h | 143 | ||||
-rw-r--r-- | src/scriptapi.cpp | 218 | ||||
-rw-r--r-- | src/server.cpp | 31 | ||||
-rw-r--r-- | src/serverobject.cpp | 6 | ||||
-rw-r--r-- | src/serverobject.h | 24 | ||||
-rw-r--r-- | src/tooldef.cpp | 7 | ||||
-rw-r--r-- | src/tooldef.h | 3 |
14 files changed, 477 insertions, 575 deletions
diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 011a3f408..20eb3cf1b 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -2126,6 +2126,8 @@ public: if(player && player->isLocal()) m_is_local_player = true; + pos_translator.init(m_position); + updateNodePos(); } diff --git a/src/content_sao.cpp b/src/content_sao.cpp index a4c9c59f8..e0f230bbc 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" // For g_profiler #include "profiler.h" #include "serialization.h" // For compressZlib +#include "materials.h" // For MaterialProperties +#include "tooldef.h" // ToolDiggingProperties core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; @@ -241,7 +243,7 @@ InventoryItem * ItemSAO::createInventoryItem() } } -void ItemSAO::punch(ServerActiveObject *puncher) +void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { InventoryItem *item = createInventoryItem(); bool fits = puncher->addToInventory(item); @@ -432,7 +434,7 @@ std::string RatSAO::getStaticData() return os.str(); } -void RatSAO::punch(ServerActiveObject *puncher) +void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { std::istringstream is("CraftItem rat 1", std::ios_base::binary); IGameDef *gamedef = m_env->getGameDef(); @@ -687,36 +689,28 @@ std::string Oerkki1SAO::getStaticData() return os.str(); } -void Oerkki1SAO::punch(ServerActiveObject *puncher) +void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { + if(!puncher) + return; + v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); + m_speed_f += dir*12*BS; - std::string toolname = ""; - InventoryItem *item = puncher->getWieldedItem(); - if(item && (std::string)item->getName() == "ToolItem"){ - ToolItem *titem = (ToolItem*)item; - toolname = titem->getToolName(); - } + // "Material" properties of an oerkki + MaterialProperties mp; + mp.diggability = DIGGABLE_NORMAL; + mp.crackiness = -1.0; + mp.cuttability = 1.0; - m_speed_f += dir*12*BS; + ToolDiggingProperties tp; + puncher->getWieldDiggingProperties(&tp); - u16 amount = 5; - /* See tool names in inventory.h */ - if(toolname == "WSword") - amount = 10; - if(toolname == "STSword") - amount = 12; - if(toolname == "SteelSword") - amount = 16; - if(toolname == "STAxe") - amount = 7; - if(toolname == "SteelAxe") - amount = 9; - if(toolname == "SteelPick") - amount = 7; - doDamage(amount); - - puncher->damageWieldedItem(65536/100); + HittingProperties hitprop = getHittingProperties(&mp, &tp, + time_from_last_punch); + + doDamage(hitprop.hp); + puncher->damageWieldedItem(hitprop.wear); } void Oerkki1SAO::doDamage(u16 d) @@ -1365,25 +1359,20 @@ void MobV2SAO::step(float dtime, bool send_recommended) } } -void MobV2SAO::punch(ServerActiveObject *puncher) +void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { + if(!puncher) + return; + v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); - std::string toolname = ""; - InventoryItem *item = puncher->getWieldedItem(); - if(item && (std::string)item->getName() == "ToolItem"){ - ToolItem *titem = (ToolItem*)item; - toolname = titem->getToolName(); - } - // A quick hack; SAO description is player name for player std::string playername = puncher->getDescription(); Map *map = &m_env->getMap(); actionstream<<playername<<" punches mob id="<<m_id - <<" with a \""<<toolname<<"\" at " - <<PP(m_base_position/BS)<<std::endl; + <<" at "<<PP(m_base_position/BS)<<std::endl; m_disturb_timer = 0; m_disturbing_player = playername; @@ -1405,23 +1394,21 @@ void MobV2SAO::punch(ServerActiveObject *puncher) } sendPosition(); - u16 amount = 2; - /* See tool names in inventory.h */ - if(toolname == "WSword") - amount = 4; - if(toolname == "STSword") - amount = 6; - if(toolname == "SteelSword") - amount = 8; - if(toolname == "STAxe") - amount = 3; - if(toolname == "SteelAxe") - amount = 4; - if(toolname == "SteelPick") - amount = 3; - doDamage(amount); - - puncher->damageWieldedItem(65536/100); + + // "Material" properties of the MobV2 + MaterialProperties mp; + mp.diggability = DIGGABLE_NORMAL; + mp.crackiness = -1.0; + mp.cuttability = 1.0; + + ToolDiggingProperties tp; + puncher->getWieldDiggingProperties(&tp); + + HittingProperties hitprop = getHittingProperties(&mp, &tp, + time_from_last_punch); + + doDamage(hitprop.hp); + puncher->damageWieldedItem(hitprop.wear); } bool MobV2SAO::isPeaceful() @@ -1686,7 +1673,7 @@ InventoryItem* LuaEntitySAO::createPickedUpItem() return item; } -void LuaEntitySAO::punch(ServerActiveObject *puncher) +void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { if(!m_registered) return; @@ -1799,96 +1786,3 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) m_messages_out.push_back(aom); } -/* - PlayerSAO -*/ - -// Prototype -PlayerSAO proto_PlayerSAO(NULL, v3f(0,0,0), NULL); - -PlayerSAO::PlayerSAO(ServerEnvironment *env, v3f pos, - ServerRemotePlayer *player): - ServerActiveObject(env, pos), - m_player(player), - m_position_updated(true) -{ - if(m_player) - m_player->setSAO(this); -} - -PlayerSAO::~PlayerSAO() -{ - if(m_player) - m_player->setSAO(NULL); -} - -void PlayerSAO::step(float dtime, bool send_recommended) -{ - if(!m_player) - return; - - if(send_recommended == false) - return; - - if(m_position_updated) - { - m_position_updated = false; - - std::ostringstream os(std::ios::binary); - // command (0 = update position) - writeU8(os, 0); - // pos - writeV3F1000(os, m_player->getPosition()); - // yaw - writeF1000(os, m_player->getYaw()); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); - } -} - -std::string PlayerSAO::getClientInitializationData() -{ - if(!m_player) - return ""; - - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // name - os<<serializeString(m_player->getName()); - // pos - writeV3F1000(os, m_player->getPosition()); - // yaw - writeF1000(os, m_player->getYaw()); - return os.str(); -} - -std::string PlayerSAO::getStaticData() -{ - assert(0); - return ""; -} - -void PlayerSAO::punch(ServerActiveObject *puncher) -{ - infostream<<"TODO: PlayerSAO::punch()"<<std::endl; -} - -void PlayerSAO::setPlayer(ServerRemotePlayer *player) -{ - infostream<<"PlayerSAO id="<<getId()<<" got player \"" - <<(player?player->getName():"(NULL)")<<"\""<<std::endl; - m_player = player; -} - -ServerRemotePlayer* PlayerSAO::getPlayer() -{ - return m_player; -} - -void PlayerSAO::positionUpdated() -{ - m_position_updated = true; -} - diff --git a/src/content_sao.h b/src/content_sao.h index 19b0e74ba..51461bc95 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -50,7 +50,7 @@ public: std::string getClientInitializationData(); std::string getStaticData(); InventoryItem* createInventoryItem(); - void punch(ServerActiveObject *puncher); + void punch(ServerActiveObject *puncher, float time_from_last_punch); float getMinimumSavedMovement(){ return 0.1*BS; } private: std::string m_inventorystring; @@ -70,7 +70,7 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(); std::string getStaticData(); - void punch(ServerActiveObject *puncher); + void punch(ServerActiveObject *puncher, float time_from_last_punch); private: bool m_is_active; IntervalLimiter m_inactive_interval; @@ -96,7 +96,7 @@ public: std::string getClientInitializationData(); std::string getStaticData(); InventoryItem* createPickedUpItem(){return NULL;} - void punch(ServerActiveObject *puncher); + void punch(ServerActiveObject *puncher, float time_from_last_punch); bool isPeaceful(){return false;} private: void doDamage(u16 d); @@ -156,7 +156,7 @@ public: std::string getClientInitializationData(); void step(float dtime, bool send_recommended); InventoryItem* createPickedUpItem(){return NULL;} - void punch(ServerActiveObject *puncher); + void punch(ServerActiveObject *puncher, float time_from_last_punch); bool isPeaceful(); private: void sendPosition(); @@ -210,7 +210,7 @@ public: std::string getClientInitializationData(); std::string getStaticData(); InventoryItem* createPickedUpItem(); - void punch(ServerActiveObject *puncher); + void punch(ServerActiveObject *puncher, float time_from_last_punch); void rightClick(ServerActiveObject *clicker); void setPos(v3f pos); void moveTo(v3f pos, bool continuous); @@ -240,30 +240,5 @@ private: float m_last_sent_move_precision; }; -class ServerRemotePlayer; - -class PlayerSAO : public ServerActiveObject -{ -public: - PlayerSAO(ServerEnvironment *env, v3f pos, - ServerRemotePlayer *player); - ~PlayerSAO(); - u8 getType() const - {return ACTIVEOBJECT_TYPE_PLAYER;} - void step(float dtime, bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - bool isStaticAllowed() const - { return false; } - void punch(ServerActiveObject *puncher); - /* PlayerSAO-specific */ - void setPlayer(ServerRemotePlayer *player); - ServerRemotePlayer* getPlayer(); - void positionUpdated(); -private: - ServerRemotePlayer *m_player; - bool m_position_updated; -}; - #endif diff --git a/src/environment.cpp b/src/environment.cpp index 833ed93c2..17c9ecfff 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -750,7 +750,8 @@ void ServerEnvironment::clearAllObjects() scriptapi_rm_object_reference(m_lua, obj); // Delete active object - delete obj; + if(obj->environmentDeletes()) + delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } @@ -1181,7 +1182,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj) succeeded = false; } - delete obj; + if(obj->environmentDeletes()) + delete obj; return succeeded; } @@ -1296,7 +1298,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, { errorstream<<"ServerEnvironment::addActiveObjectRaw(): " <<"no free ids available"<<std::endl; - delete object; + if(object->environmentDeletes()) + delete object; return 0; } object->setId(new_id); @@ -1309,7 +1312,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, { errorstream<<"ServerEnvironment::addActiveObjectRaw(): " <<"id is not free ("<<object->getId()<<")"<<std::endl; - delete object; + if(object->environmentDeletes()) + delete object; return 0; } /*infostream<<"ServerEnvironment::addActiveObjectRaw(): " @@ -1411,7 +1415,8 @@ void ServerEnvironment::removeRemovedObjects() scriptapi_rm_object_reference(m_lua, obj); // Delete - delete obj; + if(obj->environmentDeletes()) + delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } @@ -1699,7 +1704,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) scriptapi_rm_object_reference(m_lua, obj); // Delete active object - delete obj; + if(obj->environmentDeletes()) + delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } diff --git a/src/materials.cpp b/src/materials.cpp index ed0b00925..3f88f9d45 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -49,34 +49,65 @@ void MaterialProperties::deSerialize(std::istream &is) flammability = readF1000(is); } -DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp, - INodeDefManager *nodemgr) +DiggingProperties getDiggingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp, float time_from_last_punch) { - assert(tp); - const MaterialProperties &mp = nodemgr->get(content).material; - if(mp.diggability == DIGGABLE_NOT) + if(mp->diggability == DIGGABLE_NOT) return DiggingProperties(false, 0, 0); - if(mp.diggability == DIGGABLE_CONSTANT) - return DiggingProperties(true, mp.constant_time, 0); + if(mp->diggability == DIGGABLE_CONSTANT) + return DiggingProperties(true, mp->constant_time, 0); float time = tp->basetime; - time += tp->dt_weight * mp.weight; - time += tp->dt_crackiness * mp.crackiness; - time += tp->dt_crumbliness * mp.crumbliness; - time += tp->dt_cuttability * mp.cuttability; + time += tp->dt_weight * mp->weight; + time += tp->dt_crackiness * mp->crackiness; + time += tp->dt_crumbliness * mp->crumbliness; + time += tp->dt_cuttability * mp->cuttability; if(time < 0.2) time = 0.2; float durability = tp->basedurability; - durability += tp->dd_weight * mp.weight; - durability += tp->dd_crackiness * mp.crackiness; - durability += tp->dd_crumbliness * mp.crumbliness; - durability += tp->dd_cuttability * mp.cuttability; + durability += tp->dd_weight * mp->weight; + durability += tp->dd_crackiness * mp->crackiness; + durability += tp->dd_crumbliness * mp->crumbliness; + durability += tp->dd_cuttability * mp->cuttability; if(durability < 1) durability = 1; + + if(time_from_last_punch < tp->full_punch_interval){ + float f = time_from_last_punch / tp->full_punch_interval; + time /= f; + durability /= f; + } float wear = 1.0 / durability; u16 wear_i = 65535.*wear; return DiggingProperties(true, time, wear_i); } +DiggingProperties getDiggingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp) +{ + return getDiggingProperties(mp, tp, 1000000); +} + +DiggingProperties getDiggingProperties(u16 content, + const ToolDiggingProperties *tp, INodeDefManager *nodemgr) +{ + const MaterialProperties &mp = nodemgr->get(content).material; + return getDiggingProperties(&mp, tp); +} + +HittingProperties getHittingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp, float time_from_last_punch) +{ + DiggingProperties digprop = getDiggingProperties(mp, tp, + time_from_last_punch); + + // If digging time would be 1 second, 2 hearts go in 1 second. + s16 hp = 2.0 * 2.0 / digprop.time + 0.5; + // Wear is the same as for digging a single node + s16 wear = (float)digprop.wear + 0.5; + + return HittingProperties(hp, wear); +} + diff --git a/src/materials.h b/src/materials.h index bcf930581..b25d047be 100644 --- a/src/materials.h +++ b/src/materials.h @@ -74,30 +74,44 @@ struct MaterialProperties struct DiggingProperties { - DiggingProperties(): - diggable(false), - time(0.0), - wear(0) - { - } - DiggingProperties(bool a_diggable, float a_time, u16 a_wear): - diggable(a_diggable), - time(a_time), - wear(a_wear) - { - } bool diggable; // Digging time in seconds float time; // Caused wear u16 wear; + + DiggingProperties(bool a_diggable=false, float a_time=0, u16 a_wear=0): + diggable(a_diggable), + time(a_time), + wear(a_wear) + {} }; struct ToolDiggingProperties; class INodeDefManager; -DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp, - INodeDefManager *nodemgr); +DiggingProperties getDiggingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp, float time_from_last_punch); + +DiggingProperties getDiggingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp); + +DiggingProperties getDiggingProperties(u16 content, + const ToolDiggingProperties *tp, INodeDefManager *nodemgr); + +struct HittingProperties +{ + s16 hp; + s16 wear; + + HittingProperties(s16 hp_=0, s16 wear_=0): + hp(hp_), + wear(wear_) + {} +}; + +HittingProperties getHittingProperties(const MaterialProperties *mp, + const ToolDiggingProperties *tp, float time_from_last_punch); #endif diff --git a/src/player.cpp b/src/player.cpp index 937ca9a3f..882566896 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "gamedef.h" #include "content_sao.h" +#include "tooldef.h" +#include "materials.h" Player::Player(IGameDef *gamedef): touching_ground(false), @@ -188,7 +190,9 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env): m_additional_items(), m_inventory_not_sent(false), m_hp_not_sent(false), - m_sao(NULL) + m_respawn_active(false), + m_is_in_environment(false), + m_position_not_sent(false) { } ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_, @@ -197,7 +201,8 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee ServerActiveObject(env, pos_), m_inventory_not_sent(false), m_hp_not_sent(false), - m_sao(NULL) + m_is_in_environment(false), + m_position_not_sent(false) { setPosition(pos_); peer_id = peer_id_; @@ -206,39 +211,136 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee ServerRemotePlayer::~ServerRemotePlayer() { clearAddToInventoryLater(); - if(m_sao) - m_sao->setPlayer(NULL); } void ServerRemotePlayer::setPosition(const v3f &position) { Player::setPosition(position); ServerActiveObject::setBasePosition(position); - if(m_sao) - m_sao->positionUpdated(); + m_position_not_sent = true; } -void ServerRemotePlayer::setSAO(PlayerSAO *sao) +InventoryItem* ServerRemotePlayer::getWieldedItem() { - infostream<<"ServerRemotePlayer \""<<getName() - <<"\" got sao="<<sao<<std::endl; - m_sao = sao; + InventoryList *list = inventory.getList("main"); + if (list) + return list->getItem(m_selected_item); + return NULL; } -PlayerSAO* ServerRemotePlayer::getSAO() +/* ServerActiveObject interface */ + +void ServerRemotePlayer::addedToEnvironment() { - return m_sao; + assert(!m_is_in_environment); + m_is_in_environment = true; } -/* ServerActiveObject interface */ +void ServerRemotePlayer::removingFromEnvironment() +{ + assert(m_is_in_environment); + m_is_in_environment = false; +} -InventoryItem* ServerRemotePlayer::getWieldedItem() +void ServerRemotePlayer::step(float dtime, bool send_recommended) { - InventoryList *list = inventory.getList("main"); - if (list) - return list->getItem(m_selected_item); - return NULL; + if(send_recommended == false) + return; + + if(m_position_not_sent) + { + m_position_not_sent = false; + + std::ostringstream os(std::ios::binary); + // command (0 = update position) + writeU8(os, 0); + // pos + writeV3F1000(os, getPosition()); + // yaw + writeF1000(os, getYaw()); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } +} + +std::string ServerRemotePlayer::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // name + os<<serializeString(getName()); + // pos + writeV3F1000(os, getPosition()); + // yaw + writeF1000(os, getYaw()); + return os.str(); +} + +std::string ServerRemotePlayer::getStaticData() +{ + assert(0); + return ""; +} + +void ServerRemotePlayer::punch(ServerActiveObject *puncher, + float time_from_last_punch) +{ + if(!puncher) + return; + + // "Material" properties of a player + MaterialProperties mp; + mp.diggability = DIGGABLE_NORMAL; + mp.crackiness = -1.0; + mp.cuttability = 1.0; + + ToolDiggingProperties tp; + puncher->getWieldDiggingProperties(&tp); + + HittingProperties hitprop = getHittingProperties(&mp, &tp, + time_from_last_punch); + + infostream<<"1. getHP()="<<getHP()<<std::endl; + setHP(getHP() - hitprop.hp); + infostream<<"2. getHP()="<<getHP()<<std::endl; + puncher->damageWieldedItem(hitprop.wear); +} + +void ServerRemotePlayer::rightClick(ServerActiveObject *clicker) +{ +} + +void ServerRemotePlayer::setPos(v3f pos) +{ + setPosition(pos); + // Movement caused by this command is always valid + m_last_good_position = pos; + m_last_good_position_age = 0; +} +void ServerRemotePlayer::moveTo(v3f pos, bool continuous) +{ + setPosition(pos); + // Movement caused by this command is always valid + m_last_good_position = pos; + m_last_good_position_age = 0; +} + +void ServerRemotePlayer::getWieldDiggingProperties(ToolDiggingProperties *dst) +{ + IGameDef *gamedef = m_env->getGameDef(); + IToolDefManager *tdef = gamedef->tdef(); + + InventoryItem *item = getWieldedItem(); + if(item == NULL || std::string(item->getName()) != "ToolItem"){ + *dst = ToolDiggingProperties(); + return; + } + ToolItem *titem = (ToolItem*)item; + *dst = tdef->getDiggingProperties(titem->getToolName()); } + void ServerRemotePlayer::damageWieldedItem(u16 amount) { infostream<<"Damaging "<<getName()<<"'s wielded item for amount=" @@ -332,13 +434,12 @@ void ServerRemotePlayer::setHP(s16 hp_) { s16 oldhp = hp; - hp = hp_; - // FIXME: don't hardcode maximum HP, make configurable per object - if(hp < 0) - hp = 0; - else if(hp > 20) - hp = 20; + if(hp_ < 0) + hp_ = 0; + else if(hp_ > 20) + hp_ = 20; + hp = hp_; if(hp != oldhp) m_hp_not_sent = true; @@ -348,129 +449,6 @@ s16 ServerRemotePlayer::getHP() return hp; } -/* - RemotePlayer -*/ - -#ifndef SERVER - -#if 0 -RemotePlayer::RemotePlayer( - IGameDef *gamedef, - scene::ISceneNode* parent, - IrrlichtDevice *device, - s32 id): - Player(gamedef), - scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id), - m_text(NULL) -{ - m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2); - - if(parent != NULL && device != NULL) - { - // ISceneNode stores a member called SceneManager - scene::ISceneManager* mgr = SceneManager; - video::IVideoDriver* driver = mgr->getVideoDriver(); - gui::IGUIEnvironment* gui = device->getGUIEnvironment(); - - // Add a text node for showing the name - wchar_t wname[1] = {0}; - m_text = mgr->addTextSceneNode(gui->getBuiltInFont(), - wname, video::SColor(255,255,255,255), this); - m_text->setPosition(v3f(0, (f32)BS*2.1, 0)); - - // Attach a simple mesh to the player for showing an image - scene::SMesh *mesh = new scene::SMesh(); - { // Front - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - } - { // Back - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - } - m_node = mgr->addMeshSceneNode(mesh, this); - mesh->drop(); - m_node->setPosition(v3f(0,0,0)); - } -} - -RemotePlayer::~RemotePlayer() -{ - if(SceneManager != NULL) - ISceneNode::remove(); -} - -void RemotePlayer::updateName(const char *name) -{ - Player::updateName(name); - if(m_text != NULL) - { - wchar_t wname[PLAYERNAME_SIZE]; - mbstowcs(wname, m_name, strlen(m_name)+1); - m_text->setText(wname); - } -} - -void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d) -{ - m_pos_animation_time_counter += dtime; - m_pos_animation_counter += dtime; - v3f movevector = m_position - m_oldpos; - f32 moveratio; - if(m_pos_animation_time < 0.001) - moveratio = 1.0; - else - moveratio = m_pos_animation_counter / m_pos_animation_time; - if(moveratio > 1.5) - moveratio = 1.5; - m_showpos = m_oldpos + movevector * moveratio; - - ISceneNode::setPosition(m_showpos); -} -#endif - -#endif - #ifndef SERVER /* LocalPlayer diff --git a/src/player.h b/src/player.h index 34fb5128c..c9dbe76bb 100644 --- a/src/player.h +++ b/src/player.h @@ -201,32 +201,34 @@ public: virtual void setPosition(const v3f &position); - void setSAO(PlayerSAO *sao); - PlayerSAO* getSAO(); - + // Returns a reference + virtual InventoryItem* getWieldedItem(); + /* ServerActiveObject interface */ u8 getType() const {return ACTIVEOBJECT_TYPE_PLAYER;} - virtual void setPos(v3f pos) - { - setPosition(pos); - // Movement caused by this command is always valid - m_last_good_position = pos; - m_last_good_position_age = 0; - } - virtual void moveTo(v3f pos, bool continuous) - { - setPosition(pos); - // Movement caused by this command is always valid - m_last_good_position = pos; - m_last_good_position_age = 0; - } + // Called after id has been set and has been inserted in environment + void addedToEnvironment(); + // Called before removing from environment + void removingFromEnvironment(); + bool environmentDeletes() const + { return false; } + bool isStaticAllowed() const + { return false; } + + void step(float dtime, bool send_recommended); + std::string getClientInitializationData(); + std::string getStaticData(); + void punch(ServerActiveObject *puncher, float time_from_last_punch); + void rightClick(ServerActiveObject *clicker); + void setPos(v3f pos); + void moveTo(v3f pos, bool continuous); virtual std::string getDescription(){return getName();} - // Returns a reference - virtual InventoryItem* getWieldedItem(); + + virtual void getWieldDiggingProperties(ToolDiggingProperties *dst); virtual void damageWieldedItem(u16 amount); // If all fits, eats item and returns true. Otherwise returns false. virtual bool addToInventory(InventoryItem *item); @@ -241,111 +243,14 @@ public: std::vector<InventoryItem*> m_additional_items; bool m_inventory_not_sent; bool m_hp_not_sent; + bool m_respawn_active; private: - - PlayerSAO *m_sao; + bool m_is_in_environment; + bool m_position_not_sent; }; #ifndef SERVER - -#if 0 -/* - All the other players on the client are these -*/ - -class RemotePlayer : public Player, public scene::ISceneNode -{ -public: - RemotePlayer( - IGameDef *gamedef, - scene::ISceneNode* parent=NULL, - IrrlichtDevice *device=NULL, - s32 id=0); - - virtual ~RemotePlayer(); - - /* - ISceneNode methods - */ - - virtual void OnRegisterSceneNode() - { - if (IsVisible) - SceneManager->registerNodeForRendering(this); - - ISceneNode::OnRegisterSceneNode(); - } - - virtual void render() - { - // Do nothing - } - - virtual const core::aabbox3d<f32>& getBoundingBox() const - { - return m_box; - } - - void setPosition(const v3f &position) - { - m_oldpos = m_showpos; - - if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0) - m_pos_animation_time = m_pos_animation_time_counter; - else - m_pos_animation_time = m_pos_animation_time * 0.9 - + m_pos_animation_time_counter * 0.1; - m_pos_animation_time_counter = 0; - m_pos_animation_counter = 0; - - Player::setPosition(position); - //ISceneNode::setPosition(position); - } - - virtual void setYaw(f32 yaw) - { - Player::setYaw(yaw); - ISceneNode::setRotation(v3f(0, -yaw, 0)); - } - - bool isLocal() const - { - return false; - } - - void updateName(const char *name); - - virtual void updateLight(u8 light_at_pos) - { - Player::updateLight(light_at_pos); - - if(m_node == NULL) - return; - - u8 li = decode_light(light_at_pos); - video::SColor color(255,li,li,li); - setMeshVerticesColor(m_node->getMesh(), color); - } - - void move(f32 dtime, Map &map, f32 pos_max_d); - -private: - scene::IMeshSceneNode *m_node; - scene::ITextSceneNode* m_text; - core::aabbox3d<f32> m_box; - - v3f m_oldpos; - f32 m_pos_animation_counter; - f32 m_pos_animation_time; - f32 m_pos_animation_time_counter; - v3f m_showpos; -}; -#endif - -#endif // !SERVER - -#ifndef SERVER struct PlayerControl { PlayerControl() diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index a87e7eabf..40e31bb9f 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -386,6 +386,15 @@ static int getenumfield(lua_State *L, int table, return result; } +static void setfloatfield(lua_State *L, int table, + const char *fieldname, float value) +{ + lua_pushnumber(L, value); + if(table < 0) + table -= 1; + lua_setfield(L, table, fieldname); +} + /* Inventory stuff */ @@ -456,6 +465,71 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name, } /* + ToolDiggingProperties +*/ + +static ToolDiggingProperties read_tool_digging_properties( + lua_State *L, int table) +{ + ToolDiggingProperties prop; + getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); + getfloatfield(L, table, "basetime", prop.basetime); + getfloatfield(L, table, "dt_weight", prop.dt_weight); + getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); + getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); + getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); + getfloatfield(L, table, "basedurability", prop.basedurability); + getfloatfield(L, table, "dd_weight", prop.dd_weight); + getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); + getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); + getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); + return prop; +} + +static void set_tool_digging_properties(lua_State *L, int table, + const ToolDiggingProperties &prop) +{ + setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); + setfloatfield(L, table, "basetime", prop.basetime); + setfloatfield(L, table, "dt_weight", prop.dt_weight); + setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); + setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); + setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); + setfloatfield(L, table, "basedurability", prop.basedurability); + setfloatfield(L, table, "dd_weight", prop.dd_weight); + setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); + setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); + setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); +} + +static void push_tool_digging_properties(lua_State *L, + const ToolDiggingProperties &prop) +{ + lua_newtable(L); + set_tool_digging_properties(L, -1, prop); +} + +/* + ToolDefinition +*/ + +static ToolDefinition read_tool_definition(lua_State *L, int table) +{ + ToolDefinition def; + getstringfield(L, table, "image", def.imagename); + def.properties = read_tool_digging_properties(L, table); + return def; +} + +static void push_tool_definition(lua_State *L, const ToolDefinition &def) +{ + lua_newtable(L); + lua_pushstring(L, def.imagename.c_str()); + lua_setfield(L, -2, "image"); + set_tool_digging_properties(L, -1, def.properties); +} + +/* EnumString definitions */ @@ -672,19 +746,7 @@ static int l_register_tool(lua_State *L) IWritableToolDefManager *tooldef = server->getWritableToolDefManager(); - ToolDefinition def; - - getstringfield(L, table, "image", def.imagename); - getfloatfield(L, table, "basetime", def.properties.basetime); - getfloatfield(L, table, "dt_weight", def.properties.dt_weight); - getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness); - getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness); - getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability); - getfloatfield(L, table, "basedurability", def.properties.basedurability); - getfloatfield(L, table, "dd_weight", def.properties.dd_weight); - getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness); - getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness); - getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability); + ToolDefinition def = read_tool_definition(L, table); tooldef->registerTool(name, def); return 0; /* number of results */ @@ -1588,9 +1650,7 @@ private: return NULL; if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) return NULL; - PlayerSAO *player_sao = static_cast<PlayerSAO*>(obj); - return player_sao->getPlayer(); - //return static_cast<ServerRemotePlayer*>(obj); + return static_cast<ServerRemotePlayer*>(obj); } // Exported functions @@ -1690,65 +1750,16 @@ private: return 0; } - // get_wielded_itemstring(self) - static int l_get_wielded_itemstring(lua_State *L) + // get_wield_digging_properties(self) + static int l_get_wield_digging_properties(lua_State *L) { ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; // Do it - InventoryItem *item = co->getWieldedItem(); - if(item == NULL){ - lua_pushnil(L); - return 1; - } - lua_pushstring(L, item->getItemString().c_str()); - return 1; - } - - // get_wielded_item(self) - static int l_get_wielded_item(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - InventoryItem *item0 = co->getWieldedItem(); - if(item0 == NULL){ - lua_pushnil(L); - return 1; - } - if(std::string("MaterialItem") == item0->getName()){ - MaterialItem *item = (MaterialItem*)item0; - lua_newtable(L); - lua_pushstring(L, "NodeItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getNodeName().c_str()); - lua_setfield(L, -2, "name"); - } - else if(std::string("CraftItem") == item0->getName()){ - CraftItem *item = (CraftItem*)item0; - lua_newtable(L); - lua_pushstring(L, "CraftItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getSubName().c_str()); - lua_setfield(L, -2, "name"); - } - else if(std::string("ToolItem") == item0->getName()){ - ToolItem *item = (ToolItem*)item0; - lua_newtable(L); - lua_pushstring(L, "ToolItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getToolName().c_str()); - lua_setfield(L, -2, "name"); - lua_pushstring(L, itos(item->getWear()).c_str()); - lua_setfield(L, -2, "wear"); - } - else{ - errorstream<<"l_get_wielded_item: Unknown item name: \"" - <<item0->getName()<<"\""<<std::endl; - lua_pushnil(L); - } + ToolDiggingProperties prop; + co->getWieldDiggingProperties(&prop); + push_tool_digging_properties(L, prop); return 1; } @@ -1976,6 +1987,68 @@ private: return 1; } + // get_wielded_itemstring(self) + static int l_get_wielded_itemstring(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + InventoryItem *item = player->getWieldedItem(); + if(item == NULL){ + lua_pushnil(L); + return 1; + } + lua_pushstring(L, item->getItemString().c_str()); + return 1; + } + + // get_wielded_item(self) + static int l_get_wielded_item(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + InventoryItem *item0 = player->getWieldedItem(); + if(item0 == NULL){ + lua_pushnil(L); + return 1; + } + if(std::string("MaterialItem") == item0->getName()){ + MaterialItem *item = (MaterialItem*)item0; + lua_newtable(L); + lua_pushstring(L, "NodeItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getNodeName().c_str()); + lua_setfield(L, -2, "name"); + } + else if(std::string("CraftItem") == item0->getName()){ + CraftItem *item = (CraftItem*)item0; + lua_newtable(L); + lua_pushstring(L, "CraftItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getSubName().c_str()); + lua_setfield(L, -2, "name"); + } + else if(std::string("ToolItem") == item0->getName()){ + ToolItem *item = (ToolItem*)item0; + lua_newtable(L); + lua_pushstring(L, "ToolItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getToolName().c_str()); + lua_setfield(L, -2, "name"); + lua_pushstring(L, itos(item->getWear()).c_str()); + lua_setfield(L, -2, "wear"); + } + else{ + errorstream<<"l_get_wielded_item: Unknown item name: \"" + <<item0->getName()<<"\""<<std::endl; + lua_pushnil(L); + } + return 1; + } + public: ObjectRef(ServerActiveObject *object): m_object(object) @@ -2046,8 +2119,7 @@ const luaL_reg ObjectRef::methods[] = { method(ObjectRef, moveto), method(ObjectRef, punch), method(ObjectRef, right_click), - method(ObjectRef, get_wielded_itemstring), - method(ObjectRef, get_wielded_item), + method(ObjectRef, get_wield_digging_properties), method(ObjectRef, damage_wielded_item), method(ObjectRef, add_to_inventory), method(ObjectRef, add_to_inventory_later), @@ -2063,6 +2135,8 @@ const luaL_reg ObjectRef::methods[] = { method(ObjectRef, get_player_name), method(ObjectRef, inventory_set_list), method(ObjectRef, inventory_get_list), + method(ObjectRef, get_wielded_itemstring), + method(ObjectRef, get_wielded_item), {0,0} }; diff --git a/src/server.cpp b/src/server.cpp index eebf96901..2dceb805b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1432,6 +1432,11 @@ void Server::AsyncRunStep() } /* + Handle player HPs + */ + HandlePlayerHP(player, 0); + + /* Send player inventories and HPs if necessary */ if(player->m_inventory_not_sent){ @@ -2230,8 +2235,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // Add PlayerSAO - PlayerSAO *sao = new PlayerSAO(m_env, player->getPosition(), player); - m_env->addActiveObject(sao); + player->m_removed = false; + m_env->addActiveObject(player); /* Answer with a TOCLIENT_INIT @@ -2983,6 +2988,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) actionstream<<player->getName()<<" respawns at " <<PP(player->getPosition()/BS)<<std::endl; + + srp->m_removed = false; + m_env->addActiveObject(srp); } else if(command == TOSERVER_INTERACT) { @@ -4523,6 +4531,11 @@ void Server::SendTextures(u16 peer_id) void Server::HandlePlayerHP(Player *player, s16 damage) { + ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player); + + if(srp->m_respawn_active) + return; + if(player->hp > damage) { player->hp -= damage; @@ -4549,6 +4562,8 @@ void Server::HandlePlayerHP(Player *player, s16 damage) if(client->net_proto_version >= 3) { SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0)); + srp->m_removed = true; + srp->m_respawn_active = true; } else { @@ -4561,6 +4576,7 @@ void Server::RespawnPlayer(Player *player) { player->hp = 20; ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player); + srp->m_respawn_active = false; bool repositioned = scriptapi_on_respawnplayer(m_lua, srp); if(!repositioned){ v3f pos = findSpawnPos(m_env->getServerMap()); @@ -4983,16 +4999,9 @@ void Server::handlePeerChange(PeerChange &c) } } - // Remove PlayerSAO + // Remove from environment if(player != NULL) - { - PlayerSAO *sao = player->getSAO(); - if(sao){ - sao->setPlayer(NULL); - sao->m_removed = true; - } - player->setSAO(NULL); - } + player->m_removed = true; // Set player client disconnected if(player != NULL) diff --git a/src/serverobject.cpp b/src/serverobject.cpp index 344ae406a..ca3d2c3b9 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include <fstream> #include "inventory.h" +#include "tooldef.h" ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos): ActiveObject(0), @@ -66,5 +67,10 @@ void ServerActiveObject::registerType(u16 type, Factory f) m_types.insert(type, f); } +void ServerActiveObject::getWieldDiggingProperties(ToolDiggingProperties *dst) +{ + *dst = ToolDiggingProperties(); +} + diff --git a/src/serverobject.h b/src/serverobject.h index 4dac46863..1386136ce 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -43,6 +43,7 @@ Some planning class ServerEnvironment; class InventoryItem; class Player; +struct ToolDiggingProperties; class ServerActiveObject : public ActiveObject { @@ -128,23 +129,24 @@ public: virtual bool isStaticAllowed() const {return true;} - virtual void punch(ServerActiveObject *puncher){} - virtual void rightClick(ServerActiveObject *clicker){} - - // Returns a reference - virtual InventoryItem* getWieldedItem() - { return NULL; } + // time_from_last_punch is used for lessening damage if punching fast + virtual void punch(ServerActiveObject *puncher, + float time_from_last_punch=1000000) + {} + virtual void rightClick(ServerActiveObject *clicker) + {} + virtual void getWieldDiggingProperties(ToolDiggingProperties *dst); virtual void damageWieldedItem(u16 amount) - {} + {} // If all fits, eats item and returns true. Otherwise returns false. virtual bool addToInventory(InventoryItem *item) - {return false;} + { return false; } virtual void addToInventoryLater(InventoryItem *item) - {} + {} virtual void setHP(s16 hp) - {} + {} virtual s16 getHP() - {return 0;} + { return 0; } /* Number of players which know about this object. Object won't be diff --git a/src/tooldef.cpp b/src/tooldef.cpp index 1284a52ab..45193f46b 100644 --- a/src/tooldef.cpp +++ b/src/tooldef.cpp @@ -23,9 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <sstream> #include "utility.h" -ToolDiggingProperties::ToolDiggingProperties( +ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_, float a, float b, float c, float d, float e, float f, float g, float h, float i, float j): + full_punch_interval(full_punch_interval_), basetime(a), dt_weight(b), dt_crackiness(c), @@ -60,6 +61,7 @@ void ToolDefinition::serialize(std::ostream &os) writeF1000(os, properties.dd_crackiness); writeF1000(os, properties.dd_crumbliness); writeF1000(os, properties.dd_cuttability); + writeF1000(os, properties.full_punch_interval); } void ToolDefinition::deSerialize(std::istream &is) @@ -78,6 +80,9 @@ void ToolDefinition::deSerialize(std::istream &is) properties.dd_crackiness = readF1000(is); properties.dd_crumbliness = readF1000(is); properties.dd_cuttability = readF1000(is); + try{ + properties.full_punch_interval = readF1000(is); + }catch(SerializationError &e){} // Temporary for 0.4.dev } class CToolDefManager: public IWritableToolDefManager diff --git a/src/tooldef.h b/src/tooldef.h index 9741d7088..aa4cb6931 100644 --- a/src/tooldef.h +++ b/src/tooldef.h @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., struct ToolDiggingProperties { // time = basetime + sum(feature here * feature in MaterialProperties) + float full_punch_interval; float basetime; float dt_weight; float dt_crackiness; @@ -37,7 +38,7 @@ struct ToolDiggingProperties float dd_crumbliness; float dd_cuttability; - ToolDiggingProperties( + ToolDiggingProperties(float full_punch_interval_=1.0, float a=0.75, float b=0, float c=0, float d=0, float e=0, float f=50, float g=0, float h=0, float i=0, float j=0); }; |