This commit is contained in:
2025-08-23 12:54:48 +02:00
parent 73dd2dabfa
commit 1d436aa1c3
12 changed files with 93 additions and 24 deletions

View File

@@ -3,27 +3,38 @@
#include <client/IClientSocket.h> #include <client/IClientSocket.h>
#include <client/PlayerManager.h> #include <client/PlayerManager.h>
#include <td/common/StateMachine.h> #include <td/common/StateMachine.h>
#include <optional>
namespace td { namespace td {
namespace client { namespace client {
class ClientState; class ClientState;
class LoggingState;
class Client : public StateMachine<Client, void, float> { class Client : public StateMachine<Client, void, float> {
private: private:
std::shared_ptr<IClientSocket> m_Socket; std::shared_ptr<IClientSocket> m_Socket;
PlayerManager m_Players; PlayerManager m_Players;
std::optional<PlayerID> m_Id;
public: public:
Client(const std::shared_ptr<IClientSocket>& a_Socket, const std::string& a_PlayerName); Client(const std::shared_ptr<IClientSocket>& a_Socket);
~Client();
void SendPacket(const protocol::PacketBase& a_Packet); void SendPacket(const protocol::PacketBase& a_Packet);
void Disconnect();
const PlayerManager& GetPlayers() const { const PlayerManager& GetPlayers() const {
return m_Players; return m_Players;
} }
const std::optional<PlayerID> GetId() const {
return m_Id;
}
friend class ClientState; friend class ClientState;
friend class LoggingState;
}; };
} // namespace client } // namespace client

View File

@@ -14,6 +14,7 @@ class IClientSocket {
utils::Signal<const protocol::PacketBase&> OnReceive; utils::Signal<const protocol::PacketBase&> OnReceive;
virtual void Send(const protocol::PacketBase& a_Packet) = 0; virtual void Send(const protocol::PacketBase& a_Packet) = 0;
virtual void Disconnect() = 0;
IClientSocket() {} IClientSocket() {}
virtual ~IClientSocket() {} virtual ~IClientSocket() {}

View File

@@ -27,6 +27,7 @@ class FakeSocket : public IClientSocket {
void ReceiveFromFakePeer(PeerID a_Peer, const protocol::PacketBase& a_Packet); void ReceiveFromFakePeer(PeerID a_Peer, const protocol::PacketBase& a_Packet);
virtual void Send(const protocol::PacketBase& a_Packet) override; virtual void Send(const protocol::PacketBase& a_Packet) override;
virtual void Disconnect() override;
}; };
} // namespace client } // namespace client

View File

@@ -6,6 +6,7 @@
#include <td/render/Renderer.h> #include <td/render/Renderer.h>
#include <td/simulation/ClientSimulation.h> #include <td/simulation/ClientSimulation.h>
#include <client/state/GameState.h> #include <client/state/GameState.h>
#include <server/socket/FakeSocket.h>
namespace td { namespace td {
@@ -13,11 +14,13 @@ class DebugWorldState : public DisplayState {
private: private:
render::RenderPipeline m_Renderer; render::RenderPipeline m_Renderer;
render::Camera m_Camera; render::Camera m_Camera;
std::unique_ptr<client::Client> m_Client;
std::unique_ptr<client::Client> m_Client2;
std::unique_ptr<server::Server> m_Server; std::unique_ptr<server::Server> m_Server;
std::unique_ptr<client::Client> m_Client;
client::GameState* m_ClientState; client::GameState* m_ClientState;
std::vector<std::unique_ptr<client::Client>> m_FakeClients;
std::shared_ptr<server::FakeSocket> m_ServerSocket;
public: public:
DebugWorldState(Display& a_Display); DebugWorldState(Display& a_Display);
~DebugWorldState(); ~DebugWorldState();

View File

@@ -42,8 +42,11 @@ class RenderPipeline {
virtual ~RenderPipeline() {} virtual ~RenderPipeline() {}
template <typename T, typename... Args> template <typename T, typename... Args>
void AddRenderer(Args&&... args) { T& AddRenderer(Args&&... args) {
m_Renderers.push_back(std::make_unique<T>(args...)); auto ptr = std::make_unique<T>(args...);
auto rawPtr = ptr.get();
m_Renderers.push_back(std::move(ptr));
return *rawPtr;
} }
void Clear() { void Clear() {

View File

@@ -6,10 +6,17 @@
namespace td { namespace td {
namespace render { namespace render {
/**
* \brief This is a debug class
*/
class PlayerListRenderer : public BasicRenderer { class PlayerListRenderer : public BasicRenderer {
private: private:
const client::PlayerManager& m_Players; const client::PlayerManager& m_Players;
public: public:
utils::Signal<> OnPlayerCreate;
// utils::Signal<> OnRequestPOV;
utils::Signal<PlayerID> OnPlayerKick;
virtual void Render(float a_Lerp) override; virtual void Render(float a_Lerp) override;
PlayerListRenderer(const client::PlayerManager& a_Players); PlayerListRenderer(const client::PlayerManager& a_Players);

View File

@@ -5,13 +5,21 @@
namespace td { namespace td {
namespace client { namespace client {
Client::Client(const std::shared_ptr<IClientSocket>& a_Socket, const std::string& a_PlayerName) : m_Socket(a_Socket), m_Players(a_Socket) { Client::Client(const std::shared_ptr<IClientSocket>& a_Socket) : m_Socket(a_Socket), m_Players(a_Socket) {
// ChangeState<LoggingState>(a_PlayerName); // ChangeState<LoggingState>(a_PlayerName);
} }
Client::~Client() {
Disconnect();
}
void Client::SendPacket(const protocol::PacketBase& a_Packet) { void Client::SendPacket(const protocol::PacketBase& a_Packet) {
m_Socket->Send(a_Packet); m_Socket->Send(a_Packet);
} }
void Client::Disconnect() {
m_Socket->Disconnect();
}
} // namespace client } // namespace client
} // namespace td } // namespace td

View File

@@ -15,5 +15,9 @@ std::shared_ptr<FakeSocket> FakeSocket::Connect(const std::shared_ptr<server::Fa
return socket; return socket;
} }
void FakeSocket::Disconnect() {
m_Server->DisconnectFakePeer(m_PeerId);
}
} // namespace client } // namespace client
} // namespace td } // namespace td

View File

@@ -19,6 +19,7 @@ void LoggingState::Handle(const protocol::packets::PlayerJoinPacket& a_Packet) {
} }
void LoggingState::Handle(const protocol::packets::LoggingSuccessPacket& a_Packet) { void LoggingState::Handle(const protocol::packets::LoggingSuccessPacket& a_Packet) {
m_StateMachine.m_Id = a_Packet->m_PlayerId;
ChangeState<LobbyState>(); ChangeState<LobbyState>();
} }

View File

@@ -36,14 +36,13 @@ void PlayerManager::ConnectionHandler::Handle(const protocol::packets::Disconnec
PlayerManager::PlayerManager(const std::shared_ptr<IServerSocket>& a_Socket) : m_Socket(a_Socket) { PlayerManager::PlayerManager(const std::shared_ptr<IServerSocket>& a_Socket) : m_Socket(a_Socket) {
a_Socket->RegisterHandler([this](PlayerID a_PlayerId) { return std::make_unique<ConnectionHandler>(*this, a_PlayerId); }); a_Socket->RegisterHandler([this](PlayerID a_PlayerId) { return std::make_unique<ConnectionHandler>(*this, a_PlayerId); });
a_Socket->OnPlayerDisconnect.Connect(std::bind(&PlayerManager::RemovePlayer, this, std::placeholders::_1)); a_Socket->OnPlayerDisconnect.Connect(std::bind(&PlayerManager::Disconnect, this, std::placeholders::_1));
} }
void PlayerManager::Disconnect(PlayerID a_Player) { void PlayerManager::Disconnect(PlayerID a_Player) {
if (!m_Players.contains(a_Player)) if (!m_Players.contains(a_Player))
return; return;
std::cout << "[Server] " << +a_Player << " wants to disconnect !\n"; std::cout << "[Server] " << +a_Player << " wants to disconnect !\n";
m_Socket->Disconnect(a_Player);
m_Socket->Broadcast(protocol::packets::PlayerLeavePacket(a_Player)); m_Socket->Broadcast(protocol::packets::PlayerLeavePacket(a_Player));
m_Players.erase(a_Player); m_Players.erase(a_Player);
} }
@@ -51,6 +50,7 @@ void PlayerManager::Disconnect(PlayerID a_Player) {
PlayerManager::~PlayerManager() {} PlayerManager::~PlayerManager() {}
void PlayerManager::RemovePlayer(PlayerID a_Player) { void PlayerManager::RemovePlayer(PlayerID a_Player) {
m_Socket->Disconnect(a_Player);
Disconnect(a_Player); Disconnect(a_Player);
} }

View File

@@ -26,12 +26,12 @@ namespace td {
DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) { DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
// server // server
auto serverFakeSocket = std::make_shared<server::FakeSocket>(); m_ServerSocket = std::make_shared<server::FakeSocket>();
m_Server = std::make_unique<server::Server>(serverFakeSocket); m_Server = std::make_unique<server::Server>(m_ServerSocket);
// client // client
auto clientFakeSocket = client::FakeSocket::Connect(serverFakeSocket); auto clientFakeSocket = client::FakeSocket::Connect(m_ServerSocket);
m_Client = std::make_unique<client::Client>(clientFakeSocket, "Player0"); m_Client = std::make_unique<client::Client>(clientFakeSocket);
// TODO: make it better // TODO: make it better
m_Client->OnStateChange.Connect([this](client::Client::State& a_State) { m_Client->OnStateChange.Connect([this](client::Client::State& a_State) {
@@ -41,7 +41,24 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
m_Renderer.AddRenderer<render::WorldRenderer>(m_Camera, clientWorld); m_Renderer.AddRenderer<render::WorldRenderer>(m_Camera, clientWorld);
m_Renderer.AddRenderer<render::EntityRenderer>(m_Camera, clientWorld); m_Renderer.AddRenderer<render::EntityRenderer>(m_Camera, clientWorld);
m_Renderer.AddRenderer<render::TowerRenderer>(m_Camera, clientWorld); m_Renderer.AddRenderer<render::TowerRenderer>(m_Camera, clientWorld);
m_Renderer.AddRenderer<render::PlayerListRenderer>(m_Client->GetPlayers());
auto& list = m_Renderer.AddRenderer<render::PlayerListRenderer>(m_Client->GetPlayers());
list.OnPlayerCreate.Connect([this]() {
auto newSocket = client::FakeSocket::Connect(m_ServerSocket);
auto newClient = std::make_unique<client::Client>(newSocket);
newClient->ChangeState<client::LoggingState>("Bot");
m_FakeClients.push_back(std::move(newClient));
});
list.OnPlayerKick.Connect([this](PlayerID a_Player) {
auto it = std::find_if(m_FakeClients.begin(), m_FakeClients.end(), [a_Player](auto& clientPtr){
if (!clientPtr->GetId().has_value())
return false;
return clientPtr->GetId().value() == a_Player;
});
m_FakeClients.erase(it);
});
// update state // update state
m_ClientState = gameState; m_ClientState = gameState;
@@ -50,11 +67,6 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
m_Client->ChangeState<client::LoggingState>("Player0"); m_Client->ChangeState<client::LoggingState>("Player0");
// client2
auto clientFakeSocket2 = client::FakeSocket::Connect(serverFakeSocket);
m_Client2 = std::make_unique<client::Client>(clientFakeSocket2, "Player1");
m_Client2->ChangeState<client::LoggingState>("Player1");
// camera // camera
m_Camera.SetCamPos({77, 7, 13}); m_Camera.SetCamPos({77, 7, 13});
m_Camera.UpdatePerspective(m_StateMachine.GetAspectRatio()); m_Camera.UpdatePerspective(m_StateMachine.GetAspectRatio());
@@ -73,10 +85,17 @@ void DebugWorldState::OnAspectRatioChange(float a_Ratio) {
void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) { void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) {
// temporary tests // temporary tests
if (a_Key == SDLK_A) { switch (a_Key) {
m_Client->SendPacket(td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1)); case SDLK_A:
} else if (a_Key == SDLK_Z) { m_Client->SendPacket(td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1));
m_Client->SendPacket(td::protocol::packets::PlaceTowerPacket(td::TowerType::Archer, td::TowerCoords(77, 13))); break;
case SDLK_Z:
m_Client->SendPacket(td::protocol::packets::PlaceTowerPacket(td::TowerType::Archer, td::TowerCoords(77, 13)));
break;
default:
break;
} }
} }

View File

@@ -1,18 +1,29 @@
#include <td/render/renderer/PlayerListRenderer.h> #include <td/render/renderer/PlayerListRenderer.h>
#include <imgui.h> #include <imgui.h>
#include <optional>
#include <iostream>
namespace td { namespace td {
namespace render { namespace render {
void PlayerListRenderer::Render(float a_Lerp) { void PlayerListRenderer::Render(float a_Lerp) {
ImGui::Begin("Players"); ImGui::Begin("Players");
if (ImGui::Button("Add player")) {
OnPlayerCreate();
}
std::optional<PlayerID> kick;
for (const auto& [id, player] : m_Players) { for (const auto& [id, player] : m_Players) {
ImGui::PushID(id);
ImGui::Text("[%i] %s", id, player.m_PlayerName.c_str()); ImGui::Text("[%i] %s", id, player.m_PlayerName.c_str());
ImGui::SameLine();
if (ImGui::Button("Kick")){
kick = id;
}
ImGui::PopID();
} }
ImGui::End(); ImGui::End();
if (kick.has_value())
OnPlayerKick(*kick);
} }
PlayerListRenderer::PlayerListRenderer(const client::PlayerManager& a_Players) : m_Players(a_Players) {} PlayerListRenderer::PlayerListRenderer(const client::PlayerManager& a_Players) : m_Players(a_Players) {}