Compare commits
12 Commits
alpha-0.1.
...
alpha-0.2.
| Author | SHA1 | Date | |
|---|---|---|---|
| 784c558840 | |||
| 5d366b6f6c | |||
| f70661694b | |||
| 36a1ab0572 | |||
| 409268b604 | |||
| 174d144d26 | |||
| 360258e4cf | |||
| 2148c0050c | |||
| 61166023df | |||
| e7bf22cea6 | |||
| f09f79198d | |||
| 8c19d3cc3c |
@@ -12,11 +12,25 @@ enum class GameState : std::uint8_t {
|
|||||||
Game,
|
Game,
|
||||||
EndGame,
|
EndGame,
|
||||||
Disconnected,
|
Disconnected,
|
||||||
|
Closed
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<std::uint8_t, Player> PlayerList;
|
typedef std::map<std::uint8_t, Player> PlayerList;
|
||||||
|
|
||||||
class Game {
|
class GameListener {
|
||||||
|
public:
|
||||||
|
virtual void OnPlayerJoin(PlayerID player) {}
|
||||||
|
virtual void OnPlayerLeave(PlayerID player) {}
|
||||||
|
|
||||||
|
virtual void OnGameStateUpdate(GameState newState) {}
|
||||||
|
virtual void OnGameBegin() {}
|
||||||
|
virtual void OnGameEnd() {}
|
||||||
|
virtual void OnGameClose() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef utils::ObjectNotifier<GameListener> GameNotifier;
|
||||||
|
|
||||||
|
class Game : public GameNotifier {
|
||||||
protected:
|
protected:
|
||||||
World* m_World;
|
World* m_World;
|
||||||
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
||||||
|
|||||||
@@ -111,11 +111,13 @@ public:
|
|||||||
|
|
||||||
virtual bool OnDeath(World* world) { return true; }
|
virtual bool OnDeath(World* world) { return true; }
|
||||||
|
|
||||||
|
MobID getMobID() const { return m_ID; }
|
||||||
const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); }
|
const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); }
|
||||||
const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); }
|
const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); }
|
||||||
PlayerID getSender() const { return m_Sender; }
|
PlayerID getSender() const { return m_Sender; }
|
||||||
MobLevel getLevel() const { return m_Level; }
|
MobLevel getLevel() const { return m_Level; }
|
||||||
const MobStats* getStats() const { return getMobStats(getType(), m_Level); }
|
const MobStats* getStats() const { return getMobStats(getType(), m_Level); }
|
||||||
|
void setHealth(float newHealth) { m_Health = newHealth; }
|
||||||
float getHealth() const { return m_Health; }
|
float getHealth() const { return m_Health; }
|
||||||
bool isDead() const { return m_Health <= 0; }
|
bool isDead() const { return m_Health <= 0; }
|
||||||
bool isAlive() const { return m_Health > 0; }
|
bool isAlive() const { return m_Health > 0; }
|
||||||
|
|||||||
@@ -160,8 +160,6 @@ protected:
|
|||||||
public:
|
public:
|
||||||
World(Game* game);
|
World(Game* game);
|
||||||
|
|
||||||
static constexpr std::uint8_t CastleWidth = 5, CastleHeight = 5;
|
|
||||||
|
|
||||||
bool loadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
bool loadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
||||||
bool loadMap(const protocol::WorldDataPacket* worldData);
|
bool loadMap(const protocol::WorldDataPacket* worldData);
|
||||||
|
|
||||||
@@ -234,7 +232,6 @@ public:
|
|||||||
// MobListener
|
// MobListener
|
||||||
|
|
||||||
virtual void OnMobDamage(Mob* target, float damage, Tower* source);
|
virtual void OnMobDamage(Mob* target, float damage, Tower* source);
|
||||||
virtual void OnMobDie(Mob* mob);
|
|
||||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage);
|
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ class Client {
|
|||||||
private:
|
private:
|
||||||
render::Renderer* m_Renderer;
|
render::Renderer* m_Renderer;
|
||||||
ClientConnexion m_Connexion;
|
ClientConnexion m_Connexion;
|
||||||
ClientGame m_Game;
|
std::unique_ptr<ClientGame> m_Game;
|
||||||
bool m_Connected;
|
bool m_Connected;
|
||||||
public:
|
public:
|
||||||
Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(this), m_Connected(false) {}
|
Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(std::make_unique<ClientGame>(this)), m_Connected(false) {}
|
||||||
|
|
||||||
const ClientGame& getGame() const { return m_Game; }
|
const ClientGame& getGame() const { return *m_Game; }
|
||||||
const ClientConnexion& getConnexion() const { return m_Connexion; }
|
const ClientConnexion& getConnexion() const { return m_Connexion; }
|
||||||
render::Renderer* getRenderer() const { return m_Renderer; }
|
render::Renderer* getRenderer() const { return m_Renderer; }
|
||||||
|
|
||||||
ClientGame& getGame() { return m_Game; }
|
ClientGame& getGame() { return *m_Game; }
|
||||||
ClientConnexion& getConnexion() { return m_Connexion; }
|
ClientConnexion& getConnexion() { return m_Connexion; }
|
||||||
|
|
||||||
void tick(std::uint64_t delta);
|
void tick(std::uint64_t delta);
|
||||||
@@ -45,6 +45,8 @@ public:
|
|||||||
void placeTower(game::TowerType type, const glm::vec2& position);
|
void placeTower(game::TowerType type, const glm::vec2& position);
|
||||||
void upgradeTower(game::TowerID tower, game::TowerLevel level);
|
void upgradeTower(game::TowerID tower, game::TowerLevel level);
|
||||||
void removeTower(game::TowerID tower);
|
void removeTower(game::TowerID tower);
|
||||||
|
private:
|
||||||
|
void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public:
|
|||||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet);
|
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet);
|
||||||
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet);
|
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet);
|
||||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet);
|
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet);
|
||||||
|
virtual void HandlePacket(const protocol::UpdateMobStatesPacket* packet);
|
||||||
|
virtual void HandlePacket(const protocol::UpdateCastleLifePacket* packet);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,12 +61,11 @@ private:
|
|||||||
bool m_ServerRunning;
|
bool m_ServerRunning;
|
||||||
public:
|
public:
|
||||||
Server(const std::string& worldFilePath);
|
Server(const std::string& worldFilePath);
|
||||||
virtual ~Server() {}
|
virtual ~Server();
|
||||||
|
|
||||||
bool start(std::uint16_t port);
|
bool start(std::uint16_t port);
|
||||||
void stop();
|
void stop(); // force the server to stop
|
||||||
|
void close(); // at the end of a game
|
||||||
void lauchGame();
|
|
||||||
|
|
||||||
void removeConnexion(std::uint8_t connexionID);
|
void removeConnexion(std::uint8_t connexionID);
|
||||||
|
|
||||||
@@ -74,6 +73,8 @@ public:
|
|||||||
|
|
||||||
float getTPS() const { return m_TickCounter.getTPS(); }
|
float getTPS() const { return m_TickCounter.getTPS(); }
|
||||||
|
|
||||||
|
bool isRunning() { return m_ServerRunning; }
|
||||||
|
|
||||||
const ServerGame& getGame() const { return m_Game; }
|
const ServerGame& getGame() const { return m_Game; }
|
||||||
ServerGame& getGame() { return m_Game; }
|
ServerGame& getGame() { return m_Game; }
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ private:
|
|||||||
void accept();
|
void accept();
|
||||||
void updateSockets();
|
void updateSockets();
|
||||||
|
|
||||||
|
void clean();
|
||||||
void startThread();
|
void startThread();
|
||||||
void stopThread();
|
void stopThread();
|
||||||
void tick(std::uint64_t delta);
|
void tick(std::uint64_t delta);
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ namespace server {
|
|||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
class ServerGame : public game::Game {
|
class ServerGame : public game::Game, public game::GameListener {
|
||||||
private:
|
private:
|
||||||
Server* m_Server;
|
Server* m_Server;
|
||||||
ServerWorld m_ServerWorld;
|
ServerWorld m_ServerWorld;
|
||||||
utils::AutoTimer m_GoldMineTimer{ 1000, std::bind(&ServerGame::updateGoldMines, this) };
|
utils::AutoTimer m_GoldMineTimer;
|
||||||
|
utils::AutoTimer m_MobStatesTimer;
|
||||||
|
utils::CooldownTimer m_EndGameCooldown;
|
||||||
public:
|
public:
|
||||||
ServerGame(Server* server);
|
ServerGame(Server* server);
|
||||||
~ServerGame() {}
|
~ServerGame() {}
|
||||||
@@ -22,8 +24,16 @@ public:
|
|||||||
|
|
||||||
virtual void tick(std::uint64_t delta);
|
virtual void tick(std::uint64_t delta);
|
||||||
void startGame();
|
void startGame();
|
||||||
|
|
||||||
|
// GameListener
|
||||||
|
|
||||||
|
virtual void OnGameStateUpdate(game::GameState newState);
|
||||||
|
virtual void OnGameBegin();
|
||||||
|
virtual void OnGameEnd();
|
||||||
|
virtual void OnGameClose();
|
||||||
private:
|
private:
|
||||||
void balanceTeams();
|
void balanceTeams();
|
||||||
|
void updateMobStates();
|
||||||
void updateGoldMines();
|
void updateGoldMines();
|
||||||
void updatePlayerStats();
|
void updatePlayerStats();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ public:
|
|||||||
void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);
|
void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);
|
||||||
game::TowerPtr placeTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder);
|
game::TowerPtr placeTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder);
|
||||||
|
|
||||||
|
virtual void OnMobDie(game::Mob* mob);
|
||||||
|
|
||||||
|
virtual void OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
@@ -338,7 +338,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <basetsd.h>
|
#include <basetsd.h>
|
||||||
typedef SSIZE_T ssize_t;
|
//typedef SSIZE_T ssize_t;
|
||||||
|
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public:
|
|||||||
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
||||||
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
||||||
|
virtual void HandlePacket(const UpdateMobStatesPacket* packet) {}
|
||||||
|
virtual void HandlePacket(const UpdateCastleLifePacket* packet) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ enum class PacketType : std::uint8_t {
|
|||||||
UpdatePlayerTeam,
|
UpdatePlayerTeam,
|
||||||
ServerTps,
|
ServerTps,
|
||||||
WorldAddTower,
|
WorldAddTower,
|
||||||
|
UpdateMobStates,
|
||||||
|
UpdateCastleLife,
|
||||||
|
|
||||||
// client <--> server
|
// client <--> server
|
||||||
KeepAlive,
|
KeepAlive,
|
||||||
@@ -515,5 +517,60 @@ public:
|
|||||||
virtual PacketType getType() const { return PacketType::UpgradeTower; }
|
virtual PacketType getType() const { return PacketType::UpgradeTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MobState {
|
||||||
|
using Point = utils::shape::Point;
|
||||||
|
private:
|
||||||
|
game::MobID m_MobID;
|
||||||
|
Point m_MobPosition;
|
||||||
|
float m_MobLife;
|
||||||
|
game::Direction m_MobDirection;
|
||||||
|
public:
|
||||||
|
MobState() {}
|
||||||
|
MobState(game::MobID id, Point position, float life, game::Direction direction) :
|
||||||
|
m_MobID(id), m_MobPosition(position), m_MobLife(life), m_MobDirection(direction) {}
|
||||||
|
|
||||||
|
game::MobID getMobId() const { return m_MobID; }
|
||||||
|
Point getMobPosition() const { return m_MobPosition; }
|
||||||
|
float getMobLife() const { return m_MobLife; }
|
||||||
|
game::Direction getMobDirection() const { return m_MobDirection; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpdateMobStatesPacket : public Packet {
|
||||||
|
private:
|
||||||
|
std::vector<MobState> m_MobStates;
|
||||||
|
public:
|
||||||
|
UpdateMobStatesPacket() {}
|
||||||
|
virtual ~UpdateMobStatesPacket() {}
|
||||||
|
|
||||||
|
virtual DataBuffer Serialize() const;
|
||||||
|
virtual void Deserialize(DataBuffer& data);
|
||||||
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
|
void addMobState(MobState mobState) { m_MobStates.push_back(mobState); }
|
||||||
|
|
||||||
|
const std::vector<MobState>& getMobStates() const { return m_MobStates; }
|
||||||
|
|
||||||
|
virtual PacketType getType() const { return PacketType::UpdateMobStates; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpdateCastleLifePacket : public Packet {
|
||||||
|
private:
|
||||||
|
std::uint16_t m_CastleLife;
|
||||||
|
game::TeamColor m_Team;
|
||||||
|
public:
|
||||||
|
UpdateCastleLifePacket() {}
|
||||||
|
UpdateCastleLifePacket(std::uint16_t life, game::TeamColor team) : m_CastleLife(life), m_Team(team) {}
|
||||||
|
virtual ~UpdateCastleLifePacket() {}
|
||||||
|
|
||||||
|
virtual DataBuffer Serialize() const;
|
||||||
|
virtual void Deserialize(DataBuffer& data);
|
||||||
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
|
std::uint16_t getCastleLife() const { return m_CastleLife; }
|
||||||
|
game::TeamColor getTeamColor() const { return m_Team; }
|
||||||
|
|
||||||
|
virtual PacketType getType() const { return PacketType::UpdateCastleLife; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ public:
|
|||||||
virtual void render();
|
virtual void render();
|
||||||
|
|
||||||
void setCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
void setCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
||||||
|
bool isShown() { return m_Castle != nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -10,15 +10,17 @@ namespace gui {
|
|||||||
|
|
||||||
class GuiManager {
|
class GuiManager {
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<GuiWidget>> m_Widgets;
|
std::vector<std::unique_ptr<GuiWidget>> m_Widgets;
|
||||||
public:
|
public:
|
||||||
|
GuiManager(){}
|
||||||
|
|
||||||
void renderWidgets() {
|
void renderWidgets() {
|
||||||
for (auto widget : m_Widgets) {
|
for (auto& widget : m_Widgets) {
|
||||||
widget->render();
|
widget->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addWidgets(const std::shared_ptr<GuiWidget>& widget) {
|
void addWidget(std::unique_ptr<GuiWidget>&& widget) {
|
||||||
m_Widgets.push_back(std::move(widget));
|
m_Widgets.push_back(std::move(widget));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public:
|
|||||||
virtual void render();
|
virtual void render();
|
||||||
|
|
||||||
void setMob(const game::Mob* mob) { m_Mob = mob; }
|
void setMob(const game::Mob* mob) { m_Mob = mob; }
|
||||||
|
bool isShown() { return m_Mob != nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "render/gui/GuiManager.h"
|
||||||
|
|
||||||
struct SDL_Window;
|
struct SDL_Window;
|
||||||
typedef void* SDL_GLContext;
|
typedef void* SDL_GLContext;
|
||||||
|
|
||||||
@@ -20,15 +22,6 @@ class Client;
|
|||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
||||||
namespace gui {
|
|
||||||
|
|
||||||
class MainMenu;
|
|
||||||
class GameMenu;
|
|
||||||
class FrameMenu;
|
|
||||||
class UpdateMenu;
|
|
||||||
|
|
||||||
} // namespace gui
|
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
@@ -38,11 +31,8 @@ private:
|
|||||||
SDL_Window* m_Window;
|
SDL_Window* m_Window;
|
||||||
SDL_GLContext m_GlContext;
|
SDL_GLContext m_GlContext;
|
||||||
td::render::Renderer* m_Renderer;
|
td::render::Renderer* m_Renderer;
|
||||||
|
td::gui::GuiManager m_GuiManager;
|
||||||
std::unique_ptr<td::client::Client> m_Client;
|
std::unique_ptr<td::client::Client> m_Client;
|
||||||
std::unique_ptr<td::gui::MainMenu> m_MainMenu;
|
|
||||||
std::unique_ptr<td::gui::GameMenu> m_GameMenu;
|
|
||||||
std::unique_ptr<td::gui::FrameMenu> m_FrameMenu;
|
|
||||||
std::unique_ptr<td::gui::UpdateMenu> m_UpdateMenu;
|
|
||||||
public:
|
public:
|
||||||
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
||||||
~TowerGui();
|
~TowerGui();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "misc/DataBuffer.h"
|
#include "misc/DataBuffer.h"
|
||||||
|
|
||||||
#define TD_VERSION "alpha-0.1.1"
|
#define TD_VERSION "alpha-0.2.0"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ bool World::saveMap(const std::string& fileName) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::tick(std::uint64_t delta) {
|
void World::tick(std::uint64_t delta) {
|
||||||
|
if (m_Game->getGameState() != GameState::Game) return;
|
||||||
|
|
||||||
tickMobs(delta);
|
tickMobs(delta);
|
||||||
for (TowerPtr tower : m_Towers) {
|
for (TowerPtr tower : m_Towers) {
|
||||||
tower->tick(delta, this);
|
tower->tick(delta, this);
|
||||||
@@ -219,17 +221,6 @@ bool World::CanPlaceBigTower(const glm::vec2& worldPos, PlayerID playerID) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::OnMobDie(Mob* mob) {
|
|
||||||
if (mob->OnDeath(this)) { // check if the mob is actually dead (slimes ...)
|
|
||||||
//reward players
|
|
||||||
Player* sender = m_Game->getPlayerById(mob->getSender());
|
|
||||||
sender->addExp(mob->getStats()->getExpReward());
|
|
||||||
|
|
||||||
Player* killer = m_Game->getPlayerById(mob->getLastDamageTower()->getBuilder());
|
|
||||||
killer->addGold(mob->getStats()->getMoneyCost());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::cleanDeadMobs() {
|
void World::cleanDeadMobs() {
|
||||||
// safely remove mobs when unused
|
// safely remove mobs when unused
|
||||||
for (std::size_t i = 0; i < m_Mobs.size(); i++) {
|
for (std::size_t i = 0; i < m_Mobs.size(); i++) {
|
||||||
@@ -293,7 +284,7 @@ void World::OnExplosion(utils::shape::Circle explosion, float centerDamage, Towe
|
|||||||
void World::OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {
|
void World::OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {
|
||||||
enemyCastle->damage(damage);
|
enemyCastle->damage(damage);
|
||||||
if (enemyCastle->getLife() <= 0) {
|
if (enemyCastle->getLife() <= 0) {
|
||||||
// TODO: a team has won
|
m_Game->notifyListeners(&GameListener::OnGameEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,13 +40,19 @@ void Client::tick(std::uint64_t delta) {
|
|||||||
m_Connected = m_Connexion.updateSocket();
|
m_Connected = m_Connexion.updateSocket();
|
||||||
if (!m_Connected) {
|
if (!m_Connected) {
|
||||||
std::cout << "Disconnected ! (Reason : " << m_Connexion.getDisconnectReason() << ")\n";
|
std::cout << "Disconnected ! (Reason : " << m_Connexion.getDisconnectReason() << ")\n";
|
||||||
|
reset();
|
||||||
} else {
|
} else {
|
||||||
m_Game.tick(delta);
|
m_Game->tick(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::render() {
|
void Client::render() {
|
||||||
m_Game.renderWorld();
|
m_Game->renderWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::reset() {
|
||||||
|
m_Game.reset(0);
|
||||||
|
m_Game = std::make_unique<ClientGame>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::sendMobs(const std::vector<protocol::MobSend>& mobSends) {
|
void Client::sendMobs(const std::vector<protocol::MobSend>& mobSends) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
ClientConnexion::ClientConnexion() : Connexion(&m_Dispatcher) {
|
ClientConnexion::ClientConnexion() : Connexion(&m_Dispatcher), m_ServerTPS(0) {
|
||||||
registerHandlers();
|
registerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ WorldClient::WorldClient(ClientGame* game) : game::World(game), protocol::Packet
|
|||||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
|
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
|
||||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
|
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
|
||||||
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
|
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
|
||||||
|
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateCastleLife, this);
|
||||||
|
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMobStates, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldClient::HandlePacket(const protocol::WorldBeginDataPacket* packet) {
|
void WorldClient::HandlePacket(const protocol::WorldBeginDataPacket* packet) {
|
||||||
loadMap(packet);
|
loadMap(packet);
|
||||||
if (m_Game->getGameState() == game::GameState::Game) {
|
if (m_Game->getGameState() == game::GameState::Game) {
|
||||||
const game::Color& backgroundColor = getBackgroundColor();
|
const game::Color& backgroundColor = getBackgroundColor();
|
||||||
m_Game->getRenderer()->setBackgroundColor({ static_cast<float>(backgroundColor.r / 255.0f), static_cast<float>(backgroundColor.g / 255.0f),
|
m_Game->getRenderer()->setBackgroundColor({ static_cast<float>(backgroundColor.r / 255.0f), static_cast<float>(backgroundColor.g / 255.0f),
|
||||||
static_cast<float>(backgroundColor.b / 255.0f) });
|
static_cast<float>(backgroundColor.b / 255.0f) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,5 +55,22 @@ void WorldClient::HandlePacket(const protocol::RemoveTowerPacket* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldClient::HandlePacket(const protocol::UpdateMobStatesPacket* packet) {
|
||||||
|
for (auto mobState : packet->getMobStates()) {
|
||||||
|
game::MobID mobId = mobState.getMobId();
|
||||||
|
auto it = std::find_if(getMobList().begin(), getMobList().end(), [mobId](game::MobPtr mob) { return mob->getMobID() == mobId; });
|
||||||
|
if (it != getMobList().end()) {
|
||||||
|
game::MobPtr& mob = *it;
|
||||||
|
mob->setCenter(mobState.getMobPosition());
|
||||||
|
mob->setDirection(mobState.getMobDirection());
|
||||||
|
mob->setHealth(mobState.getMobLife());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldClient::HandlePacket(const protocol::UpdateCastleLifePacket* packet) {
|
||||||
|
getTeam(packet->getTeamColor()).getCastle().setLife(packet->getCastleLife());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -37,10 +37,8 @@ void Lobby::tick() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (utils::getTime() - m_StartTimerTime >= LobbyWaitingTime) {
|
if (utils::getTime() - m_StartTimerTime >= LobbyWaitingTime) {
|
||||||
protocol::UpdateGameStatePacket packet(game::GameState::Game);
|
m_Server->getGame().notifyListeners(&game::GameListener::OnGameBegin);
|
||||||
m_Server->broadcastPacket(&packet);
|
|
||||||
m_GameStarted = true;
|
m_GameStarted = true;
|
||||||
m_Server->lauchGame();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ Server::Server(const std::string& worldFilePath) : m_ServerRunning(false) {
|
|||||||
m_Game.getWorld()->loadMapFromFile(worldFilePath);
|
m_Game.getWorld()->loadMapFromFile(worldFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::lauchGame() {
|
Server::~Server() {
|
||||||
m_Game.startGame();
|
if (m_Thread.joinable())
|
||||||
|
m_Thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::startThread() {
|
void Server::startThread() {
|
||||||
@@ -29,13 +30,16 @@ void Server::startThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
clean();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::close() {
|
||||||
|
stopThread();
|
||||||
|
}
|
||||||
|
|
||||||
void Server::stopThread() {
|
void Server::stopThread() {
|
||||||
m_ServerRunning = false;
|
m_ServerRunning = false;
|
||||||
if (m_Thread.joinable())
|
|
||||||
m_Thread.join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::start(std::uint16_t port) {
|
bool Server::start(std::uint16_t port) {
|
||||||
@@ -54,19 +58,24 @@ bool Server::start(std::uint16_t port) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::stop() {
|
void Server::clean() {
|
||||||
if (!m_ServerRunning)
|
|
||||||
return;
|
|
||||||
stopThread();
|
|
||||||
|
|
||||||
protocol::DisconnectPacket packet("Server closed");
|
|
||||||
broadcastPacket(&packet);
|
|
||||||
|
|
||||||
m_Listener.close();
|
m_Listener.close();
|
||||||
m_Listener.destroy();
|
m_Listener.destroy();
|
||||||
|
|
||||||
m_Connections.clear();
|
m_Connections.clear();
|
||||||
getPlayers().clear();
|
getPlayers().clear();
|
||||||
|
|
||||||
|
std::cout << "Server successfully stopped !\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::stop() {
|
||||||
|
if (!m_ServerRunning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
protocol::DisconnectPacket packet("Server closed");
|
||||||
|
broadcastPacket(&packet);
|
||||||
|
|
||||||
|
stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::tick(std::uint64_t delta) {
|
void Server::tick(std::uint64_t delta) {
|
||||||
|
|||||||
@@ -4,14 +4,22 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace server {
|
namespace server {
|
||||||
|
|
||||||
ServerGame::ServerGame(server::Server* server) : game::Game(&m_ServerWorld), m_Server(server), m_ServerWorld(server, this) {
|
ServerGame::ServerGame(server::Server* server) : game::Game(&m_ServerWorld), m_Server(server), m_ServerWorld(server, this),
|
||||||
|
m_GoldMineTimer{ 1000, std::bind(&ServerGame::updateGoldMines, this) },
|
||||||
|
m_MobStatesTimer{ 5000, std::bind(&ServerGame::updateMobStates, this) },
|
||||||
|
m_EndGameCooldown{ 1000 * 10 } {
|
||||||
|
bindListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerGame::tick(std::uint64_t delta) {
|
void ServerGame::tick(std::uint64_t delta) {
|
||||||
if (m_GameState == game::GameState::Game) {
|
if (m_GameState == game::GameState::Game) {
|
||||||
Game::tick(delta);
|
Game::tick(delta);
|
||||||
|
m_MobStatesTimer.update(delta);
|
||||||
updatePlayerStats();
|
updatePlayerStats();
|
||||||
|
} else if (m_GameState == game::GameState::EndGame) {
|
||||||
|
if (m_EndGameCooldown.update(delta)) {
|
||||||
|
notifyListeners(&game::GameListener::OnGameClose);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +59,14 @@ void ServerGame::updateGoldMines() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerGame::updateMobStates() {
|
||||||
|
protocol::UpdateMobStatesPacket packet;
|
||||||
|
for (auto mob : m_World->getMobList()) {
|
||||||
|
packet.addMobState({ mob->getMobID(), mob->getCenter(), mob->getHealth(), mob->getDirection() });
|
||||||
|
}
|
||||||
|
m_Server->broadcastPacket(&packet);
|
||||||
|
}
|
||||||
|
|
||||||
void ServerGame::balanceTeams() {
|
void ServerGame::balanceTeams() {
|
||||||
for (auto& playerInfo : Game::m_Players) {
|
for (auto& playerInfo : Game::m_Players) {
|
||||||
game::Player& player = playerInfo.second;
|
game::Player& player = playerInfo.second;
|
||||||
@@ -70,5 +86,31 @@ void ServerGame::balanceTeams() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerGame::OnGameStateUpdate(game::GameState newState) {
|
||||||
|
setGameState(newState);
|
||||||
|
protocol::UpdateGameStatePacket packet(newState);
|
||||||
|
m_Server->broadcastPacket(&packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerGame::OnGameBegin() {
|
||||||
|
notifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Game);
|
||||||
|
startGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerGame::OnGameEnd() {
|
||||||
|
notifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::EndGame);
|
||||||
|
m_EndGameCooldown.applyCooldown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerGame::OnGameClose() {
|
||||||
|
notifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Closed);
|
||||||
|
// Disconnect clients
|
||||||
|
protocol::DisconnectPacket packet("Game finished");
|
||||||
|
m_Server->broadcastPacket(&packet);
|
||||||
|
|
||||||
|
// Closing server
|
||||||
|
m_Server->close();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -55,5 +55,24 @@ game::TowerPtr ServerWorld::placeTowerAt(game::TowerType type, std::int32_t x, s
|
|||||||
return tower;
|
return tower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerWorld::OnMobDie(game::Mob* mob) {
|
||||||
|
if (mob->OnDeath(this)) { // check if the mob is actually dead (slimes ...)
|
||||||
|
//reward players
|
||||||
|
game::Player* sender = m_Game->getPlayerById(mob->getSender());
|
||||||
|
sender->addExp(mob->getStats()->getExpReward());
|
||||||
|
|
||||||
|
game::Player* killer = m_Game->getPlayerById(mob->getLastDamageTower()->getBuilder());
|
||||||
|
killer->addGold(mob->getStats()->getMoneyCost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerWorld::OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage) {
|
||||||
|
// calling base class event
|
||||||
|
World::OnMobCastleDamage(damager, enemyCastle, damage);
|
||||||
|
|
||||||
|
protocol::UpdateCastleLifePacket packet(enemyCastle->getLife(), enemyCastle->getTeam()->getColor());
|
||||||
|
m_Server->broadcastPacket(&packet);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ static std::map<PacketType, PacketCreator> packets = {
|
|||||||
{PacketType::RemoveTower, []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
|
{PacketType::RemoveTower, []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
|
||||||
{PacketType::SendMobs, []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
|
{PacketType::SendMobs, []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
|
||||||
{PacketType::UpgradeTower, []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
|
{PacketType::UpgradeTower, []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
|
||||||
|
{PacketType::UpdateCastleLife, []() -> PacketPtr {return std::make_unique<UpdateCastleLifePacket>(); } },
|
||||||
|
{PacketType::UpdateMobStates, []() -> PacketPtr {return std::make_unique<UpdateMobStatesPacket>(); } },
|
||||||
};
|
};
|
||||||
|
|
||||||
PacketPtr createPacket(PacketType type, DataBuffer& buffer) {
|
PacketPtr createPacket(PacketType type, DataBuffer& buffer) {
|
||||||
|
|||||||
@@ -535,6 +535,34 @@ void UpgradeTowerPacket::Deserialize(DataBuffer& data) {
|
|||||||
data >> m_TowerID >> m_TowerLevel;
|
data >> m_TowerID >> m_TowerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataBuffer UpdateCastleLifePacket::Serialize() const {
|
||||||
|
DataBuffer data;
|
||||||
|
data << getID() << m_CastleLife << m_Team;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCastleLifePacket::Deserialize(DataBuffer& data) {
|
||||||
|
data >> m_CastleLife >> m_Team;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer UpdateMobStatesPacket::Serialize() const {
|
||||||
|
DataBuffer data;
|
||||||
|
data << getID() << static_cast<std::uint64_t>(m_MobStates.size());
|
||||||
|
for (auto mobState : m_MobStates) {
|
||||||
|
data << mobState;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMobStatesPacket::Deserialize(DataBuffer& data) {
|
||||||
|
std::uint64_t mobCount;
|
||||||
|
data >> mobCount;
|
||||||
|
m_MobStates.resize(mobCount);
|
||||||
|
for (std::uint64_t mobIndex = 0; mobIndex < mobCount; mobIndex++) {
|
||||||
|
data >> m_MobStates[mobIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
REGISTER_DISPATCH_CLASS(PlayerLoginPacket);
|
REGISTER_DISPATCH_CLASS(PlayerLoginPacket);
|
||||||
REGISTER_DISPATCH_CLASS(WorldBeginDataPacket);
|
REGISTER_DISPATCH_CLASS(WorldBeginDataPacket);
|
||||||
REGISTER_DISPATCH_CLASS(WorldDataPacket);
|
REGISTER_DISPATCH_CLASS(WorldDataPacket);
|
||||||
@@ -557,6 +585,8 @@ REGISTER_DISPATCH_CLASS(WorldAddTowerPacket);
|
|||||||
REGISTER_DISPATCH_CLASS(RemoveTowerPacket);
|
REGISTER_DISPATCH_CLASS(RemoveTowerPacket);
|
||||||
REGISTER_DISPATCH_CLASS(SendMobsPacket);
|
REGISTER_DISPATCH_CLASS(SendMobsPacket);
|
||||||
REGISTER_DISPATCH_CLASS(UpgradeTowerPacket);
|
REGISTER_DISPATCH_CLASS(UpgradeTowerPacket);
|
||||||
|
REGISTER_DISPATCH_CLASS(UpdateCastleLifePacket);
|
||||||
|
REGISTER_DISPATCH_CLASS(UpdateMobStatesPacket);
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
} // namespace td
|
} // namespace td
|
||||||
@@ -101,6 +101,8 @@ void WorldRenderer::renderTowers() const {
|
|||||||
void WorldRenderer::renderTileSelect() const {
|
void WorldRenderer::renderTileSelect() const {
|
||||||
if (ImGui::IsAnyItemHovered()) return;
|
if (ImGui::IsAnyItemHovered()) return;
|
||||||
|
|
||||||
|
if(m_MobTooltip->isShown() || m_CastleTooltip->isShown()) return;
|
||||||
|
|
||||||
Renderer::Model tileSelectModel;
|
Renderer::Model tileSelectModel;
|
||||||
tileSelectModel.vao = m_SelectTileVao.get();
|
tileSelectModel.vao = m_SelectTileVao.get();
|
||||||
tileSelectModel.positon = { (int)m_CursorPos.x, (int)m_CursorPos.y };
|
tileSelectModel.positon = { (int)m_CursorPos.x, (int)m_CursorPos.y };
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ GameMenu::GameMenu(client::Client* client) : GuiWidget(client), m_SummonMenu(std
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameMenu::render() {
|
void GameMenu::render() {
|
||||||
|
if(!m_Client->isConnected()) return;
|
||||||
|
|
||||||
if (getClient()->getGame().getGameState() == td::game::GameState::Lobby) {
|
if (getClient()->getGame().getGameState() == td::game::GameState::Lobby) {
|
||||||
ImGui::Begin("Lobby");
|
ImGui::Begin("Lobby");
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ MainMenu::~MainMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainMenu::render() {
|
void MainMenu::render() {
|
||||||
|
if (m_Server != nullptr && !m_Server->isRunning()) {
|
||||||
|
m_Server.reset(0); // destroying server if it stoped
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_Client->isConnected()) return;
|
||||||
|
|
||||||
ImGui::Begin("Main Menu");
|
ImGui::Begin("Main Menu");
|
||||||
if (ImGui::Button("Rejoindre une partie##join")) {
|
if (ImGui::Button("Rejoindre une partie##join")) {
|
||||||
ImGui::OpenPopup("Rejoindre une partie##join_popup");
|
ImGui::OpenPopup("Rejoindre une partie##join_popup");
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ namespace td {
|
|||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
void TowerGui::initWidgets() {
|
void TowerGui::initWidgets() {
|
||||||
m_MainMenu = std::make_unique<td::gui::MainMenu>(m_Client.get());
|
m_GuiManager.addWidget(std::make_unique<td::gui::MainMenu>(m_Client.get()));
|
||||||
m_GameMenu = std::make_unique<td::gui::GameMenu>(m_Client.get());
|
m_GuiManager.addWidget(std::make_unique<td::gui::GameMenu>(m_Client.get()));
|
||||||
m_FrameMenu = std::make_unique<td::gui::FrameMenu>(m_Client.get());
|
m_GuiManager.addWidget(std::make_unique<td::gui::FrameMenu>(m_Client.get()));
|
||||||
m_UpdateMenu = std::make_unique<td::gui::UpdateMenu>(m_Client.get());
|
m_GuiManager.addWidget(std::make_unique<td::gui::UpdateMenu>(m_Client.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TowerGui::TowerGui(SDL_Window* sdl_window, SDL_GLContext glContext, td::render::Renderer* renderer) : m_Window(sdl_window),
|
TowerGui::TowerGui(SDL_Window* sdl_window, SDL_GLContext glContext, td::render::Renderer* renderer) : m_Window(sdl_window),
|
||||||
@@ -69,13 +69,8 @@ void TowerGui::render() {
|
|||||||
beginFrame();
|
beginFrame();
|
||||||
|
|
||||||
m_Client->render();
|
m_Client->render();
|
||||||
if (m_Client->isConnected())
|
|
||||||
m_GameMenu->render();
|
|
||||||
else
|
|
||||||
m_MainMenu->render();
|
|
||||||
|
|
||||||
m_FrameMenu->render();
|
m_GuiManager.renderWidgets();
|
||||||
m_UpdateMenu->render();
|
|
||||||
|
|
||||||
endFrame();
|
endFrame();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user