From 129544d127a1678d5957e1325591066b0a7578c4 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Thu, 4 Nov 2021 10:03:37 +0100 Subject: [PATCH] feat: add summon menu --- include/game/Mobs.h | 60 +++++++++++++++++++- include/game/client/Client.h | 3 + include/game/server/ServerConnexion.h | 1 + include/protocol/PacketHandler.h | 1 + include/protocol/Protocol.h | 24 ++++++++ include/render/gui/GuiManager.h | 27 +++++++++ include/render/gui/GuiWidget.h | 25 ++++++++ include/render/gui/SummonMenu.h | 26 +++++++++ src/game/Mobs.cpp | 12 +++- src/game/client/Client.cpp | 5 ++ src/game/server/ServerConnexion.cpp | 12 ++++ src/protocol/PacketFactory.cpp | 1 + src/protocol/Protocol.cpp | 20 +++++++ src/render/gui/SummonMenu.cpp | 82 +++++++++++++++++++++++++++ src/render/gui/TowerGui.cpp | 59 ++++--------------- 15 files changed, 307 insertions(+), 51 deletions(-) create mode 100644 include/render/gui/GuiManager.h create mode 100644 include/render/gui/GuiWidget.h create mode 100644 include/render/gui/SummonMenu.h create mode 100644 src/render/gui/SummonMenu.cpp diff --git a/include/game/Mobs.h b/include/game/Mobs.h index 15e4034..3b4ef38 100644 --- a/include/game/Mobs.h +++ b/include/game/Mobs.h @@ -27,7 +27,9 @@ enum class MobType : std::uint8_t { Blaze, Witch, Slime, - Giant + Giant, + + MOB_COUNT }; typedef std::uint32_t MobID; @@ -132,6 +134,62 @@ public: virtual MobType getType() const { return MobType::Spider; } }; +class Skeleton : public Mob { +public: + Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Skeleton; } +}; + +class PigMan : public Mob { +public: + PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Pigman; } +}; + +class Creeper : public Mob { +public: + Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Creeper; } +}; + +class Silverfish : public Mob { +public: + Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Silverfish; } +}; + +class Blaze : public Mob { +public: + Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Blaze; } +}; + +class Witch : public Mob { +public: + Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Witch; } +}; + +class Slime : public Mob { +public: + Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Slime; } +}; + +class Giant : public Mob { +public: + Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } + + virtual MobType getType() const { return MobType::Giant; } +}; + namespace MobFactory { MobPtr createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender); } diff --git a/include/game/client/Client.h b/include/game/client/Client.h index 6f7d648..96cba66 100644 --- a/include/game/client/Client.h +++ b/include/game/client/Client.h @@ -6,6 +6,8 @@ #include "game/Team.h" #include "game/Player.h" +#include "protocol/Protocol.h" + #include "render/Renderer.h" #include "network/Network.h" @@ -39,6 +41,7 @@ public: bool isConnected() const { return m_Connexion.getSocketStatus() == network::Socket::Connected; } void selectTeam(game::TeamColor team); + void sendMobs(const std::vector& mobSends); }; } // namespace client diff --git a/include/game/server/ServerConnexion.h b/include/game/server/ServerConnexion.h index 841be8e..27bb654 100644 --- a/include/game/server/ServerConnexion.h +++ b/include/game/server/ServerConnexion.h @@ -38,6 +38,7 @@ public: virtual void HandlePacket(protocol::SelectTeamPacket* packet); virtual void HandlePacket(protocol::DisconnectPacket* packet); virtual void HandlePacket(protocol::PlaceTowerPacket* packet); + virtual void HandlePacket(protocol::SendMobsPacket* packet); std::uint8_t getID() const { return m_ID; } const game::Player* getPlayer() const { return m_Player; } diff --git a/include/protocol/PacketHandler.h b/include/protocol/PacketHandler.h index add3149..74034f5 100644 --- a/include/protocol/PacketHandler.h +++ b/include/protocol/PacketHandler.h @@ -36,6 +36,7 @@ public: virtual void HandlePacket(PlaceTowerPacket* packet) {} virtual void HandlePacket(WorldAddTowerPacket* packet) {} virtual void HandlePacket(WorldRemoveTowerPacket* packet) {} + virtual void HandlePacket(SendMobsPacket* packet) {} }; } // namespace protocol diff --git a/include/protocol/Protocol.h b/include/protocol/Protocol.h index f5efe41..11af889 100644 --- a/include/protocol/Protocol.h +++ b/include/protocol/Protocol.h @@ -28,6 +28,7 @@ enum class PacketType : std::uint8_t { UpdatePlayerTeam, ServerTps, SpawnMob, + SendMobs, PlaceTower, WorldAddTower, WorldRemoveTower, @@ -369,6 +370,29 @@ public: virtual PacketType getType() const { return PacketType::ServerTps; } }; +struct MobSend { // represents a mob send + game::MobType mobType; + game::MobLevel mobLevel; + std::uint8_t mobCount; // the max is 12 +}; + +class SendMobsPacket : public Packet { +private: + std::vector m_MobSends; +public: + SendMobsPacket() {} + SendMobsPacket(const std::vector& mobSends) : m_MobSends(mobSends) {} + virtual ~SendMobsPacket() {} + + virtual DataBuffer Serialize() const; + virtual void Deserialize(DataBuffer& data); + virtual void Dispatch(PacketHandler* handler); + + const std::vector& getMobSends() const { return m_MobSends; } + + virtual PacketType getType() const { return PacketType::SendMobs; } +}; + class SpawnMobPacket : public Packet { private: game::MobID m_MobID; diff --git a/include/render/gui/GuiManager.h b/include/render/gui/GuiManager.h new file mode 100644 index 0000000..4aad19b --- /dev/null +++ b/include/render/gui/GuiManager.h @@ -0,0 +1,27 @@ +#pragma once + +#include "GuiWidget.h" + +#include +#include + +namespace td { +namespace gui { + +class GuiManager { +private: + std::vector> m_Widgets; +public: + void renderWidgets(){ + for(auto widget : m_Widgets){ + widget->render(); + } + } + + void addWidgets(const std::shared_ptr& widget){ + m_Widgets.push_back(std::move(widget)); + } +}; + +} // namespace gui +} // namespace td diff --git a/include/render/gui/GuiWidget.h b/include/render/gui/GuiWidget.h new file mode 100644 index 0000000..605bb15 --- /dev/null +++ b/include/render/gui/GuiWidget.h @@ -0,0 +1,25 @@ +#pragma once + +namespace td { + +namespace client { +class Client; +} // namespace client + +namespace gui { + +class GuiWidget { +protected: + client::Client* m_Client; +public: + GuiWidget(client::Client* client) { + m_Client = client; + } + + client::Client* getClient() { return m_Client; } + + virtual void render() = 0; +}; + +} // namespace gui +} // namespace td diff --git a/include/render/gui/SummonMenu.h b/include/render/gui/SummonMenu.h new file mode 100644 index 0000000..01c3dbc --- /dev/null +++ b/include/render/gui/SummonMenu.h @@ -0,0 +1,26 @@ +#pragma once + +#include "GuiWidget.h" + +#include +#include "game/Mobs.h" + +namespace td { +namespace gui { + +class SummonMenu : public GuiWidget{ +private: + bool m_MenuOpened; + int m_ImageWidth = 100; + static constexpr int m_MobTypeCount = static_cast(td::game::MobType::MOB_COUNT); + std::array(m_MobTypeCount)> m_Values; +public: + SummonMenu(client::Client* client); + + virtual void render(); +private: + void setSummonMax(int valueIndex); +}; + +} // namespace gui +} // namespace td diff --git a/src/game/Mobs.cpp b/src/game/Mobs.cpp index aa2af3f..b5094ae 100644 --- a/src/game/Mobs.cpp +++ b/src/game/Mobs.cpp @@ -253,8 +253,16 @@ MobPtr MobFactory::createMob(MobID id, MobType type, std::uint8_t level, PlayerI using MobCreator = std::function(MobID, std::uint8_t, PlayerID)>; static std::map mobFactory = { - {MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, - {MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Skeleton, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Pigman, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Creeper, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Silverfish, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Blaze, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Witch, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Slime, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, + {MobType::Giant, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared(id, level, sender);} }, }; return mobFactory[type](id, level, sender); diff --git a/src/game/client/Client.cpp b/src/game/client/Client.cpp index ea0ea7e..6063825 100644 --- a/src/game/client/Client.cpp +++ b/src/game/client/Client.cpp @@ -49,5 +49,10 @@ void Client::render() { m_Game.renderWorld(); } +void Client::sendMobs(const std::vector& mobSends){ + protocol::SendMobsPacket packet(mobSends); + m_Connexion.sendPacket(&packet); +} + } // namespace client } // namespace td diff --git a/src/game/server/ServerConnexion.cpp b/src/game/server/ServerConnexion.cpp index df2178b..3bf52c8 100644 --- a/src/game/server/ServerConnexion.cpp +++ b/src/game/server/ServerConnexion.cpp @@ -39,6 +39,7 @@ void ServerConnexion::registerHandlers() { GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this); GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this); GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this); + GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this); } bool ServerConnexion::updateSocket() { @@ -147,6 +148,7 @@ void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) { game::TowerType towerType = packet->getTowerType(); const game::TowerInfo& towerInfo = game::getTowerInfo(towerType); server::ServerWorld* world = m_Server->getGame().getServerWorld(); + if (towerInfo.isBigTower()) { if (!world->CanPlaceBigTower({ packet->getTowerX(), packet->getTowerY() }, m_ID)) return; @@ -161,6 +163,16 @@ void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) { m_Server->broadcastPacket(&addTowerPacket); } +void ServerConnexion::HandlePacket(protocol::SendMobsPacket* packet) { + const std::vector& mobSent = packet->getMobSends(); + + //TODO: verify the packet + + for(protocol::MobSend mobSend : mobSent){ + m_Server->getGame().getServerWorld()->spawnMobs(mobSend.mobType, mobSend.mobLevel, m_ID, mobSend.mobCount); + } +} + ServerConnexion::~ServerConnexion() { if (GetDispatcher() != nullptr) GetDispatcher()->UnregisterHandler(this); diff --git a/src/protocol/PacketFactory.cpp b/src/protocol/PacketFactory.cpp index 8c6bbc7..1fd53ce 100644 --- a/src/protocol/PacketFactory.cpp +++ b/src/protocol/PacketFactory.cpp @@ -29,6 +29,7 @@ static std::map packets = { {PacketType::PlaceTower, []() -> Packet* {return new PlaceTowerPacket(); } }, {PacketType::WorldAddTower, []() -> Packet* {return new WorldAddTowerPacket(); } }, {PacketType::WorldRemoveTower, []() -> Packet* {return new WorldRemoveTowerPacket(); } }, + {PacketType::SendMobs, []() -> Packet* {return new SendMobsPacket(); } }, }; Packet* createPacket(PacketType type, DataBuffer& buffer) { diff --git a/src/protocol/Protocol.cpp b/src/protocol/Protocol.cpp index e371fd5..c82d0f7 100644 --- a/src/protocol/Protocol.cpp +++ b/src/protocol/Protocol.cpp @@ -495,6 +495,25 @@ void WorldRemoveTowerPacket::Deserialize(DataBuffer& data) { data >> m_TowerID; } +DataBuffer SendMobsPacket::Serialize() const { + DataBuffer data; + data << getID() << static_cast(m_MobSends.size()); + for(const MobSend& mobSend : m_MobSends){ + data << mobSend; + } + return data; +} + +void SendMobsPacket::Deserialize(DataBuffer& data) { + std::uint8_t mobSendCount; + data >> mobSendCount; + protocol::MobSend mobSend; + for(int i = 0; i < mobSendCount; i++){ + data >> mobSend; + m_MobSends.push_back(mobSend); + } +} + REGISTER_DISPATCH_CLASS(PlayerLoginPacket); REGISTER_DISPATCH_CLASS(WorldBeginDataPacket); REGISTER_DISPATCH_CLASS(WorldDataPacket); @@ -515,6 +534,7 @@ REGISTER_DISPATCH_CLASS(SpawnMobPacket); REGISTER_DISPATCH_CLASS(PlaceTowerPacket); REGISTER_DISPATCH_CLASS(WorldAddTowerPacket); REGISTER_DISPATCH_CLASS(WorldRemoveTowerPacket); +REGISTER_DISPATCH_CLASS(SendMobsPacket); } // namespace protocol } // namespace td \ No newline at end of file diff --git a/src/render/gui/SummonMenu.cpp b/src/render/gui/SummonMenu.cpp new file mode 100644 index 0000000..b464f21 --- /dev/null +++ b/src/render/gui/SummonMenu.cpp @@ -0,0 +1,82 @@ +#include "render/gui/SummonMenu.h" +#include "game/client/Client.h" +#include "render/gui/imgui/imgui.h" + +namespace td { +namespace gui { + +SummonMenu::SummonMenu(client::Client* client) : GuiWidget(client), m_MenuOpened(true){ + m_Values.fill(0); +} + +void SummonMenu::render(){ + if (m_MenuOpened) { + ImGui::Begin("Summon", &m_MenuOpened); + ImTextureID my_tex_id = ImGui::GetIO().Fonts->TexID; + for (int i = 0; i < m_MobTypeCount / 2; i++) { + ImGui::SameLine(); + ImGui::PushID(i); + ImGui::Image(my_tex_id, ImVec2(100, 100)); + ImGui::PopID(); + } + ImGui::Separator(); + ImGui::PushItemWidth(m_ImageWidth); + for (int i = 0; i < m_MobTypeCount / 2; i++) { + ImGui::SameLine(); + ImGui::PushID(i); + if (ImGui::InputInt("", m_Values.data() + i, 1, 10)) { + setSummonMax(i); + } + ImGui::PopID(); + } + ImGui::PopItemWidth(); + ImGui::Separator(); + for (int i = m_MobTypeCount / 2; i < m_MobTypeCount; i++) { + ImGui::SameLine(); + ImGui::PushID(i); + ImGui::Image(my_tex_id, ImVec2(100, 100)); + ImGui::PopID(); + } + ImGui::Separator(); + ImGui::PushItemWidth(m_ImageWidth); + for (int i = m_MobTypeCount / 2; i < m_MobTypeCount; i++) { + ImGui::SameLine(); + ImGui::PushID(i); + if (ImGui::InputInt("", m_Values.data() + i, 1, m_MobTypeCount)) { + setSummonMax(i); + } + ImGui::PopID(); + } + ImGui::PopItemWidth(); + if (ImGui::Button("Send")) { + std::vector mobSent; + protocol::MobSend mobSend; + for(int i = 0; i < m_MobTypeCount; i++){ + if(m_Values[i] != 0){ + mobSend.mobCount = m_Values[i]; + mobSend.mobLevel = 1; // TODO: add mob levels + mobSend.mobType = td::game::MobType(i); + mobSent.push_back(mobSend); + } + } + m_Client->sendMobs(mobSent); + m_Values.fill(0); + } + ImGui::End(); + } +} + +void SummonMenu::setSummonMax(int valueIndex){ + int& value = m_Values[valueIndex]; + value = std::max(0, value); + value = std::min(12, value); + int total = 0; + for (std::size_t i = 0; i < m_Values.size(); i++) { + total += m_Values[i]; + } + if (total == 13) // if the total is greater than the maximum, we substract the value + value--; +} + +} // namespace gui +} // namespace td diff --git a/src/render/gui/TowerGui.cpp b/src/render/gui/TowerGui.cpp index 64e312c..6c27949 100644 --- a/src/render/gui/TowerGui.cpp +++ b/src/render/gui/TowerGui.cpp @@ -18,6 +18,9 @@ #include "render/Renderer.h" #include "network/Network.h" +#include "render/gui/GuiManager.h" +#include "render/gui/SummonMenu.h" + #include #include @@ -28,9 +31,14 @@ static SDL_GLContext gl_context; static std::unique_ptr client; static std::thread* serverThread; static td::render::Renderer* renderer; +static td::gui::GuiManager guiManager; bool serverShouldStop = false; +void initWidgets(){ + guiManager.addWidgets(std::make_shared(client.get())); +} + void init(SDL_Window* sdl_window, SDL_GLContext sdlContext, td::render::Renderer* render) { window = sdl_window; gl_context = sdlContext; @@ -44,6 +52,7 @@ void init(SDL_Window* sdl_window, SDL_GLContext sdlContext, td::render::Renderer ImGui::GetIO().Fonts->AddFontDefault(&c); renderer = render; client = std::make_unique(render); + initWidgets(); } void beginFrame() { @@ -237,53 +246,7 @@ void capValues(int* values, int& value) { } void renderSummonMenu() { - static bool menu_open = true; - if (menu_open) { - - ImGui::Begin("Summon", &menu_open); - static int width = 100; - static int values[16]{ 0 }; - ImTextureID my_tex_id = ImGui::GetIO().Fonts->TexID; - for (int i = 0; i < 8; i++) { - ImGui::SameLine(); - ImGui::PushID(i); - ImGui::Image(my_tex_id, ImVec2(100, 100)); - ImGui::PopID(); - } - ImGui::Separator(); - ImGui::PushItemWidth(width); - for (int i = 0; i < 8; i++) { - ImGui::SameLine(); - ImGui::PushID(i); - if (ImGui::InputInt("", values + i, 1, 10)) { - capValues(values, values[i]); - } - ImGui::PopID(); - } - ImGui::PopItemWidth(); - ImGui::Separator(); - for (int i = 0; i < 8; i++) { - ImGui::SameLine(); - ImGui::PushID(i); - ImGui::Image(my_tex_id, ImVec2(100, 100)); - ImGui::PopID(); - } - ImGui::Separator(); - ImGui::PushItemWidth(width); - for (int i = 8; i < 16; i++) { - ImGui::SameLine(); - ImGui::PushID(i); - if (ImGui::InputInt("", values + i, 1, 10)) { - capValues(values, values[i]); - } - ImGui::PopID(); - } - ImGui::PopItemWidth(); - if (ImGui::Button("Send")) { - std::cout << "Sending Troops ...\n"; - } - ImGui::End(); - } + } void renderGame() { @@ -303,7 +266,7 @@ void renderGame() { showTPS(); showStats(); showPlayers(); - renderSummonMenu(); + guiManager.renderWidgets(); ImGui::End(); }