diff options
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/clientenvironment.cpp | 14 | ||||
-rw-r--r-- | src/client/clientenvironment.h | 2 | ||||
-rw-r--r-- | src/client/clientobject.h | 8 | ||||
-rw-r--r-- | src/client/content_cao.cpp | 201 | ||||
-rw-r--r-- | src/client/content_cao.h | 21 |
5 files changed, 144 insertions, 102 deletions
diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index a788c93c2..11dbcc35b 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -47,8 +47,6 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, m_texturesource(texturesource), m_client(client) { - char zero = 0; - memset(attachement_parent_ids, zero, sizeof(attachement_parent_ids)); } ClientEnvironment::~ClientEnvironment() @@ -392,7 +390,17 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, <<std::endl; } - addActiveObject(obj); + u16 new_id = addActiveObject(obj); + // Object initialized: + if ((obj = getActiveObject(new_id))) { + // Final step is to update all children which are already known + // Data provided by GENERIC_CMD_SPAWN_INFANT + const auto &children = obj->getAttachmentChildIds(); + for (auto c_id : children) { + if (auto *o = getActiveObject(c_id)) + o->updateAttachments(); + } + } } void ClientEnvironment::processActiveObjectMessage(u16 id, const std::string &data) diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h index 4fa3f4848..f182b5951 100644 --- a/src/client/clientenvironment.h +++ b/src/client/clientenvironment.h @@ -138,8 +138,6 @@ public: std::vector<PointedThing> &objects ); - u16 attachement_parent_ids[USHRT_MAX + 1]; - const std::list<std::string> &getPlayerNames() { return m_player_names; } void addPlayerName(const std::string &name) { m_player_names.push_back(name); } void removePlayerName(const std::string &name) { m_player_names.remove(name); } diff --git a/src/client/clientobject.h b/src/client/clientobject.h index 5e34177e4..987005730 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "activeobject.h" #include <unordered_map> +#include <unordered_set> + class ClientEnvironment; class ITextureSource; @@ -51,8 +53,12 @@ public: virtual scene::ISceneNode *getSceneNode() { return NULL; } virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() { return NULL; } virtual bool isLocalPlayer() const {return false;} + virtual ClientActiveObject *getParent() const { return nullptr; }; - virtual void setAttachments() {} + virtual const std::unordered_set<int> &getAttachmentChildIds() const + { static std::unordered_set<int> rv; return rv; } + virtual void updateAttachments() {}; + virtual bool doShowSelectionBox(){return true;} // Step object in time diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 388a71873..d2ab0631a 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -17,36 +17,35 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "content_cao.h" +#include <IBillboardSceneNode.h> #include <ICameraSceneNode.h> #include <ITextSceneNode.h> -#include <IBillboardSceneNode.h> #include <IMeshManipulator.h> #include <IAnimatedMeshSceneNode.h> -#include "content_cao.h" -#include "util/numeric.h" // For IntervalLimiter & setPitchYawRoll -#include "util/serialize.h" -#include "util/basic_macros.h" +#include "client/client.h" +#include "client/renderingengine.h" #include "client/sound.h" #include "client/tile.h" -#include "environment.h" +#include "util/basic_macros.h" +#include "util/numeric.h" // For IntervalLimiter & setPitchYawRoll +#include "util/serialize.h" +#include "camera.h" // CameraModes #include "collision.h" -#include "settings.h" -#include "serialization.h" // For decompressZlib -#include "clientobject.h" -#include "mesh.h" -#include "itemdef.h" -#include "tool.h" #include "content_cso.h" -#include "sound.h" -#include "nodedef.h" +#include "environment.h" +#include "itemdef.h" #include "localplayer.h" #include "map.h" -#include "camera.h" // CameraModes -#include "client.h" +#include "mesh.h" +#include "nodedef.h" +#include "serialization.h" // For decompressZlib +#include "settings.h" +#include "sound.h" +#include "tool.h" #include "wieldmesh.h" #include <algorithm> #include <cmath> -#include "client/renderingengine.h" class Settings; struct ToolCapabilities; @@ -305,6 +304,7 @@ void TestCAO::processMessage(const std::string &data) */ #include "genericobject.h" +#include "clientobject.h" GenericCAO::GenericCAO(Client *client, ClientEnvironment *env): ClientActiveObject(0, client, env) @@ -372,6 +372,7 @@ void GenericCAO::processInitData(const std::string &data) m_position = readV3F32(is); m_rotation = readV3F32(is); m_hp = readU16(is); + const u8 num_messages = readU8(is); for (int i = 0; i < num_messages; i++) { @@ -443,7 +444,7 @@ scene::IAnimatedMeshSceneNode* GenericCAO::getAnimatedMeshSceneNode() void GenericCAO::setChildrenVisible(bool toset) { - for (u16 cao_id : m_children) { + for (u16 cao_id : m_attachment_child_ids) { GenericCAO *obj = m_env->getGenericCAO(cao_id); if (obj) { obj->setVisible(toset); @@ -451,43 +452,79 @@ void GenericCAO::setChildrenVisible(bool toset) } } -void GenericCAO::setAttachments() +void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation) { + int old_parent = m_attachment_parent_id; + m_attachment_parent_id = parent_id; + m_attachment_bone = bone; + m_attachment_position = position; + m_attachment_rotation = rotation; + + ClientActiveObject *parent = m_env->getActiveObject(parent_id); + + if (parent_id != old_parent) { + if (auto *o = m_env->getActiveObject(old_parent)) + o->removeAttachmentChild(m_id); + if (parent) + parent->addAttachmentChild(m_id); + } + updateAttachments(); } -ClientActiveObject* GenericCAO::getParent() const +void GenericCAO::getAttachment(int *parent_id, std::string *bone, v3f *position, + v3f *rotation) const +{ + *parent_id = m_attachment_parent_id; + *bone = m_attachment_bone; + *position = m_attachment_position; + *rotation = m_attachment_rotation; +} + +void GenericCAO::clearChildAttachments() { - ClientActiveObject *obj = NULL; + // Cannot use for-loop here: setAttachment() modifies 'm_attachment_child_ids'! + while (!m_attachment_child_ids.empty()) { + int child_id = *m_attachment_child_ids.begin(); - u16 attached_id = m_env->attachement_parent_ids[getId()]; + if (ClientActiveObject *child = m_env->getActiveObject(child_id)) + child->setAttachment(0, "", v3f(), v3f()); - if ((attached_id != 0) && - (attached_id != getId())) { - obj = m_env->getActiveObject(attached_id); + removeAttachmentChild(child_id); } - return obj; } -void GenericCAO::removeFromScene(bool permanent) +void GenericCAO::clearParentAttachment() { - // Should be true when removing the object permanently and false when refreshing (eg: updating visuals) - if((m_env != NULL) && (permanent)) - { - for (u16 ci : m_children) { - if (m_env->attachement_parent_ids[ci] == getId()) { - m_env->attachement_parent_ids[ci] = 0; - } - } - m_children.clear(); + if (m_attachment_parent_id) + setAttachment(0, "", m_attachment_position, m_attachment_rotation); + else + setAttachment(0, "", v3f(), v3f()); +} - m_env->attachement_parent_ids[getId()] = 0; +void GenericCAO::addAttachmentChild(int child_id) +{ + m_attachment_child_ids.insert(child_id); +} - LocalPlayer* player = m_env->getLocalPlayer(); - if (this == player->parent) { - player->parent = nullptr; - player->isAttached = false; - } +void GenericCAO::removeAttachmentChild(int child_id) +{ + m_attachment_child_ids.erase(child_id); +} + +ClientActiveObject* GenericCAO::getParent() const +{ + return m_attachment_parent_id ? m_env->getActiveObject(m_attachment_parent_id) : + nullptr; +} + +void GenericCAO::removeFromScene(bool permanent) +{ + // Should be true when removing the object permanently + // and false when refreshing (eg: updating visuals) + if (m_env && permanent) { + clearChildAttachments(); + clearParentAttachment(); } if (m_meshnode) { @@ -711,6 +748,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) updateTextures(m_current_texture_modifier); scene::ISceneNode *node = getSceneNode(); + if (node && !m_prop.nametag.empty() && !m_is_local_player) { // Add nametag v3f pos; @@ -736,7 +774,7 @@ void GenericCAO::updateLight(u8 light_at_pos) updateLightNoCheck(light_at_pos); // Update light of all children - for (u16 i : m_children) { + for (u16 i : m_attachment_child_ids) { ClientActiveObject *obj = m_env->getActiveObject(i); if (obj) { obj->updateLightNoCheck(light_at_pos); @@ -871,12 +909,8 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) // Attachments, part 1: All attached objects must be unparented first, // or Irrlicht causes a segmentation fault - for (auto ci = m_children.begin(); ci != m_children.end();) { - if (m_env->attachement_parent_ids[*ci] != getId()) { - ci = m_children.erase(ci); - continue; - } - ClientActiveObject *obj = m_env->getActiveObject(*ci); + for (u16 cao_id : m_attachment_child_ids) { + ClientActiveObject *obj = m_env->getActiveObject(cao_id); if (obj) { scene::ISceneNode *child_node = obj->getSceneNode(); // The node's parent is always an IDummyTraformationSceneNode, @@ -884,18 +918,16 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) if (child_node) child_node->getParent()->setParent(m_smgr->getRootSceneNode()); } - ++ci; } removeFromScene(false); addToScene(m_client->tsrc()); // Attachments, part 2: Now that the parent has been refreshed, put its attachments back - for (u16 cao_id : m_children) { - // Get the object of the child + for (u16 cao_id : m_attachment_child_ids) { ClientActiveObject *obj = m_env->getActiveObject(cao_id); if (obj) - obj->setAttachments(); + obj->updateAttachments(); } } @@ -916,7 +948,6 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) { LocalPlayer *player = m_env->getLocalPlayer(); player->overridePosition = getParent()->getPosition(); - m_env->getLocalPlayer()->parent = getParent(); } } else { rot_translator.translate(dtime); @@ -1296,6 +1327,14 @@ void GenericCAO::updateBonePosition() void GenericCAO::updateAttachments() { ClientActiveObject *parent = getParent(); + + m_attached_to_local = parent && parent->isLocalPlayer(); + + if (!parent && m_attachment_parent_id) { + //m_is_visible = false; maybe later. needs better handling + return; + } + if (!parent) { // Detach or don't attach if (m_matrixnode) { v3f old_pos = m_matrixnode->getAbsolutePosition(); @@ -1303,10 +1342,6 @@ void GenericCAO::updateAttachments() getPosRotMatrix().setTranslation(old_pos); m_matrixnode->updateAbsolutePosition(); } - if (m_is_local_player) { - LocalPlayer *player = m_env->getLocalPlayer(); - player->isAttached = false; - } } else // Attach { @@ -1325,10 +1360,11 @@ void GenericCAO::updateAttachments() getPosRotMatrix().setRotationDegrees(m_attachment_rotation); m_matrixnode->updateAbsolutePosition(); } - if (m_is_local_player) { - LocalPlayer *player = m_env->getLocalPlayer(); - player->isAttached = true; - } + } + if (m_is_local_player) { + LocalPlayer *player = m_env->getLocalPlayer(); + player->isAttached = parent; + player->parent = parent; } } @@ -1488,31 +1524,15 @@ void GenericCAO::processMessage(const std::string &data) updateBonePosition(); } else if (cmd == GENERIC_CMD_ATTACH_TO) { u16 parent_id = readS16(is); - u16 &old_parent_id = m_env->attachement_parent_ids[getId()]; - if (parent_id != old_parent_id) { - if (GenericCAO *old_parent = m_env->getGenericCAO(old_parent_id)) { - old_parent->m_children.erase(std::remove( - m_children.begin(), m_children.end(), - getId()), m_children.end()); - } - if (GenericCAO *new_parent = m_env->getGenericCAO(parent_id)) - new_parent->m_children.push_back(getId()); - - old_parent_id = parent_id; - } + std::string bone = deSerializeString(is); + v3f position = readV3F32(is); + v3f rotation = readV3F32(is); - m_attachment_bone = deSerializeString(is); - m_attachment_position = readV3F32(is); - m_attachment_rotation = readV3F32(is); + setAttachment(parent_id, bone, position, rotation); // localplayer itself can't be attached to localplayer - if (!m_is_local_player) { - m_attached_to_local = getParent() != NULL && getParent()->isLocalPlayer(); - // Objects attached to the local player should be hidden by default + if (!m_is_local_player) m_is_visible = !m_attached_to_local; - } - - updateAttachments(); } else if (cmd == GENERIC_CMD_PUNCHED) { u16 result_hp = readU16(is); @@ -1539,6 +1559,12 @@ void GenericCAO::processMessage(const std::string &data) m_reset_textures_timer += 0.05 * damage; updateTextures(m_current_texture_modifier + "^[brighten"); } + } else { + // Same as 'Server::DiePlayer' + clearParentAttachment(); + // Same as 'ObjectRef::l_remove' + if (!m_is_player) + clearChildAttachments(); } } else if (cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) { m_armor_groups.clear(); @@ -1561,13 +1587,10 @@ void GenericCAO::processMessage(const std::string &data) } } else if (cmd == GENERIC_CMD_SPAWN_INFANT) { u16 child_id = readU16(is); - u8 type = readU8(is); + u8 type = readU8(is); // maybe this will be useful later + (void)type; - if (GenericCAO *childobj = m_env->getGenericCAO(child_id)) { - childobj->processInitData(deSerializeLongString(is)); - } else { - m_env->addActiveObject(child_id, type, deSerializeLongString(is)); - } + addAttachmentChild(child_id); } else { warningstream << FUNCTION_NAME << ": unknown command or outdated client \"" diff --git a/src/client/content_cao.h b/src/client/content_cao.h index ca1518fb2..aef1f1296 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -102,10 +102,14 @@ private: bool m_animation_loop = true; // stores position and rotation for each bone name std::unordered_map<std::string, core::vector2d<v3f>> m_bone_position; + + int m_attachment_parent_id = 0; + std::unordered_set<int> m_attachment_child_ids; std::string m_attachment_bone = ""; v3f m_attachment_position; v3f m_attachment_rotation; bool m_attached_to_local = false; + int m_anim_frame = 0; int m_anim_num_frames = 1; float m_anim_framelength = 0.2f; @@ -122,8 +126,6 @@ private: bool m_is_visible = false; s8 m_glow = 0; - std::vector<u16> m_children; - public: GenericCAO(Client *client, ClientEnvironment *env); @@ -199,10 +201,17 @@ public: } void setChildrenVisible(bool toset); - + void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation); + void getAttachment(int *parent_id, std::string *bone, v3f *position, + v3f *rotation) const; + void clearChildAttachments(); + void clearParentAttachment(); + void addAttachmentChild(int child_id); + void removeAttachmentChild(int child_id); ClientActiveObject *getParent() const; - - void setAttachments(); + const std::unordered_set<int> &getAttachmentChildIds() const + { return m_attachment_child_ids; } + void updateAttachments(); void removeFromScene(bool permanent); @@ -235,8 +244,6 @@ public: void updateBonePosition(); - void updateAttachments(); - void processMessage(const std::string &data); bool directReportPunch(v3f dir, const ItemStack *punchitem=NULL, |