From 5146086a64d5eeb480948d612a008a2ec81455d4 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Sat, 11 Apr 2020 11:22:15 +0200 Subject: Drop content_sao.{cpp,h} Move LuaEntitySAO to a new dedicated file Drop TestSAO (useless object) Drop the old static startup initialized SAO factory, which was pretty useless. This factory was using a std::map for 2 elements, now just use a simple condition owned by ServerEnvironment, which will be lightweight, that will also drop a one time useful test on each LuaEntitySAO creation. This should reduce server load on massive SAO creation --- src/server/luaentity_sao.cpp | 581 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 581 insertions(+) create mode 100644 src/server/luaentity_sao.cpp (limited to 'src/server/luaentity_sao.cpp') diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp new file mode 100644 index 000000000..125939241 --- /dev/null +++ b/src/server/luaentity_sao.cpp @@ -0,0 +1,581 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2013-2020 Minetest core developers & community + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "luaentity_sao.h" +#include "collision.h" +#include "constants.h" +#include "player_sao.h" +#include "scripting_server.h" +#include "server.h" +#include "serverenvironment.h" + +LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &data) + : UnitSAO(env, pos) +{ + std::string name; + std::string state; + u16 hp = 1; + v3f velocity; + v3f rotation; + + while (!data.empty()) { // breakable, run for one iteration + std::istringstream is(data, std::ios::binary); + // 'version' does not allow to incrementally extend the parameter list thus + // we need another variable to build on top of 'version=1'. Ugly hack but works™ + u8 version2 = 0; + u8 version = readU8(is); + + name = deSerializeString(is); + state = deSerializeLongString(is); + + if (version < 1) + break; + + hp = readU16(is); + velocity = readV3F1000(is); + // yaw must be yaw to be backwards-compatible + rotation.Y = readF1000(is); + + if (is.good()) // EOF for old formats + version2 = readU8(is); + + if (version2 < 1) // PROTOCOL_VERSION < 37 + break; + + // version2 >= 1 + rotation.X = readF1000(is); + rotation.Z = readF1000(is); + + // if (version2 < 2) + // break; + // + break; + } + // create object + infostream << "LuaEntitySAO::create(name=\"" << name << "\" state=\"" + << state << "\")" << std::endl; + + m_init_name = name; + m_init_state = state; + m_hp = hp; + m_velocity = velocity; + m_rotation = rotation; +} + +LuaEntitySAO::~LuaEntitySAO() +{ + if(m_registered){ + m_env->getScriptIface()->luaentity_Remove(m_id); + } + + for (u32 attached_particle_spawner : m_attached_particle_spawners) { + m_env->deleteParticleSpawner(attached_particle_spawner, false); + } +} + +void LuaEntitySAO::addedToEnvironment(u32 dtime_s) +{ + ServerActiveObject::addedToEnvironment(dtime_s); + + // Create entity from name + m_registered = m_env->getScriptIface()-> + luaentity_Add(m_id, m_init_name.c_str()); + + if(m_registered){ + // Get properties + m_env->getScriptIface()-> + luaentity_GetProperties(m_id, this, &m_prop); + // Initialize HP from properties + m_hp = m_prop.hp_max; + // Activate entity, supplying serialized state + m_env->getScriptIface()-> + luaentity_Activate(m_id, m_init_state, dtime_s); + } else { + m_prop.infotext = m_init_name; + } +} + +void LuaEntitySAO::step(float dtime, bool send_recommended) +{ + if(!m_properties_sent) + { + m_properties_sent = true; + std::string str = getPropertyPacket(); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + + // If attached, check that our parent is still there. If it isn't, detach. + if(m_attachment_parent_id && !isAttached()) + { + m_attachment_parent_id = 0; + m_attachment_bone = ""; + m_attachment_position = v3f(0,0,0); + m_attachment_rotation = v3f(0,0,0); + sendPosition(false, true); + } + + m_last_sent_position_timer += dtime; + + // 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; + m_velocity = v3f(0,0,0); + m_acceleration = v3f(0,0,0); + } + else + { + if(m_prop.physical){ + aabb3f box = m_prop.collisionbox; + box.MinEdge *= BS; + box.MaxEdge *= BS; + collisionMoveResult moveresult; + f32 pos_max_d = BS*0.25; // Distance per iteration + v3f p_pos = m_base_position; + v3f p_velocity = m_velocity; + v3f p_acceleration = m_acceleration; + moveresult = collisionMoveSimple(m_env, m_env->getGameDef(), + pos_max_d, box, m_prop.stepheight, dtime, + &p_pos, &p_velocity, p_acceleration, + this, m_prop.collideWithObjects); + + // Apply results + m_base_position = p_pos; + m_velocity = p_velocity; + m_acceleration = p_acceleration; + } else { + m_base_position += dtime * m_velocity + 0.5 * dtime + * dtime * m_acceleration; + m_velocity += dtime * m_acceleration; + } + + if (m_prop.automatic_face_movement_dir && + (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) { + float target_yaw = atan2(m_velocity.Z, m_velocity.X) * 180 / M_PI + + m_prop.automatic_face_movement_dir_offset; + float max_rotation_per_sec = + m_prop.automatic_face_movement_max_rotation_per_sec; + + if (max_rotation_per_sec > 0) { + m_rotation.Y = wrapDegrees_0_360(m_rotation.Y); + wrappedApproachShortest(m_rotation.Y, target_yaw, + dtime * max_rotation_per_sec, 360.f); + } else { + // Negative values of max_rotation_per_sec mean disabled. + m_rotation.Y = target_yaw; + } + } + } + + if(m_registered){ + m_env->getScriptIface()->luaentity_Step(m_id, dtime); + } + + if (!send_recommended) + return; + + if(!isAttached()) + { + // TODO: force send when acceleration changes enough? + float minchange = 0.2*BS; + if(m_last_sent_position_timer > 1.0){ + minchange = 0.01*BS; + } else if(m_last_sent_position_timer > 0.2){ + minchange = 0.05*BS; + } + float move_d = m_base_position.getDistanceFrom(m_last_sent_position); + move_d += m_last_sent_move_precision; + float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); + if (move_d > minchange || vel_d > minchange || + std::fabs(m_rotation.X - m_last_sent_rotation.X) > 1.0f || + std::fabs(m_rotation.Y - m_last_sent_rotation.Y) > 1.0f || + std::fabs(m_rotation.Z - m_last_sent_rotation.Z) > 1.0f) { + + sendPosition(true, false); + } + } + + if (!m_armor_groups_sent) { + m_armor_groups_sent = true; + // create message and add to list + m_messages_out.emplace(getId(), true, generateUpdateArmorGroupsCommand()); + } + + if (!m_animation_sent) { + m_animation_sent = true; + std::string str = generateUpdateAnimationCommand(); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + + if (!m_animation_speed_sent) { + m_animation_speed_sent = true; + std::string str = generateUpdateAnimationSpeedCommand(); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + + if (!m_bone_position_sent) { + m_bone_position_sent = true; + for (std::unordered_map>::const_iterator + ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ + std::string str = generateUpdateBonePositionCommand((*ii).first, + (*ii).second.X, (*ii).second.Y); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + } + + if (!m_attachment_sent) { + m_attachment_sent = true; + std::string str = generateUpdateAttachmentCommand(); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } +} + +std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) +{ + std::ostringstream os(std::ios::binary); + + // PROTOCOL_VERSION >= 37 + writeU8(os, 1); // version + os << serializeString(""); // name + writeU8(os, 0); // is_player + writeU16(os, getId()); //id + writeV3F32(os, m_base_position); + writeV3F32(os, m_rotation); + 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 + for (std::unordered_map>::const_iterator + ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { + msg_os << serializeLongString(generateUpdateBonePositionCommand((*ii).first, + (*ii).second.X, (*ii).second.Y)); // m_bone_position.size + } + msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4 + int message_count = 4 + m_bone_position.size(); + for (std::unordered_set::const_iterator ii = m_attachment_child_ids.begin(); + (ii != m_attachment_child_ids.end()); ++ii) { + if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { + message_count++; + // TODO after a protocol bump: only send the object initialization data + // to older clients (superfluous since this message exists) + msg_os << serializeLongString(obj->generateUpdateInfantCommand(*ii, protocol_version)); + } + } + + msg_os << serializeLongString(generateSetTextureModCommand()); + message_count++; + + writeU8(os, message_count); + os.write(msg_os.str().c_str(), msg_os.str().size()); + + // return result + return os.str(); +} + +void LuaEntitySAO::getStaticData(std::string *result) const +{ + verbosestream<getScriptIface()-> + luaentity_GetStaticdata(m_id); + os<= 37 + + writeF1000(os, m_rotation.X); + writeF1000(os, m_rotation.Z); + + // + + *result = os.str(); +} + +u16 LuaEntitySAO::punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, + float time_from_last_punch) +{ + if (!m_registered) { + // Delete unknown LuaEntities when punched + m_pending_removal = true; + return 0; + } + + FATAL_ERROR_IF(!puncher, "Punch action called without SAO"); + + s32 old_hp = getHP(); + ItemStack selected_item, hand_item; + ItemStack tool_item = puncher->getWieldedItem(&selected_item, &hand_item); + + PunchDamageResult result = getPunchDamage( + m_armor_groups, + toolcap, + &tool_item, + time_from_last_punch); + + bool damage_handled = m_env->getScriptIface()->luaentity_Punch(m_id, puncher, + time_from_last_punch, toolcap, dir, result.did_punch ? result.damage : 0); + + if (!damage_handled) { + if (result.did_punch) { + setHP((s32)getHP() - result.damage, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); + + // create message and add to list + sendPunchCommand(); + } + } + + if (getHP() == 0 && !isGone()) { + clearParentAttachment(); + clearChildAttachments(); + m_env->getScriptIface()->luaentity_on_death(m_id, puncher); + m_pending_removal = true; + } + + actionstream << puncher->getDescription() << " (id=" << puncher->getId() << + ", hp=" << puncher->getHP() << ") punched " << + getDescription() << " (id=" << m_id << ", hp=" << m_hp << + "), damage=" << (old_hp - (s32)getHP()) << + (damage_handled ? " (handled by Lua)" : "") << std::endl; + + // TODO: give Lua control over wear + return result.wear; +} + +void LuaEntitySAO::rightClick(ServerActiveObject *clicker) +{ + if (!m_registered) + return; + + m_env->getScriptIface()->luaentity_Rightclick(m_id, clicker); +} + +void LuaEntitySAO::setPos(const v3f &pos) +{ + if(isAttached()) + return; + m_base_position = pos; + sendPosition(false, true); +} + +void LuaEntitySAO::moveTo(v3f pos, bool continuous) +{ + if(isAttached()) + return; + m_base_position = pos; + if(!continuous) + sendPosition(true, true); +} + +float LuaEntitySAO::getMinimumSavedMovement() +{ + return 0.1 * BS; +} + +std::string LuaEntitySAO::getDescription() +{ + std::ostringstream oss; + oss << "LuaEntitySAO \"" << m_init_name << "\" "; + auto pos = floatToInt(m_base_position, BS); + oss << "at " << PP(pos); + return oss.str(); +} + +void LuaEntitySAO::setHP(s32 hp, const PlayerHPChangeReason &reason) +{ + m_hp = rangelim(hp, 0, U16_MAX); +} + +u16 LuaEntitySAO::getHP() const +{ + return m_hp; +} + +void LuaEntitySAO::setVelocity(v3f velocity) +{ + m_velocity = velocity; +} + +v3f LuaEntitySAO::getVelocity() +{ + return m_velocity; +} + +void LuaEntitySAO::setAcceleration(v3f acceleration) +{ + m_acceleration = acceleration; +} + +v3f LuaEntitySAO::getAcceleration() +{ + return m_acceleration; +} + +void LuaEntitySAO::setTextureMod(const std::string &mod) +{ + m_current_texture_modifier = mod; + // create message and add to list + m_messages_out.emplace(getId(), true, generateSetTextureModCommand()); +} + +std::string LuaEntitySAO::getTextureMod() const +{ + return m_current_texture_modifier; +} + + +std::string LuaEntitySAO::generateSetTextureModCommand() const +{ + std::ostringstream os(std::ios::binary); + // command + writeU8(os, AO_CMD_SET_TEXTURE_MOD); + // parameters + os << serializeString(m_current_texture_modifier); + return os.str(); +} + +std::string LuaEntitySAO::generateSetSpriteCommand(v2s16 p, u16 num_frames, + f32 framelength, bool select_horiz_by_yawpitch) +{ + std::ostringstream os(std::ios::binary); + // command + writeU8(os, AO_CMD_SET_SPRITE); + // parameters + writeV2S16(os, p); + writeU16(os, num_frames); + writeF32(os, framelength); + writeU8(os, select_horiz_by_yawpitch); + return os.str(); +} + +void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength, + bool select_horiz_by_yawpitch) +{ + std::string str = generateSetSpriteCommand( + p, + num_frames, + framelength, + select_horiz_by_yawpitch + ); + // create message and add to list + m_messages_out.emplace(getId(), true, str); +} + +std::string LuaEntitySAO::getName() +{ + return m_init_name; +} + +std::string LuaEntitySAO::getPropertyPacket() +{ + return generateSetPropertiesCommand(m_prop); +} + +void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) +{ + // If the object is attached client-side, don't waste bandwidth sending its position to clients + if(isAttached()) + return; + + m_last_sent_move_precision = m_base_position.getDistanceFrom( + m_last_sent_position); + m_last_sent_position_timer = 0; + m_last_sent_position = m_base_position; + m_last_sent_velocity = m_velocity; + //m_last_sent_acceleration = m_acceleration; + m_last_sent_rotation = m_rotation; + + float update_interval = m_env->getSendRecommendedInterval(); + + std::string str = generateUpdatePositionCommand( + m_base_position, + m_velocity, + m_acceleration, + m_rotation, + do_interpolate, + is_movement_end, + update_interval + ); + // create message and add to list + m_messages_out.emplace(getId(), false, str); +} + +bool LuaEntitySAO::getCollisionBox(aabb3f *toset) const +{ + if (m_prop.physical) + { + //update collision box + toset->MinEdge = m_prop.collisionbox.MinEdge * BS; + toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS; + + toset->MinEdge += m_base_position; + toset->MaxEdge += m_base_position; + + return true; + } + + return false; +} + +bool LuaEntitySAO::getSelectionBox(aabb3f *toset) const +{ + if (!m_prop.is_visible || !m_prop.pointable) { + return false; + } + + toset->MinEdge = m_prop.selectionbox.MinEdge * BS; + toset->MaxEdge = m_prop.selectionbox.MaxEdge * BS; + + return true; +} + +bool LuaEntitySAO::collideWithObjects() const +{ + return m_prop.collideWithObjects; +} -- cgit v1.2.3 From 3475759d1adbd4a64c6250fd87981f783e64f69c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 14 Apr 2020 14:11:33 +0200 Subject: Expose collision information to LuaEntity on_step --- builtin/game/features.lua | 1 + doc/lua_api.txt | 25 ++++++++++++++++++- src/script/common/c_content.cpp | 54 +++++++++++++++++++++++++++++++++++++++++ src/script/common/c_content.h | 4 ++- src/script/cpp_api/s_entity.cpp | 12 ++++++--- src/script/cpp_api/s_entity.h | 4 ++- src/server/luaentity_sao.cpp | 8 +++--- 7 files changed, 98 insertions(+), 10 deletions(-) (limited to 'src/server/luaentity_sao.cpp') diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 623f8183b..a15475333 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -16,6 +16,7 @@ core.features = { formspec_version_element = true, area_store_persistent_ids = true, pathfinder_works = true, + object_step_has_moveresult = true, } function core.has_feature(arg) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 3ca32649a..5e4e18b62 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4147,6 +4147,8 @@ Utilities area_store_persistent_ids = true, -- Whether minetest.find_path is functional (5.2.0) pathfinder_works = true, + -- Whether Collision info is available to an objects' on_step (5.3.0) + object_step_has_moveresult = true, } * `minetest.has_feature(arg)`: returns `boolean, missing_features` @@ -6579,7 +6581,10 @@ Used by `minetest.register_entity`. on_activate = function(self, staticdata, dtime_s), - on_step = function(self, dtime), + on_step = function(self, dtime, moveresult), + -- Called every server step + -- dtime: Elapsed time + -- moveresult: Table with collision info (only available if physical=true) on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir), @@ -6594,6 +6599,24 @@ Used by `minetest.register_entity`. -- for more info) by using a '_' prefix } +Collision info passed to `on_step`: + + { + touching_ground = boolean, + collides = boolean, + standing_on_object = boolean, + collisions = { + { + type = string, -- "node" or "object", + axis = string, -- "x", "y" or "z" + node_pos = vector, -- if type is "node" + old_speed = vector, + new_speed = vector, + }, + ... + } + } + ABM (ActiveBlockModifier) definition ------------------------------------ diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 8335fccb5..6ff642738 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_types.h" #include "nodedef.h" #include "object_properties.h" +#include "collision.h" #include "cpp_api/s_node.h" #include "lua_api/l_object.h" #include "lua_api/l_item.h" @@ -2002,3 +2003,56 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) } return stat; } + +/******************************************************************************/ + +// Indices must match values in `enum CollisionType` exactly!! +static const char *collision_type_str[] = { + "node", + "object", +}; + +// Indices must match values in `enum CollisionAxis` exactly!! +static const char *collision_axis_str[] = { + "x", + "y", + "z", +}; + +void push_collision_move_result(lua_State *L, const collisionMoveResult &res) +{ + lua_createtable(L, 0, 4); + + setboolfield(L, -1, "touching_ground", res.touching_ground); + setboolfield(L, -1, "collides", res.collides); + setboolfield(L, -1, "standing_on_object", res.standing_on_object); + + /* collisions */ + lua_createtable(L, res.collisions.size(), 0); + int i = 1; + for (const auto &c : res.collisions) { + lua_createtable(L, 0, 5); + + lua_pushstring(L, collision_type_str[c.type]); + lua_setfield(L, -2, "type"); + + assert(c.axis != COLLISION_AXIS_NONE); + lua_pushstring(L, collision_axis_str[c.axis]); + lua_setfield(L, -2, "axis"); + + if (c.type == COLLISION_NODE) { + push_v3s16(L, c.node_p); + lua_setfield(L, -2, "node_pos"); + } + + push_v3f(L, c.old_speed / BS); + lua_setfield(L, -2, "old_speed"); + + push_v3f(L, c.new_speed / BS); + lua_setfield(L, -2, "new_speed"); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "collisions"); + /**/ +} diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 9e755682f..8f32e58eb 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -63,7 +63,9 @@ struct EnumString; struct NoiseParams; class Schematic; class ServerActiveObject; +struct collisionMoveResult; +extern struct EnumString es_TileAnimationType[]; ContentFeatures read_content_features (lua_State *L, int index); void push_content_features (lua_State *L, @@ -196,4 +198,4 @@ void push_hud_element (lua_State *L, HudElement *elem); HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value); -extern struct EnumString es_TileAnimationType[]; +void push_collision_move_result(lua_State *L, const collisionMoveResult &res); diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index 26c7e8cd4..ea9320051 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -178,12 +178,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id, lua_pop(L, 1); } -void ScriptApiEntity::luaentity_Step(u16 id, float dtime) +void ScriptApiEntity::luaentity_Step(u16 id, float dtime, + const collisionMoveResult *moveresult) { SCRIPTAPI_PRECHECKHEADER - //infostream<<"scriptapi_luaentity_step: id="<getScriptIface()->luaentity_Step(m_id, dtime); + if(m_registered) { + m_env->getScriptIface()->luaentity_Step(m_id, dtime, moveresult_p); } if (!send_recommended) -- cgit v1.2.3 From 471e567657dfd75a994a1b54d7a23cf4541a6bed Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 26 May 2020 17:38:31 +0200 Subject: Value copy / allocation optimizations mostly in server, SAO and serialize code --- src/client/game.cpp | 2 +- src/client/sky.cpp | 4 ++-- src/client/sky.h | 2 +- src/content/mods.cpp | 2 +- src/content/mods.h | 2 +- src/script/cpp_api/s_node.cpp | 2 +- src/script/cpp_api/s_node.h | 2 +- src/server.cpp | 43 ++++++++++++++++++--------------------- src/server/luaentity_sao.cpp | 15 +++++--------- src/server/player_sao.cpp | 7 ++----- src/server/serveractiveobject.cpp | 2 +- src/server/serverinventorymgr.h | 2 +- src/serverenvironment.cpp | 8 ++++---- src/serverenvironment.h | 4 ++-- src/tool.cpp | 2 +- src/util/serialize.cpp | 17 ++++++++-------- 16 files changed, 52 insertions(+), 64 deletions(-) (limited to 'src/server/luaentity_sao.cpp') diff --git a/src/client/game.cpp b/src/client/game.cpp index e7663a113..cdf4da21e 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2806,7 +2806,7 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) // Shows the mesh skybox sky->setVisible(true); // Update mesh based skybox colours if applicable. - sky->setSkyColors(*event->set_sky); + sky->setSkyColors(event->set_sky->sky_color); sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, diff --git a/src/client/sky.cpp b/src/client/sky.cpp index d21b56fcc..2e0cbca86 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -907,9 +907,9 @@ void Sky::setStarCount(u16 star_count, bool force_update) } } -void Sky::setSkyColors(const SkyboxParams sky) +void Sky::setSkyColors(const SkyColor &sky_color) { - m_sky_params.sky_color = sky.sky_color; + m_sky_params.sky_color = sky_color; } void Sky::setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, diff --git a/src/client/sky.h b/src/client/sky.h index 8637f96d4..3227e8f59 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -94,7 +94,7 @@ public: m_bgcolor = bgcolor; m_skycolor = skycolor; } - void setSkyColors(const SkyboxParams sky); + void setSkyColors(const SkyColor &sky_color); void setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, std::string use_sun_tint); void setInClouds(bool clouds) { m_in_clouds = clouds; } diff --git a/src/content/mods.cpp b/src/content/mods.cpp index 676666f78..95ab0290a 100644 --- a/src/content/mods.cpp +++ b/src/content/mods.cpp @@ -167,7 +167,7 @@ std::map getModsInPath( return result; } -std::vector flattenMods(std::map mods) +std::vector flattenMods(const std::map &mods) { std::vector result; for (const auto &it : mods) { diff --git a/src/content/mods.h b/src/content/mods.h index 6e2506dbf..b3500fbc8 100644 --- a/src/content/mods.h +++ b/src/content/mods.h @@ -68,7 +68,7 @@ std::map getModsInPath( const std::string &path, bool part_of_modpack = false); // replaces modpack Modspecs with their content -std::vector flattenMods(std::map mods); +std::vector flattenMods(const std::map &mods); // a ModConfiguration is a subset of installed mods, expected to have // all dependencies fullfilled, so it can be used as a list of mods to diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index d93a4c3ad..e0f9bcd78 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -94,7 +94,7 @@ struct EnumString ScriptApiNode::es_NodeBoxType[] = }; bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, - ServerActiveObject *puncher, PointedThing pointed) + ServerActiveObject *puncher, const PointedThing &pointed) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h index e7c0c01d1..81b44f0f0 100644 --- a/src/script/cpp_api/s_node.h +++ b/src/script/cpp_api/s_node.h @@ -36,7 +36,7 @@ public: virtual ~ScriptApiNode() = default; bool node_on_punch(v3s16 p, MapNode node, - ServerActiveObject *puncher, PointedThing pointed); + ServerActiveObject *puncher, const PointedThing &pointed); bool node_on_dig(v3s16 p, MapNode node, ServerActiveObject *digger); void node_on_construct(v3s16 p, MapNode node); diff --git a/src/server.cpp b/src/server.cpp index 8c62584c8..6ecbd7097 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -718,34 +718,35 @@ void Server::AsyncRunStep(bool initial_step) std::unordered_map*> buffered_messages; // Get active object messages from environment + ActiveObjectMessage aom(0); + u32 aom_count = 0; for(;;) { - ActiveObjectMessage aom = m_env->getActiveObjectMessage(); - if (aom.id == 0) + if (!m_env->getActiveObjectMessage(&aom)) break; std::vector* message_list = nullptr; - std::unordered_map* >::iterator n; - n = buffered_messages.find(aom.id); + auto n = buffered_messages.find(aom.id); if (n == buffered_messages.end()) { message_list = new std::vector; buffered_messages[aom.id] = message_list; - } - else { + } else { message_list = n->second; } - message_list->push_back(aom); + message_list->push_back(std::move(aom)); + aom_count++; } - m_aom_buffer_counter->increment(buffered_messages.size()); + m_aom_buffer_counter->increment(aom_count); m_clients.lock(); const RemoteClientMap &clients = m_clients.getClientList(); // Route data to every client + std::string reliable_data, unreliable_data; for (const auto &client_it : clients) { + reliable_data.clear(); + unreliable_data.clear(); RemoteClient *client = client_it.second; PlayerSAO *player = getPlayerSAO(client->peer_id); - std::string reliable_data; - std::string unreliable_data; // Go through all objects in message buffer for (const auto &buffered_message : buffered_messages) { // If object does not exist or is not known by client, skip it @@ -770,19 +771,15 @@ void Server::AsyncRunStep(bool initial_step) client->m_known_objects.end()) continue; } - // Compose the full new data with header - std::string new_data; - // Add object id - char buf[2]; - writeU16((u8*)&buf[0], aom.id); - new_data.append(buf, 2); - // Add data - new_data += serializeString(aom.datastring); - // Add data to buffer - if (aom.reliable) - reliable_data += new_data; - else - unreliable_data += new_data; + + // Add full new data to appropriate buffer + std::string &buffer = aom.reliable ? reliable_data : unreliable_data; + char idbuf[2]; + writeU16((u8*) idbuf, aom.id); + // u16 id + // std::string data + buffer.append(idbuf, sizeof(idbuf)); + buffer.append(serializeString(aom.datastring)); } } /* diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index 51e1ca90e..8174da265 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -119,8 +119,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); } // If attached, check that our parent is still there. If it isn't, detach. @@ -228,16 +227,14 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) m_animation_sent = true; std::string str = generateUpdateAnimationCommand(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); } if (!m_animation_speed_sent) { m_animation_speed_sent = true; std::string str = generateUpdateAnimationSpeedCommand(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); } if (!m_bone_position_sent) { @@ -247,8 +244,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) std::string str = generateUpdateBonePositionCommand((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); } } @@ -256,8 +252,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) m_attachment_sent = true; std::string str = generateUpdateAttachmentCommand(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); } } diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index a4d0f4ce7..3ea3536e2 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -223,8 +223,7 @@ void PlayerSAO::step(float dtime, bool send_recommended) m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, str); m_env->getScriptIface()->player_event(this, "properties_changed"); } @@ -324,10 +323,8 @@ void PlayerSAO::step(float dtime, bool send_recommended) if (!m_attachment_sent) { m_attachment_sent = true; - std::string str = generateUpdateAttachmentCommand(); // create message and add to list - ActiveObjectMessage aom(getId(), true, str); - m_messages_out.push(aom); + m_messages_out.emplace(getId(), true, generateUpdateAttachmentCommand()); } } diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index 8345ebd47..fdcb13bd8 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -75,7 +75,7 @@ std::string ServerActiveObject::generateUpdateNametagAttributesCommand(const vid void ServerActiveObject::dumpAOMessagesToQueue(std::queue &queue) { while (!m_messages_out.empty()) { - queue.push(m_messages_out.front()); + queue.push(std::move(m_messages_out.front())); m_messages_out.pop(); } } \ No newline at end of file diff --git a/src/server/serverinventorymgr.h b/src/server/serverinventorymgr.h index d0aac4dae..ccf6d3b2e 100644 --- a/src/server/serverinventorymgr.h +++ b/src/server/serverinventorymgr.h @@ -57,4 +57,4 @@ private: ServerEnvironment *m_env = nullptr; std::unordered_map m_detached_inventories; -}; \ No newline at end of file +}; diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index d485c32e8..222b4d203 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1603,14 +1603,14 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock( } } -ActiveObjectMessage ServerEnvironment::getActiveObjectMessage() +bool ServerEnvironment::getActiveObjectMessage(ActiveObjectMessage *dest) { if(m_active_object_messages.empty()) - return ActiveObjectMessage(0); + return false; - ActiveObjectMessage message = m_active_object_messages.front(); + *dest = std::move(m_active_object_messages.front()); m_active_object_messages.pop(); - return message; + return true; } void ServerEnvironment::getSelectedActiveObjects( diff --git a/src/serverenvironment.h b/src/serverenvironment.h index e2f1a3784..4b453d39a 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -289,9 +289,9 @@ public: /* Get the next message emitted by some active object. - Returns a message with id=0 if no messages are available. + Returns false if no messages are available, true otherwise. */ - ActiveObjectMessage getActiveObjectMessage(); + bool getActiveObjectMessage(ActiveObjectMessage *dest); virtual void getSelectedActiveObjects( const core::line3d &shootline_on_map, diff --git a/src/tool.cpp b/src/tool.cpp index d911c518f..22e41d28e 100644 --- a/src/tool.cpp +++ b/src/tool.cpp @@ -130,7 +130,7 @@ void ToolCapabilities::serializeJson(std::ostream &os) const root["punch_attack_uses"] = punch_attack_uses; Json::Value groupcaps_object; - for (auto groupcap : groupcaps) { + for (const auto &groupcap : groupcaps) { groupcap.second.toJson(groupcaps_object[groupcap.first]); } root["groupcaps"] = groupcaps_object; diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp index f0e177d57..5b276668d 100644 --- a/src/util/serialize.cpp +++ b/src/util/serialize.cpp @@ -110,6 +110,7 @@ std::string serializeString(const std::string &plain) if (plain.size() > STRING_MAX_LEN) throw SerializationError("String too long for serializeString"); + s.reserve(2 + plain.size()); writeU16((u8 *)&buf[0], plain.size()); s.append(buf, 2); @@ -131,13 +132,11 @@ std::string deSerializeString(std::istream &is) if (s_size == 0) return s; - Buffer buf2(s_size); - is.read(&buf2[0], s_size); + s.resize(s_size); + is.read(&s[0], s_size); if (is.gcount() != s_size) throw SerializationError("deSerializeString: couldn't read all chars"); - s.reserve(s_size); - s.append(&buf2[0], s_size); return s; } @@ -152,6 +151,7 @@ std::string serializeWideString(const std::wstring &plain) if (plain.size() > WIDE_STRING_MAX_LEN) throw SerializationError("String too long for serializeWideString"); + s.reserve(2 + 2 * plain.size()); writeU16((u8 *)buf, plain.size()); s.append(buf, 2); @@ -196,13 +196,14 @@ std::wstring deSerializeWideString(std::istream &is) std::string serializeLongString(const std::string &plain) { + std::string s; char buf[4]; if (plain.size() > LONG_STRING_MAX_LEN) throw SerializationError("String too long for serializeLongString"); + s.reserve(4 + plain.size()); writeU32((u8*)&buf[0], plain.size()); - std::string s; s.append(buf, 4); s.append(plain); return s; @@ -227,13 +228,11 @@ std::string deSerializeLongString(std::istream &is) "string too long: " + itos(s_size) + " bytes"); } - Buffer buf2(s_size); - is.read(&buf2[0], s_size); + s.resize(s_size); + is.read(&s[0], s_size); if ((u32)is.gcount() != s_size) throw SerializationError("deSerializeLongString: couldn't read all chars"); - s.reserve(s_size); - s.append(&buf2[0], s_size); return s; } -- cgit v1.2.3 From c1e01bc638637efa788b5698238a465406bc3f5e Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 4 Jun 2020 19:31:46 +0200 Subject: Move shared parameters sending to UnitSAO (#9968) Better header sorting by topic Make UnitSAO-specific parameters private Skip redundant recursive entity sending code (since ~5.2.0) --- src/client/content_cao.cpp | 1 + src/server/luaentity_sao.cpp | 71 ++++++++++----------------------------- src/server/player_sao.cpp | 57 +++++++++---------------------- src/server/serveractiveobject.cpp | 7 +++- src/server/unit_sao.cpp | 33 ++++++++++++++++++ src/server/unit_sao.h | 56 +++++++++++++++++++----------- 6 files changed, 110 insertions(+), 115 deletions(-) (limited to 'src/server/luaentity_sao.cpp') diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index d0682e51e..702d089af 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -475,6 +475,7 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit parent->addAttachmentChild(m_id); } + updateAttachments(); } diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index 8174da265..d504c42ca 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -123,12 +123,11 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) } // If attached, check that our parent is still there. If it isn't, detach. - if(m_attachment_parent_id && !isAttached()) - { - m_attachment_parent_id = 0; - m_attachment_bone = ""; - m_attachment_position = v3f(0,0,0); - m_attachment_rotation = v3f(0,0,0); + if (m_attachment_parent_id && !isAttached()) { + // This is handled when objects are removed from the map + warningstream << "LuaEntitySAO::step() id=" << m_id << + " is attached to nonexistent parent. This is a bug." << std::endl; + clearParentAttachment(); sendPosition(false, true); } @@ -217,43 +216,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) } } - if (!m_armor_groups_sent) { - m_armor_groups_sent = true; - // create message and add to list - m_messages_out.emplace(getId(), true, generateUpdateArmorGroupsCommand()); - } - - if (!m_animation_sent) { - m_animation_sent = true; - std::string str = generateUpdateAnimationCommand(); - // create message and add to list - m_messages_out.emplace(getId(), true, str); - } - - if (!m_animation_speed_sent) { - m_animation_speed_sent = true; - std::string str = generateUpdateAnimationSpeedCommand(); - // create message and add to list - m_messages_out.emplace(getId(), true, str); - } - - if (!m_bone_position_sent) { - m_bone_position_sent = true; - for (std::unordered_map>::const_iterator - ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ - std::string str = generateUpdateBonePositionCommand((*ii).first, - (*ii).second.X, (*ii).second.Y); - // create message and add to list - m_messages_out.emplace(getId(), true, str); - } - } - - if (!m_attachment_sent) { - m_attachment_sent = true; - std::string str = generateUpdateAttachmentCommand(); - // create message and add to list - m_messages_out.emplace(getId(), true, str); - } + sendOutdatedData(); } std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) @@ -273,20 +236,19 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) msg_os << serializeLongString(getPropertyPacket()); // message 1 msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 - for (std::unordered_map>::const_iterator - ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { - msg_os << serializeLongString(generateUpdateBonePositionCommand((*ii).first, - (*ii).second.X, (*ii).second.Y)); // m_bone_position.size + 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 << serializeLongString(generateUpdateAttachmentCommand()); // 4 + int message_count = 4 + m_bone_position.size(); - for (std::unordered_set::const_iterator ii = m_attachment_child_ids.begin(); - (ii != m_attachment_child_ids.end()); ++ii) { - if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { + + for (const auto &id : getAttachmentChildIds()) { + if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - // TODO after a protocol bump: only send the object initialization data - // to older clients (superfluous since this message exists) - msg_os << serializeLongString(obj->generateUpdateInfantCommand(*ii, protocol_version)); + msg_os << serializeLongString(obj->generateUpdateInfantCommand( + id, protocol_version)); } } @@ -294,7 +256,8 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) message_count++; writeU8(os, message_count); - os.write(msg_os.str().c_str(), msg_os.str().size()); + std::string serialized = msg_os.str(); + os.write(serialized.c_str(), serialized.size()); // return result return os.str(); diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 9ea0743f7..67efed210 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -120,24 +120,26 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) msg_os << serializeLongString(getPropertyPacket()); // message 1 msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2 msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3 - for (std::unordered_map>::const_iterator - ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { - msg_os << serializeLongString(generateUpdateBonePositionCommand((*ii).first, - (*ii).second.X, (*ii).second.Y)); // m_bone_position.size + 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 << serializeLongString(generateUpdateAttachmentCommand()); // 4 msg_os << serializeLongString(generateUpdatePhysicsOverrideCommand()); // 5 + int message_count = 5 + m_bone_position.size(); - for (std::unordered_set::const_iterator ii = m_attachment_child_ids.begin(); - ii != m_attachment_child_ids.end(); ++ii) { - if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { + + for (const auto &id : getAttachmentChildIds()) { + if (ServerActiveObject *obj = m_env->getActiveObject(id)) { message_count++; - msg_os << serializeLongString(obj->generateUpdateInfantCommand(*ii, protocol_version)); + msg_os << serializeLongString(obj->generateUpdateInfantCommand( + id, protocol_version)); } } writeU8(os, message_count); - os.write(msg_os.str().c_str(), msg_os.str().size()); + std::string serialized = msg_os.str(); + os.write(serialized.c_str(), serialized.size()); // return result return os.str(); @@ -227,10 +229,10 @@ void PlayerSAO::step(float dtime, bool send_recommended) // If attached, check that our parent is still there. If it isn't, detach. if (m_attachment_parent_id && !isAttached()) { - m_attachment_parent_id = 0; - m_attachment_bone = ""; - m_attachment_position = v3f(0.0f, 0.0f, 0.0f); - m_attachment_rotation = v3f(0.0f, 0.0f, 0.0f); + // This is handled when objects are removed from the map + warningstream << "PlayerSAO::step() id=" << m_id << + " is attached to nonexistent parent. This is a bug." << std::endl; + clearParentAttachment(); setBasePosition(m_last_good_position); m_env->getGameDef()->SendMovePlayer(m_peer_id); } @@ -290,40 +292,13 @@ void PlayerSAO::step(float dtime, bool send_recommended) m_messages_out.emplace(getId(), false, str); } - if (!m_armor_groups_sent) { - m_armor_groups_sent = true; - // create message and add to list - m_messages_out.emplace(getId(), true, generateUpdateArmorGroupsCommand()); - } - if (!m_physics_override_sent) { m_physics_override_sent = true; // create message and add to list m_messages_out.emplace(getId(), true, generateUpdatePhysicsOverrideCommand()); } - if (!m_animation_sent) { - m_animation_sent = true; - // create message and add to list - m_messages_out.emplace(getId(), true, generateUpdateAnimationCommand()); - } - - if (!m_bone_position_sent) { - m_bone_position_sent = true; - for (std::unordered_map>::const_iterator - ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { - std::string str = generateUpdateBonePositionCommand((*ii).first, - (*ii).second.X, (*ii).second.Y); - // create message and add to list - m_messages_out.emplace(getId(), true, str); - } - } - - if (!m_attachment_sent) { - m_attachment_sent = true; - // create message and add to list - m_messages_out.emplace(getId(), true, generateUpdateAttachmentCommand()); - } + sendOutdatedData(); } std::string PlayerSAO::generateUpdatePhysicsOverrideCommand() const diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index dbf25e3bc..3341dc008 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -57,7 +57,12 @@ std::string ServerActiveObject::generateUpdateInfantCommand(u16 infant_id, u16 p // parameters writeU16(os, infant_id); writeU8(os, getSendType()); - os << serializeLongString(getClientInitializationData(protocol_version)); + if (protocol_version < 38) { + // 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)); + } return os.str(); } diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index 74b0508b8..ef0e87f2c 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -88,6 +88,39 @@ void UnitSAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotat *rotation = m_bone_position[bone].Y; } +// clang-format off +void UnitSAO::sendOutdatedData() +{ + if (!m_armor_groups_sent) { + m_armor_groups_sent = true; + m_messages_out.emplace(getId(), true, generateUpdateArmorGroupsCommand()); + } + + if (!m_animation_sent) { + m_animation_sent = true; + m_animation_speed_sent = true; + m_messages_out.emplace(getId(), true, generateUpdateAnimationCommand()); + } else if (!m_animation_speed_sent) { + // Animation speed is also sent when 'm_animation_sent == false' + m_animation_speed_sent = true; + m_messages_out.emplace(getId(), true, generateUpdateAnimationSpeedCommand()); + } + + if (!m_bone_position_sent) { + m_bone_position_sent = true; + for (const auto &bone_pos : m_bone_position) { + m_messages_out.emplace(getId(), true, generateUpdateBonePositionCommand( + bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); + } + } + + if (!m_attachment_sent) { + m_attachment_sent = true; + m_messages_out.emplace(getId(), true, generateUpdateAttachmentCommand()); + } +} +// clang-format on + void UnitSAO::setAttachment( int parent_id, const std::string &bone, v3f position, v3f rotation) { diff --git a/src/server/unit_sao.h b/src/server/unit_sao.h index c73115855..3cb7f0ad5 100644 --- a/src/server/unit_sao.h +++ b/src/server/unit_sao.h @@ -29,6 +29,11 @@ public: UnitSAO(ServerEnvironment *env, v3f pos); virtual ~UnitSAO() = default; + u16 getHP() const { return m_hp; } + // Use a function, if isDead can be defined by other conditions + bool isDead() const { return m_hp == 0; } + + // Rotation void setRotation(v3f rotation) { m_rotation = rotation; } const v3f &getRotation() const { return m_rotation; } v3f getRadRotation() { return m_rotation * core::DEGTORAD; } @@ -36,26 +41,28 @@ public: // Deprecated f32 getRadYawDep() const { return (m_rotation.Y + 90.) * core::DEGTORAD; } - u16 getHP() const { return m_hp; } - // Use a function, if isDead can be defined by other conditions - bool isDead() const { return m_hp == 0; } - - inline bool isAttached() const { return getParent(); } - + // Armor groups inline bool isImmortal() const { return itemgroup_get(getArmorGroups(), "immortal"); } - void setArmorGroups(const ItemGroupList &armor_groups); const ItemGroupList &getArmorGroups() const; + + // Animation void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop); void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop); void setAnimationSpeed(float frame_speed); + + // Bone position void setBonePosition(const std::string &bone, v3f position, v3f rotation); void getBonePosition(const std::string &bone, v3f *position, v3f *rotation); + + // Attachments + ServerActiveObject *getParent() const; + inline bool isAttached() const { return getParent(); } void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation); void getAttachment(int *parent_id, std::string *bone, v3f *position, @@ -65,10 +72,13 @@ public: void addAttachmentChild(int child_id); void removeAttachmentChild(int child_id); const std::unordered_set &getAttachmentChildIds() const; - ServerActiveObject *getParent() const; + + // Object properties ObjectProperties *accessObjectProperties(); void notifyObjectPropertiesModified(); + void sendOutdatedData(); + // Update packets std::string generateUpdateAttachmentCommand() const; std::string generateUpdateAnimationSpeedCommand() const; std::string generateUpdateAnimationCommand() const; @@ -77,21 +87,36 @@ public: const v3f &velocity, const v3f &acceleration, const v3f &rotation, bool do_interpolate, bool is_movement_end, f32 update_interval); std::string generateSetPropertiesCommand(const ObjectProperties &prop) const; - void sendPunchCommand(); static std::string generateUpdateBonePositionCommand(const std::string &bone, const v3f &position, const v3f &rotation); + void sendPunchCommand(); protected: u16 m_hp = 1; v3f m_rotation; + ItemGroupList m_armor_groups; + + // Object properties bool m_properties_sent = true; ObjectProperties m_prop; - ItemGroupList m_armor_groups; + // Stores position and rotation for each bone name + std::unordered_map> m_bone_position; + + int m_attachment_parent_id = 0; + +private: + void onAttach(int parent_id); + void onDetach(int parent_id); + + std::string generatePunchCommand(u16 result_hp) const; + + // Armor groups bool m_armor_groups_sent = false; + // Animation v2f m_animation_range; float m_animation_speed = 0.0f; float m_animation_blend = 0.0f; @@ -99,20 +124,13 @@ protected: bool m_animation_sent = false; bool m_animation_speed_sent = false; - // Stores position and rotation for each bone name - std::unordered_map> m_bone_position; + // Bone positions bool m_bone_position_sent = false; - int m_attachment_parent_id = 0; + // Attachments std::unordered_set m_attachment_child_ids; std::string m_attachment_bone = ""; v3f m_attachment_position; v3f m_attachment_rotation; bool m_attachment_sent = false; - -private: - void onAttach(int parent_id); - void onDetach(int parent_id); - - std::string generatePunchCommand(u16 result_hp) const; }; -- cgit v1.2.3