X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcontent_sao.cpp;h=5b0dc3eb4739649f53b987f540f5fb5919e6ea65;hb=18350ad37fbfb7027f2ab82ead5be58c1435cdf0;hp=02a4eb1eb14d98b6722db38ae6e4a7329497db54;hpb=8db89b8136686a5721080d18e8a14f03404aa095;p=minetest.git diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 02a4eb1eb..5b0dc3eb4 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -26,6 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" // For compressZlib #include "tool.h" // For ToolCapabilities #include "gamedef.h" +#include "player.h" +#include "scriptapi.h" +#include "genericobject.h" core::map ServerActiveObject::m_types; @@ -333,7 +336,6 @@ ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, LuaEntitySAO */ -#include "scriptapi.h" #include "luaentity_common.h" // Prototype (registers item for deserialization) @@ -350,6 +352,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, m_velocity(0,0,0), m_acceleration(0,0,0), m_yaw(0), + m_properties_sent(true), m_last_sent_yaw(0), m_last_sent_position(0,0,0), m_last_sent_velocity(0,0,0), @@ -381,42 +384,45 @@ void LuaEntitySAO::addedToEnvironment() { ServerActiveObject::addedToEnvironment(); - // Create entity from name and state + // Create entity from name lua_State *L = m_env->getLua(); - m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(), - m_init_state.c_str()); + m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str()); if(m_registered){ // Get properties scriptapi_luaentity_get_properties(L, m_id, m_prop); + // Initialize HP from properties + m_hp = m_prop->hp_max; } + + // Activate entity, supplying serialized state + scriptapi_luaentity_activate(L, m_id, m_init_state.c_str()); } ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { - std::istringstream is(data, std::ios::binary); - // read version - u8 version = readU8(is); std::string name; std::string state; s16 hp = 1; v3f velocity; float yaw = 0; - // check if version is supported - if(version == 0){ - name = deSerializeString(is); - state = deSerializeLongString(is); - } - else if(version == 1){ - name = deSerializeString(is); - state = deSerializeLongString(is); - hp = readS16(is); - velocity = readV3F1000(is); - yaw = readF1000(is); - } - else{ - return NULL; + if(data != ""){ + std::istringstream is(data, std::ios::binary); + // read version + u8 version = readU8(is); + // check if version is supported + if(version == 0){ + name = deSerializeString(is); + state = deSerializeLongString(is); + } + else if(version == 1){ + name = deSerializeString(is); + state = deSerializeLongString(is); + hp = readS16(is); + velocity = readV3F1000(is); + yaw = readF1000(is); + } } // create object infostream<<"LuaEntitySAO::create(name=\""<physical){ @@ -479,16 +494,10 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) if(m_armor_groups_sent == false){ m_armor_groups_sent = true; - std::ostringstream os(std::ios::binary); - writeU8(os, LUAENTITY_CMD_UPDATE_ARMOR_GROUPS); - writeU16(os, m_armor_groups.size()); - for(ItemGroupList::const_iterator i = m_armor_groups.begin(); - i != m_armor_groups.end(); i++){ - os<first); - writeS16(os, i->second); - } + std::string str = gob_cmd_update_armor_groups( + m_armor_groups); // create message and add to list - ActiveObjectMessage aom(getId(), true, os.str()); + ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } } @@ -496,25 +505,26 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string LuaEntitySAO::getClientInitializationData() { std::ostringstream os(std::ios::binary); - // version - writeU8(os, 1); - // pos + writeU8(os, 0); // version + os<serialize(prop_os); - os<initial_sprite_basepos, + 1, 1.0, false + )); // return result return os.str(); } std::string LuaEntitySAO::getStaticData() { - infostream<<__FUNCTION_NAME<getDescription()<<", damage "<getLua(); @@ -598,17 +605,6 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker) scriptapi_luaentity_rightclick(L, m_id, clicker); } -void LuaEntitySAO::setHP(s16 hp) -{ - if(hp < 0) hp = 0; - m_hp = hp; -} - -s16 LuaEntitySAO::getHP() -{ - return m_hp; -} - void LuaEntitySAO::setPos(v3f pos) { m_base_position = pos; @@ -635,7 +631,24 @@ std::string LuaEntitySAO::getDescription() os<<(m_base_position.Y/BS)<<","; os<<(m_base_position.Z/BS); os<<")"; - return std::string("LuaEntitySAO"); + return os.str(); +} + +void LuaEntitySAO::setHP(s16 hp) +{ + if(hp < 0) hp = 0; + m_hp = hp; +} + +s16 LuaEntitySAO::getHP() const +{ + return m_hp; +} + +void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups) +{ + m_armor_groups = armor_groups; + m_armor_groups_sent = false; } void LuaEntitySAO::setVelocity(v3f velocity) @@ -670,29 +683,23 @@ float LuaEntitySAO::getYaw() void LuaEntitySAO::setTextureMod(const std::string &mod) { - std::ostringstream os(std::ios::binary); - // command - writeU8(os, LUAENTITY_CMD_SET_TEXTURE_MOD); - // parameters - os<hp_max, + m_prop->physical, + m_prop->weight, + m_prop->collisionbox, + m_prop->visual, + m_prop->visual_size, + m_prop->textures, + m_prop->spritediv, + true, // is_visible + false // makes_footstep_sound + ); } void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) @@ -719,27 +736,391 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) float update_interval = m_env->getSendRecommendedInterval(); + std::string str = gob_cmd_update_position( + m_base_position, + m_velocity, + m_acceleration, + m_yaw, + do_interpolate, + is_movement_end, + update_interval + ); + // create message and add to list + ActiveObjectMessage aom(getId(), false, str); +} + +/* + PlayerSAO +*/ + +// No prototype, PlayerSAO does not need to be deserialized + +PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_): + ServerActiveObject(env_, v3f(0,0,0)), + m_player(player_), + m_peer_id(peer_id_), + m_inventory(NULL), + m_last_good_position(0,0,0), + m_last_good_position_age(0), + m_time_from_last_punch(0), + m_wield_index(0), + m_position_not_sent(false), + m_armor_groups_sent(false), + m_properties_sent(true), + m_teleported(false), + m_inventory_not_sent(false), + m_hp_not_sent(false), + m_wielded_item_not_sent(false) +{ + assert(m_player); + assert(m_peer_id != 0); + setBasePosition(m_player->getPosition()); + m_inventory = &m_player->inventory; + m_armor_groups["choppy"] = 2; + m_armor_groups["fleshy"] = 3; +} + +PlayerSAO::~PlayerSAO() +{ + if(m_inventory != &m_player->inventory) + delete m_inventory; + +} + +std::string PlayerSAO::getDescription() +{ + return std::string("player ") + m_player->getName(); +} + +// Called after id has been set and has been inserted in environment +void PlayerSAO::addedToEnvironment() +{ + ServerActiveObject::addedToEnvironment(); + ServerActiveObject::setBasePosition(m_player->getPosition()); + m_player->setPlayerSAO(this); + m_player->peer_id = m_peer_id; + m_last_good_position = m_player->getPosition(); + m_last_good_position_age = 0.0; +} + +// Called before removing from environment +void PlayerSAO::removingFromEnvironment() +{ + ServerActiveObject::removingFromEnvironment(); + if(m_player->getPlayerSAO() == this) + { + m_player->setPlayerSAO(NULL); + m_player->peer_id = 0; + } +} + +bool PlayerSAO::isStaticAllowed() const +{ + return false; +} + +bool PlayerSAO::unlimitedTransferDistance() const +{ + return g_settings->getBool("unlimited_player_transfer_distance"); +} + +std::string PlayerSAO::getClientInitializationData() +{ std::ostringstream os(std::ios::binary); - // command - writeU8(os, LUAENTITY_CMD_UPDATE_POSITION); + writeU8(os, 0); // version + os<getName()); // name + writeU8(os, 1); // is_player + writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); + writeF1000(os, m_player->getYaw()); + writeS16(os, getHP()); + writeU8(os, 2); // number of messages stuffed in here + os<= 1.0){ + float age = m_last_good_position_age; + v3f diff = (m_player->getPosition() - m_last_good_position); + float d_vert = diff.Y; + diff.Y = 0; + float d_horiz = diff.getLength(); + /*infostream<getName()<<"'s horizontal speed is " + <<(d_horiz/age)<getPosition(); + } else { + actionstream<<"Player "<getName() + <<" moved too fast; resetting position" + <setPosition(m_last_good_position); + m_teleported = true; + } + m_last_good_position_age = 0; + } + + if(send_recommended == false) + return; + + if(m_position_not_sent) + { + m_position_not_sent = false; + float update_interval = m_env->getSendRecommendedInterval(); + std::string str = gob_cmd_update_position( + m_player->getPosition() + v3f(0,BS*1,0), + v3f(0,0,0), + v3f(0,0,0), + m_player->getYaw(), + true, + false, + update_interval + ); + // create message and add to list + ActiveObjectMessage aom(getId(), false, str); + m_messages_out.push_back(aom); + } + + if(m_wielded_item_not_sent) + { + m_wielded_item_not_sent = false; + // GenericCAO has no special way to show this + } + + if(m_armor_groups_sent == false){ + m_armor_groups_sent = true; + std::string str = gob_cmd_update_armor_groups( + m_armor_groups); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push_back(aom); + } +} + +void PlayerSAO::setBasePosition(const v3f &position) +{ + ServerActiveObject::setBasePosition(position); + m_position_not_sent = true; +} + +void PlayerSAO::setPos(v3f pos) +{ + m_player->setPosition(pos); + // Movement caused by this command is always valid + m_last_good_position = pos; + m_last_good_position_age = 0; + // Force position change on client + m_teleported = true; +} + +void PlayerSAO::moveTo(v3f pos, bool continuous) +{ + m_player->setPosition(pos); + // Movement caused by this command is always valid + m_last_good_position = pos; + m_last_good_position_age = 0; + // Force position change on client + m_teleported = true; +} + +int PlayerSAO::punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, + float time_from_last_punch) +{ + if(!toolcap) + return 0; + + // No effect if PvP disabled + if(g_settings->getBool("enable_pvp") == false){ + if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER){ + std::string str = gob_cmd_punched(0, getHP()); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push_back(aom); + return 0; + } + } + + HitParams hitparams = getHitParams(m_armor_groups, toolcap, + time_from_last_punch); + + actionstream<<"Player "<getName()<<" punched by " + <getDescription()<<", damage "<hp; +} + +void PlayerSAO::setHP(s16 hp) +{ + s16 oldhp = m_player->hp; + + if(hp < 0) + hp = 0; + else if(hp > PLAYER_MAX_HP) + hp = PLAYER_MAX_HP; + + if(hp < oldhp && g_settings->getBool("enable_damage") == false) + { + m_hp_not_sent = true; // fix wrong prediction on client + return; + } + + m_player->hp = hp; + + if(hp != oldhp) + m_hp_not_sent = true; + + // On death or reincarnation send an active object message + if((hp == 0) != (oldhp == 0)) + { + // Will send new is_visible value based on (getHP()!=0) + m_properties_sent = false; + // Send new HP + std::string str = gob_cmd_punched(0, getHP()); + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push_back(aom); + } +} + +void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups) +{ + m_armor_groups = armor_groups; + m_armor_groups_sent = false; +} + +Inventory* PlayerSAO::getInventory() +{ + return m_inventory; +} +const Inventory* PlayerSAO::getInventory() const +{ + return m_inventory; +} + +InventoryLocation PlayerSAO::getInventoryLocation() const +{ + InventoryLocation loc; + loc.setPlayer(m_player->getName()); + return loc; +} + +void PlayerSAO::setInventoryModified() +{ + m_inventory_not_sent = true; +} + +std::string PlayerSAO::getWieldList() const +{ + return "main"; +} + +int PlayerSAO::getWieldIndex() const +{ + return m_wield_index; +} + +void PlayerSAO::setWieldIndex(int i) +{ + if(i != m_wield_index) + { + m_wield_index = i; + m_wielded_item_not_sent = true; + } +} + +void PlayerSAO::disconnected() +{ + m_peer_id = 0; + m_removed = true; + if(m_player->getPlayerSAO() == this) + { + m_player->setPlayerSAO(NULL); + m_player->peer_id = 0; + } +} + +void PlayerSAO::createCreativeInventory() +{ + if(m_inventory != &m_player->inventory) + delete m_inventory; + + m_inventory = new Inventory(m_player->inventory); + m_inventory->clearContents(); + scriptapi_get_creative_inventory(m_env->getLua(), this); +} + +std::string PlayerSAO::getPropertyPacket() +{ + core::array textures; + textures.push_back("player.png"); + textures.push_back("player_back.png"); + return gob_cmd_set_properties( + PLAYER_MAX_HP, + false, + 75, + core::aabbox3d(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.), + "upright_sprite", + v2f(1, 2), + textures, + v2s16(1,1), + (getHP() != 0), // is_visible + true // makes_footstep_sound + ); }