aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/activeobjectmgr.cpp15
-rw-r--r--src/server/activeobjectmgr.h3
-rw-r--r--src/server/luaentity_sao.cpp56
-rw-r--r--src/server/luaentity_sao.h6
-rw-r--r--src/server/mods.cpp13
-rw-r--r--src/server/mods.h8
-rw-r--r--src/server/player_sao.cpp55
-rw-r--r--src/server/player_sao.h4
-rw-r--r--src/server/serveractiveobject.cpp18
-rw-r--r--src/server/serveractiveobject.h62
-rw-r--r--src/server/unit_sao.cpp23
-rw-r--r--src/server/unit_sao.h5
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> &current_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> &current_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;
};