diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index f8d3a006b7..1cb9ebdaaa 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -204,3 +204,36 @@ core.register_chatcommand("text", { core.register_on_mods_loaded(function() core.log("Yeah preview mod is loaded with other CSM mods.") end) + + +-- Test commands + +local id_list = {} +core.register_chatcommand("test_hud", { + func = function(param) + if param == "list" then + print(dump(core.localplayer:hud_get_all())) + return true, "See stdout" + elseif param == "add" then + local n = math.random(5) + 1 + for i = 1, n do + id_list[#id_list + 1] = core.localplayer:hud_add({ + type = "text", + position = {x=math.random(), y=math.random()}, + name = "lab:" .. math.random(999), + text = math.random(999999) + }) + end + return true, "Added " .. n .. " elements" + elseif param == "clear" then + local n = #id_list + for _, id in ipairs(id_list) do + assert(core.localplayer:hud_remove(id)) + end + id_list = {} + return true, "Removed " .. n .. " elements" + end + + return false, "Unknown command?" + end +}) diff --git a/src/client/game.cpp b/src/client/game.cpp index 2bc63169e1..d443e96bf9 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2300,7 +2300,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) e->text2 = event->hudadd->text2; e->style = event->hudadd->style; e->hideable = event->hudadd->hideable; - m_hud_server_to_client[server_id] = player->addHud(std::move(e)); + m_hud_server_to_client[server_id] = player->hud.add(std::move(e)); delete event->hudadd; } @@ -2311,7 +2311,7 @@ void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *ca auto i = m_hud_server_to_client.find(event->hudrm.id); if (i != m_hud_server_to_client.end()) { - player->removeHud(i->second); + player->hud.remove(i->second); m_hud_server_to_client.erase(i); } @@ -2325,7 +2325,7 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca auto i = m_hud_server_to_client.find(event->hudchange->id); if (i != m_hud_server_to_client.end()) { - e = player->getHud(i->second); + e = player->hud.get(i->second); } if (e == nullptr) { diff --git a/src/client/hud.cpp b/src/client/hud.cpp index d55ae33893..a21a334c4f 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -308,7 +308,11 @@ void Hud::drawItems(v2s32 screen_pos, v2s32 screen_offset, s32 itemcount, v2f al bool Hud::hasElementOfType(HudElementType type) { - for (auto const &e : player->getHudElements()) { + for (auto const &e : player->hud.getElements()) { + if (e && e->type == type) + return true; + } + for (auto const &e : player->csm_hud.getElements()) { if (e && e->type == type) return true; } @@ -342,7 +346,12 @@ void Hud::drawLuaElements(const v3s16 &camera_offset, bool only_unhidable) std::vector elems; - for (auto const &e : player->getHudElements()) { + elems.reserve(player->hud.getElements().size() + player->csm_hud.getElements().size()); + for (auto const &e : player->hud.getElements()) { + if (e) + elems.push_back(e.get()); + } + for (auto const &e : player->csm_hud.getElements()) { if (e) elems.push_back(e.get()); } diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index a33178d0d7..a3ba7f7400 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -12,6 +12,7 @@ #include "map.h" #include "client.h" #include "content_cao.h" +#include "hud_element.h" /* PlayerSettings diff --git a/src/client/localplayer.h b/src/client/localplayer.h index 225b6df5c0..568be69774 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -106,6 +106,8 @@ public: float hurt_tilt_timer = 0.0f; float hurt_tilt_strength = 0.0f; + PlayerHud csm_hud; + GenericCAO *getCAO() const { return m_cao; } ClientActiveObject *getParent() const; diff --git a/src/player.cpp b/src/player.cpp index 10c421de2d..6f7ee9ffbc 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -103,41 +103,51 @@ ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const return (hand && selected->name.empty()) ? *hand : *selected; } -u32 Player::addHud(std::unique_ptr toadd) +u32 PlayerHud::getFreeID() { - u32 id = getFreeHudID(); + size_t size = m_elements.size(); + for (size_t i = 0; i != size; i++) { + if (!m_elements[i]) + return i; + } + return size; +} - if (id < hud.size()) - hud[id] = std::move(toadd); +u32 PlayerHud::add(std::unique_ptr toadd) +{ + u32 id = getFreeID(); + + if (id < m_elements.size()) + m_elements[id] = std::move(toadd); else - hud.push_back(std::move(toadd)); + m_elements.push_back(std::move(toadd)); return id; } -HudElement* Player::getHud(u32 id) +HudElement* PlayerHud::get(u32 id) { - if (id < hud.size()) - return hud[id].get(); + if (id < m_elements.size()) + return m_elements[id].get(); return nullptr; } -bool Player::removeHud(u32 id) +bool PlayerHud::remove(u32 id) { bool removed = false; - if (id < hud.size()) { - hud[id].reset(); + if (id < m_elements.size()) { + m_elements[id].reset(); removed = true; } // shrink list if possible - while (!hud.empty() && hud.back() == nullptr) - hud.pop_back(); + while (!m_elements.empty() && m_elements.back() == nullptr) + m_elements.pop_back(); return removed; } -void Player::clearHud() +void PlayerHud::clear() { - hud.clear(); + m_elements.clear(); } u16 Player::getMaxHotbarItemcount() diff --git a/src/player.h b/src/player.h index a989cef8e3..99c56d41d3 100644 --- a/src/player.h +++ b/src/player.h @@ -124,6 +124,25 @@ struct PlayerPhysicsOverride } }; +struct HudElement; + +struct PlayerHud +{ + const auto &getElements() const { return m_elements; } + /// Returns `nullptr` if not found + HudElement *get(u32 id); + /// Returns the ID of the added element + u32 add(std::unique_ptr e); + /// Returns whether removal succeeded + bool remove(u32 id); + void clear(); + +private: + u32 getFreeID(); + + std::vector> m_elements; +}; + /// @note numeric values are part of network protocol enum CameraMode : int { // not a mode. indicates that any may be used. @@ -137,8 +156,6 @@ enum CameraMode : int { extern const struct EnumString es_CameraMode[]; -struct HudElement; - class Player { public: @@ -159,16 +176,6 @@ public: const std::string& getName() const { return m_name; } - u32 getFreeHudID() - { - size_t size = hud.size(); - for (size_t i = 0; i != size; i++) { - if (!hud[i]) - return i; - } - return size; - } - CameraMode allowed_camera_mode = CAMERA_MODE_ANY; v3f eye_offset_first; @@ -219,11 +226,7 @@ public: return m_fov_override_spec; } - const auto &getHudElements() const { return hud; } - HudElement* getHud(u32 id); - u32 addHud(std::unique_ptr hud); - bool removeHud(u32 id); - void clearHud(); + PlayerHud hud; u32 hud_flags; s32 hud_hotbar_itemcount; @@ -236,7 +239,4 @@ protected: v3f m_speed; // velocity; in BS-space u16 m_wield_index = 0; PlayerFovSpec m_fov_override_spec = { 0.0f, false, 0.0f }; - -private: - std::vector> hud; }; diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 9f93318c50..2da8758630 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -360,7 +360,7 @@ int LuaLocalPlayer::l_hud_add(lua_State *L) auto elem = std::make_unique(); read_hud_element(L, elem.get()); - u32 id = player->addHud(std::move(elem)); + u32 id = player->csm_hud.add(std::move(elem)); if (id == U32_MAX) { return 0; } @@ -373,7 +373,7 @@ int LuaLocalPlayer::l_hud_remove(lua_State *L) { LocalPlayer *player = getobject(L, 1); u32 id = luaL_checkinteger(L, 2); - lua_pushboolean(L, player->removeHud(id)); + lua_pushboolean(L, player->csm_hud.remove(id)); return 1; } @@ -384,7 +384,7 @@ int LuaLocalPlayer::l_hud_change(lua_State *L) u32 id = luaL_checkinteger(L, 2); - HudElement *element = player->getHud(id); + HudElement *element = player->csm_hud.get(id); if (!element) return 0; @@ -403,7 +403,7 @@ int LuaLocalPlayer::l_hud_get(lua_State *L) u32 id = luaL_checkinteger(L, -1); - HudElement *e = player->getHud(id); + HudElement *e = player->csm_hud.get(id); if (!e) { lua_pushnil(L); return 1; @@ -422,7 +422,7 @@ int LuaLocalPlayer::l_hud_get_all(lua_State *L) lua_newtable(L); u32 id = 0; - for (auto const &elem : player->getHudElements()) { + for (auto const &elem : player->csm_hud.getElements()) { if (elem != nullptr) { push_hud_element(L, elem.get()); lua_rawseti(L, -2, id); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 0fd41d369d..f4e1a3181f 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2014,7 +2014,7 @@ int ObjectRef::l_hud_change(lua_State *L) u32 id = luaL_checkint(L, 2); - HudElement *elem = player->getHud(id); + HudElement *elem = player->hud.get(id); if (elem == nullptr) return 0; @@ -2041,7 +2041,7 @@ int ObjectRef::l_hud_get(lua_State *L) u32 id = luaL_checkint(L, 2); - HudElement *elem = player->getHud(id); + HudElement *elem = player->hud.get(id); if (elem == nullptr) return 0; @@ -2060,7 +2060,7 @@ int ObjectRef::l_hud_get_all(lua_State *L) lua_newtable(L); u32 id = 0; - for (auto const &elem : player->getHudElements()) { + for (auto const &elem : player->hud.getElements()) { if (elem != nullptr) { push_hud_element(L, elem.get()); lua_rawseti(L, -2, id); diff --git a/src/server.cpp b/src/server.cpp index edff9b5f59..f1cb641425 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1261,7 +1261,7 @@ PlayerSAO *Server::StageTwoClientInit(session_t peer_id) m_env->addPlayer(player); /* Clean up old HUD elements from previous sessions */ - player->clearHud(); + player->hud.clear(); /* Add object to environment */ PlayerSAO *playersao = sao.get(); @@ -3536,9 +3536,9 @@ u32 Server::hudAdd(RemotePlayer *player, std::unique_ptr form) if (!player) return -1; - u32 id = player->addHud(std::move(form)); + u32 id = player->hud.add(std::move(form)); - SendHUDAdd(player->getPeerId(), id, player->getHud(id)); + SendHUDAdd(player->getPeerId(), id, player->hud.get(id)); return id; } @@ -3547,7 +3547,7 @@ bool Server::hudRemove(RemotePlayer *player, u32 id) { if (!player) return false; - if (!player->removeHud(id)) + if (!player->hud.remove(id)) return false; SendHUDRemove(player->getPeerId(), id);