diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/activeobjectmgr.cpp | 15 | ||||
-rw-r--r-- | src/server/activeobjectmgr.h | 3 | ||||
-rw-r--r-- | src/server/luaentity_sao.cpp | 56 | ||||
-rw-r--r-- | src/server/luaentity_sao.h | 6 | ||||
-rw-r--r-- | src/server/mods.cpp | 13 | ||||
-rw-r--r-- | src/server/mods.h | 8 | ||||
-rw-r--r-- | src/server/player_sao.cpp | 55 | ||||
-rw-r--r-- | src/server/player_sao.h | 4 | ||||
-rw-r--r-- | src/server/serveractiveobject.cpp | 18 | ||||
-rw-r--r-- | src/server/serveractiveobject.h | 62 | ||||
-rw-r--r-- | src/server/unit_sao.cpp | 23 | ||||
-rw-r--r-- | src/server/unit_sao.h | 5 |
12 files changed, 181 insertions, 87 deletions
diff --git a/src/server/activeobjectmgr.cpp b/src/server/activeobjectmgr.cpp index 1b8e31409..acd6611f4 100644 --- a/src/server/activeobjectmgr.cpp +++ b/src/server/activeobjectmgr.cpp @@ -127,6 +127,21 @@ void ActiveObjectMgr::getObjectsInsideRadius(const v3f &pos, float radius, } } +void ActiveObjectMgr::getObjectsInArea(const aabb3f &box, + std::vector<ServerActiveObject *> &result, + std::function<bool(ServerActiveObject *obj)> include_obj_cb) +{ + for (auto &activeObject : m_active_objects) { + ServerActiveObject *obj = activeObject.second; + const v3f &objectpos = obj->getBasePosition(); + if (!box.isPointInside(objectpos)) + continue; + + if (!include_obj_cb || include_obj_cb(obj)) + result.push_back(obj); + } +} + void ActiveObjectMgr::getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius, f32 player_radius, std::set<u16> ¤t_objects, std::queue<u16> &added_objects) diff --git a/src/server/activeobjectmgr.h b/src/server/activeobjectmgr.h index bc2085499..d43f5643c 100644 --- a/src/server/activeobjectmgr.h +++ b/src/server/activeobjectmgr.h @@ -38,6 +38,9 @@ public: void getObjectsInsideRadius(const v3f &pos, float radius, std::vector<ServerActiveObject *> &result, std::function<bool(ServerActiveObject *obj)> include_obj_cb); + void getObjectsInArea(const aabb3f &box, + std::vector<ServerActiveObject *> &result, + std::function<bool(ServerActiveObject *obj)> include_obj_cb); void getAddedActiveObjectsAroundPos(const v3f &player_pos, f32 radius, f32 player_radius, std::set<u16> ¤t_objects, diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index d504c42ca..3bcbe107b 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -42,8 +42,8 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &d u8 version2 = 0; u8 version = readU8(is); - name = deSerializeString(is); - state = deSerializeLongString(is); + name = deSerializeString16(is); + state = deSerializeString32(is); if (version < 1) break; @@ -112,6 +112,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s) } } +void LuaEntitySAO::dispatchScriptDeactivate() +{ + // Ensure that this is in fact a registered entity, + // and that it isn't already gone. + // The latter also prevents this from ever being called twice. + if (m_registered && !isGone()) + m_env->getScriptIface()->luaentity_Deactivate(m_id); +} + void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) @@ -137,15 +146,11 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally // If the object gets detached this comes into effect automatically from the last known origin - if(isAttached()) - { - v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); - m_base_position = pos; + if (auto *parent = getParent()) { + m_base_position = parent->getBasePosition(); m_velocity = v3f(0,0,0); m_acceleration = v3f(0,0,0); - } - else - { + } else { if(m_prop.physical){ aabb3f box = m_prop.collisionbox; box.MinEdge *= BS; @@ -225,7 +230,7 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) // PROTOCOL_VERSION >= 37 writeU8(os, 1); // version - os << serializeString(""); // name + os << serializeString16(""); // name writeU8(os, 0); // is_player writeU16(os, getId()); //id writeV3F32(os, m_base_position); @@ -233,26 +238,26 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) writeU16(os, m_hp); std::ostringstream msg_os(std::ios::binary); - msg_os << serializeLongString(getPropertyPacket()); // message 1 - msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 - msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 + msg_os << serializeString32(getPropertyPacket()); // message 1 + msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2 + msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { - msg_os << serializeLongString(generateUpdateBonePositionCommand( - bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size + msg_os << serializeString32(generateUpdateBonePositionCommand( + bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N } - msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size int message_count = 4 + m_bone_position.size(); for (const auto &id : getAttachmentChildIds()) { if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - msg_os << serializeLongString(obj->generateUpdateInfantCommand( + msg_os << serializeString32(obj->generateUpdateInfantCommand( id, protocol_version)); } } - msg_os << serializeLongString(generateSetTextureModCommand()); + msg_os << serializeString32(generateSetTextureModCommand()); message_count++; writeU8(os, message_count); @@ -270,14 +275,14 @@ void LuaEntitySAO::getStaticData(std::string *result) const // version must be 1 to keep backwards-compatibility. See version2 writeU8(os, 1); // name - os<<serializeString(m_init_name); + os<<serializeString16(m_init_name); // state if(m_registered){ std::string state = m_env->getScriptIface()-> luaentity_GetStaticdata(m_id); - os<<serializeLongString(state); + os<<serializeString32(state); } else { - os<<serializeLongString(m_init_state); + os<<serializeString32(m_init_state); } writeU16(os, m_hp); writeV3F1000(os, m_velocity); @@ -302,7 +307,7 @@ u16 LuaEntitySAO::punch(v3f dir, { if (!m_registered) { // Delete unknown LuaEntities when punched - m_pending_removal = true; + markForRemoval(); return 0; } @@ -335,7 +340,7 @@ u16 LuaEntitySAO::punch(v3f dir, clearParentAttachment(); clearChildAttachments(); m_env->getScriptIface()->luaentity_on_death(m_id, puncher); - m_pending_removal = true; + markForRemoval(); } actionstream << puncher->getDescription() << " (id=" << puncher->getId() << @@ -436,7 +441,7 @@ std::string LuaEntitySAO::generateSetTextureModCommand() const // command writeU8(os, AO_CMD_SET_TEXTURE_MOD); // parameters - os << serializeString(m_current_texture_modifier); + os << serializeString16(m_current_texture_modifier); return os.str(); } @@ -483,6 +488,9 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) if(isAttached()) return; + // Send attachment updates instantly to the client prior updating position + sendOutdatedData(); + m_last_sent_move_precision = m_base_position.getDistanceFrom( m_last_sent_position); m_last_sent_position_timer = 0; diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h index 2520c8f5d..6883ae1b9 100644 --- a/src/server/luaentity_sao.h +++ b/src/server/luaentity_sao.h @@ -42,6 +42,7 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(u16 protocol_version); bool isStaticAllowed() const { return m_prop.static_save; } + bool shouldUnload() const { return true; } void getStaticData(std::string *result) const; u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr, ServerActiveObject *puncher = nullptr, @@ -70,6 +71,11 @@ public: bool getSelectionBox(aabb3f *toset) const; bool collideWithObjects() const; +protected: + void dispatchScriptDeactivate(); + virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); } + virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); } + private: std::string getPropertyPacket(); void sendPosition(bool do_interpolate, bool is_movement_end); diff --git a/src/server/mods.cpp b/src/server/mods.cpp index 6ac530739..83fa12da9 100644 --- a/src/server/mods.cpp +++ b/src/server/mods.cpp @@ -98,11 +98,12 @@ void ServerModManager::getModNames(std::vector<std::string> &modlist) const void ServerModManager::getModsMediaPaths(std::vector<std::string> &paths) const { - for (const ModSpec &spec : m_sorted_mods) { - paths.push_back(spec.path + DIR_DELIM + "textures"); - paths.push_back(spec.path + DIR_DELIM + "sounds"); - paths.push_back(spec.path + DIR_DELIM + "media"); - paths.push_back(spec.path + DIR_DELIM + "models"); - paths.push_back(spec.path + DIR_DELIM + "locale"); + for (auto it = m_sorted_mods.crbegin(); it != m_sorted_mods.crend(); it++) { + const ModSpec &spec = *it; + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "textures"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "sounds"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "media"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "models"); + fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "locale"); } } diff --git a/src/server/mods.h b/src/server/mods.h index 54774bd86..8954bbf72 100644 --- a/src/server/mods.h +++ b/src/server/mods.h @@ -42,5 +42,13 @@ public: void loadMods(ServerScripting *script); const ModSpec *getModSpec(const std::string &modname) const; void getModNames(std::vector<std::string> &modlist) const; + /** + * Recursively gets all paths of mod folders that can contain media files. + * + * Result is ordered in descending priority, ie. files from an earlier path + * should not be replaced by files from a latter one. + * + * @param paths result vector + */ void getModsMediaPaths(std::vector<std::string> &paths) const; }; diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 67efed210..0d31f2e0b 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -55,6 +55,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p m_prop.backface_culling = false; m_prop.makes_footstep_sound = true; m_prop.stepheight = PLAYER_DEFAULT_STEPHEIGHT * BS; + m_prop.show_on_minimap = true; m_hp = m_prop.hp_max; m_breath = m_prop.breath_max; // Disable zoom in survival mode using a value of 0 @@ -109,7 +110,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) // Protocol >= 15 writeU8(os, 1); // version - os << serializeString(m_player->getName()); // name + os << serializeString16(m_player->getName()); // name writeU8(os, 1); // is_player writeS16(os, getId()); // id writeV3F32(os, m_base_position); @@ -117,22 +118,22 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) writeU16(os, getHP()); std::ostringstream msg_os(std::ios::binary); - msg_os << serializeLongString(getPropertyPacket()); // message 1 - msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 - msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 + msg_os << serializeString32(getPropertyPacket()); // message 1 + msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2 + msg_os << serializeString32(generateUpdateAnimationCommand()); // 3 for (const auto &bone_pos : m_bone_position) { - msg_os << serializeLongString(generateUpdateBonePositionCommand( - bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size + msg_os << serializeString32(generateUpdateBonePositionCommand( + bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N } - msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4 - msg_os << serializeLongString(generateUpdatePhysicsOverrideCommand()); // 5 + msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size + msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + m_bone_position.size int message_count = 5 + m_bone_position.size(); for (const auto &id : getAttachmentChildIds()) { if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - msg_os << serializeLongString(obj->generateUpdateInfantCommand( + msg_os << serializeString32(obj->generateUpdateInfantCommand( id, protocol_version)); } } @@ -147,7 +148,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) void PlayerSAO::getStaticData(std::string * result) const { - FATAL_ERROR("Obsolete function"); + FATAL_ERROR("This function shall not be called for PlayerSAO"); } void PlayerSAO::step(float dtime, bool send_recommended) @@ -259,10 +260,13 @@ void PlayerSAO::step(float dtime, bool send_recommended) // otherwise it's calculated normally. // If the object gets detached this comes into effect automatically from // the last known origin. - if (isAttached()) { - v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); + if (auto *parent = getParent()) { + v3f pos = parent->getBasePosition(); m_last_good_position = pos; setBasePosition(pos); + + if (m_player) + m_player->setSpeed(v3f()); } if (!send_recommended) @@ -455,22 +459,32 @@ u16 PlayerSAO::punch(v3f dir, return hitparams.wear; } +void PlayerSAO::rightClick(ServerActiveObject *clicker) +{ + m_env->getScriptIface()->on_rightclickplayer(this, clicker); +} + void PlayerSAO::setHP(s32 hp, const PlayerHPChangeReason &reason) { - s32 oldhp = m_hp; + if (hp == (s32)m_hp) + return; // Nothing to do - hp = rangelim(hp, 0, m_prop.hp_max); + if (m_hp <= 0 && hp < (s32)m_hp) + return; // Cannot take more damage - if (oldhp != hp) { - s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp, reason); + { + s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - m_hp, reason); if (hp_change == 0) return; - hp = rangelim(oldhp + hp_change, 0, m_prop.hp_max); + hp = m_hp + hp_change; } + s32 oldhp = m_hp; + hp = rangelim(hp, 0, m_prop.hp_max); + if (hp < oldhp && isImmortal()) - return; + return; // Do not allow immortal players to be damaged m_hp = hp; @@ -525,7 +539,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item) void PlayerSAO::disconnected() { m_peer_id = PEER_ID_INEXISTENT; - m_pending_removal = true; + markForRemoval(); } void PlayerSAO::unlinkPlayerSessionAndSave() @@ -558,7 +572,8 @@ void PlayerSAO::setMaxSpeedOverride(const v3f &vel) bool PlayerSAO::checkMovementCheat() { - if (isAttached() || m_is_singleplayer || + if (m_is_singleplayer || + isAttached() || g_settings->getBool("disable_anticheat")) { m_last_good_position = m_base_position; return false; diff --git a/src/server/player_sao.h b/src/server/player_sao.h index 8571bd4f9..8e2d8803f 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -83,6 +83,7 @@ public: void addedToEnvironment(u32 dtime_s); void removingFromEnvironment(); bool isStaticAllowed() const { return false; } + bool shouldUnload() const { return false; } std::string getClientInitializationData(u16 protocol_version); void getStaticData(std::string *result) const; void step(float dtime, bool send_recommended); @@ -110,10 +111,9 @@ public: u16 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher, float time_from_last_punch); - void rightClick(ServerActiveObject *clicker) {} + void rightClick(ServerActiveObject *clicker); void setHP(s32 hp, const PlayerHPChangeReason &reason); void setHPRaw(u16 hp) { m_hp = hp; } - s16 readDamage(); u16 getBreath() const { return m_breath; } void setBreath(const u16 breath, bool send = true); diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index 3341dc008..96b433d1d 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -61,7 +61,7 @@ std::string ServerActiveObject::generateUpdateInfantCommand(u16 infant_id, u16 p // Clients since 4aa9a66 so no longer need this data // Version 38 is the first bump after that commit. // See also: ClientEnvironment::addActiveObject - os << serializeLongString(getClientInitializationData(protocol_version)); + os << serializeString32(getClientInitializationData(protocol_version)); } return os.str(); } @@ -73,3 +73,19 @@ void ServerActiveObject::dumpAOMessagesToQueue(std::queue<ActiveObjectMessage> & m_messages_out.pop(); } } + +void ServerActiveObject::markForRemoval() +{ + if (!m_pending_removal) { + onMarkedForRemoval(); + m_pending_removal = true; + } +} + +void ServerActiveObject::markForDeactivation() +{ + if (!m_pending_deactivation) { + onMarkedForDeactivation(); + m_pending_deactivation = true; + } +} diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h index 927009aef..51f445914 100644 --- a/src/server/serveractiveobject.h +++ b/src/server/serveractiveobject.h @@ -70,6 +70,10 @@ public: virtual bool environmentDeletes() const { return true; } + // Safely mark the object for removal or deactivation + void markForRemoval(); + void markForDeactivation(); + // Create a certain type of ServerActiveObject static ServerActiveObject* create(ActiveObjectType type, ServerEnvironment *env, u16 id, v3f pos, @@ -125,6 +129,7 @@ public: assert(isStaticAllowed()); *result = ""; } + /* Return false in here to never save and instead remove object on unload. getStaticData() will not be called in that case. @@ -132,6 +137,14 @@ public: virtual bool isStaticAllowed() const {return true;} + /* + Return false here to never unload the object. + isStaticAllowed && shouldUnload -> unload when out of active block range + !isStaticAllowed && shouldUnload -> unload when block is unloaded + */ + virtual bool shouldUnload() const + { return true; } + // Returns tool wear virtual u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr, @@ -149,8 +162,6 @@ public: {} virtual const ItemGroupList &getArmorGroups() const { static ItemGroupList rv; return rv; } - virtual void setPhysicsOverride(float physics_override_speed, float physics_override_jump, float physics_override_gravity) - {} virtual void setAnimation(v2f frames, float frame_speed, float frame_blend, bool frame_loop) {} virtual void getAnimation(v2f *frames, float *frame_speed, float *frame_blend, bool *frame_loop) @@ -193,7 +204,6 @@ public: } std::string generateUpdateInfantCommand(u16 infant_id, u16 protocol_version); - std::string generateUpdateNametagAttributesCommand(const video::SColor &color) const; void dumpAOMessagesToQueue(std::queue<ActiveObjectMessage> &queue); @@ -205,31 +215,15 @@ public: u16 m_known_by_count = 0; /* - - Whether this object is to be removed when nobody knows about - it anymore. - - Removal is delayed to preserve the id for the time during which - it could be confused to some other object by some client. - - This is usually set to true by the step() method when the object wants - to be deleted but can be set by anything else too. - */ - bool m_pending_removal = false; - - /* - Same purpose as m_pending_removal but for deactivation. - deactvation = save static data in block, remove active object - - If this is set alongside with m_pending_removal, removal takes - priority. - */ - bool m_pending_deactivation = false; - - /* A getter that unifies the above to answer the question: "Can the environment still interact with this object?" */ inline bool isGone() const { return m_pending_removal || m_pending_deactivation; } + inline bool isPendingRemoval() const + { return m_pending_removal; } + /* Whether the object's static data has been stored to a block */ @@ -241,6 +235,9 @@ public: v3s16 m_static_block = v3s16(1337,1337,1337); protected: + virtual void onMarkedForDeactivation() {} + virtual void onMarkedForRemoval() {} + virtual void onAttach(int parent_id) {} virtual void onDetach(int parent_id) {} @@ -249,6 +246,27 @@ protected: std::unordered_set<u32> m_attached_particle_spawners; /* + Same purpose as m_pending_removal but for deactivation. + deactvation = save static data in block, remove active object + + If this is set alongside with m_pending_removal, removal takes + priority. + Note: Do not assign this directly, use markForDeactivation() instead. + */ + bool m_pending_deactivation = false; + + /* + - Whether this object is to be removed when nobody knows about + it anymore. + - Removal is delayed to preserve the id for the time during which + it could be confused to some other object by some client. + - This is usually set to true by the step() method when the object wants + to be deleted but can be set by anything else too. + Note: Do not assign this directly, use markForRemoval() instead. + */ + bool m_pending_removal = false; + + /* Queue of messages to be sent to the client */ std::queue<ActiveObjectMessage> m_messages_out; diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index ef0e87f2c..2371640ca 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -121,8 +121,8 @@ void UnitSAO::sendOutdatedData() } // clang-format on -void UnitSAO::setAttachment( - int parent_id, const std::string &bone, v3f position, v3f rotation) +void UnitSAO::setAttachment(int parent_id, const std::string &bone, v3f position, + v3f rotation, bool force_visible) { // Attachments need to be handled on both the server and client. // If we just attach on the server, we can only copy the position of the parent. @@ -137,6 +137,7 @@ void UnitSAO::setAttachment( m_attachment_bone = bone; m_attachment_position = position; m_attachment_rotation = rotation; + m_force_visible = force_visible; m_attachment_sent = false; if (parent_id != old_parent) { @@ -145,13 +146,14 @@ void UnitSAO::setAttachment( } } -void UnitSAO::getAttachment( - int *parent_id, std::string *bone, v3f *position, v3f *rotation) const +void UnitSAO::getAttachment(int *parent_id, std::string *bone, v3f *position, + v3f *rotation, bool *force_visible) const { *parent_id = m_attachment_parent_id; *bone = m_attachment_bone; *position = m_attachment_position; *rotation = m_attachment_rotation; + *force_visible = m_force_visible; } void UnitSAO::clearChildAttachments() @@ -159,7 +161,7 @@ void UnitSAO::clearChildAttachments() for (int child_id : m_attachment_child_ids) { // Child can be NULL if it was deleted earlier if (ServerActiveObject *child = m_env->getActiveObject(child_id)) - child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0)); + child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false); } m_attachment_child_ids.clear(); } @@ -169,9 +171,9 @@ void UnitSAO::clearParentAttachment() ServerActiveObject *parent = nullptr; if (m_attachment_parent_id) { parent = m_env->getActiveObject(m_attachment_parent_id); - setAttachment(0, "", m_attachment_position, m_attachment_rotation); + setAttachment(0, "", m_attachment_position, m_attachment_rotation, false); } else { - setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0)); + setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false); } // Do it if (parent) @@ -242,9 +244,10 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const writeU8(os, AO_CMD_ATTACH_TO); // parameters writeS16(os, m_attachment_parent_id); - os << serializeString(m_attachment_bone); + os << serializeString16(m_attachment_bone); writeV3F32(os, m_attachment_position); writeV3F32(os, m_attachment_rotation); + writeU8(os, m_force_visible); return os.str(); } @@ -255,7 +258,7 @@ std::string UnitSAO::generateUpdateBonePositionCommand( // command writeU8(os, AO_CMD_SET_BONE_POSITION); // parameters - os << serializeString(bone); + os << serializeString16(bone); writeV3F32(os, position); writeV3F32(os, rotation); return os.str(); @@ -291,7 +294,7 @@ std::string UnitSAO::generateUpdateArmorGroupsCommand() const writeU8(os, AO_CMD_UPDATE_ARMOR_GROUPS); writeU16(os, m_armor_groups.size()); for (const auto &armor_group : m_armor_groups) { - os << serializeString(armor_group.first); + os << serializeString16(armor_group.first); writeS16(os, armor_group.second); } return os.str(); diff --git a/src/server/unit_sao.h b/src/server/unit_sao.h index 3cb7f0ad5..a21e055c5 100644 --- a/src/server/unit_sao.h +++ b/src/server/unit_sao.h @@ -64,9 +64,9 @@ public: ServerActiveObject *getParent() const; inline bool isAttached() const { return getParent(); } void setAttachment(int parent_id, const std::string &bone, v3f position, - v3f rotation); + v3f rotation, bool force_visible); void getAttachment(int *parent_id, std::string *bone, v3f *position, - v3f *rotation) const; + v3f *rotation, bool *force_visible) const; void clearChildAttachments(); void clearParentAttachment(); void addAttachmentChild(int child_id); @@ -133,4 +133,5 @@ private: v3f m_attachment_position; v3f m_attachment_rotation; bool m_attachment_sent = false; + bool m_force_visible = false; }; |