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/PlayerManager.h>
#include <td/common/StateMachine.h>
#include <optional>
namespace td {
namespace client {
class ClientState;
class LoggingState;
class Client : public StateMachine<Client, void, float> {
private:
std::shared_ptr<IClientSocket> m_Socket;
PlayerManager m_Players;
std::optional<PlayerID> m_Id;
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 Disconnect();
const PlayerManager& GetPlayers() const {
return m_Players;
}
const std::optional<PlayerID> GetId() const {
return m_Id;
}
friend class ClientState;
friend class LoggingState;
};
} // namespace client

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,13 +5,21 @@
namespace td {
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);
}
Client::~Client() {
Disconnect();
}
void Client::SendPacket(const protocol::PacketBase& a_Packet) {
m_Socket->Send(a_Packet);
}
void Client::Disconnect() {
m_Socket->Disconnect();
}
} // namespace client
} // namespace td

View File

@@ -15,5 +15,9 @@ std::shared_ptr<FakeSocket> FakeSocket::Connect(const std::shared_ptr<server::Fa
return socket;
}
void FakeSocket::Disconnect() {
m_Server->DisconnectFakePeer(m_PeerId);
}
} // namespace client
} // 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) {
m_StateMachine.m_Id = a_Packet->m_PlayerId;
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) {
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) {
if (!m_Players.contains(a_Player))
return;
std::cout << "[Server] " << +a_Player << " wants to disconnect !\n";
m_Socket->Disconnect(a_Player);
m_Socket->Broadcast(protocol::packets::PlayerLeavePacket(a_Player));
m_Players.erase(a_Player);
}
@@ -51,6 +50,7 @@ void PlayerManager::Disconnect(PlayerID a_Player) {
PlayerManager::~PlayerManager() {}
void PlayerManager::RemovePlayer(PlayerID a_Player) {
m_Socket->Disconnect(a_Player);
Disconnect(a_Player);
}

View File

@@ -26,12 +26,12 @@ namespace td {
DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
// server
auto serverFakeSocket = std::make_shared<server::FakeSocket>();
m_Server = std::make_unique<server::Server>(serverFakeSocket);
m_ServerSocket = std::make_shared<server::FakeSocket>();
m_Server = std::make_unique<server::Server>(m_ServerSocket);
// client
auto clientFakeSocket = client::FakeSocket::Connect(serverFakeSocket);
m_Client = std::make_unique<client::Client>(clientFakeSocket, "Player0");
auto clientFakeSocket = client::FakeSocket::Connect(m_ServerSocket);
m_Client = std::make_unique<client::Client>(clientFakeSocket);
// TODO: make it better
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::EntityRenderer>(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
m_ClientState = gameState;
@@ -50,11 +67,6 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
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
m_Camera.SetCamPos({77, 7, 13});
m_Camera.UpdatePerspective(m_StateMachine.GetAspectRatio());
@@ -73,10 +85,17 @@ void DebugWorldState::OnAspectRatioChange(float a_Ratio) {
void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) {
// temporary tests
if (a_Key == SDLK_A) {
switch (a_Key) {
case SDLK_A:
m_Client->SendPacket(td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1));
} else if (a_Key == SDLK_Z) {
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 <imgui.h>
#include <iostream>
#include <optional>
namespace td {
namespace render {
void PlayerListRenderer::Render(float a_Lerp) {
ImGui::Begin("Players");
if (ImGui::Button("Add player")) {
OnPlayerCreate();
}
std::optional<PlayerID> kick;
for (const auto& [id, player] : m_Players) {
ImGui::PushID(id);
ImGui::Text("[%i] %s", id, player.m_PlayerName.c_str());
ImGui::SameLine();
if (ImGui::Button("Kick")){
kick = id;
}
ImGui::PopID();
}
ImGui::End();
if (kick.has_value())
OnPlayerKick(*kick);
}
PlayerListRenderer::PlayerListRenderer(const client::PlayerManager& a_Players) : m_Players(a_Players) {}