indent with tabs
This commit is contained in:
@@ -4,48 +4,48 @@ namespace td {
|
||||
|
||||
template<typename T>
|
||||
struct Vec2 {
|
||||
union {
|
||||
T x;
|
||||
T r;
|
||||
};
|
||||
union {
|
||||
T x;
|
||||
T r;
|
||||
};
|
||||
|
||||
union {
|
||||
T y;
|
||||
T g;
|
||||
};
|
||||
union {
|
||||
T y;
|
||||
T g;
|
||||
};
|
||||
|
||||
constexpr Vec2(T X = 0, T Y = 0) : x(X), y(Y) {}
|
||||
constexpr Vec2(T X = 0, T Y = 0) : x(X), y(Y) {}
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const Vec2<T>& vec2, const Vec2<T>& other) {
|
||||
return vec2.x == other.x && vec2.y == other.y;
|
||||
inline bool operator==(const Vec2<T>& vec2, const Vec2<T>& other) {
|
||||
return vec2.x == other.x && vec2.y == other.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Vec3 {
|
||||
union {
|
||||
T x;
|
||||
T r;
|
||||
};
|
||||
union {
|
||||
T x;
|
||||
T r;
|
||||
};
|
||||
|
||||
union {
|
||||
T y;
|
||||
T g;
|
||||
};
|
||||
union {
|
||||
T y;
|
||||
T g;
|
||||
};
|
||||
|
||||
union {
|
||||
T z;
|
||||
T b;
|
||||
};
|
||||
union {
|
||||
T z;
|
||||
T b;
|
||||
};
|
||||
|
||||
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
|
||||
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const Vec3<T>& vec3, const Vec3<T>& other) {
|
||||
return vec3.x == other.x && vec3.y == other.y && vec3.z == other.z;
|
||||
inline bool operator==(const Vec3<T>& vec3, const Vec3<T>& other) {
|
||||
return vec3.x == other.x && vec3.y == other.y && vec3.z == other.z;
|
||||
}
|
||||
|
||||
using Vec2i = Vec2<int>;
|
||||
|
||||
@@ -8,62 +8,62 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
enum class GameState : std::uint8_t {
|
||||
Lobby,
|
||||
Game,
|
||||
EndGame,
|
||||
Disconnected,
|
||||
Closed
|
||||
Lobby,
|
||||
Game,
|
||||
EndGame,
|
||||
Disconnected,
|
||||
Closed
|
||||
};
|
||||
|
||||
typedef std::map<std::uint8_t, Player> PlayerList;
|
||||
|
||||
class GameListener {
|
||||
public:
|
||||
virtual void OnPlayerJoin(PlayerID player) {}
|
||||
virtual void OnPlayerLeave(PlayerID player) {}
|
||||
virtual void OnPlayerJoin(PlayerID player) {}
|
||||
virtual void OnPlayerLeave(PlayerID player) {}
|
||||
|
||||
virtual void OnGameStateUpdate(GameState newState) {}
|
||||
virtual void OnGameBegin() {}
|
||||
virtual void OnGameEnd() {}
|
||||
virtual void OnGameClose() {}
|
||||
virtual void OnGameStateUpdate(GameState newState) {}
|
||||
virtual void OnGameBegin() {}
|
||||
virtual void OnGameEnd() {}
|
||||
virtual void OnGameClose() {}
|
||||
};
|
||||
|
||||
typedef utils::ObjectNotifier<GameListener> GameNotifier;
|
||||
|
||||
class Game : public GameNotifier {
|
||||
protected:
|
||||
World* m_World;
|
||||
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
||||
GameState m_GameState = GameState::Lobby;
|
||||
PlayerList m_Players;
|
||||
World* m_World;
|
||||
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
||||
GameState m_GameState = GameState::Lobby;
|
||||
PlayerList m_Players;
|
||||
public:
|
||||
Game(World* world);
|
||||
virtual ~Game();
|
||||
Game(World* world);
|
||||
virtual ~Game();
|
||||
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
|
||||
Team& GetRedTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
const Team& GetRedTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
Team& GetRedTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
const Team& GetRedTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
|
||||
Team& GetBlueTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)]; }
|
||||
const Team& GetBlueTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
Team& GetBlueTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)]; }
|
||||
const Team& GetBlueTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||
|
||||
Team& GetTeam(TeamColor team) { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||
const Team& GetTeam(TeamColor team) const { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||
Team& GetTeam(TeamColor team) { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||
const Team& GetTeam(TeamColor team) const { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||
|
||||
GameState GetGameState() const { return m_GameState; }
|
||||
void SetGameState(GameState gameState) { m_GameState = gameState; };
|
||||
GameState GetGameState() const { return m_GameState; }
|
||||
void SetGameState(GameState gameState) { m_GameState = gameState; };
|
||||
|
||||
const World* GetWorld() const { return m_World; }
|
||||
World* GetWorld() { return m_World; }
|
||||
const World* GetWorld() const { return m_World; }
|
||||
World* GetWorld() { return m_World; }
|
||||
|
||||
const PlayerList& GetPlayers() const { return m_Players; }
|
||||
PlayerList& GetPlayers() { return m_Players; }
|
||||
const PlayerList& GetPlayers() const { return m_Players; }
|
||||
PlayerList& GetPlayers() { return m_Players; }
|
||||
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
Player* GetPlayerById(PlayerID id);
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
Player* GetPlayerById(PlayerID id);
|
||||
|
||||
const TeamList& GetTeams() const { return m_Teams; }
|
||||
const TeamList& GetTeams() const { return m_Teams; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -10,26 +10,26 @@ namespace protocol {
|
||||
|
||||
class Connexion : public protocol::PacketHandler {
|
||||
protected:
|
||||
protocol::PacketDispatcher m_Dispatcher;
|
||||
protocol::PacketDispatcher m_Dispatcher;
|
||||
private:
|
||||
network::TCPSocket m_Socket;
|
||||
network::TCPSocket m_Socket;
|
||||
public:
|
||||
Connexion();
|
||||
Connexion(Connexion&& move);
|
||||
Connexion(protocol::PacketDispatcher* dispatcher);
|
||||
Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket);
|
||||
virtual ~Connexion();
|
||||
Connexion();
|
||||
Connexion(Connexion&& move);
|
||||
Connexion(protocol::PacketDispatcher* dispatcher);
|
||||
Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket);
|
||||
virtual ~Connexion();
|
||||
|
||||
virtual bool UpdateSocket();
|
||||
void CloseConnection();
|
||||
virtual bool UpdateSocket();
|
||||
void CloseConnection();
|
||||
|
||||
bool Connect(const std::string& address, std::uint16_t port);
|
||||
bool Connect(const std::string& address, std::uint16_t port);
|
||||
|
||||
network::Socket::Status GetSocketStatus() const { return m_Socket.GetStatus(); }
|
||||
network::Socket::Status GetSocketStatus() const { return m_Socket.GetStatus(); }
|
||||
|
||||
void SendPacket(const protocol::Packet* packet);
|
||||
void SendPacket(const protocol::Packet* packet);
|
||||
|
||||
REMOVE_COPY(Connexion);
|
||||
REMOVE_COPY(Connexion);
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -16,26 +16,26 @@ namespace game {
|
||||
struct WalkableTile;
|
||||
|
||||
enum class EffectType : std::uint8_t {
|
||||
Slowness = 0,
|
||||
Stun,
|
||||
Fire,
|
||||
Poison,
|
||||
Heal,
|
||||
Slowness = 0,
|
||||
Stun,
|
||||
Fire,
|
||||
Poison,
|
||||
Heal,
|
||||
};
|
||||
|
||||
enum class MobType : std::uint8_t {
|
||||
Zombie = 0,
|
||||
Spider,
|
||||
Skeleton,
|
||||
Pigman,
|
||||
Creeper,
|
||||
Silverfish,
|
||||
Blaze,
|
||||
Witch,
|
||||
Slime,
|
||||
Giant,
|
||||
Zombie = 0,
|
||||
Spider,
|
||||
Skeleton,
|
||||
Pigman,
|
||||
Creeper,
|
||||
Silverfish,
|
||||
Blaze,
|
||||
Witch,
|
||||
Slime,
|
||||
Giant,
|
||||
|
||||
MOB_COUNT
|
||||
MOB_COUNT
|
||||
};
|
||||
|
||||
typedef std::uint32_t MobID;
|
||||
@@ -45,34 +45,34 @@ typedef std::vector<EffectType> EffectImmunities;
|
||||
|
||||
class MobStats {
|
||||
private:
|
||||
float m_Damage;
|
||||
float m_Speed;
|
||||
Vec2f m_Size;
|
||||
std::uint16_t m_MoneyCost;
|
||||
std::uint16_t m_ExpCost;
|
||||
std::uint16_t m_MaxLife;
|
||||
std::uint16_t m_ExpReward;
|
||||
float m_Damage;
|
||||
float m_Speed;
|
||||
Vec2f m_Size;
|
||||
std::uint16_t m_MoneyCost;
|
||||
std::uint16_t m_ExpCost;
|
||||
std::uint16_t m_MaxLife;
|
||||
std::uint16_t m_ExpReward;
|
||||
public:
|
||||
MobStats(float damage, float speed, Vec2f size, std::uint16_t moneyCost,
|
||||
std::uint16_t expCost, std::uint16_t expReward,
|
||||
std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed),
|
||||
m_Size(size), m_MoneyCost(moneyCost), m_ExpCost(expCost),
|
||||
m_MaxLife(maxLife), m_ExpReward(expReward) {
|
||||
}
|
||||
MobStats(float damage, float speed, Vec2f size, std::uint16_t moneyCost,
|
||||
std::uint16_t expCost, std::uint16_t expReward,
|
||||
std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed),
|
||||
m_Size(size), m_MoneyCost(moneyCost), m_ExpCost(expCost),
|
||||
m_MaxLife(maxLife), m_ExpReward(expReward) {
|
||||
}
|
||||
|
||||
float GetDamage() const { return m_Damage; }
|
||||
float GetMovementSpeed() const { return m_Speed; }
|
||||
const Vec2f& GetSize() const { return m_Size; }
|
||||
std::uint16_t GetMoneyCost() const { return m_MoneyCost; }
|
||||
std::uint16_t GetExpCost() const { return m_ExpCost; }
|
||||
std::uint16_t GetExpReward() const { return m_ExpReward; }
|
||||
std::uint16_t GetMaxLife() const { return m_MaxLife; }
|
||||
float GetDamage() const { return m_Damage; }
|
||||
float GetMovementSpeed() const { return m_Speed; }
|
||||
const Vec2f& GetSize() const { return m_Size; }
|
||||
std::uint16_t GetMoneyCost() const { return m_MoneyCost; }
|
||||
std::uint16_t GetExpCost() const { return m_ExpCost; }
|
||||
std::uint16_t GetExpReward() const { return m_ExpReward; }
|
||||
std::uint16_t GetMaxLife() const { return m_MaxLife; }
|
||||
};
|
||||
|
||||
struct EffectDuration {
|
||||
EffectType type;
|
||||
float duration; // in seconds
|
||||
Tower* tower; // the tower that gived the effect
|
||||
EffectType type;
|
||||
float duration; // in seconds
|
||||
Tower* tower; // the tower that gived the effect
|
||||
};
|
||||
|
||||
const MobStats* GetMobStats(MobType type, std::uint8_t level);
|
||||
@@ -81,149 +81,149 @@ const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level)
|
||||
|
||||
class Mob : public utils::shape::Rectangle {
|
||||
protected:
|
||||
float m_Health;
|
||||
float m_Health;
|
||||
private:
|
||||
MobID m_ID;
|
||||
PlayerID m_Sender;
|
||||
MobLevel m_Level;
|
||||
Direction m_Direction;
|
||||
std::vector<EffectDuration> m_Effects;
|
||||
const Tower* m_LastDamage; // the last tower that damaged the mob
|
||||
MobID m_ID;
|
||||
PlayerID m_Sender;
|
||||
MobLevel m_Level;
|
||||
Direction m_Direction;
|
||||
std::vector<EffectDuration> m_Effects;
|
||||
const Tower* m_LastDamage; // the last tower that damaged the mob
|
||||
|
||||
utils::Timer m_EffectFireTimer;
|
||||
utils::Timer m_EffectPoisonTimer;
|
||||
utils::Timer m_EffectHealTimer;
|
||||
utils::Timer m_EffectFireTimer;
|
||||
utils::Timer m_EffectPoisonTimer;
|
||||
utils::Timer m_EffectHealTimer;
|
||||
|
||||
TeamCastle* m_CastleTarget;
|
||||
utils::CooldownTimer m_AttackTimer;
|
||||
TeamCastle* m_CastleTarget;
|
||||
utils::CooldownTimer m_AttackTimer;
|
||||
|
||||
public:
|
||||
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level),
|
||||
m_EffectFireTimer(1000), m_EffectPoisonTimer(1000),
|
||||
m_EffectHealTimer(1000), m_CastleTarget(nullptr), m_AttackTimer(1000) {
|
||||
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level),
|
||||
m_EffectFireTimer(1000), m_EffectPoisonTimer(1000),
|
||||
m_EffectHealTimer(1000), m_CastleTarget(nullptr), m_AttackTimer(1000) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual MobType GetType() const = 0;
|
||||
virtual MobType GetType() const = 0;
|
||||
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
|
||||
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 EffectImmunities& GetEffectImmunities() const { return GetMobEffectImmunities(GetType(), m_Level); }
|
||||
PlayerID GetSender() const { return m_Sender; }
|
||||
MobLevel GetLevel() const { return m_Level; }
|
||||
const MobStats* GetStats() const { return GetMobStats(GetType(), m_Level); }
|
||||
void SetHealth(float newHealth) { m_Health = newHealth; }
|
||||
float GetHealth() const { return m_Health; }
|
||||
bool IsDead() const { return m_Health <= 0; }
|
||||
bool IsAlive() const { return m_Health > 0; }
|
||||
const Tower* GetLastDamageTower() { return m_LastDamage; }
|
||||
bool HasReachedEnemyCastle() { return m_CastleTarget != nullptr; }
|
||||
MobID GetMobID() const { return m_ID; }
|
||||
const TowerImmunities& GetTowerImmunities() const { return GetMobTowerImmunities(GetType(), m_Level); }
|
||||
const EffectImmunities& GetEffectImmunities() const { return GetMobEffectImmunities(GetType(), m_Level); }
|
||||
PlayerID GetSender() const { return m_Sender; }
|
||||
MobLevel GetLevel() const { return m_Level; }
|
||||
const MobStats* GetStats() const { return GetMobStats(GetType(), m_Level); }
|
||||
void SetHealth(float newHealth) { m_Health = newHealth; }
|
||||
float GetHealth() const { return m_Health; }
|
||||
bool IsDead() const { return m_Health <= 0; }
|
||||
bool IsAlive() const { return m_Health > 0; }
|
||||
const Tower* GetLastDamageTower() { return m_LastDamage; }
|
||||
bool HasReachedEnemyCastle() { return m_CastleTarget != nullptr; }
|
||||
|
||||
void Damage(float dmg, const Tower* damager) { m_Health = std::max(0.0f, m_Health - dmg); m_LastDamage = damager; }
|
||||
void Heal(float heal) { m_Health = std::min(static_cast<float>(GetStats()->GetMaxLife()), m_Health + heal); }
|
||||
void SetMobReachedCastle(TeamCastle* castle) { m_CastleTarget = castle; } // used when mob is in front of the castle
|
||||
void Damage(float dmg, const Tower* damager) { m_Health = std::max(0.0f, m_Health - dmg); m_LastDamage = damager; }
|
||||
void Heal(float heal) { m_Health = std::min(static_cast<float>(GetStats()->GetMaxLife()), m_Health + heal); }
|
||||
void SetMobReachedCastle(TeamCastle* castle) { m_CastleTarget = castle; } // used when mob is in front of the castle
|
||||
|
||||
bool IsImmuneTo(TowerType type);
|
||||
bool IsImmuneTo(TowerType type);
|
||||
|
||||
bool IsImmuneTo(EffectType type);
|
||||
void AddEffect(EffectType type, float durationSec, Tower* tower);
|
||||
bool HasEffect(EffectType type);
|
||||
bool IsImmuneTo(EffectType type);
|
||||
void AddEffect(EffectType type, float durationSec, Tower* tower);
|
||||
bool HasEffect(EffectType type);
|
||||
|
||||
float GetTileX() { return GetCenterX() - static_cast<float>(static_cast<std::int32_t>(GetCenterX())); } // returns a float between 0 and 1 excluded
|
||||
float GetTileY() { return GetCenterY() - static_cast<float>(static_cast<std::int32_t>(GetCenterY())); } // returns a float between 0 and 1 excluded
|
||||
float GetTileX() { return GetCenterX() - static_cast<float>(static_cast<std::int32_t>(GetCenterX())); } // returns a float between 0 and 1 excluded
|
||||
float GetTileY() { return GetCenterY() - static_cast<float>(static_cast<std::int32_t>(GetCenterY())); } // returns a float between 0 and 1 excluded
|
||||
|
||||
Direction GetDirection() const { return m_Direction; }
|
||||
void SetDirection(Direction dir) { m_Direction = dir; }
|
||||
Direction GetDirection() const { return m_Direction; }
|
||||
void SetDirection(Direction dir) { m_Direction = dir; }
|
||||
protected:
|
||||
void InitMob() {
|
||||
m_Health = static_cast<float>(GetStats()->GetMaxLife());
|
||||
SetSize(GetStats()->GetSize().x, GetStats()->GetSize().y);
|
||||
}
|
||||
void InitMob() {
|
||||
m_Health = static_cast<float>(GetStats()->GetMaxLife());
|
||||
SetSize(GetStats()->GetSize().x, GetStats()->GetSize().y);
|
||||
}
|
||||
private:
|
||||
void UpdateEffects(std::uint64_t delta, World* world);
|
||||
void AttackCastle(std::uint64_t delta, World* world);
|
||||
void Move(std::uint64_t delta, World* world);
|
||||
void Walk(std::uint64_t delta, World* world);
|
||||
void MoveBack(const TeamCastle& castle, World* world);
|
||||
void ChangeDirection(const WalkableTile& tile, World* world);
|
||||
bool IsTouchingCastle(const TeamCastle& castle) const;
|
||||
EffectDuration& GetEffect(EffectType type);
|
||||
void UpdateEffects(std::uint64_t delta, World* world);
|
||||
void AttackCastle(std::uint64_t delta, World* world);
|
||||
void Move(std::uint64_t delta, World* world);
|
||||
void Walk(std::uint64_t delta, World* world);
|
||||
void MoveBack(const TeamCastle& castle, World* world);
|
||||
void ChangeDirection(const WalkableTile& tile, World* world);
|
||||
bool IsTouchingCastle(const TeamCastle& castle) const;
|
||||
EffectDuration& GetEffect(EffectType type);
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Mob> MobPtr;
|
||||
|
||||
class Zombie : public Mob {
|
||||
public:
|
||||
Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Zombie; }
|
||||
virtual MobType GetType() const { return MobType::Zombie; }
|
||||
};
|
||||
|
||||
class Spider : public Mob {
|
||||
public:
|
||||
Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Spider; }
|
||||
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) { InitMob(); }
|
||||
Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Skeleton; }
|
||||
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) { InitMob(); }
|
||||
PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Pigman; }
|
||||
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) { InitMob(); }
|
||||
Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Creeper; }
|
||||
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) { InitMob(); }
|
||||
Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Silverfish; }
|
||||
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) { InitMob(); }
|
||||
Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Blaze; }
|
||||
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) { InitMob(); }
|
||||
Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Witch; }
|
||||
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) { InitMob(); }
|
||||
Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Slime; }
|
||||
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) { InitMob(); }
|
||||
Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||
|
||||
virtual MobType GetType() const { return MobType::Giant; }
|
||||
virtual MobType GetType() const { return MobType::Giant; }
|
||||
};
|
||||
|
||||
namespace MobFactory {
|
||||
@@ -235,13 +235,13 @@ std::string GetMobName(MobType type);
|
||||
|
||||
class MobListener {
|
||||
public:
|
||||
virtual void OnMobSpawn(Mob* mob) {}
|
||||
virtual void OnMobDie(Mob* mob) {}
|
||||
virtual void OnMobSpawn(Mob* mob) {}
|
||||
virtual void OnMobDie(Mob* mob) {}
|
||||
|
||||
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
||||
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
||||
|
||||
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
|
||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}
|
||||
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
|
||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}
|
||||
};
|
||||
|
||||
typedef utils::ObjectNotifier<MobListener> MobNotifier;
|
||||
|
||||
@@ -10,41 +10,41 @@ namespace game {
|
||||
|
||||
class Player {
|
||||
private:
|
||||
TeamColor m_TeamColor;
|
||||
TeamColor m_TeamColor;
|
||||
PlayerUpgrades m_Upgrades;
|
||||
|
||||
std::uint32_t m_Gold;
|
||||
std::uint32_t m_Exp;
|
||||
std::string m_Name;
|
||||
PlayerID m_ID;
|
||||
std::uint32_t m_Gold;
|
||||
std::uint32_t m_Exp;
|
||||
std::string m_Name;
|
||||
PlayerID m_ID;
|
||||
|
||||
public:
|
||||
|
||||
Player(std::uint8_t id = 0) : m_TeamColor(TeamColor::None), m_Gold(0), m_Exp(0), m_ID(id) {}
|
||||
Player(std::uint8_t id = 0) : m_TeamColor(TeamColor::None), m_Gold(0), m_Exp(0), m_ID(id) {}
|
||||
|
||||
const std::string& GetName() const { return m_Name; }
|
||||
void SetName(const std::string& name) { m_Name = name; }
|
||||
const std::string& GetName() const { return m_Name; }
|
||||
void SetName(const std::string& name) { m_Name = name; }
|
||||
|
||||
TeamColor GetTeamColor() const { return m_TeamColor; }
|
||||
void SetTeamColor(TeamColor teamColor) { m_TeamColor = teamColor; }
|
||||
TeamColor GetTeamColor() const { return m_TeamColor; }
|
||||
void SetTeamColor(TeamColor teamColor) { m_TeamColor = teamColor; }
|
||||
|
||||
std::uint32_t GetGold() const { return m_Gold; }
|
||||
void SetGold(std::uint32_t gold) { m_Gold = gold; }
|
||||
void AddGold(std::uint32_t gold) { m_Gold += gold; }
|
||||
void RemoveGold(std::uint32_t gold) { m_Gold -= gold; }
|
||||
std::uint32_t GetGold() const { return m_Gold; }
|
||||
void SetGold(std::uint32_t gold) { m_Gold = gold; }
|
||||
void AddGold(std::uint32_t gold) { m_Gold += gold; }
|
||||
void RemoveGold(std::uint32_t gold) { m_Gold -= gold; }
|
||||
|
||||
std::uint32_t GetExp() const { return m_Exp; }
|
||||
void SetExp(std::uint32_t exp) { m_Exp = exp; }
|
||||
void AddExp(std::uint32_t exp) { m_Exp += exp; }
|
||||
void RemoveExp(std::uint32_t exp) { m_Exp -= exp; }
|
||||
std::uint32_t GetExp() const { return m_Exp; }
|
||||
void SetExp(std::uint32_t exp) { m_Exp = exp; }
|
||||
void AddExp(std::uint32_t exp) { m_Exp += exp; }
|
||||
void RemoveExp(std::uint32_t exp) { m_Exp -= exp; }
|
||||
|
||||
const PlayerUpgrades& getUpgrades() const { return m_Upgrades; }
|
||||
PlayerUpgrades& getUpgrades() { return m_Upgrades; }
|
||||
|
||||
bool HasEnoughGold(std::uint32_t gold) const { return m_Gold >= gold; }
|
||||
bool HasEnoughExp(std::uint32_t exp) const { return m_Exp >= exp; }
|
||||
bool HasEnoughGold(std::uint32_t gold) const { return m_Gold >= gold; }
|
||||
bool HasEnoughExp(std::uint32_t exp) const { return m_Exp >= exp; }
|
||||
|
||||
PlayerID GetID() const { return m_ID; }
|
||||
PlayerID GetID() const { return m_ID; }
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -7,27 +7,27 @@ namespace game {
|
||||
|
||||
class PlayerUpgrades {
|
||||
private:
|
||||
std::uint8_t m_ClickerLevel;
|
||||
std::uint8_t m_ClickerLevel;
|
||||
std::uint8_t m_GoldPerSecond;
|
||||
std::array<std::uint8_t, static_cast<std::size_t>(MobType::MOB_COUNT)> m_MobsUpgradeLevel;
|
||||
std::array<std::uint8_t, static_cast<std::size_t>(MobType::MOB_COUNT)> m_MobsUpgradeLevel;
|
||||
public:
|
||||
static const int MAX_MOB_LEVEL = 5;
|
||||
static const int MAX_CLICKER_LEVEL = 3;
|
||||
static const int MAX_MOB_LEVEL = 5;
|
||||
static const int MAX_CLICKER_LEVEL = 3;
|
||||
|
||||
PlayerUpgrades() : m_ClickerLevel(1), m_GoldPerSecond(5) {}
|
||||
PlayerUpgrades() : m_ClickerLevel(1), m_GoldPerSecond(5) {}
|
||||
|
||||
std::uint8_t GetClickerLevel() const { return m_ClickerLevel; }
|
||||
std::uint8_t GetMobUpgradeLevel(MobType mob) const { return m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob)); }
|
||||
std::uint8_t GetGoldPerSecond() const { return m_GoldPerSecond; }
|
||||
std::uint8_t GetClickerLevel() const { return m_ClickerLevel; }
|
||||
std::uint8_t GetMobUpgradeLevel(MobType mob) const { return m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob)); }
|
||||
std::uint8_t GetGoldPerSecond() const { return m_GoldPerSecond; }
|
||||
|
||||
|
||||
void UpgradeMob(MobType mob) {
|
||||
void UpgradeMob(MobType mob) {
|
||||
std::uint8_t& mobLevel = m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob));
|
||||
mobLevel = std::min(mobLevel + 1, MAX_MOB_LEVEL);
|
||||
mobLevel = std::min(mobLevel + 1, MAX_MOB_LEVEL);
|
||||
}
|
||||
|
||||
void UpgradeClicker() { m_ClickerLevel = std::min(m_ClickerLevel + 1, MAX_CLICKER_LEVEL); }
|
||||
void SetGoldPerSecond(std::uint8_t goldPerSecond) { m_GoldPerSecond = goldPerSecond; }
|
||||
void SetGoldPerSecond(std::uint8_t goldPerSecond) { m_GoldPerSecond = goldPerSecond; }
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -14,76 +14,76 @@ namespace game {
|
||||
class Player;
|
||||
|
||||
enum class TeamColor : std::int8_t {
|
||||
None = -1,
|
||||
Red,
|
||||
Blue
|
||||
None = -1,
|
||||
Red,
|
||||
Blue
|
||||
};
|
||||
|
||||
class Spawn : public utils::shape::Rectangle {
|
||||
private:
|
||||
Direction m_Direction;
|
||||
Direction m_Direction;
|
||||
public:
|
||||
Spawn() {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
Spawn() {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
|
||||
Direction GetDirection() const { return m_Direction; }
|
||||
Direction GetDirection() const { return m_Direction; }
|
||||
|
||||
void SetDirection(Direction direction) { m_Direction = direction; }
|
||||
void SetDirection(Direction direction) { m_Direction = direction; }
|
||||
};
|
||||
|
||||
class Team;
|
||||
|
||||
class TeamCastle : public utils::shape::Rectangle {
|
||||
private:
|
||||
const Team* m_Team;
|
||||
float m_Life;
|
||||
const Team* m_Team;
|
||||
float m_Life;
|
||||
public:
|
||||
static constexpr int CastleMaxLife = 1000;
|
||||
static constexpr int CastleMaxLife = 1000;
|
||||
|
||||
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
|
||||
TeamCastle() : TeamCastle(nullptr) {}
|
||||
TeamCastle() : TeamCastle(nullptr) {}
|
||||
|
||||
float GetLife() const { return m_Life; }
|
||||
float GetLife() const { return m_Life; }
|
||||
|
||||
const Team* GetTeam() const { return m_Team; }
|
||||
void SetTeam(const Team* team) { m_Team = team; }
|
||||
const Team* GetTeam() const { return m_Team; }
|
||||
void SetTeam(const Team* team) { m_Team = team; }
|
||||
|
||||
void SetLife(float life) { m_Life = life; }
|
||||
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
||||
void SetLife(float life) { m_Life = life; }
|
||||
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
||||
|
||||
void SetShape(utils::shape::Rectangle rect) {
|
||||
SetCenter(rect.GetCenter());
|
||||
SetSize(rect.GetSize());
|
||||
}
|
||||
void SetShape(utils::shape::Rectangle rect) {
|
||||
SetCenter(rect.GetCenter());
|
||||
SetSize(rect.GetSize());
|
||||
}
|
||||
};
|
||||
|
||||
class Team {
|
||||
private:
|
||||
std::vector<Player*> m_Players;
|
||||
TeamColor m_Color;
|
||||
Spawn m_Spawn;
|
||||
TeamCastle m_TeamCastle;
|
||||
std::vector<Player*> m_Players;
|
||||
TeamColor m_Color;
|
||||
Spawn m_Spawn;
|
||||
TeamCastle m_TeamCastle;
|
||||
public:
|
||||
Team(TeamColor color);
|
||||
Team(TeamColor color);
|
||||
|
||||
void AddPlayer(Player* newPlayer);
|
||||
void RemovePlayer(const Player* player);
|
||||
void AddPlayer(Player* newPlayer);
|
||||
void RemovePlayer(const Player* player);
|
||||
|
||||
TeamColor GetColor() const;
|
||||
TeamColor GetColor() const;
|
||||
|
||||
const Spawn& GetSpawn() const { return m_Spawn; }
|
||||
Spawn& GetSpawn() { return m_Spawn; }
|
||||
const Spawn& GetSpawn() const { return m_Spawn; }
|
||||
Spawn& GetSpawn() { return m_Spawn; }
|
||||
|
||||
const TeamCastle& GetCastle() const { return m_TeamCastle; }
|
||||
TeamCastle& GetCastle() { return m_TeamCastle; }
|
||||
const TeamCastle& GetCastle() const { return m_TeamCastle; }
|
||||
TeamCastle& GetCastle() { return m_TeamCastle; }
|
||||
|
||||
std::uint8_t GetPlayerCount() const;
|
||||
std::uint8_t GetPlayerCount() const;
|
||||
};
|
||||
|
||||
typedef std::array<Team, 2> TeamList;
|
||||
|
||||
@@ -17,69 +17,69 @@ class Mob;
|
||||
typedef std::shared_ptr<Mob> MobPtr;
|
||||
|
||||
enum class TowerType : std::uint8_t {
|
||||
Archer = 0,
|
||||
Ice,
|
||||
Sorcerer,
|
||||
Zeus,
|
||||
Mage,
|
||||
Artillery,
|
||||
Quake,
|
||||
Poison,
|
||||
Archer = 0,
|
||||
Ice,
|
||||
Sorcerer,
|
||||
Zeus,
|
||||
Mage,
|
||||
Artillery,
|
||||
Quake,
|
||||
Poison,
|
||||
|
||||
Leach,
|
||||
Turret,
|
||||
Necromancer,
|
||||
Leach,
|
||||
Turret,
|
||||
Necromancer,
|
||||
|
||||
TowerCount
|
||||
TowerCount
|
||||
};
|
||||
|
||||
enum class TowerSize : std::uint8_t {
|
||||
Little = 3, // 3x3
|
||||
Big = 5, // 5x5
|
||||
Little = 3, // 3x3
|
||||
Big = 5, // 5x5
|
||||
};
|
||||
|
||||
enum class TowerPath : std::uint8_t {
|
||||
Top = 0,
|
||||
Base, // Base Path
|
||||
Bottom
|
||||
Top = 0,
|
||||
Base, // Base Path
|
||||
Bottom
|
||||
};
|
||||
|
||||
class TowerStats {
|
||||
private:
|
||||
float m_Rate;
|
||||
float m_Damage;
|
||||
std::uint8_t m_Range;
|
||||
float m_Rate;
|
||||
float m_Damage;
|
||||
std::uint8_t m_Range;
|
||||
public:
|
||||
TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage),
|
||||
m_Range(range) {
|
||||
}
|
||||
TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage),
|
||||
m_Range(range) {
|
||||
}
|
||||
|
||||
float GetDamageRate() const { return m_Rate; }
|
||||
float GetDamage() const { return m_Damage; }
|
||||
std::uint8_t GetRange() const { return m_Range; }
|
||||
float GetDamageRate() const { return m_Rate; }
|
||||
float GetDamage() const { return m_Damage; }
|
||||
std::uint8_t GetRange() const { return m_Range; }
|
||||
};
|
||||
|
||||
class TowerLevel {
|
||||
private:
|
||||
// 1, 2, 3, 4
|
||||
std::uint8_t m_Level : 3;
|
||||
// 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path)
|
||||
TowerPath m_Path : 2;
|
||||
// 1, 2, 3, 4
|
||||
std::uint8_t m_Level : 3;
|
||||
// 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path)
|
||||
TowerPath m_Path : 2;
|
||||
public:
|
||||
TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {}
|
||||
TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {}
|
||||
TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {}
|
||||
TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {}
|
||||
|
||||
std::uint8_t GetLevel() const { return m_Level; }
|
||||
TowerPath GetPath() const { return m_Path; }
|
||||
std::uint8_t GetLevel() const { return m_Level; }
|
||||
TowerPath GetPath() const { return m_Path; }
|
||||
|
||||
void SetLevel(std::uint8_t level) { m_Level = level; }
|
||||
void SetPath(TowerPath path) { m_Path = path; }
|
||||
void SetLevel(std::uint8_t level) { m_Level = level; }
|
||||
void SetPath(TowerPath path) { m_Path = path; }
|
||||
|
||||
// operator to sort maps
|
||||
friend bool operator<(const TowerLevel& level, const TowerLevel& other) {
|
||||
return level.GetLevel() + static_cast<std::uint8_t>(level.GetPath()) * 4 <
|
||||
other.GetLevel() + static_cast<std::uint8_t>(other.GetPath()) * 4;
|
||||
}
|
||||
// operator to sort maps
|
||||
friend bool operator<(const TowerLevel& level, const TowerLevel& other) {
|
||||
return level.GetLevel() + static_cast<std::uint8_t>(level.GetPath()) * 4 <
|
||||
other.GetLevel() + static_cast<std::uint8_t>(other.GetPath()) * 4;
|
||||
}
|
||||
};
|
||||
|
||||
const TowerStats* GetTowerStats(TowerType type, TowerLevel level);
|
||||
@@ -88,36 +88,36 @@ typedef std::uint16_t TowerID;
|
||||
|
||||
class Tower : public utils::shape::Circle {
|
||||
private:
|
||||
TowerID m_ID;
|
||||
TowerType m_Type;
|
||||
TowerLevel m_Level{};
|
||||
PlayerID m_Builder;
|
||||
TowerID m_ID;
|
||||
TowerType m_Type;
|
||||
TowerLevel m_Level{};
|
||||
PlayerID m_Builder;
|
||||
protected:
|
||||
utils::CooldownTimer m_Timer;
|
||||
utils::CooldownTimer m_Timer;
|
||||
public:
|
||||
Tower(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) : utils::shape::Circle(x + 0.5f, y + 0.5f, 0), m_ID(id), m_Type(type), m_Builder(builder),
|
||||
m_Timer(GetStats()->GetDamageRate() * 1000) { // converting seconds to millis
|
||||
SetRadius(GetStats()->GetRange());
|
||||
}
|
||||
Tower(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) : utils::shape::Circle(x + 0.5f, y + 0.5f, 0), m_ID(id), m_Type(type), m_Builder(builder),
|
||||
m_Timer(GetStats()->GetDamageRate() * 1000) { // converting seconds to millis
|
||||
SetRadius(GetStats()->GetRange());
|
||||
}
|
||||
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual TowerSize GetSize() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual TowerSize GetSize() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
|
||||
void Upgrade(std::uint8_t level, TowerPath path) {
|
||||
m_Level.SetLevel(level);
|
||||
m_Level.SetPath(path);
|
||||
m_Timer.SetCooldown(GetStats()->GetDamageRate() * 1000); // converting seconds to millis
|
||||
m_Timer.Reset();
|
||||
SetRadius(GetStats()->GetRange());
|
||||
}
|
||||
void Upgrade(std::uint8_t level, TowerPath path) {
|
||||
m_Level.SetLevel(level);
|
||||
m_Level.SetPath(path);
|
||||
m_Timer.SetCooldown(GetStats()->GetDamageRate() * 1000); // converting seconds to millis
|
||||
m_Timer.Reset();
|
||||
SetRadius(GetStats()->GetRange());
|
||||
}
|
||||
|
||||
std::uint16_t GetID() const { return m_ID; }
|
||||
const TowerLevel& GetLevel() const { return m_Level; }
|
||||
const TowerStats* GetStats() const { return GetTowerStats(m_Type, m_Level); }
|
||||
PlayerID GetBuilder() const { return m_Builder; }
|
||||
std::uint16_t GetID() const { return m_ID; }
|
||||
const TowerLevel& GetLevel() const { return m_Level; }
|
||||
const TowerStats* GetStats() const { return GetTowerStats(m_Type, m_Level); }
|
||||
PlayerID GetBuilder() const { return m_Builder; }
|
||||
|
||||
bool IsMobInRange(MobPtr mob);
|
||||
bool IsMobInRange(MobPtr mob);
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Tower> TowerPtr;
|
||||
@@ -132,16 +132,17 @@ std::string GetTowerName(TowerType type);
|
||||
|
||||
class TowerInfo {
|
||||
private:
|
||||
std::string m_Name, m_Description;
|
||||
bool m_IsBigTower;
|
||||
std::string m_Name, m_Description;
|
||||
bool m_IsBigTower;
|
||||
public:
|
||||
TowerInfo(std::string&& name, std::string&& description, bool big) : m_Name(std::move(name)),
|
||||
m_Description(std::move(description)), m_IsBigTower(big) {}
|
||||
TowerInfo(std::string&& name, std::string&& description, bool big) : m_Name(std::move(name)),
|
||||
m_Description(std::move(description)), m_IsBigTower(big) {
|
||||
}
|
||||
|
||||
const std::string& GetName() const { return m_Name; }
|
||||
const std::string& GetDescription() const { return m_Description; }
|
||||
const std::string& GetName() const { return m_Name; }
|
||||
const std::string& GetDescription() const { return m_Description; }
|
||||
|
||||
bool IsBigTower() const { return m_IsBigTower; }
|
||||
bool IsBigTower() const { return m_IsBigTower; }
|
||||
};
|
||||
|
||||
const TowerInfo& GetTowerInfo(TowerType type);
|
||||
@@ -150,115 +151,115 @@ const TowerInfo& GetTowerInfo(TowerType type);
|
||||
|
||||
class LittleTower : public Tower {
|
||||
public:
|
||||
LittleTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||
LittleTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||
|
||||
virtual TowerSize GetSize() const { return TowerSize::Little; }
|
||||
virtual TowerSize GetSize() const { return TowerSize::Little; }
|
||||
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
};
|
||||
|
||||
class ArcherTower : public LittleTower {
|
||||
public:
|
||||
ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
constexpr static float ExplosionRadius = 1.5f;
|
||||
constexpr static float FireDurationSec = 10.0f;
|
||||
constexpr static float ExplosionRadius = 1.5f;
|
||||
constexpr static float FireDurationSec = 10.0f;
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Archer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Archer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class IceTower : public LittleTower {
|
||||
public:
|
||||
IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Ice; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Ice; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class MageTower : public LittleTower {
|
||||
public:
|
||||
MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Mage; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Mage; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class PoisonTower : public LittleTower {
|
||||
public:
|
||||
PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Poison; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Poison; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class QuakeTower : public LittleTower {
|
||||
public:
|
||||
QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Quake; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Quake; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class ArtilleryTower : public LittleTower {
|
||||
public:
|
||||
ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Artillery; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Artillery; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class SorcererTower : public LittleTower {
|
||||
public:
|
||||
SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Sorcerer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Sorcerer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class ZeusTower : public LittleTower {
|
||||
public:
|
||||
ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Zeus; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Zeus; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
// ---------- Big Towers ----------
|
||||
|
||||
class BigTower : public Tower {
|
||||
public:
|
||||
BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||
BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||
|
||||
virtual TowerSize GetSize() const { return TowerSize::Big; }
|
||||
virtual TowerSize GetSize() const { return TowerSize::Big; }
|
||||
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
};
|
||||
|
||||
class TurretTower : public BigTower {
|
||||
public:
|
||||
TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Turret; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Turret; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class NecromancerTower : public BigTower {
|
||||
public:
|
||||
NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Necromancer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Necromancer; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
class LeachTower : public BigTower {
|
||||
public:
|
||||
LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||
|
||||
virtual TowerType GetType() const { return TowerType::Leach; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
virtual TowerType GetType() const { return TowerType::Leach; }
|
||||
virtual void Tick(std::uint64_t delta, World* world);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
enum class Direction : std::uint8_t {
|
||||
PositiveX = 1 << 0,
|
||||
NegativeX = 1 << 1,
|
||||
PositiveY = 1 << 2,
|
||||
NegativeY = 1 << 3,
|
||||
PositiveX = 1 << 0,
|
||||
NegativeX = 1 << 1,
|
||||
PositiveY = 1 << 2,
|
||||
NegativeY = 1 << 3,
|
||||
};
|
||||
|
||||
typedef std::uint8_t PlayerID;
|
||||
|
||||
@@ -13,11 +13,11 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
struct ChunkCoord {
|
||||
std::int16_t x, y;
|
||||
std::int16_t x, y;
|
||||
|
||||
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
||||
return first.x == other.x && first.y == other.y;
|
||||
}
|
||||
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
||||
return first.x == other.x && first.y == other.y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ struct ChunkCoord {
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<td::game::ChunkCoord> {
|
||||
std::size_t operator()(const td::game::ChunkCoord& key) const noexcept{
|
||||
return std::hash<std::int16_t>()(key.x << 16 | key.y);
|
||||
}
|
||||
std::size_t operator()(const td::game::ChunkCoord& key) const noexcept {
|
||||
return std::hash<std::int16_t>()(key.x << 16 | key.y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,15 +47,15 @@ namespace game {
|
||||
class Game;
|
||||
|
||||
enum class TileType : std::uint8_t {
|
||||
None = 0,
|
||||
Tower,
|
||||
Walk,
|
||||
Decoration,
|
||||
/*Heal,
|
||||
Lava,
|
||||
Bedrock,
|
||||
Freeze,
|
||||
Ice,*/
|
||||
None = 0,
|
||||
Tower,
|
||||
Walk,
|
||||
Decoration,
|
||||
/*Heal,
|
||||
Lava,
|
||||
Bedrock,
|
||||
Freeze,
|
||||
Ice,*/
|
||||
};
|
||||
|
||||
static constexpr Color BLACK{ 0, 0, 0 };
|
||||
@@ -66,26 +66,26 @@ static constexpr Color GREEN{ 0, 255, 0 };
|
||||
static constexpr Color BLUE{ 0, 0, 255 };
|
||||
|
||||
struct Tile {
|
||||
virtual TileType GetType() const = 0;
|
||||
virtual TileType GetType() const = 0;
|
||||
};
|
||||
|
||||
struct TowerTile : Tile {
|
||||
std::uint8_t color_palette_ref;
|
||||
TeamColor team_owner;
|
||||
std::uint8_t color_palette_ref;
|
||||
TeamColor team_owner;
|
||||
|
||||
virtual TileType GetType() const { return TileType::Tower; }
|
||||
virtual TileType GetType() const { return TileType::Tower; }
|
||||
};
|
||||
|
||||
struct WalkableTile : Tile {
|
||||
Direction direction;
|
||||
Direction direction;
|
||||
|
||||
virtual TileType GetType() const { return TileType::Walk; }
|
||||
virtual TileType GetType() const { return TileType::Walk; }
|
||||
};
|
||||
|
||||
struct DecorationTile : Tile {
|
||||
std::uint16_t color_palette_ref;
|
||||
std::uint16_t color_palette_ref;
|
||||
|
||||
virtual TileType GetType() const { return TileType::Decoration; }
|
||||
virtual TileType GetType() const { return TileType::Decoration; }
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Tile> TilePtr;
|
||||
@@ -97,19 +97,19 @@ typedef std::uint32_t TileIndex;
|
||||
|
||||
//32 x 32 area
|
||||
struct Chunk {
|
||||
enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
|
||||
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
||||
enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
|
||||
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
||||
|
||||
// stores index of tile palette
|
||||
ChunkData tiles{ 0 };
|
||||
ChunkPalette palette;
|
||||
// stores index of tile palette
|
||||
ChunkData tiles{ 0 };
|
||||
ChunkPalette palette;
|
||||
|
||||
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
||||
TileIndex chunkPaletteIndex = tiles.at(tileNumber);
|
||||
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
||||
return 0;
|
||||
return palette.at(chunkPaletteIndex);
|
||||
}
|
||||
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
||||
TileIndex chunkPaletteIndex = tiles.at(tileNumber);
|
||||
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
||||
return 0;
|
||||
return palette.at(chunkPaletteIndex);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||
@@ -126,119 +126,119 @@ typedef std::vector<TowerPtr> TowerList;
|
||||
|
||||
class WorldListener {
|
||||
public:
|
||||
WorldListener() {}
|
||||
WorldListener() {}
|
||||
|
||||
virtual void OnTowerAdd(TowerPtr tower) {}
|
||||
virtual void OnTowerRemove(TowerPtr tower) {}
|
||||
virtual void OnTowerAdd(TowerPtr tower) {}
|
||||
virtual void OnTowerRemove(TowerPtr tower) {}
|
||||
|
||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {}
|
||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {}
|
||||
|
||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {}
|
||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {}
|
||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {}
|
||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {}
|
||||
};
|
||||
|
||||
typedef utils::ObjectNotifier<WorldListener> WorldNotifier;
|
||||
|
||||
class World : public WorldListener, public MobListener {
|
||||
protected:
|
||||
TowerTileColorPalette m_TowerPlacePalette;
|
||||
Color m_WalkablePalette;
|
||||
std::vector<Color> m_DecorationPalette;
|
||||
Color m_Background;
|
||||
TowerTileColorPalette m_TowerPlacePalette;
|
||||
Color m_WalkablePalette;
|
||||
std::vector<Color> m_DecorationPalette;
|
||||
Color m_Background;
|
||||
|
||||
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
||||
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
||||
|
||||
SpawnColorPalette m_SpawnColorPalette;
|
||||
SpawnColorPalette m_SpawnColorPalette;
|
||||
|
||||
TilePalette m_TilePalette;
|
||||
TilePalette m_TilePalette;
|
||||
|
||||
MobList m_Mobs;
|
||||
MobList m_Mobs;
|
||||
|
||||
TowerList m_Towers;
|
||||
TowerList m_Towers;
|
||||
|
||||
Game* m_Game;
|
||||
Game* m_Game;
|
||||
|
||||
WorldNotifier m_WorldNotifier;
|
||||
MobNotifier m_MobNotifier;
|
||||
WorldNotifier m_WorldNotifier;
|
||||
MobNotifier m_MobNotifier;
|
||||
public:
|
||||
World(Game* game);
|
||||
World(Game* game);
|
||||
|
||||
bool LoadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
||||
bool LoadMap(const protocol::WorldDataPacket* worldData);
|
||||
bool LoadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
||||
bool LoadMap(const protocol::WorldDataPacket* worldData);
|
||||
|
||||
bool LoadMapFromFile(const std::string& fileName);
|
||||
bool SaveMap(const std::string& fileName) const;
|
||||
bool LoadMapFromFile(const std::string& fileName);
|
||||
bool SaveMap(const std::string& fileName) const;
|
||||
|
||||
void Tick(std::uint64_t delta);
|
||||
void Tick(std::uint64_t delta);
|
||||
|
||||
void SpawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir);
|
||||
void SpawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir);
|
||||
|
||||
TowerPtr PlaceTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder);
|
||||
TowerPtr RemoveTower(TowerID id);
|
||||
TowerPtr PlaceTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder);
|
||||
TowerPtr RemoveTower(TowerID id);
|
||||
|
||||
TilePtr GetTile(std::int32_t x, std::int32_t y) const;
|
||||
TilePtr GetTile(std::int32_t x, std::int32_t y) const;
|
||||
|
||||
const TowerTileColorPalette& GetTowerTileColorPalette() const { return m_TowerPlacePalette; }
|
||||
const Color& GetWalkableTileColor() const { return m_WalkablePalette; }
|
||||
const std::vector<Color>& GetDecorationPalette() const { return m_DecorationPalette; }
|
||||
const Color& GetBackgroundColor() const { return m_Background; }
|
||||
const TowerTileColorPalette& GetTowerTileColorPalette() const { return m_TowerPlacePalette; }
|
||||
const Color& GetWalkableTileColor() const { return m_WalkablePalette; }
|
||||
const std::vector<Color>& GetDecorationPalette() const { return m_DecorationPalette; }
|
||||
const Color& GetBackgroundColor() const { return m_Background; }
|
||||
|
||||
const TilePalette& GetTilePalette() const { return m_TilePalette; }
|
||||
const TilePalette& GetTilePalette() const { return m_TilePalette; }
|
||||
|
||||
TilePtr GetTilePtr(TileIndex index) const {
|
||||
if (index == 0)
|
||||
return nullptr;
|
||||
return m_TilePalette.at(index - 1);
|
||||
}
|
||||
TilePtr GetTilePtr(TileIndex index) const {
|
||||
if (index == 0)
|
||||
return nullptr;
|
||||
return m_TilePalette.at(index - 1);
|
||||
}
|
||||
|
||||
bool CanPlaceLittleTower(const Vec2f& worldPos, PlayerID player) const;
|
||||
bool CanPlaceBigTower(const Vec2f& worldPos, PlayerID player) const;
|
||||
bool CanPlaceLittleTower(const Vec2f& worldPos, PlayerID player) const;
|
||||
bool CanPlaceBigTower(const Vec2f& worldPos, PlayerID player) const;
|
||||
|
||||
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
||||
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
||||
|
||||
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const { return m_Chunks; }
|
||||
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const { return m_Chunks; }
|
||||
|
||||
const Color& GetSpawnColor(TeamColor color) const { return m_SpawnColorPalette[static_cast<std::size_t>(color)]; }
|
||||
const SpawnColorPalette& GetSpawnColors() const { return m_SpawnColorPalette; }
|
||||
const Color& GetSpawnColor(TeamColor color) const { return m_SpawnColorPalette[static_cast<std::size_t>(color)]; }
|
||||
const SpawnColorPalette& GetSpawnColors() const { return m_SpawnColorPalette; }
|
||||
|
||||
const MobList& GetMobList() const { return m_Mobs; }
|
||||
MobList& GetMobList() { return m_Mobs; }
|
||||
const MobList& GetMobList() const { return m_Mobs; }
|
||||
MobList& GetMobList() { return m_Mobs; }
|
||||
|
||||
const Color* GetTileColor(TilePtr tile) const;
|
||||
const Color* GetTileColor(TilePtr tile) const;
|
||||
|
||||
Team& GetRedTeam();
|
||||
const Team& GetRedTeam() const;
|
||||
Team& GetRedTeam();
|
||||
const Team& GetRedTeam() const;
|
||||
|
||||
Team& GetBlueTeam();
|
||||
const Team& GetBlueTeam() const;
|
||||
Team& GetBlueTeam();
|
||||
const Team& GetBlueTeam() const;
|
||||
|
||||
Team& GetTeam(TeamColor team);
|
||||
const Team& GetTeam(TeamColor team) const;
|
||||
Team& GetTeam(TeamColor team);
|
||||
const Team& GetTeam(TeamColor team) const;
|
||||
|
||||
const TeamList& GetTeams() const;
|
||||
const TeamList& GetTeams() const;
|
||||
|
||||
const TowerList& GetTowers() const { return m_Towers; }
|
||||
TowerPtr GetTowerById(TowerID tower);
|
||||
const TowerList& GetTowers() const { return m_Towers; }
|
||||
TowerPtr GetTowerById(TowerID tower);
|
||||
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
|
||||
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
|
||||
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
|
||||
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
|
||||
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
|
||||
|
||||
// WorldListener
|
||||
// WorldListener
|
||||
|
||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) override;
|
||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) override;
|
||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) override;
|
||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) override;
|
||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) override;
|
||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) override;
|
||||
|
||||
// MobListener
|
||||
// MobListener
|
||||
|
||||
virtual void OnMobDamage(Mob* target, float damage, Tower* source) override;
|
||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) override;
|
||||
virtual void OnMobDamage(Mob* target, float damage, Tower* source) override;
|
||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) override;
|
||||
|
||||
private:
|
||||
void TickMobs(std::uint64_t delta);
|
||||
void CleanDeadMobs();
|
||||
void TickMobs(std::uint64_t delta);
|
||||
void CleanDeadMobs();
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -17,38 +17,38 @@ namespace client {
|
||||
|
||||
class Client {
|
||||
private:
|
||||
render::Renderer* m_Renderer;
|
||||
ClientConnexion m_Connexion;
|
||||
std::unique_ptr<ClientGame> m_Game;
|
||||
bool m_Connected;
|
||||
render::Renderer* m_Renderer;
|
||||
ClientConnexion m_Connexion;
|
||||
std::unique_ptr<ClientGame> m_Game;
|
||||
bool m_Connected;
|
||||
public:
|
||||
Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(std::make_unique<ClientGame>(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 ClientConnexion& GetConnexion() const { return m_Connexion; }
|
||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||
const ClientGame& GetGame() const { return *m_Game; }
|
||||
const ClientConnexion& GetConnexion() const { return m_Connexion; }
|
||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||
|
||||
ClientGame& GetGame() { return *m_Game; }
|
||||
ClientConnexion& GetConnexion() { return m_Connexion; }
|
||||
ClientGame& GetGame() { return *m_Game; }
|
||||
ClientConnexion& GetConnexion() { return m_Connexion; }
|
||||
|
||||
const game::Player* GetPlayer() { return m_Game->GetPlayer(); }
|
||||
const game::Player* GetPlayer() { return m_Game->GetPlayer(); }
|
||||
|
||||
void Tick(std::uint64_t delta);
|
||||
void Tick(std::uint64_t delta);
|
||||
|
||||
void Render();
|
||||
void Render();
|
||||
|
||||
bool Connect(const network::IPAddresses& addresses, std::uint16_t port);
|
||||
void CloseConnection();
|
||||
bool Connect(const network::IPAddresses& addresses, std::uint16_t port);
|
||||
void CloseConnection();
|
||||
|
||||
bool IsConnected() const { return m_Connexion.GetSocketStatus() == network::Socket::Connected; }
|
||||
bool IsConnected() const { return m_Connexion.GetSocketStatus() == network::Socket::Connected; }
|
||||
|
||||
void SelectTeam(game::TeamColor team);
|
||||
void SendMobs(const std::vector<protocol::MobSend>& mobSends);
|
||||
void PlaceTower(game::TowerType type, const Vec2f& position);
|
||||
void UpgradeTower(game::TowerID tower, game::TowerLevel level);
|
||||
void RemoveTower(game::TowerID tower);
|
||||
void SelectTeam(game::TeamColor team);
|
||||
void SendMobs(const std::vector<protocol::MobSend>& mobSends);
|
||||
void PlaceTower(game::TowerType type, const Vec2f& position);
|
||||
void UpgradeTower(game::TowerID tower, game::TowerLevel level);
|
||||
void RemoveTower(game::TowerID tower);
|
||||
private:
|
||||
void Reset();
|
||||
void Reset();
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -9,28 +9,28 @@ namespace client {
|
||||
|
||||
class ClientConnexion : public protocol::Connexion {
|
||||
private:
|
||||
std::uint8_t m_ConnectionID;
|
||||
std::string m_DisconnectReason;
|
||||
float m_ServerTPS;
|
||||
int m_Ping = 0;
|
||||
std::uint8_t m_ConnectionID;
|
||||
std::string m_DisconnectReason;
|
||||
float m_ServerTPS;
|
||||
int m_Ping = 0;
|
||||
public:
|
||||
ClientConnexion();
|
||||
ClientConnexion();
|
||||
|
||||
virtual bool UpdateSocket();
|
||||
virtual bool UpdateSocket();
|
||||
|
||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::ServerTpsPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::ServerTpsPacket* packet) override;
|
||||
|
||||
const std::string& GetDisconnectReason() const { return m_DisconnectReason; }
|
||||
float GetServerTPS() const { return m_ServerTPS; }
|
||||
int GetServerPing() const { return m_Ping; }
|
||||
const std::string& GetDisconnectReason() const { return m_DisconnectReason; }
|
||||
float GetServerTPS() const { return m_ServerTPS; }
|
||||
int GetServerPing() const { return m_Ping; }
|
||||
|
||||
REMOVE_COPY(ClientConnexion);
|
||||
REMOVE_COPY(ClientConnexion);
|
||||
private:
|
||||
void RegisterHandlers();
|
||||
void Login();
|
||||
void RegisterHandlers();
|
||||
void Login();
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -16,40 +16,40 @@ class Client;
|
||||
|
||||
class ClientGame : public protocol::PacketHandler, public game::Game {
|
||||
private:
|
||||
Client* m_Client;
|
||||
std::uint8_t m_ConnexionID;
|
||||
std::uint32_t m_LobbyTime = 0;
|
||||
game::Player* m_Player = nullptr;
|
||||
render::Renderer* m_Renderer;
|
||||
client::WorldClient m_WorldClient;
|
||||
render::WorldRenderer m_WorldRenderer;
|
||||
Client* m_Client;
|
||||
std::uint8_t m_ConnexionID;
|
||||
std::uint32_t m_LobbyTime = 0;
|
||||
game::Player* m_Player = nullptr;
|
||||
render::Renderer* m_Renderer;
|
||||
client::WorldClient m_WorldClient;
|
||||
render::WorldRenderer m_WorldRenderer;
|
||||
public:
|
||||
ClientGame(Client* client);
|
||||
virtual ~ClientGame();
|
||||
ClientGame(Client* client);
|
||||
virtual ~ClientGame();
|
||||
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
|
||||
void RenderWorld();
|
||||
void RenderWorld();
|
||||
|
||||
std::uint32_t GetLobbyTime() const { return m_LobbyTime; }
|
||||
const game::Player* GetPlayer() const { return m_Player; }
|
||||
const WorldClient& GetWorld() const { return m_WorldClient; }
|
||||
Client* GetClient() const { return m_Client; }
|
||||
std::uint32_t GetLobbyTime() const { return m_LobbyTime; }
|
||||
const game::Player* GetPlayer() const { return m_Player; }
|
||||
const WorldClient& GetWorld() const { return m_WorldClient; }
|
||||
Client* GetClient() const { return m_Client; }
|
||||
|
||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||
WorldClient& GetWorldClient() { return m_WorldClient; }
|
||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||
WorldClient& GetWorldClient() { return m_WorldClient; }
|
||||
|
||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerJoinPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerLeavePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerListPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdatePlayerTeamPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateLobbyTimePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateMoneyPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateExpPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerJoinPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerLeavePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerListPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdatePlayerTeamPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateLobbyTimePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateMoneyPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateExpPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -10,18 +10,18 @@ class ClientGame;
|
||||
|
||||
class WorldClient : public game::World, public protocol::PacketHandler {
|
||||
private:
|
||||
ClientGame* m_Game;
|
||||
ClientGame* m_Game;
|
||||
public:
|
||||
WorldClient(ClientGame* game);
|
||||
WorldClient(ClientGame* game);
|
||||
|
||||
virtual void HandlePacket(const protocol::WorldBeginDataPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SpawnMobPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateMobStatesPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateCastleLifePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldBeginDataPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SpawnMobPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateMobStatesPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateCastleLifePacket* packet) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -11,23 +11,23 @@ class Server;
|
||||
|
||||
class Lobby {
|
||||
private:
|
||||
Server* m_Server;
|
||||
bool m_GameStarted = false;
|
||||
std::uint64_t m_StartTimerTime = 0;
|
||||
std::vector<std::uint8_t> m_Players;
|
||||
utils::AutoTimer m_Timer;
|
||||
Server* m_Server;
|
||||
bool m_GameStarted = false;
|
||||
std::uint64_t m_StartTimerTime = 0;
|
||||
std::vector<std::uint8_t> m_Players;
|
||||
utils::AutoTimer m_Timer;
|
||||
public:
|
||||
Lobby(Server* server);
|
||||
Lobby(Server* server);
|
||||
|
||||
void OnPlayerJoin(std::uint8_t playerID);
|
||||
void OnPlayerLeave(std::uint8_t playerID);
|
||||
void OnPlayerJoin(std::uint8_t playerID);
|
||||
void OnPlayerLeave(std::uint8_t playerID);
|
||||
|
||||
void SendTimeRemaining();
|
||||
void SendTimeRemaining();
|
||||
|
||||
void Tick();
|
||||
void Tick();
|
||||
|
||||
//static constexpr int LobbyWaitingTime = 2 * 60 * 1000; // in millis
|
||||
static constexpr int LobbyWaitingTime = 5 * 1000; // in millis
|
||||
//static constexpr int LobbyWaitingTime = 2 * 60 * 1000; // in millis
|
||||
static constexpr int LobbyWaitingTime = 5 * 1000; // in millis
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -21,80 +21,80 @@ typedef std::map<std::uint8_t, ServerConnexion> ConnexionMap;
|
||||
|
||||
class TickCounter {
|
||||
private:
|
||||
float m_TPS;
|
||||
std::uint64_t m_LastTPSTime;
|
||||
std::uint8_t m_TickCount;
|
||||
float m_TPS;
|
||||
std::uint64_t m_LastTPSTime;
|
||||
std::uint8_t m_TickCount;
|
||||
public:
|
||||
TickCounter() {}
|
||||
TickCounter() {}
|
||||
|
||||
void Reset() {
|
||||
m_TPS = SERVER_TPS;
|
||||
m_LastTPSTime = utils::GetTime();
|
||||
m_TickCount = 0;
|
||||
}
|
||||
void Reset() {
|
||||
m_TPS = SERVER_TPS;
|
||||
m_LastTPSTime = utils::GetTime();
|
||||
m_TickCount = 0;
|
||||
}
|
||||
|
||||
bool Update() { // return true when tps is updated
|
||||
m_TickCount++;
|
||||
if (m_TickCount >= SERVER_TPS) {
|
||||
std::uint64_t timeElapsedSinceLast20Ticks = td::utils::GetTime() - m_LastTPSTime;
|
||||
m_TPS = static_cast<float>(SERVER_TPS) / static_cast<float>(timeElapsedSinceLast20Ticks / 1000.0f);
|
||||
m_TickCount = 0;
|
||||
m_LastTPSTime = td::utils::GetTime();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Update() { // return true when tps is updated
|
||||
m_TickCount++;
|
||||
if (m_TickCount >= SERVER_TPS) {
|
||||
std::uint64_t timeElapsedSinceLast20Ticks = td::utils::GetTime() - m_LastTPSTime;
|
||||
m_TPS = static_cast<float>(SERVER_TPS) / static_cast<float>(timeElapsedSinceLast20Ticks / 1000.0f);
|
||||
m_TickCount = 0;
|
||||
m_LastTPSTime = td::utils::GetTime();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float GetTPS() const { return m_TPS; }
|
||||
float GetTPS() const { return m_TPS; }
|
||||
};
|
||||
|
||||
class Server {
|
||||
private:
|
||||
network::TCPListener m_Listener;
|
||||
ConnexionMap m_Connections;
|
||||
ServerGame m_Game{ this };
|
||||
Lobby m_Lobby{ this };
|
||||
TickCounter m_TickCounter;
|
||||
network::TCPListener m_Listener;
|
||||
ConnexionMap m_Connections;
|
||||
ServerGame m_Game{ this };
|
||||
Lobby m_Lobby{ this };
|
||||
TickCounter m_TickCounter;
|
||||
|
||||
std::thread m_Thread;
|
||||
bool m_ServerRunning;
|
||||
std::thread m_Thread;
|
||||
bool m_ServerRunning;
|
||||
public:
|
||||
Server(const std::string& worldFilePath);
|
||||
virtual ~Server();
|
||||
Server(const std::string& worldFilePath);
|
||||
virtual ~Server();
|
||||
|
||||
bool Start(std::uint16_t port);
|
||||
void Stop(); // force the server to stop
|
||||
void Close(); // at the end of a game
|
||||
bool Start(std::uint16_t port);
|
||||
void Stop(); // force the server to stop
|
||||
void Close(); // at the end of a game
|
||||
|
||||
void RemoveConnexion(std::uint8_t connexionID);
|
||||
void RemoveConnexion(std::uint8_t connexionID);
|
||||
|
||||
void BroadcastPacket(const protocol::Packet* packet);
|
||||
void BroadcastPacket(const protocol::Packet* packet);
|
||||
|
||||
float GetTPS() const { return m_TickCounter.GetTPS(); }
|
||||
float GetTPS() const { return m_TickCounter.GetTPS(); }
|
||||
|
||||
bool IsRunning() { return m_ServerRunning; }
|
||||
bool IsRunning() { return m_ServerRunning; }
|
||||
|
||||
const ServerGame& GetGame() const { return m_Game; }
|
||||
ServerGame& GetGame() { return m_Game; }
|
||||
const ServerGame& GetGame() const { return m_Game; }
|
||||
ServerGame& GetGame() { return m_Game; }
|
||||
|
||||
const Lobby& GetLobby() const { return m_Lobby; }
|
||||
const ConnexionMap& GetConnexions() const { return m_Connections; }
|
||||
ConnexionMap& GetConnexions() { return m_Connections; }
|
||||
const Lobby& GetLobby() const { return m_Lobby; }
|
||||
const ConnexionMap& GetConnexions() const { return m_Connections; }
|
||||
ConnexionMap& GetConnexions() { return m_Connections; }
|
||||
|
||||
const game::PlayerList& GetPlayers() const { return m_Game.GetPlayers(); }
|
||||
game::PlayerList& GetPlayers() { return m_Game.GetPlayers(); }
|
||||
const game::PlayerList& GetPlayers() const { return m_Game.GetPlayers(); }
|
||||
game::PlayerList& GetPlayers() { return m_Game.GetPlayers(); }
|
||||
|
||||
private:
|
||||
void Accept();
|
||||
void UpdateSockets();
|
||||
void Accept();
|
||||
void UpdateSockets();
|
||||
|
||||
void Clean();
|
||||
void StartThread();
|
||||
void StopThread();
|
||||
void Tick(std::uint64_t delta);
|
||||
void Clean();
|
||||
void StartThread();
|
||||
void StopThread();
|
||||
void Tick(std::uint64_t delta);
|
||||
|
||||
void OnPlayerJoin(std::uint8_t id);
|
||||
void OnPlayerLeave(std::uint8_t id);
|
||||
void OnPlayerJoin(std::uint8_t id);
|
||||
void OnPlayerLeave(std::uint8_t id);
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -11,49 +11,48 @@ namespace server {
|
||||
|
||||
class Server;
|
||||
|
||||
struct KeepAlive
|
||||
{
|
||||
std::uint64_t keepAliveID = 0;
|
||||
std::uint64_t sendTime;
|
||||
bool recievedResponse = false;
|
||||
struct KeepAlive {
|
||||
std::uint64_t keepAliveID = 0;
|
||||
std::uint64_t sendTime;
|
||||
bool recievedResponse = false;
|
||||
};
|
||||
|
||||
|
||||
class ServerConnexion : public protocol::Connexion {
|
||||
private:
|
||||
Server* m_Server = nullptr;
|
||||
std::uint8_t m_ID;
|
||||
KeepAlive m_KeepAlive;
|
||||
game::Player* m_Player;
|
||||
Server* m_Server = nullptr;
|
||||
std::uint8_t m_ID;
|
||||
KeepAlive m_KeepAlive;
|
||||
game::Player* m_Player;
|
||||
public:
|
||||
ServerConnexion();
|
||||
ServerConnexion(network::TCPSocket& socket, std::uint8_t id);
|
||||
ServerConnexion(ServerConnexion&& move);
|
||||
virtual ~ServerConnexion();
|
||||
ServerConnexion();
|
||||
ServerConnexion(network::TCPSocket& socket, std::uint8_t id);
|
||||
ServerConnexion(ServerConnexion&& move);
|
||||
virtual ~ServerConnexion();
|
||||
|
||||
void SetServer(Server* server);
|
||||
void SetServer(Server* server);
|
||||
|
||||
virtual void HandlePacket(const protocol::PlayerLoginPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SelectTeamPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlaceTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SendMobsPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerLoginPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SelectTeamPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlaceTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::SendMobsPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||
|
||||
std::uint8_t GetID() const { return m_ID; }
|
||||
const game::Player* GetPlayer() const { return m_Player; }
|
||||
game::Player* GetPlayer() { return m_Player; }
|
||||
std::uint8_t GetID() const { return m_ID; }
|
||||
const game::Player* GetPlayer() const { return m_Player; }
|
||||
game::Player* GetPlayer() { return m_Player; }
|
||||
|
||||
virtual bool UpdateSocket();
|
||||
virtual bool UpdateSocket();
|
||||
|
||||
REMOVE_COPY(ServerConnexion);
|
||||
REMOVE_COPY(ServerConnexion);
|
||||
private:
|
||||
void RegisterHandlers();
|
||||
void CheckKeepAlive();
|
||||
void SendKeepAlive();
|
||||
void InitConnection();
|
||||
void RegisterHandlers();
|
||||
void CheckKeepAlive();
|
||||
void SendKeepAlive();
|
||||
void InitConnection();
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -11,32 +11,32 @@ class Server;
|
||||
|
||||
class ServerGame : public game::Game, public game::GameListener {
|
||||
private:
|
||||
Server* m_Server;
|
||||
ServerWorld m_ServerWorld;
|
||||
utils::AutoTimer m_GoldMineTimer;
|
||||
utils::AutoTimer m_MobStatesTimer;
|
||||
utils::CooldownTimer m_EndGameCooldown;
|
||||
Server* m_Server;
|
||||
ServerWorld m_ServerWorld;
|
||||
utils::AutoTimer m_GoldMineTimer;
|
||||
utils::AutoTimer m_MobStatesTimer;
|
||||
utils::CooldownTimer m_EndGameCooldown;
|
||||
public:
|
||||
ServerGame(Server* server);
|
||||
~ServerGame() {}
|
||||
ServerGame(Server* server);
|
||||
~ServerGame() {}
|
||||
|
||||
ServerWorld* GetServerWorld() { return &m_ServerWorld; }
|
||||
ServerWorld* GetServerWorld() { return &m_ServerWorld; }
|
||||
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
void StartGame();
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
void StartGame();
|
||||
|
||||
// GameListener
|
||||
// GameListener
|
||||
|
||||
virtual void OnGameStateUpdate(game::GameState newState) override;
|
||||
virtual void OnGameBegin() override;
|
||||
virtual void OnGameEnd() override;
|
||||
virtual void OnGameClose() override;
|
||||
virtual void OnGameStateUpdate(game::GameState newState) override;
|
||||
virtual void OnGameBegin() override;
|
||||
virtual void OnGameEnd() override;
|
||||
virtual void OnGameClose() override;
|
||||
private:
|
||||
void BalanceTeams();
|
||||
void InitPlayerStats();
|
||||
void UpdateMobStates();
|
||||
void UpdateGoldMines();
|
||||
void UpdatePlayerStats();
|
||||
void BalanceTeams();
|
||||
void InitPlayerStats();
|
||||
void UpdateMobStates();
|
||||
void UpdateGoldMines();
|
||||
void UpdatePlayerStats();
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -10,19 +10,19 @@ class ServerGame;
|
||||
|
||||
class ServerWorld : public game::World {
|
||||
private:
|
||||
game::MobID m_CurrentMobID;
|
||||
game::TowerID m_CurrentTowerID;
|
||||
Server* m_Server;
|
||||
game::MobID m_CurrentMobID;
|
||||
game::TowerID m_CurrentTowerID;
|
||||
Server* m_Server;
|
||||
public:
|
||||
static constexpr float MobSpawnBorder = 0.01f;
|
||||
static constexpr float MobSpawnBorder = 0.01f;
|
||||
|
||||
ServerWorld(Server* server, ServerGame* game);
|
||||
ServerWorld(Server* server, ServerGame* game);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
virtual void OnMobDie(game::Mob* mob) override;
|
||||
virtual void OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage) override;
|
||||
virtual void OnMobDie(game::Mob* mob) override;
|
||||
virtual void OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -10,166 +10,166 @@ namespace td {
|
||||
|
||||
class DataBuffer {
|
||||
private:
|
||||
typedef std::vector<std::uint8_t> Data;
|
||||
Data m_Buffer;
|
||||
std::size_t m_ReadOffset;
|
||||
typedef std::vector<std::uint8_t> Data;
|
||||
Data m_Buffer;
|
||||
std::size_t m_ReadOffset;
|
||||
|
||||
public:
|
||||
typedef Data::iterator iterator;
|
||||
typedef Data::const_iterator const_iterator;
|
||||
typedef Data::reference reference;
|
||||
typedef Data::const_reference const_reference;
|
||||
typedef Data::iterator iterator;
|
||||
typedef Data::const_iterator const_iterator;
|
||||
typedef Data::reference reference;
|
||||
typedef Data::const_reference const_reference;
|
||||
|
||||
DataBuffer();
|
||||
DataBuffer(const DataBuffer& other);
|
||||
DataBuffer(const DataBuffer& other, Data::difference_type offset);
|
||||
DataBuffer(DataBuffer&& other);
|
||||
DataBuffer(const std::string& str);
|
||||
DataBuffer();
|
||||
DataBuffer(const DataBuffer& other);
|
||||
DataBuffer(const DataBuffer& other, Data::difference_type offset);
|
||||
DataBuffer(DataBuffer&& other);
|
||||
DataBuffer(const std::string& str);
|
||||
|
||||
DataBuffer& operator=(const DataBuffer& other);
|
||||
DataBuffer& operator=(DataBuffer&& other);
|
||||
DataBuffer& operator=(const DataBuffer& other);
|
||||
DataBuffer& operator=(DataBuffer&& other);
|
||||
|
||||
template <typename T>
|
||||
void Append(T data) {
|
||||
std::size_t size = sizeof(data);
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + size);
|
||||
memcpy(&m_Buffer[end_pos], &data, size);
|
||||
}
|
||||
template <typename T>
|
||||
void Append(T data) {
|
||||
std::size_t size = sizeof(data);
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + size);
|
||||
memcpy(&m_Buffer[end_pos], &data, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DataBuffer& operator<<(T data) {
|
||||
// Switch to big endian
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
Append(data);
|
||||
return *this;
|
||||
}
|
||||
template <typename T>
|
||||
DataBuffer& operator<<(T data) {
|
||||
// Switch to big endian
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
Append(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(std::string str) {
|
||||
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
||||
return *this;
|
||||
}
|
||||
DataBuffer& operator<<(std::string str) {
|
||||
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(DataBuffer& data) {
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
DataBuffer& operator<<(DataBuffer& data) {
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator<<(const DataBuffer& data) {
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
DataBuffer& operator<<(const DataBuffer& data) {
|
||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DataBuffer& operator>>(T& data) {
|
||||
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
||||
data = *(reinterpret_cast<T*>(&m_Buffer[m_ReadOffset]));
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
m_ReadOffset += sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
template <typename T>
|
||||
DataBuffer& operator>>(T& data) {
|
||||
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
||||
data = *(reinterpret_cast<T*>(&m_Buffer[m_ReadOffset]));
|
||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||
m_ReadOffset += sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator>>(DataBuffer& data) {
|
||||
data.Resize(GetSize() - m_ReadOffset);
|
||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
||||
m_ReadOffset = m_Buffer.size();
|
||||
return *this;
|
||||
}
|
||||
DataBuffer& operator>>(DataBuffer& data) {
|
||||
data.Resize(GetSize() - m_ReadOffset);
|
||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
||||
m_ReadOffset = m_Buffer.size();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& operator>>(std::string& str) {
|
||||
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
||||
str.resize(stringSize);
|
||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset),
|
||||
m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset + stringSize), str.begin());
|
||||
m_ReadOffset += stringSize;
|
||||
return *this;
|
||||
}
|
||||
DataBuffer& operator>>(std::string& str) {
|
||||
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
||||
str.resize(stringSize);
|
||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset),
|
||||
m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset + stringSize), str.begin());
|
||||
m_ReadOffset += stringSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void WriteSome(const char* buffer, std::size_t amount) {
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + amount);
|
||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||
}
|
||||
void WriteSome(const char* buffer, std::size_t amount) {
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + amount);
|
||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||
}
|
||||
|
||||
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + amount);
|
||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||
}
|
||||
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
||||
std::size_t end_pos = m_Buffer.size();
|
||||
m_Buffer.resize(m_Buffer.size() + amount);
|
||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||
}
|
||||
|
||||
void ReadSome(char* buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
void ReadSome(char* buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.Resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.Resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void ReadSome(std::string& buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
void ReadSome(std::string& buffer, std::size_t amount) {
|
||||
assert(m_ReadOffset + amount <= GetSize());
|
||||
buffer.resize(amount);
|
||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||
m_ReadOffset += amount;
|
||||
}
|
||||
|
||||
void Resize(std::size_t size) {
|
||||
m_Buffer.resize(size);
|
||||
}
|
||||
void Resize(std::size_t size) {
|
||||
m_Buffer.resize(size);
|
||||
}
|
||||
|
||||
void Reserve(std::size_t amount) {
|
||||
m_Buffer.reserve(amount);
|
||||
}
|
||||
void Reserve(std::size_t amount) {
|
||||
m_Buffer.reserve(amount);
|
||||
}
|
||||
|
||||
void erase(iterator it) {
|
||||
m_Buffer.erase(it);
|
||||
}
|
||||
void erase(iterator it) {
|
||||
m_Buffer.erase(it);
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
m_Buffer.clear();
|
||||
m_ReadOffset = 0;
|
||||
}
|
||||
void Clear() {
|
||||
m_Buffer.clear();
|
||||
m_ReadOffset = 0;
|
||||
}
|
||||
|
||||
bool IsFinished() const {
|
||||
return m_ReadOffset >= m_Buffer.size();
|
||||
}
|
||||
bool IsFinished() const {
|
||||
return m_ReadOffset >= m_Buffer.size();
|
||||
}
|
||||
|
||||
std::uint8_t* data() {
|
||||
return m_Buffer.data();
|
||||
}
|
||||
std::uint8_t* data() {
|
||||
return m_Buffer.data();
|
||||
}
|
||||
|
||||
const std::uint8_t* data() const {
|
||||
return m_Buffer.data();
|
||||
}
|
||||
const std::uint8_t* data() const {
|
||||
return m_Buffer.data();
|
||||
}
|
||||
|
||||
std::size_t GetReadOffset() const { return m_ReadOffset; }
|
||||
void SetReadOffset(std::size_t pos);
|
||||
std::size_t GetReadOffset() const { return m_ReadOffset; }
|
||||
void SetReadOffset(std::size_t pos);
|
||||
|
||||
std::string ToString() const;
|
||||
std::size_t GetSize() const;
|
||||
bool IsEmpty() const;
|
||||
std::size_t GetRemaining() const;
|
||||
std::string ToString() const;
|
||||
std::size_t GetSize() const;
|
||||
bool IsEmpty() const;
|
||||
std::size_t GetRemaining() const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
reference operator[](Data::size_type i) { return m_Buffer[i]; }
|
||||
const_reference operator[](Data::size_type i) const { return m_Buffer[i]; }
|
||||
reference operator[](Data::size_type i) { return m_Buffer[i]; }
|
||||
const_reference operator[](Data::size_type i) const { return m_Buffer[i]; }
|
||||
|
||||
bool ReadFile(const std::string& fileName);
|
||||
bool WriteFile(const std::string& fileName);
|
||||
bool ReadFile(const std::string& fileName);
|
||||
bool WriteFile(const std::string& fileName);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
namespace td {
|
||||
namespace utils {
|
||||
|
||||
|
||||
template <typename... Args>
|
||||
std::string format(const std::string& format, Args... args){
|
||||
std::string format(const std::string& format, Args... args) {
|
||||
int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||
if (size <= 0){
|
||||
if (size <= 0) {
|
||||
throw std::runtime_error("Error during formatting.");
|
||||
}
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
|
||||
@@ -10,26 +10,26 @@ namespace utils {
|
||||
template <typename Listener>
|
||||
class ObjectNotifier {
|
||||
protected:
|
||||
std::vector<Listener*> m_Listeners;
|
||||
std::vector<Listener*> m_Listeners;
|
||||
|
||||
public:
|
||||
void BindListener(Listener* listener) {
|
||||
m_Listeners.push_back(listener);
|
||||
}
|
||||
void BindListener(Listener* listener) {
|
||||
m_Listeners.push_back(listener);
|
||||
}
|
||||
|
||||
void UnbindListener(Listener* listener) {
|
||||
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
|
||||
void UnbindListener(Listener* listener) {
|
||||
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
|
||||
|
||||
if (iter == m_Listeners.end()) return;
|
||||
if (iter == m_Listeners.end()) return;
|
||||
|
||||
m_Listeners.erase(iter);
|
||||
}
|
||||
m_Listeners.erase(iter);
|
||||
}
|
||||
|
||||
template <typename Func, typename... Args>
|
||||
void NotifyListeners(Func function, Args... args) {
|
||||
for (Listener* listener : m_Listeners)
|
||||
std::bind(function, listener, args...)();
|
||||
}
|
||||
template <typename Func, typename... Args>
|
||||
void NotifyListeners(Func function, Args... args) {
|
||||
for (Listener* listener : m_Listeners)
|
||||
std::bind(function, listener, args...)();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -4,49 +4,49 @@ namespace td {
|
||||
namespace utils {
|
||||
|
||||
enum class Os {
|
||||
Windows = 0,
|
||||
Linux,
|
||||
Android,
|
||||
Unknown,
|
||||
Windows = 0,
|
||||
Linux,
|
||||
Android,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
enum class Architecture {
|
||||
x86_64 = 0,
|
||||
x86,
|
||||
Arm64,
|
||||
Armhf,
|
||||
Unknown,
|
||||
x86_64 = 0,
|
||||
x86,
|
||||
Arm64,
|
||||
Armhf,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
inline Os GetSystemOs() {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
return Os::Windows;
|
||||
return Os::Windows;
|
||||
#elif defined(__ANDROID__)
|
||||
return Os::Android;
|
||||
return Os::Android;
|
||||
#elif defined(__unix__)
|
||||
return Os::Linux;
|
||||
return Os::Linux;
|
||||
#else
|
||||
#pragma message ("Target OS unknown or unsupported !")
|
||||
return Os::Unknown;
|
||||
return Os::Unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Architecture GetSystemArchitecture() {
|
||||
#if defined(_WIN64)
|
||||
return Architecture::x86_64;
|
||||
return Architecture::x86_64;
|
||||
#elif defined(_WIN32)
|
||||
return Architecture::x86;
|
||||
return Architecture::x86;
|
||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||
return Architecture::x86_64;
|
||||
return Architecture::x86_64;
|
||||
#elif defined(_M_IX86) || defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
|
||||
return Architecture::x86;
|
||||
return Architecture::x86;
|
||||
#elif defined(__aarch64__)
|
||||
return Architecture::Arm64;
|
||||
return Architecture::Arm64;
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
return Architecture::Armhf;
|
||||
return Architecture::Armhf;
|
||||
#else
|
||||
#pragma message ("Target CPU architecture unknown or unsupported !")
|
||||
return Architecture::Unknown;
|
||||
return Architecture::Unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@ namespace utils {
|
||||
|
||||
template<typename NumberType>
|
||||
NumberType GetRandomInt(NumberType min, NumberType max) {
|
||||
std::random_device randomDevice;
|
||||
std::mt19937 generator(randomDevice());
|
||||
std::uniform_int_distribution<NumberType> distrib(min, max);
|
||||
return distrib(generator);
|
||||
std::random_device randomDevice;
|
||||
std::mt19937 generator(randomDevice());
|
||||
std::uniform_int_distribution<NumberType> distrib(min, max);
|
||||
return distrib(generator);
|
||||
}
|
||||
|
||||
template<typename NumberType>
|
||||
NumberType GetRandomReal(NumberType min, NumberType max) {
|
||||
std::random_device randomDevice;
|
||||
std::mt19937 generator(randomDevice());
|
||||
std::uniform_real_distribution<NumberType> distrib(min, max);
|
||||
return distrib(generator);
|
||||
std::random_device randomDevice;
|
||||
std::mt19937 generator(randomDevice());
|
||||
std::uniform_real_distribution<NumberType> distrib(min, max);
|
||||
return distrib(generator);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -8,87 +8,87 @@ namespace shape {
|
||||
|
||||
class Point {
|
||||
private:
|
||||
float m_X, m_Y;
|
||||
float m_X, m_Y;
|
||||
public:
|
||||
Point() : m_X(0), m_Y(0) {}
|
||||
Point(float x, float y) : m_X(x), m_Y(y) {}
|
||||
Point() : m_X(0), m_Y(0) {}
|
||||
Point(float x, float y) : m_X(x), m_Y(y) {}
|
||||
|
||||
float GetX() const { return m_X; }
|
||||
float GetY() const { return m_Y; }
|
||||
float GetX() const { return m_X; }
|
||||
float GetY() const { return m_Y; }
|
||||
|
||||
void SetX(float x) { m_X = x; }
|
||||
void SetY(float y) { m_Y = y; }
|
||||
void SetX(float x) { m_X = x; }
|
||||
void SetY(float y) { m_Y = y; }
|
||||
|
||||
float Distance(const Point& point) const;
|
||||
float DistanceSquared(const Point& point) const;
|
||||
float Distance(const Point& point) const;
|
||||
float DistanceSquared(const Point& point) const;
|
||||
};
|
||||
|
||||
class Circle;
|
||||
|
||||
class Rectangle {
|
||||
private:
|
||||
Point m_Center;
|
||||
float m_Width, m_Height;
|
||||
Point m_Center;
|
||||
float m_Width, m_Height;
|
||||
public:
|
||||
Rectangle() {}
|
||||
Rectangle() {}
|
||||
|
||||
const Point& GetCenter() const { return m_Center; }
|
||||
float GetCenterX() const { return m_Center.GetX(); }
|
||||
float GetCenterY() const { return m_Center.GetY(); }
|
||||
const Point& GetCenter() const { return m_Center; }
|
||||
float GetCenterX() const { return m_Center.GetX(); }
|
||||
float GetCenterY() const { return m_Center.GetY(); }
|
||||
|
||||
float GetWidth() const { return m_Width; }
|
||||
float GetHeight() const { return m_Height; }
|
||||
float GetWidth() const { return m_Width; }
|
||||
float GetHeight() const { return m_Height; }
|
||||
|
||||
Point GetTopLeft() const { return { m_Center.GetX() - (m_Width / 2.0f), m_Center.GetY() - (m_Height / 2.0f) }; }
|
||||
Point GetBottomRight() const { return { m_Center.GetX() + (m_Width / 2.0f), m_Center.GetY() + (m_Height / 2.0f) }; }
|
||||
Point GetTopLeft() const { return { m_Center.GetX() - (m_Width / 2.0f), m_Center.GetY() - (m_Height / 2.0f) }; }
|
||||
Point GetBottomRight() const { return { m_Center.GetX() + (m_Width / 2.0f), m_Center.GetY() + (m_Height / 2.0f) }; }
|
||||
|
||||
void SetCenter(const Point& center) { m_Center = center; }
|
||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||
void SetCenter(const Point& center) { m_Center = center; }
|
||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||
|
||||
void SetSize(float width, float height) { SetWidth(width); SetHeight(height); }
|
||||
void SetSize(Point size) { SetSize(size.GetX(), size.GetY()); }
|
||||
Point GetSize() { return { m_Width, m_Height }; }
|
||||
void SetSize(float width, float height) { SetWidth(width); SetHeight(height); }
|
||||
void SetSize(Point size) { SetSize(size.GetX(), size.GetY()); }
|
||||
Point GetSize() { return { m_Width, m_Height }; }
|
||||
|
||||
void SetWidth(float width) { m_Width = width; }
|
||||
void SetHeight(float height) { m_Height = height; }
|
||||
void SetWidth(float width) { m_Width = width; }
|
||||
void SetHeight(float height) { m_Height = height; }
|
||||
|
||||
bool CollidesWith(const Point& point) const;
|
||||
bool CollidesWith(const Rectangle& rect) const;
|
||||
bool CollidesWith(const Circle& circle) const;
|
||||
bool CollidesWith(const Point& point) const;
|
||||
bool CollidesWith(const Rectangle& rect) const;
|
||||
bool CollidesWith(const Circle& circle) const;
|
||||
|
||||
// distance from the closest side of the rectangle
|
||||
float Distance(const Circle& circle) const;
|
||||
float DistanceSquared(const Circle& circle) const;
|
||||
// distance from the closest side of the rectangle
|
||||
float Distance(const Circle& circle) const;
|
||||
float DistanceSquared(const Circle& circle) const;
|
||||
};
|
||||
|
||||
class Circle {
|
||||
private:
|
||||
Point m_Center;
|
||||
float m_Radius;
|
||||
Point m_Center;
|
||||
float m_Radius;
|
||||
public:
|
||||
Circle(float x, float y, float radius) : m_Center(x, y), m_Radius(radius) {}
|
||||
Circle() : m_Radius(0) {}
|
||||
Circle(float x, float y, float radius) : m_Center(x, y), m_Radius(radius) {}
|
||||
Circle() : m_Radius(0) {}
|
||||
|
||||
const Point& GetCenter() const { return m_Center; }
|
||||
float GetCenterX() const { return m_Center.GetX(); }
|
||||
float GetCenterY() const { return m_Center.GetY(); }
|
||||
const Point& GetCenter() const { return m_Center; }
|
||||
float GetCenterX() const { return m_Center.GetX(); }
|
||||
float GetCenterY() const { return m_Center.GetY(); }
|
||||
|
||||
float GetRadius() const { return m_Radius; }
|
||||
float GetRadius() const { return m_Radius; }
|
||||
|
||||
void SetCenter(const Point& center) { m_Center = center; }
|
||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||
void SetCenter(const Point& center) { m_Center = center; }
|
||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||
|
||||
void SetRadius(float radius) { m_Radius = radius; }
|
||||
void SetRadius(float radius) { m_Radius = radius; }
|
||||
|
||||
bool CollidesWith(const Point& point) const;
|
||||
bool CollidesWith(const Rectangle& rect) const;
|
||||
bool CollidesWith(const Circle& circle) const;
|
||||
bool CollidesWith(const Point& point) const;
|
||||
bool CollidesWith(const Rectangle& rect) const;
|
||||
bool CollidesWith(const Circle& circle) const;
|
||||
|
||||
// distance from the closest side of the rectangle
|
||||
float Distance(const Rectangle& rect) const;
|
||||
float DistanceSquared(const Rectangle& rect) const;
|
||||
// distance from the closest side of the rectangle
|
||||
float Distance(const Rectangle& rect) const;
|
||||
float DistanceSquared(const Rectangle& rect) const;
|
||||
};
|
||||
|
||||
} // namespace shape
|
||||
|
||||
@@ -14,62 +14,62 @@ typedef std::function<void()> TimerExecFunction;
|
||||
// utililty class to call function at regular period of time
|
||||
class AutoTimer {
|
||||
private:
|
||||
std::uint64_t m_Interval;
|
||||
TimerExecFunction m_Function;
|
||||
std::uint64_t m_Interval;
|
||||
TimerExecFunction m_Function;
|
||||
|
||||
std::uint64_t m_LastTime = GetTime();
|
||||
std::uint64_t m_InternalTime = 0;
|
||||
std::uint64_t m_LastTime = GetTime();
|
||||
std::uint64_t m_InternalTime = 0;
|
||||
public:
|
||||
AutoTimer() : m_Interval(0), m_Function(nullptr) {}
|
||||
AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {}
|
||||
AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {}
|
||||
AutoTimer() : m_Interval(0), m_Function(nullptr) {}
|
||||
AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {}
|
||||
AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {}
|
||||
|
||||
void Update();
|
||||
void Update(std::uint64_t delta);
|
||||
void Update();
|
||||
void Update(std::uint64_t delta);
|
||||
|
||||
void Reset();
|
||||
void Reset();
|
||||
|
||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||
std::uint64_t GetInterval() const { return m_Interval; }
|
||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||
std::uint64_t GetInterval() const { return m_Interval; }
|
||||
|
||||
void SetCallbackFunction(TimerExecFunction newCallback) { m_Function = newCallback; }
|
||||
TimerExecFunction GetCallbackFunction() const { return m_Function; }
|
||||
void SetCallbackFunction(TimerExecFunction newCallback) { m_Function = newCallback; }
|
||||
TimerExecFunction GetCallbackFunction() const { return m_Function; }
|
||||
};
|
||||
|
||||
// utililty class to call function at regular period of time
|
||||
class Timer {
|
||||
private:
|
||||
std::uint64_t m_Interval; // in millis
|
||||
std::uint64_t m_InternalTime = 0;
|
||||
std::uint64_t m_Interval; // in millis
|
||||
std::uint64_t m_InternalTime = 0;
|
||||
public:
|
||||
Timer() : m_Interval(0) {}
|
||||
Timer(std::uint64_t interval) : m_Interval(interval) {}
|
||||
Timer() : m_Interval(0) {}
|
||||
Timer(std::uint64_t interval) : m_Interval(interval) {}
|
||||
|
||||
bool Update(std::uint64_t delta);
|
||||
bool Update(std::uint64_t delta);
|
||||
|
||||
void Reset();
|
||||
void Reset();
|
||||
|
||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||
std::uint64_t GetInterval() const { return m_Interval; }
|
||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||
std::uint64_t GetInterval() const { return m_Interval; }
|
||||
};
|
||||
|
||||
// utililty class to call function at regular period of time with a cooldown (used for towers and mobs )
|
||||
class CooldownTimer {
|
||||
private:
|
||||
std::uint64_t m_Cooldown; // in millis
|
||||
std::uint64_t m_CooldownTime;
|
||||
std::uint64_t m_Cooldown; // in millis
|
||||
std::uint64_t m_CooldownTime;
|
||||
public:
|
||||
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
|
||||
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
|
||||
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
|
||||
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
|
||||
|
||||
bool Update(std::uint64_t delta);
|
||||
bool Update(std::uint64_t delta);
|
||||
|
||||
void ApplyCooldown();
|
||||
void ApplyCooldown();
|
||||
|
||||
void Reset();
|
||||
void Reset();
|
||||
|
||||
void SetCooldown(std::uint64_t newCooldown) { m_CooldownTime = newCooldown; }
|
||||
std::uint64_t GetCooldown() const { return m_CooldownTime; }
|
||||
void SetCooldown(std::uint64_t newCooldown) { m_CooldownTime = newCooldown; }
|
||||
std::uint64_t GetCooldown() const { return m_CooldownTime; }
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -11,38 +11,38 @@ namespace network {
|
||||
/* IPv4 address */
|
||||
class IPAddress {
|
||||
private:
|
||||
std::uint32_t m_Address;
|
||||
bool m_Valid;
|
||||
std::uint32_t m_Address;
|
||||
bool m_Valid;
|
||||
|
||||
public:
|
||||
/* Create an invalid address */
|
||||
IPAddress() noexcept;
|
||||
/* Create an invalid address */
|
||||
IPAddress() noexcept;
|
||||
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::string& str);
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::string& str);
|
||||
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::wstring& str);
|
||||
/* Initialize by string IP */
|
||||
IPAddress(const std::wstring& str);
|
||||
|
||||
/* Initialize by octets */
|
||||
IPAddress(std::uint8_t octet1, std::uint8_t octet2, std::uint8_t octet3, std::uint8_t octet4) noexcept;
|
||||
/* Initialize by octets */
|
||||
IPAddress(std::uint8_t octet1, std::uint8_t octet2, std::uint8_t octet3, std::uint8_t octet4) noexcept;
|
||||
|
||||
/* Get the specific octet. 1-4 */
|
||||
std::uint8_t GetOctet(std::uint8_t num) const;
|
||||
/* Get the specific octet. 1-4 */
|
||||
std::uint8_t GetOctet(std::uint8_t num) const;
|
||||
|
||||
/* Set the specific octet. 1-4 */
|
||||
void SetOctet(std::uint8_t num, std::uint8_t value);
|
||||
/* Set the specific octet. 1-4 */
|
||||
void SetOctet(std::uint8_t num, std::uint8_t value);
|
||||
|
||||
/* Make sure the IP is valid. It will be invalid if the host wasn't found. */
|
||||
bool IsValid() const noexcept { return m_Valid; }
|
||||
/* Make sure the IP is valid. It will be invalid if the host wasn't found. */
|
||||
bool IsValid() const noexcept { return m_Valid; }
|
||||
|
||||
std::string ToString() const;
|
||||
std::string ToString() const;
|
||||
|
||||
static IPAddress LocalAddress();
|
||||
static IPAddress LocalAddress();
|
||||
|
||||
bool operator==(const IPAddress& right);
|
||||
bool operator!=(const IPAddress& right);
|
||||
bool operator==(bool b);
|
||||
bool operator==(const IPAddress& right);
|
||||
bool operator!=(const IPAddress& right);
|
||||
bool operator==(bool b);
|
||||
};
|
||||
|
||||
typedef std::vector<IPAddress> IPAddresses;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace network {
|
||||
|
||||
class Dns {
|
||||
public:
|
||||
static IPAddresses Resolve(const std::string& host);
|
||||
static IPAddresses Resolve(const std::string& host);
|
||||
};
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -40,45 +40,45 @@ typedef int SocketHandle;
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
enum Status { Connected, Disconnected, Error };
|
||||
enum Type { TCP, UDP };
|
||||
enum Status { Connected, Disconnected, Error };
|
||||
enum Type { TCP, UDP };
|
||||
|
||||
private:
|
||||
bool m_Blocking;
|
||||
Type m_Type;
|
||||
Status m_Status;
|
||||
bool m_Blocking;
|
||||
Type m_Type;
|
||||
Status m_Status;
|
||||
|
||||
protected:
|
||||
SocketHandle m_Handle;
|
||||
SocketHandle m_Handle;
|
||||
|
||||
Socket(Type type);
|
||||
void SetStatus(Status status);
|
||||
Socket(Type type);
|
||||
void SetStatus(Status status);
|
||||
|
||||
public:
|
||||
virtual ~Socket();
|
||||
virtual ~Socket();
|
||||
|
||||
Socket(Socket&& rhs) = default;
|
||||
Socket& operator=(Socket&& rhs) = default;
|
||||
Socket(Socket&& rhs) = default;
|
||||
Socket& operator=(Socket&& rhs) = default;
|
||||
|
||||
bool SetBlocking(bool block);
|
||||
bool IsBlocking() const noexcept;
|
||||
bool SetBlocking(bool block);
|
||||
bool IsBlocking() const noexcept;
|
||||
|
||||
Type GetType() const noexcept;
|
||||
Status GetStatus() const noexcept;
|
||||
SocketHandle GetHandle() const noexcept;
|
||||
Type GetType() const noexcept;
|
||||
Status GetStatus() const noexcept;
|
||||
SocketHandle GetHandle() const noexcept;
|
||||
|
||||
bool Connect(const std::string& ip, std::uint16_t port);
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port) = 0;
|
||||
bool Connect(const std::string& ip, std::uint16_t port);
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port) = 0;
|
||||
|
||||
void Disconnect();
|
||||
void Disconnect();
|
||||
|
||||
std::size_t Send(const std::string& data);
|
||||
std::size_t Send(DataBuffer& buffer);
|
||||
std::size_t Send(const std::string& data);
|
||||
std::size_t Send(DataBuffer& buffer);
|
||||
|
||||
virtual std::size_t Send(const uint8_t* data, std::size_t size) = 0;
|
||||
virtual DataBuffer Receive(std::size_t amount) = 0;
|
||||
virtual std::size_t Send(const uint8_t* data, std::size_t size) = 0;
|
||||
virtual DataBuffer Receive(std::size_t amount) = 0;
|
||||
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount) = 0;
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Socket> SocketPtr;
|
||||
|
||||
@@ -5,30 +5,30 @@ namespace td {
|
||||
namespace network {
|
||||
|
||||
class TCPListener {
|
||||
int m_Handle;
|
||||
std::uint16_t m_Port;
|
||||
int m_MaxConnections;
|
||||
int m_Handle;
|
||||
std::uint16_t m_Port;
|
||||
int m_MaxConnections;
|
||||
|
||||
public:
|
||||
TCPListener();
|
||||
~TCPListener();
|
||||
TCPListener();
|
||||
~TCPListener();
|
||||
|
||||
bool Listen(std::uint16_t port, int maxConnections);
|
||||
bool Accept(TCPSocket& newSocket);
|
||||
bool Listen(std::uint16_t port, int maxConnections);
|
||||
bool Accept(TCPSocket& newSocket);
|
||||
|
||||
void Destroy();
|
||||
bool Close();
|
||||
bool SetBlocking(bool blocking);
|
||||
void Destroy();
|
||||
bool Close();
|
||||
bool SetBlocking(bool blocking);
|
||||
|
||||
std::uint16_t GetListeningPort() const {
|
||||
return m_Port;
|
||||
}
|
||||
std::uint16_t GetListeningPort() const {
|
||||
return m_Port;
|
||||
}
|
||||
|
||||
int GetMaximumConnections() const {
|
||||
return m_MaxConnections;
|
||||
}
|
||||
int GetMaximumConnections() const {
|
||||
return m_MaxConnections;
|
||||
}
|
||||
|
||||
REMOVE_COPY(TCPListener);
|
||||
REMOVE_COPY(TCPListener);
|
||||
};
|
||||
|
||||
} // namespace network
|
||||
|
||||
@@ -13,22 +13,22 @@ class TCPListener;
|
||||
|
||||
class TCPSocket : public Socket {
|
||||
private:
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr m_RemoteAddr;
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr m_RemoteAddr;
|
||||
|
||||
public:
|
||||
TCPSocket();
|
||||
TCPSocket(TCPSocket&& other);
|
||||
TCPSocket();
|
||||
TCPSocket(TCPSocket&& other);
|
||||
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
virtual std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
virtual DataBuffer Receive(std::size_t amount);
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||
virtual bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
virtual std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
virtual DataBuffer Receive(std::size_t amount);
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||
|
||||
REMOVE_COPY(TCPSocket);
|
||||
REMOVE_COPY(TCPSocket);
|
||||
|
||||
friend class TCPListener;
|
||||
friend class TCPListener;
|
||||
};
|
||||
|
||||
void SendPacket(const DataBuffer& data, network::TCPSocket& socket);
|
||||
|
||||
@@ -11,18 +11,18 @@ namespace network {
|
||||
|
||||
class UDPSocket : public Socket {
|
||||
private:
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr_in m_RemoteAddr;
|
||||
IPAddress m_RemoteIP;
|
||||
uint16_t m_Port;
|
||||
sockaddr_in m_RemoteAddr;
|
||||
|
||||
public:
|
||||
UDPSocket();
|
||||
UDPSocket();
|
||||
|
||||
bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
bool Connect(const IPAddress& address, std::uint16_t port);
|
||||
std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||
|
||||
virtual DataBuffer Receive(std::size_t amount);
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||
virtual DataBuffer Receive(std::size_t amount);
|
||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||
};
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -12,21 +12,21 @@ class PacketHandler;
|
||||
|
||||
class PacketDispatcher {
|
||||
private:
|
||||
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
|
||||
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
|
||||
|
||||
public:
|
||||
PacketDispatcher() = default;
|
||||
PacketDispatcher() = default;
|
||||
|
||||
PacketDispatcher(const PacketDispatcher& rhs) = delete;
|
||||
PacketDispatcher& operator=(const PacketDispatcher& rhs) = delete;
|
||||
PacketDispatcher(PacketDispatcher&& rhs) = delete;
|
||||
PacketDispatcher& operator=(PacketDispatcher&& rhs) = delete;
|
||||
PacketDispatcher(const PacketDispatcher& rhs) = delete;
|
||||
PacketDispatcher& operator=(const PacketDispatcher& rhs) = delete;
|
||||
PacketDispatcher(PacketDispatcher&& rhs) = delete;
|
||||
PacketDispatcher& operator=(PacketDispatcher&& rhs) = delete;
|
||||
|
||||
void Dispatch(const PacketPtr& packet);
|
||||
void Dispatch(const PacketPtr& packet);
|
||||
|
||||
void RegisterHandler(PacketType type, PacketHandler* handler);
|
||||
void UnregisterHandler(PacketType type, PacketHandler* handler);
|
||||
void UnregisterHandler(PacketHandler* handler);
|
||||
void RegisterHandler(PacketType type, PacketHandler* handler);
|
||||
void UnregisterHandler(PacketType type, PacketHandler* handler);
|
||||
void UnregisterHandler(PacketHandler* handler);
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -9,39 +9,39 @@ class PacketDispatcher;
|
||||
|
||||
class PacketHandler {
|
||||
private:
|
||||
PacketDispatcher* m_Dispatcher;
|
||||
PacketDispatcher* m_Dispatcher;
|
||||
public:
|
||||
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
|
||||
virtual ~PacketHandler() {}
|
||||
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
|
||||
virtual ~PacketHandler() {}
|
||||
|
||||
PacketDispatcher* GetDispatcher() { return m_Dispatcher; }
|
||||
PacketDispatcher* GetDispatcher() { return m_Dispatcher; }
|
||||
|
||||
virtual void HandlePacket(const ConnexionInfoPacket* packet) {}
|
||||
virtual void HandlePacket(const DisconnectPacket* packet) {}
|
||||
virtual void HandlePacket(const KeepAlivePacket* packet) {}
|
||||
virtual void HandlePacket(const PlaceTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerBuyItemPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerBuyMobUpgradePacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerJoinPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerLeavePacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerListPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerLoginPacket* packet) {}
|
||||
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const SelectTeamPacket* packet) {}
|
||||
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
||||
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
||||
virtual void HandlePacket(const SpawnMobPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateCastleLifePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateExpPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateLobbyTimePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateMobStatesPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateMoneyPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdatePlayerTeamPacket* packet) {}
|
||||
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldAddTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldBeginDataPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldDataPacket* packet) {}
|
||||
virtual void HandlePacket(const ConnexionInfoPacket* packet) {}
|
||||
virtual void HandlePacket(const DisconnectPacket* packet) {}
|
||||
virtual void HandlePacket(const KeepAlivePacket* packet) {}
|
||||
virtual void HandlePacket(const PlaceTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerBuyItemPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerBuyMobUpgradePacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerJoinPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerLeavePacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerListPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerLoginPacket* packet) {}
|
||||
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const SelectTeamPacket* packet) {}
|
||||
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
||||
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
||||
virtual void HandlePacket(const SpawnMobPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateCastleLifePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateExpPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateLobbyTimePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateMobStatesPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateMoneyPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdatePlayerTeamPacket* packet) {}
|
||||
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldAddTowerPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldBeginDataPacket* packet) {}
|
||||
virtual void HandlePacket(const WorldDataPacket* packet) {}
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -12,621 +12,625 @@ namespace protocol {
|
||||
class PacketHandler;
|
||||
|
||||
enum class PacketType : std::uint8_t {
|
||||
// client --> server
|
||||
PlayerLogin = 0,
|
||||
SelectTeam,
|
||||
SpawnMob,
|
||||
SendMobs,
|
||||
PlaceTower,
|
||||
// client --> server
|
||||
PlayerLogin = 0,
|
||||
SelectTeam,
|
||||
SpawnMob,
|
||||
SendMobs,
|
||||
PlaceTower,
|
||||
|
||||
// client <-- server
|
||||
PlayerJoin,
|
||||
PlayerLeave,
|
||||
WorldBeginData,
|
||||
WorldData,
|
||||
UpdateMoney,
|
||||
UpdateEXP,
|
||||
UpdateLobbyTime,
|
||||
UpdateGameState,
|
||||
PlayerList,
|
||||
ConnectionInfo,
|
||||
UpdatePlayerTeam,
|
||||
ServerTps,
|
||||
WorldAddTower,
|
||||
UpdateMobStates,
|
||||
UpdateCastleLife,
|
||||
// client <-- server
|
||||
PlayerJoin,
|
||||
PlayerLeave,
|
||||
WorldBeginData,
|
||||
WorldData,
|
||||
UpdateMoney,
|
||||
UpdateEXP,
|
||||
UpdateLobbyTime,
|
||||
UpdateGameState,
|
||||
PlayerList,
|
||||
ConnectionInfo,
|
||||
UpdatePlayerTeam,
|
||||
ServerTps,
|
||||
WorldAddTower,
|
||||
UpdateMobStates,
|
||||
UpdateCastleLife,
|
||||
|
||||
// client <--> server
|
||||
KeepAlive,
|
||||
Disconnect,
|
||||
UpgradeTower,
|
||||
RemoveTower,
|
||||
PlayerBuyItem,
|
||||
PlayerBuyMobUpgrade,
|
||||
// client <--> server
|
||||
KeepAlive,
|
||||
Disconnect,
|
||||
UpgradeTower,
|
||||
RemoveTower,
|
||||
PlayerBuyItem,
|
||||
PlayerBuyMobUpgrade,
|
||||
|
||||
PACKET_COUNT
|
||||
PACKET_COUNT
|
||||
};
|
||||
|
||||
struct WorldHeader {
|
||||
game::TowerTileColorPalette m_TowerPlacePalette;
|
||||
Color m_WalkablePalette;
|
||||
std::vector<Color> m_DecorationPalette;
|
||||
Color m_Background;
|
||||
game::TowerTileColorPalette m_TowerPlacePalette;
|
||||
Color m_WalkablePalette;
|
||||
std::vector<Color> m_DecorationPalette;
|
||||
Color m_Background;
|
||||
|
||||
game::SpawnColorPalette m_SpawnColorPalette;
|
||||
game::SpawnColorPalette m_SpawnColorPalette;
|
||||
|
||||
game::TilePalette m_TilePalette;
|
||||
game::TilePalette m_TilePalette;
|
||||
|
||||
game::Spawn m_RedSpawn, m_BlueSpawn;
|
||||
game::TeamCastle m_RedCastle, m_BlueCastle;
|
||||
game::Spawn m_RedSpawn, m_BlueSpawn;
|
||||
game::TeamCastle m_RedCastle, m_BlueCastle;
|
||||
|
||||
const game::World* m_World;
|
||||
const game::World* m_World;
|
||||
};
|
||||
|
||||
struct WorldData {
|
||||
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
||||
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
||||
};
|
||||
|
||||
class Packet {
|
||||
public:
|
||||
Packet() {}
|
||||
virtual ~Packet() {}
|
||||
Packet() {}
|
||||
virtual ~Packet() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const = 0;
|
||||
virtual void Deserialize(DataBuffer& data) = 0;
|
||||
virtual void Dispatch(PacketHandler* handler) const = 0;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const = 0;
|
||||
virtual void Deserialize(DataBuffer& data) = 0;
|
||||
virtual void Dispatch(PacketHandler* handler) const = 0;
|
||||
|
||||
void WritePacketID(DataBuffer& data, bool packetID) const;
|
||||
void WritePacketID(DataBuffer& data, bool packetID) const;
|
||||
|
||||
virtual PacketType GetType() const = 0;
|
||||
std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
|
||||
virtual PacketType GetType() const = 0;
|
||||
std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<Packet> PacketPtr;
|
||||
|
||||
class KeepAlivePacket : public Packet {
|
||||
private:
|
||||
std::uint64_t m_AliveID;
|
||||
std::uint64_t m_AliveID;
|
||||
public:
|
||||
KeepAlivePacket() {}
|
||||
KeepAlivePacket(std::uint64_t aliveID) : m_AliveID(aliveID) {}
|
||||
virtual ~KeepAlivePacket() {}
|
||||
KeepAlivePacket() {}
|
||||
KeepAlivePacket(std::uint64_t aliveID) : m_AliveID(aliveID) {}
|
||||
virtual ~KeepAlivePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint64_t GetAliveID() const { return m_AliveID; }
|
||||
std::uint64_t GetAliveID() const { return m_AliveID; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::KeepAlive; }
|
||||
virtual PacketType GetType() const { return PacketType::KeepAlive; }
|
||||
};
|
||||
|
||||
class PlayerLoginPacket : public Packet {
|
||||
private:
|
||||
std::string m_PlayerName;
|
||||
std::string m_PlayerName;
|
||||
public:
|
||||
PlayerLoginPacket() {}
|
||||
PlayerLoginPacket(std::string playerName) : m_PlayerName(playerName) {}
|
||||
virtual ~PlayerLoginPacket() {}
|
||||
PlayerLoginPacket() {}
|
||||
PlayerLoginPacket(std::string playerName) : m_PlayerName(playerName) {}
|
||||
virtual ~PlayerLoginPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerLogin; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerLogin; }
|
||||
|
||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||
};
|
||||
|
||||
class WorldBeginDataPacket : public Packet {
|
||||
private:
|
||||
WorldHeader m_Header;
|
||||
WorldHeader m_Header;
|
||||
public:
|
||||
WorldBeginDataPacket() {}
|
||||
WorldBeginDataPacket(const game::World* world) {
|
||||
m_Header.m_World = world;
|
||||
}
|
||||
virtual ~WorldBeginDataPacket() {}
|
||||
WorldBeginDataPacket() {}
|
||||
WorldBeginDataPacket(const game::World* world) {
|
||||
m_Header.m_World = world;
|
||||
}
|
||||
virtual ~WorldBeginDataPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::WorldBeginData; }
|
||||
virtual PacketType GetType() const { return PacketType::WorldBeginData; }
|
||||
|
||||
const game::TowerTileColorPalette& GetTowerTilePalette() const { return m_Header.m_TowerPlacePalette; }
|
||||
const Color& GetWalkableTileColor() const { return m_Header.m_WalkablePalette; }
|
||||
const std::vector<Color>& GetDecorationPalette() const { return m_Header.m_DecorationPalette; }
|
||||
const Color& GetBackgroundColor() const { return m_Header.m_Background; }
|
||||
const game::TowerTileColorPalette& GetTowerTilePalette() const { return m_Header.m_TowerPlacePalette; }
|
||||
const Color& GetWalkableTileColor() const { return m_Header.m_WalkablePalette; }
|
||||
const std::vector<Color>& GetDecorationPalette() const { return m_Header.m_DecorationPalette; }
|
||||
const Color& GetBackgroundColor() const { return m_Header.m_Background; }
|
||||
|
||||
const game::Spawn& GetRedSpawn() const { return m_Header.m_RedSpawn; }
|
||||
const game::Spawn& GetBlueSpawn() const { return m_Header.m_BlueSpawn; }
|
||||
const game::Spawn& GetRedSpawn() const { return m_Header.m_RedSpawn; }
|
||||
const game::Spawn& GetBlueSpawn() const { return m_Header.m_BlueSpawn; }
|
||||
|
||||
const game::SpawnColorPalette& GetSpawnPalette() const { return m_Header.m_SpawnColorPalette; }
|
||||
const game::SpawnColorPalette& GetSpawnPalette() const { return m_Header.m_SpawnColorPalette; }
|
||||
|
||||
const game::TeamCastle& GetRedCastle() const { return m_Header.m_RedCastle; }
|
||||
const game::TeamCastle& GetBlueCastle() const { return m_Header.m_BlueCastle; }
|
||||
const game::TeamCastle& GetRedCastle() const { return m_Header.m_RedCastle; }
|
||||
const game::TeamCastle& GetBlueCastle() const { return m_Header.m_BlueCastle; }
|
||||
|
||||
const game::TilePalette GetTilePalette() const { return m_Header.m_TilePalette; }
|
||||
const game::TilePalette GetTilePalette() const { return m_Header.m_TilePalette; }
|
||||
|
||||
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
|
||||
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
|
||||
};
|
||||
|
||||
class WorldDataPacket : public Packet {
|
||||
private:
|
||||
WorldData m_WorldData;
|
||||
WorldData m_WorldData;
|
||||
|
||||
const game::World* m_World;
|
||||
const game::World* m_World;
|
||||
public:
|
||||
WorldDataPacket() {}
|
||||
WorldDataPacket(const game::World* world) : m_World(world) {}
|
||||
virtual ~WorldDataPacket() {}
|
||||
WorldDataPacket() {}
|
||||
WorldDataPacket(const game::World* world) : m_World(world) {}
|
||||
virtual ~WorldDataPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::WorldData; }
|
||||
virtual PacketType GetType() const { return PacketType::WorldData; }
|
||||
|
||||
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& GetChunks() const { return m_WorldData.m_Chunks; }
|
||||
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& GetChunks() const { return m_WorldData.m_Chunks; }
|
||||
|
||||
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
||||
void SetWorldData(const WorldData& worldData) { m_WorldData = worldData; }
|
||||
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
||||
void SetWorldData(const WorldData& worldData) { m_WorldData = worldData; }
|
||||
};
|
||||
|
||||
class UpdateMoneyPacket : public Packet {
|
||||
private:
|
||||
std::uint32_t m_NewAmount;
|
||||
std::uint32_t m_NewAmount;
|
||||
public:
|
||||
UpdateMoneyPacket() {}
|
||||
UpdateMoneyPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||
virtual ~UpdateMoneyPacket() {}
|
||||
UpdateMoneyPacket() {}
|
||||
UpdateMoneyPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||
virtual ~UpdateMoneyPacket() {}
|
||||
|
||||
std::uint32_t GetGold() const { return m_NewAmount; }
|
||||
std::uint32_t GetGold() const { return m_NewAmount; }
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateMoney; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateMoney; }
|
||||
};
|
||||
|
||||
class UpdateExpPacket : public Packet {
|
||||
private:
|
||||
std::uint32_t m_NewAmount;
|
||||
std::uint32_t m_NewAmount;
|
||||
public:
|
||||
UpdateExpPacket() {}
|
||||
UpdateExpPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||
virtual ~UpdateExpPacket() {}
|
||||
UpdateExpPacket() {}
|
||||
UpdateExpPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||
virtual ~UpdateExpPacket() {}
|
||||
|
||||
std::uint32_t GetExp() const { return m_NewAmount; }
|
||||
std::uint32_t GetExp() const { return m_NewAmount; }
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateEXP; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateEXP; }
|
||||
};
|
||||
|
||||
class UpdateLobbyTimePacket : public Packet {
|
||||
private:
|
||||
std::uint32_t m_RemainingTime;
|
||||
std::uint32_t m_RemainingTime;
|
||||
public:
|
||||
UpdateLobbyTimePacket() {}
|
||||
UpdateLobbyTimePacket(std::uint32_t remainingTime) : m_RemainingTime(remainingTime) {}
|
||||
virtual ~UpdateLobbyTimePacket() {}
|
||||
UpdateLobbyTimePacket() {}
|
||||
UpdateLobbyTimePacket(std::uint32_t remainingTime) : m_RemainingTime(remainingTime) {}
|
||||
virtual ~UpdateLobbyTimePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint32_t GetRemainingTime() const { return m_RemainingTime; }
|
||||
std::uint32_t GetRemainingTime() const { return m_RemainingTime; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateLobbyTime; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateLobbyTime; }
|
||||
};
|
||||
|
||||
class UpdateGameStatePacket : public Packet {
|
||||
private:
|
||||
game::GameState m_GameState;
|
||||
game::GameState m_GameState;
|
||||
public:
|
||||
UpdateGameStatePacket() {}
|
||||
UpdateGameStatePacket(game::GameState gameState) : m_GameState(gameState) {}
|
||||
virtual ~UpdateGameStatePacket() {}
|
||||
UpdateGameStatePacket() {}
|
||||
UpdateGameStatePacket(game::GameState gameState) : m_GameState(gameState) {}
|
||||
virtual ~UpdateGameStatePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::GameState GetGameState() const { return m_GameState; }
|
||||
game::GameState GetGameState() const { return m_GameState; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateGameState; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateGameState; }
|
||||
};
|
||||
|
||||
struct PlayerInfo {
|
||||
std::string name;
|
||||
game::TeamColor team;
|
||||
std::string name;
|
||||
game::TeamColor team;
|
||||
};
|
||||
|
||||
class PlayerListPacket : public Packet {
|
||||
private:
|
||||
std::map<std::uint8_t, PlayerInfo> m_Players;
|
||||
std::map<std::uint8_t, PlayerInfo> m_Players;
|
||||
public:
|
||||
PlayerListPacket() {}
|
||||
PlayerListPacket(std::map<std::uint8_t, PlayerInfo> players) : m_Players(players) {}
|
||||
virtual ~PlayerListPacket() {}
|
||||
PlayerListPacket() {}
|
||||
PlayerListPacket(std::map<std::uint8_t, PlayerInfo> players) : m_Players(players) {}
|
||||
virtual ~PlayerListPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
const std::map<std::uint8_t, PlayerInfo>& GetPlayers() const { return m_Players; }
|
||||
const std::map<std::uint8_t, PlayerInfo>& GetPlayers() const { return m_Players; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerList; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerList; }
|
||||
};
|
||||
|
||||
class PlayerJoinPacket : public Packet {
|
||||
private:
|
||||
std::uint8_t m_PlayerID;
|
||||
std::string m_PlayerName;
|
||||
std::uint8_t m_PlayerID;
|
||||
std::string m_PlayerName;
|
||||
public:
|
||||
PlayerJoinPacket() {}
|
||||
PlayerJoinPacket(std::uint8_t playerID, const std::string& playerName) : m_PlayerID(playerID), m_PlayerName(playerName) {}
|
||||
virtual ~PlayerJoinPacket() {}
|
||||
PlayerJoinPacket() {}
|
||||
PlayerJoinPacket(std::uint8_t playerID, const std::string& playerName) : m_PlayerID(playerID), m_PlayerName(playerName) {}
|
||||
virtual ~PlayerJoinPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerJoin; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerJoin; }
|
||||
};
|
||||
|
||||
class PlayerLeavePacket : public Packet {
|
||||
private:
|
||||
std::uint8_t m_PlayerID;
|
||||
std::uint8_t m_PlayerID;
|
||||
public:
|
||||
PlayerLeavePacket() {}
|
||||
PlayerLeavePacket(std::uint8_t playerID) : m_PlayerID(playerID) {}
|
||||
virtual ~PlayerLeavePacket() {}
|
||||
PlayerLeavePacket() {}
|
||||
PlayerLeavePacket(std::uint8_t playerID) : m_PlayerID(playerID) {}
|
||||
virtual ~PlayerLeavePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerLeave; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerLeave; }
|
||||
};
|
||||
|
||||
class ConnexionInfoPacket : public Packet {
|
||||
private:
|
||||
std::uint8_t m_ConnectionID;
|
||||
std::uint8_t m_ConnectionID;
|
||||
public:
|
||||
ConnexionInfoPacket() {}
|
||||
ConnexionInfoPacket(std::uint8_t connectionID) : m_ConnectionID(connectionID) {}
|
||||
virtual ~ConnexionInfoPacket() {}
|
||||
ConnexionInfoPacket() {}
|
||||
ConnexionInfoPacket(std::uint8_t connectionID) : m_ConnectionID(connectionID) {}
|
||||
virtual ~ConnexionInfoPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint8_t GetConnectionID() const { return m_ConnectionID; }
|
||||
std::uint8_t GetConnectionID() const { return m_ConnectionID; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::ConnectionInfo; }
|
||||
virtual PacketType GetType() const { return PacketType::ConnectionInfo; }
|
||||
};
|
||||
|
||||
class SelectTeamPacket : public Packet {
|
||||
private:
|
||||
game::TeamColor m_SelectedTeam;
|
||||
game::TeamColor m_SelectedTeam;
|
||||
public:
|
||||
SelectTeamPacket() {}
|
||||
SelectTeamPacket(game::TeamColor selectedTeam) : m_SelectedTeam(selectedTeam) {}
|
||||
virtual ~SelectTeamPacket() {}
|
||||
SelectTeamPacket() {}
|
||||
SelectTeamPacket(game::TeamColor selectedTeam) : m_SelectedTeam(selectedTeam) {}
|
||||
virtual ~SelectTeamPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::SelectTeam; }
|
||||
virtual PacketType GetType() const { return PacketType::SelectTeam; }
|
||||
};
|
||||
|
||||
class UpdatePlayerTeamPacket : public Packet {
|
||||
private:
|
||||
std::uint8_t m_PlayerID;
|
||||
game::TeamColor m_SelectedTeam;
|
||||
std::uint8_t m_PlayerID;
|
||||
game::TeamColor m_SelectedTeam;
|
||||
public:
|
||||
UpdatePlayerTeamPacket() {}
|
||||
UpdatePlayerTeamPacket(std::uint8_t playerID, game::TeamColor selectedTeam) : m_PlayerID(playerID), m_SelectedTeam(selectedTeam) {}
|
||||
virtual ~UpdatePlayerTeamPacket() {}
|
||||
UpdatePlayerTeamPacket() {}
|
||||
UpdatePlayerTeamPacket(std::uint8_t playerID, game::TeamColor selectedTeam) : m_PlayerID(playerID), m_SelectedTeam(selectedTeam) {}
|
||||
virtual ~UpdatePlayerTeamPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdatePlayerTeam; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdatePlayerTeam; }
|
||||
};
|
||||
|
||||
class DisconnectPacket : public Packet {
|
||||
private:
|
||||
std::string m_Reason; // only when sent from server
|
||||
std::string m_Reason; // only when sent from server
|
||||
public:
|
||||
DisconnectPacket() {}
|
||||
DisconnectPacket(std::string reason) : m_Reason(reason) {}
|
||||
virtual ~DisconnectPacket() {}
|
||||
DisconnectPacket() {}
|
||||
DisconnectPacket(std::string reason) : m_Reason(reason) {}
|
||||
virtual ~DisconnectPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
const std::string& GetReason() const { return m_Reason; }
|
||||
const std::string& GetReason() const { return m_Reason; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::Disconnect; }
|
||||
virtual PacketType GetType() const { return PacketType::Disconnect; }
|
||||
};
|
||||
|
||||
class ServerTpsPacket : public Packet {
|
||||
private:
|
||||
float m_TPS;
|
||||
std::uint64_t m_PacketSendTime; // used to calculate ping
|
||||
float m_TPS;
|
||||
std::uint64_t m_PacketSendTime; // used to calculate ping
|
||||
public:
|
||||
ServerTpsPacket() {}
|
||||
ServerTpsPacket(float tps, std::uint64_t sendTime) : m_TPS(tps), m_PacketSendTime(sendTime) {}
|
||||
virtual ~ServerTpsPacket() {}
|
||||
ServerTpsPacket() {}
|
||||
ServerTpsPacket(float tps, std::uint64_t sendTime) : m_TPS(tps), m_PacketSendTime(sendTime) {}
|
||||
virtual ~ServerTpsPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
float GetTPS() const { return m_TPS; }
|
||||
std::uint64_t GetPacketSendTime() const { return m_PacketSendTime; }
|
||||
float GetTPS() const { return m_TPS; }
|
||||
std::uint64_t GetPacketSendTime() const { return m_PacketSendTime; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::ServerTps; }
|
||||
virtual PacketType GetType() const { return PacketType::ServerTps; }
|
||||
};
|
||||
|
||||
struct MobSend { // represents a mob send
|
||||
game::MobType mobType : 4;
|
||||
game::MobLevel mobLevel : 4;
|
||||
std::uint8_t mobCount; // the max is 12
|
||||
game::MobType mobType : 4;
|
||||
game::MobLevel mobLevel : 4;
|
||||
std::uint8_t mobCount; // the max is 12
|
||||
};
|
||||
|
||||
class SendMobsPacket : public Packet {
|
||||
private:
|
||||
std::vector<MobSend> m_MobSends;
|
||||
std::vector<MobSend> m_MobSends;
|
||||
public:
|
||||
SendMobsPacket() {}
|
||||
SendMobsPacket(const std::vector<MobSend>& mobSends) : m_MobSends(mobSends) {}
|
||||
virtual ~SendMobsPacket() {}
|
||||
SendMobsPacket() {}
|
||||
SendMobsPacket(const std::vector<MobSend>& mobSends) : m_MobSends(mobSends) {}
|
||||
virtual ~SendMobsPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
const std::vector<MobSend>& GetMobSends() const { return m_MobSends; }
|
||||
const std::vector<MobSend>& GetMobSends() const { return m_MobSends; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::SendMobs; }
|
||||
virtual PacketType GetType() const { return PacketType::SendMobs; }
|
||||
};
|
||||
|
||||
class SpawnMobPacket : public Packet {
|
||||
private:
|
||||
game::MobID m_MobID;
|
||||
game::MobType m_MobType;
|
||||
game::MobLevel m_MobLevel;
|
||||
game::Direction m_MobDirection;
|
||||
game::PlayerID m_Sender;
|
||||
float m_MobX, m_MobY;
|
||||
game::MobID m_MobID;
|
||||
game::MobType m_MobType;
|
||||
game::MobLevel m_MobLevel;
|
||||
game::Direction m_MobDirection;
|
||||
game::PlayerID m_Sender;
|
||||
float m_MobX, m_MobY;
|
||||
public:
|
||||
SpawnMobPacket() {}
|
||||
SpawnMobPacket(game::MobID id, game::MobType type, std::uint8_t level, game::PlayerID sender,
|
||||
float x, float y, game::Direction dir) : m_MobID(id), m_MobType(type), m_MobLevel(level),
|
||||
m_MobDirection(dir), m_Sender(sender), m_MobX(x), m_MobY(y) {}
|
||||
virtual ~SpawnMobPacket() {}
|
||||
SpawnMobPacket() {}
|
||||
SpawnMobPacket(game::MobID id, game::MobType type, std::uint8_t level, game::PlayerID sender,
|
||||
float x, float y, game::Direction dir) : m_MobID(id), m_MobType(type), m_MobLevel(level),
|
||||
m_MobDirection(dir), m_Sender(sender), m_MobX(x), m_MobY(y) {
|
||||
}
|
||||
virtual ~SpawnMobPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::MobID GetMobID() const { return m_MobID; }
|
||||
game::MobType GetMobType() const { return m_MobType; }
|
||||
game::MobLevel GetMobLevel() const { return m_MobLevel; }
|
||||
game::Direction GetMobDirection() const { return m_MobDirection; }
|
||||
game::PlayerID GetSender() const { return m_Sender; }
|
||||
float GetMobX() const { return m_MobX; }
|
||||
float GetMobY() const { return m_MobY; }
|
||||
game::MobID GetMobID() const { return m_MobID; }
|
||||
game::MobType GetMobType() const { return m_MobType; }
|
||||
game::MobLevel GetMobLevel() const { return m_MobLevel; }
|
||||
game::Direction GetMobDirection() const { return m_MobDirection; }
|
||||
game::PlayerID GetSender() const { return m_Sender; }
|
||||
float GetMobX() const { return m_MobX; }
|
||||
float GetMobY() const { return m_MobY; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::SpawnMob; }
|
||||
virtual PacketType GetType() const { return PacketType::SpawnMob; }
|
||||
};
|
||||
|
||||
class PlaceTowerPacket : public Packet {
|
||||
private:
|
||||
std::int32_t m_TowerX, m_TowerY;
|
||||
game::TowerType m_TowerType;
|
||||
std::int32_t m_TowerX, m_TowerY;
|
||||
game::TowerType m_TowerType;
|
||||
public:
|
||||
PlaceTowerPacket() {}
|
||||
PlaceTowerPacket(std::int32_t x, std::int32_t y, game::TowerType type) :
|
||||
m_TowerX(x), m_TowerY(y), m_TowerType(type) {}
|
||||
virtual ~PlaceTowerPacket() {}
|
||||
PlaceTowerPacket() {}
|
||||
PlaceTowerPacket(std::int32_t x, std::int32_t y, game::TowerType type) :
|
||||
m_TowerX(x), m_TowerY(y), m_TowerType(type) {
|
||||
}
|
||||
virtual ~PlaceTowerPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlaceTower; }
|
||||
virtual PacketType GetType() const { return PacketType::PlaceTower; }
|
||||
};
|
||||
|
||||
class WorldAddTowerPacket : public Packet {
|
||||
private:
|
||||
game::TowerID m_TowerID;
|
||||
std::int32_t m_TowerX, m_TowerY;
|
||||
game::TowerType m_TowerType;
|
||||
game::PlayerID m_Builder;
|
||||
game::TowerID m_TowerID;
|
||||
std::int32_t m_TowerX, m_TowerY;
|
||||
game::TowerType m_TowerType;
|
||||
game::PlayerID m_Builder;
|
||||
public:
|
||||
WorldAddTowerPacket() {}
|
||||
WorldAddTowerPacket(game::TowerID id, std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) :
|
||||
m_TowerID(id), m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {}
|
||||
virtual ~WorldAddTowerPacket() {}
|
||||
WorldAddTowerPacket() {}
|
||||
WorldAddTowerPacket(game::TowerID id, std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) :
|
||||
m_TowerID(id), m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {
|
||||
}
|
||||
virtual ~WorldAddTowerPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||
game::PlayerID GetBuilder() const { return m_Builder; }
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||
game::PlayerID GetBuilder() const { return m_Builder; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::WorldAddTower; }
|
||||
virtual PacketType GetType() const { return PacketType::WorldAddTower; }
|
||||
};
|
||||
|
||||
class RemoveTowerPacket : public Packet {
|
||||
private:
|
||||
game::TowerID m_TowerID;
|
||||
game::TowerID m_TowerID;
|
||||
public:
|
||||
RemoveTowerPacket() {}
|
||||
RemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
|
||||
virtual ~RemoveTowerPacket() {}
|
||||
RemoveTowerPacket() {}
|
||||
RemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
|
||||
virtual ~RemoveTowerPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::RemoveTower; }
|
||||
virtual PacketType GetType() const { return PacketType::RemoveTower; }
|
||||
};
|
||||
|
||||
class UpgradeTowerPacket : public Packet {
|
||||
private:
|
||||
game::TowerID m_TowerID;
|
||||
game::TowerLevel m_TowerLevel;
|
||||
game::TowerID m_TowerID;
|
||||
game::TowerLevel m_TowerLevel;
|
||||
public:
|
||||
UpgradeTowerPacket() {}
|
||||
UpgradeTowerPacket(game::TowerID tower, game::TowerLevel level) : m_TowerID(tower), m_TowerLevel(level) {}
|
||||
virtual ~UpgradeTowerPacket() {}
|
||||
UpgradeTowerPacket() {}
|
||||
UpgradeTowerPacket(game::TowerID tower, game::TowerLevel level) : m_TowerID(tower), m_TowerLevel(level) {}
|
||||
virtual ~UpgradeTowerPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
game::TowerLevel GetTowerLevel() const { return m_TowerLevel; }
|
||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||
game::TowerLevel GetTowerLevel() const { return m_TowerLevel; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpgradeTower; }
|
||||
virtual PacketType GetType() const { return PacketType::UpgradeTower; }
|
||||
};
|
||||
|
||||
class MobState {
|
||||
using Point = utils::shape::Point;
|
||||
using Point = utils::shape::Point;
|
||||
private:
|
||||
game::MobID m_MobID;
|
||||
Point m_MobPosition;
|
||||
float m_MobLife;
|
||||
game::Direction m_MobDirection;
|
||||
game::MobID m_MobID;
|
||||
Point m_MobPosition;
|
||||
float m_MobLife;
|
||||
game::Direction m_MobDirection;
|
||||
public:
|
||||
MobState() {}
|
||||
MobState(game::MobID id, const Point& position, float life, game::Direction direction) :
|
||||
m_MobID(id), m_MobPosition(position), m_MobLife(life), m_MobDirection(direction) {}
|
||||
MobState() {}
|
||||
MobState(game::MobID id, const 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; }
|
||||
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;
|
||||
std::vector<MobState> m_MobStates;
|
||||
public:
|
||||
UpdateMobStatesPacket() {}
|
||||
virtual ~UpdateMobStatesPacket() {}
|
||||
UpdateMobStatesPacket() {}
|
||||
virtual ~UpdateMobStatesPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
void addMobState(MobState mobState) { m_MobStates.push_back(mobState); }
|
||||
void addMobState(MobState mobState) { m_MobStates.push_back(mobState); }
|
||||
|
||||
const std::vector<MobState>& GetMobStates() const { return m_MobStates; }
|
||||
const std::vector<MobState>& GetMobStates() const { return m_MobStates; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateMobStates; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateMobStates; }
|
||||
};
|
||||
|
||||
class UpdateCastleLifePacket : public Packet {
|
||||
private:
|
||||
std::uint16_t m_CastleLife;
|
||||
game::TeamColor m_Team;
|
||||
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() {}
|
||||
UpdateCastleLifePacket() {}
|
||||
UpdateCastleLifePacket(std::uint16_t life, game::TeamColor team) : m_CastleLife(life), m_Team(team) {}
|
||||
virtual ~UpdateCastleLifePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) 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; }
|
||||
std::uint16_t GetCastleLife() const { return m_CastleLife; }
|
||||
game::TeamColor GetTeamColor() const { return m_Team; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::UpdateCastleLife; }
|
||||
virtual PacketType GetType() const { return PacketType::UpdateCastleLife; }
|
||||
};
|
||||
|
||||
enum class ItemType : std::uint8_t {
|
||||
// Upgrades
|
||||
ClickerUpgrade,
|
||||
GoldPerSecUpgrade,
|
||||
// Upgrades
|
||||
ClickerUpgrade,
|
||||
GoldPerSecUpgrade,
|
||||
|
||||
// Items
|
||||
// Items
|
||||
};
|
||||
|
||||
/** Packet used by the client to buy items or upgrades
|
||||
Packet used by the server to confirm transaction */
|
||||
Packet used by the server to confirm transaction */
|
||||
class PlayerBuyItemPacket : public Packet {
|
||||
private:
|
||||
ItemType m_ItemType;
|
||||
std::uint8_t m_Count;
|
||||
ItemType m_ItemType;
|
||||
std::uint8_t m_Count;
|
||||
public:
|
||||
PlayerBuyItemPacket() {}
|
||||
PlayerBuyItemPacket(ItemType itemType, std::uint8_t count) : m_ItemType(itemType), m_Count(count) {}
|
||||
virtual ~PlayerBuyItemPacket() {}
|
||||
PlayerBuyItemPacket() {}
|
||||
PlayerBuyItemPacket(ItemType itemType, std::uint8_t count) : m_ItemType(itemType), m_Count(count) {}
|
||||
virtual ~PlayerBuyItemPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
ItemType GetItemType() const { return m_ItemType; }
|
||||
std::uint8_t GetCount() const { return m_Count; }
|
||||
ItemType GetItemType() const { return m_ItemType; }
|
||||
std::uint8_t GetCount() const { return m_Count; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerBuyItem; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerBuyItem; }
|
||||
};
|
||||
|
||||
/** Packet used by the client to buy mob upgrades
|
||||
Packet used by the server to confirm transaction */
|
||||
Packet used by the server to confirm transaction */
|
||||
class PlayerBuyMobUpgradePacket : public Packet {
|
||||
private:
|
||||
game::MobType m_MobType;
|
||||
std::uint8_t m_MobLevel;
|
||||
game::MobType m_MobType;
|
||||
std::uint8_t m_MobLevel;
|
||||
public:
|
||||
PlayerBuyMobUpgradePacket() {}
|
||||
PlayerBuyMobUpgradePacket(game::MobType mobType, std::uint8_t level) : m_MobType(mobType), m_MobLevel(level) {}
|
||||
virtual ~PlayerBuyMobUpgradePacket() {}
|
||||
PlayerBuyMobUpgradePacket() {}
|
||||
PlayerBuyMobUpgradePacket(game::MobType mobType, std::uint8_t level) : m_MobType(mobType), m_MobLevel(level) {}
|
||||
virtual ~PlayerBuyMobUpgradePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::MobType GetMobType() const { return m_MobType; }
|
||||
std::uint8_t GetLevel() const { return m_MobLevel; }
|
||||
game::MobType GetMobType() const { return m_MobType; }
|
||||
std::uint8_t GetLevel() const { return m_MobLevel; }
|
||||
|
||||
virtual PacketType GetType() const { return PacketType::PlayerBuyMobUpgrade; }
|
||||
virtual PacketType GetType() const { return PacketType::PlayerBuyMobUpgrade; }
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
#if defined(__has_include)
|
||||
|
||||
#if __has_include(<GL/glew.h>)
|
||||
#define TD_IMPL_OPENGL_LOADER_GLEW
|
||||
#define TD_IMPL_OPENGL_LOADER_GLEW
|
||||
#elif __has_include(<glad/glad.h>)
|
||||
#define TD_IMPL_OPENGL_LOADER_GLAD
|
||||
#define TD_IMPL_OPENGL_LOADER_GLAD
|
||||
#elif __has_include(<GL/gl3w.h>)
|
||||
#define TD_IMPL_OPENGL_LOADER_GL3W
|
||||
#define TD_IMPL_OPENGL_LOADER_GL3W
|
||||
#elif __has_include(<glbinding/glbinding.h>)
|
||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING3
|
||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING3
|
||||
#elif __has_include(<glbinding/Binding.h>)
|
||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING2
|
||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING2
|
||||
#else
|
||||
#error "Cannot detect OpenGL loader!"
|
||||
#error "Cannot detect OpenGL loader!"
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@@ -11,45 +11,45 @@ namespace render {
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
static constexpr float m_AnimationSpeed = 2.0f;
|
||||
static constexpr float m_AnimationSpeed = 2.0f;
|
||||
|
||||
struct Model {
|
||||
GL::VertexArray* vao;
|
||||
Vec2f positon;
|
||||
};
|
||||
struct Model {
|
||||
GL::VertexArray* vao;
|
||||
Vec2f positon;
|
||||
};
|
||||
private:
|
||||
std::unique_ptr<shader::WorldShader> m_WorldShader;
|
||||
std::unique_ptr<shader::EntityShader> m_EntityShader;
|
||||
std::unique_ptr<shader::WorldShader> m_WorldShader;
|
||||
std::unique_ptr<shader::EntityShader> m_EntityShader;
|
||||
|
||||
Vec3f m_BackgroundColor;
|
||||
Vec3f m_BackgroundColor;
|
||||
|
||||
bool m_IsometricView = true;
|
||||
float m_IsometricShade = m_IsometricView;
|
||||
Vec2f m_CamPos{};
|
||||
bool m_IsometricView = true;
|
||||
float m_IsometricShade = m_IsometricView;
|
||||
Vec2f m_CamPos{};
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
bool Init();
|
||||
bool Init();
|
||||
|
||||
void Prepare();
|
||||
void Resize(const int width, const int height);
|
||||
void Prepare();
|
||||
void Resize(const int width, const int height);
|
||||
|
||||
void RenderVAO(const GL::VertexArray& vao);
|
||||
void RenderModel(const Model& model);
|
||||
void RenderVAO(const GL::VertexArray& vao);
|
||||
void RenderModel(const Model& model);
|
||||
|
||||
void SetZoom(float zoom);
|
||||
void SetCamMovement(const Vec2f& mov);
|
||||
void SetCamPos(const Vec2f& newPos);
|
||||
void SetIsometricView(bool isometric); // false = 2D true = Isometric
|
||||
void SetZoom(float zoom);
|
||||
void SetCamMovement(const Vec2f& mov);
|
||||
void SetCamPos(const Vec2f& newPos);
|
||||
void SetIsometricView(bool isometric); // false = 2D true = Isometric
|
||||
|
||||
void SetBackgroundColor(const Vec3f& color) { m_BackgroundColor = color; }
|
||||
void SetBackgroundColor(const Vec3f& color) { m_BackgroundColor = color; }
|
||||
|
||||
Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight);
|
||||
Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight);
|
||||
private:
|
||||
void UpdateIsometricView();
|
||||
void UpdateIsometricFade();
|
||||
void InitShaders();
|
||||
void UpdateIsometricView();
|
||||
void UpdateIsometricFade();
|
||||
void InitShaders();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -11,27 +11,27 @@ namespace render {
|
||||
|
||||
class VertexCache {
|
||||
|
||||
typedef std::vector<float> Vector;
|
||||
typedef std::vector<float> Vector;
|
||||
|
||||
struct DataIndex {
|
||||
Vector position;
|
||||
Vector color;
|
||||
};
|
||||
struct DataIndex {
|
||||
Vector position;
|
||||
Vector color;
|
||||
};
|
||||
|
||||
private:
|
||||
std::size_t m_VertexCount;
|
||||
std::unordered_map<std::uint64_t, DataIndex> m_Indexes;
|
||||
std::unique_ptr<GL::VertexArray> m_VertexArray;
|
||||
std::size_t m_VertexCount;
|
||||
std::unordered_map<std::uint64_t, DataIndex> m_Indexes;
|
||||
std::unique_ptr<GL::VertexArray> m_VertexArray;
|
||||
public:
|
||||
VertexCache() : m_VertexCount(0) {}
|
||||
VertexCache() : m_VertexCount(0) {}
|
||||
|
||||
void AddData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors);
|
||||
void RemoveData(std::uint64_t index);
|
||||
void Clear();
|
||||
void UpdateVertexArray();
|
||||
void AddData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors);
|
||||
void RemoveData(std::uint64_t index);
|
||||
void Clear();
|
||||
void UpdateVertexArray();
|
||||
|
||||
const GL::VertexArray& GetVertexArray() const { return *m_VertexArray; }
|
||||
bool IsEmpty() const { return m_VertexArray == nullptr; }
|
||||
const GL::VertexArray& GetVertexArray() const { return *m_VertexArray; }
|
||||
bool IsEmpty() const { return m_VertexArray == nullptr; }
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -24,61 +24,61 @@ namespace render {
|
||||
|
||||
class WorldRenderer : public game::WorldListener {
|
||||
private:
|
||||
client::ClientGame* m_Client;
|
||||
Renderer* m_Renderer;
|
||||
game::World* m_World;
|
||||
std::unique_ptr<GL::VertexArray> m_WorldVao, m_MobVao, m_SelectTileVao;
|
||||
Vec2f m_CamPos;
|
||||
Vec2f m_CursorPos;
|
||||
Vec2f m_HoldCursorPos;
|
||||
Vec2f m_LastClicked;
|
||||
float m_Zoom;
|
||||
float m_CamSensibility = 1;
|
||||
bool m_PopupOpened = false;
|
||||
VertexCache m_TowersCache;
|
||||
client::ClientGame* m_Client;
|
||||
Renderer* m_Renderer;
|
||||
game::World* m_World;
|
||||
std::unique_ptr<GL::VertexArray> m_WorldVao, m_MobVao, m_SelectTileVao;
|
||||
Vec2f m_CamPos;
|
||||
Vec2f m_CursorPos;
|
||||
Vec2f m_HoldCursorPos;
|
||||
Vec2f m_LastClicked;
|
||||
float m_Zoom;
|
||||
float m_CamSensibility = 1;
|
||||
bool m_PopupOpened = false;
|
||||
VertexCache m_TowersCache;
|
||||
|
||||
std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
|
||||
std::unique_ptr<gui::MobTooltip> m_MobTooltip;
|
||||
std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
|
||||
std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
|
||||
std::unique_ptr<gui::MobTooltip> m_MobTooltip;
|
||||
std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
|
||||
public:
|
||||
WorldRenderer(game::World* world, client::ClientGame* client);
|
||||
~WorldRenderer();
|
||||
WorldRenderer(game::World* world, client::ClientGame* client);
|
||||
~WorldRenderer();
|
||||
|
||||
void LoadModels();
|
||||
void LoadModels();
|
||||
|
||||
static ImVec4 GetImGuiTeamColor(game::TeamColor color);
|
||||
static ImVec4 GetImGuiTeamColor(game::TeamColor color);
|
||||
|
||||
void Update();
|
||||
void Render();
|
||||
void Update();
|
||||
void Render();
|
||||
|
||||
void SetCamPos(float camX, float camY);
|
||||
void SetCamPos(float camX, float camY);
|
||||
|
||||
void MoveCam(float relativeX, float relativeY, float aspectRatio);
|
||||
void ChangeZoom(float zoom);
|
||||
void MoveCam(float relativeX, float relativeY, float aspectRatio);
|
||||
void ChangeZoom(float zoom);
|
||||
|
||||
// WorldListener
|
||||
// WorldListener
|
||||
|
||||
virtual void OnTowerAdd(game::TowerPtr tower);
|
||||
virtual void OnTowerRemove(game::TowerPtr tower);
|
||||
virtual void OnTowerAdd(game::TowerPtr tower);
|
||||
virtual void OnTowerRemove(game::TowerPtr tower);
|
||||
private:
|
||||
void Click();
|
||||
void RenderWorld() const;
|
||||
void RenderTowers() const;
|
||||
void RenderMobs() const;
|
||||
void RenderTileSelect() const;
|
||||
void RenderPopups();
|
||||
void RenderTowerUpgradePopup();
|
||||
void RenderMobTooltip() const;
|
||||
void RenderCastleTooltip() const;
|
||||
void DetectClick();
|
||||
void DetectMobHovering() const;
|
||||
void DetectCastleHovering() const;
|
||||
void RenderTooltips() const;
|
||||
void RemoveTower();
|
||||
Vec2f GetCursorWorldPos() const;
|
||||
Vec2f GetClickWorldPos() const;
|
||||
void Click();
|
||||
void RenderWorld() const;
|
||||
void RenderTowers() const;
|
||||
void RenderMobs() const;
|
||||
void RenderTileSelect() const;
|
||||
void RenderPopups();
|
||||
void RenderTowerUpgradePopup();
|
||||
void RenderMobTooltip() const;
|
||||
void RenderCastleTooltip() const;
|
||||
void DetectClick();
|
||||
void DetectMobHovering() const;
|
||||
void DetectCastleHovering() const;
|
||||
void RenderTooltips() const;
|
||||
void RemoveTower();
|
||||
Vec2f GetCursorWorldPos() const;
|
||||
Vec2f GetClickWorldPos() const;
|
||||
|
||||
void UpdateCursorPos();
|
||||
void UpdateCursorPos();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -14,14 +14,14 @@ namespace gui {
|
||||
|
||||
class CastleTooltip : public GuiWidget {
|
||||
private:
|
||||
const game::TeamCastle* m_Castle;
|
||||
const game::TeamCastle* m_Castle;
|
||||
public:
|
||||
CastleTooltip(client::Client* client);
|
||||
CastleTooltip(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
|
||||
void SetCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
||||
bool IsShown() { return m_Castle != nullptr; }
|
||||
void SetCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
||||
bool IsShown() { return m_Castle != nullptr; }
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -7,13 +7,13 @@ namespace gui {
|
||||
|
||||
class FrameMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_VSync;
|
||||
bool m_IsometricView;
|
||||
bool m_ShowDemoWindow;
|
||||
bool m_VSync;
|
||||
bool m_IsometricView;
|
||||
bool m_ShowDemoWindow;
|
||||
public:
|
||||
FrameMenu(client::Client* client);
|
||||
FrameMenu(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -7,17 +7,17 @@ namespace gui {
|
||||
|
||||
class GameMenu : public GuiWidget {
|
||||
private:
|
||||
std::unique_ptr<SummonMenu> m_SummonMenu;
|
||||
std::unique_ptr<SummonMenu> m_SummonMenu;
|
||||
public:
|
||||
GameMenu(client::Client* client);
|
||||
GameMenu(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
private:
|
||||
void ShowTPS();
|
||||
void ShowStats();
|
||||
void ShowPlayers();
|
||||
void ShowLobbyProgress();
|
||||
void ShowTeamSelection();
|
||||
void ShowTPS();
|
||||
void ShowStats();
|
||||
void ShowPlayers();
|
||||
void ShowLobbyProgress();
|
||||
void ShowTeamSelection();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -10,19 +10,19 @@ namespace gui {
|
||||
|
||||
class GuiManager {
|
||||
private:
|
||||
std::vector<std::unique_ptr<GuiWidget>> m_Widgets;
|
||||
std::vector<std::unique_ptr<GuiWidget>> m_Widgets;
|
||||
public:
|
||||
GuiManager() {}
|
||||
GuiManager() {}
|
||||
|
||||
void RenderWidgets() {
|
||||
for (auto& widget : m_Widgets) {
|
||||
widget->Render();
|
||||
}
|
||||
}
|
||||
void RenderWidgets() {
|
||||
for (auto& widget : m_Widgets) {
|
||||
widget->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void AddWidget(std::unique_ptr<GuiWidget>&& widget) {
|
||||
m_Widgets.push_back(std::move(widget));
|
||||
}
|
||||
void AddWidget(std::unique_ptr<GuiWidget>&& widget) {
|
||||
m_Widgets.push_back(std::move(widget));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace gui {
|
||||
|
||||
class GuiWidget {
|
||||
protected:
|
||||
client::Client* m_Client;
|
||||
client::Client* m_Client;
|
||||
public:
|
||||
GuiWidget(client::Client* client) : m_Client(client) {}
|
||||
GuiWidget(client::Client* client) : m_Client(client) {}
|
||||
|
||||
client::Client* GetClient() { return m_Client; }
|
||||
client::Client* GetClient() { return m_Client; }
|
||||
|
||||
virtual void Render() = 0;
|
||||
virtual void Render() = 0;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -13,24 +13,24 @@ namespace gui {
|
||||
|
||||
class MainMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_TriedToConnect = false;
|
||||
bool m_TriedToCreate = false;
|
||||
std::string m_ConnectAddress;
|
||||
int m_ConnectPort;
|
||||
int m_ServerPort = 25565;
|
||||
std::string m_WorldFilePath;
|
||||
imgui_addons::ImGuiFileBrowser m_FileDialog;
|
||||
bool m_TriedToConnect = false;
|
||||
bool m_TriedToCreate = false;
|
||||
std::string m_ConnectAddress;
|
||||
int m_ConnectPort;
|
||||
int m_ServerPort = 25565;
|
||||
std::string m_WorldFilePath;
|
||||
imgui_addons::ImGuiFileBrowser m_FileDialog;
|
||||
|
||||
std::unique_ptr<server::Server> m_Server;
|
||||
std::unique_ptr<server::Server> m_Server;
|
||||
public:
|
||||
MainMenu(client::Client* client);
|
||||
~MainMenu();
|
||||
MainMenu(client::Client* client);
|
||||
~MainMenu();
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
|
||||
const server::Server* GetServer() const { return m_Server.get(); }
|
||||
const server::Server* GetServer() const { return m_Server.get(); }
|
||||
private:
|
||||
bool StartServer();
|
||||
bool StartServer();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -14,14 +14,14 @@ namespace gui {
|
||||
|
||||
class MobTooltip : public GuiWidget {
|
||||
private:
|
||||
const game::Mob* m_Mob;
|
||||
const game::Mob* m_Mob;
|
||||
public:
|
||||
MobTooltip(client::Client* client);
|
||||
MobTooltip(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
|
||||
void SetMob(const game::Mob* mob) { m_Mob = mob; }
|
||||
bool IsShown() { return m_Mob != nullptr; }
|
||||
void SetMob(const game::Mob* mob) { m_Mob = mob; }
|
||||
bool IsShown() { return m_Mob != nullptr; }
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -10,16 +10,16 @@ namespace gui {
|
||||
|
||||
class SummonMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_MenuOpened;
|
||||
int m_ImageWidth = 100;
|
||||
static constexpr int m_MobTypeCount = static_cast<std::size_t>(td::game::MobType::MOB_COUNT);
|
||||
std::array<int, static_cast<std::size_t>(m_MobTypeCount)> m_Values;
|
||||
bool m_MenuOpened;
|
||||
int m_ImageWidth = 100;
|
||||
static constexpr int m_MobTypeCount = static_cast<std::size_t>(td::game::MobType::MOB_COUNT);
|
||||
std::array<int, static_cast<std::size_t>(m_MobTypeCount)> m_Values;
|
||||
public:
|
||||
SummonMenu(client::Client* client);
|
||||
SummonMenu(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
private:
|
||||
void SetSummonMax(int valueIndex);
|
||||
void SetSummonMax(int valueIndex);
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -28,21 +28,21 @@ class Renderer;
|
||||
|
||||
class TowerGui {
|
||||
private:
|
||||
SDL_Window* m_Window;
|
||||
SDL_GLContext m_GlContext;
|
||||
td::render::Renderer* m_Renderer;
|
||||
td::gui::GuiManager m_GuiManager;
|
||||
std::unique_ptr<td::client::Client> m_Client;
|
||||
SDL_Window* m_Window;
|
||||
SDL_GLContext m_GlContext;
|
||||
td::render::Renderer* m_Renderer;
|
||||
td::gui::GuiManager m_GuiManager;
|
||||
std::unique_ptr<td::client::Client> m_Client;
|
||||
public:
|
||||
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
||||
~TowerGui();
|
||||
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
||||
~TowerGui();
|
||||
|
||||
void Render();
|
||||
void Render();
|
||||
private:
|
||||
void InitWidgets();
|
||||
void Tick();
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
void InitWidgets();
|
||||
void Tick();
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -9,19 +9,19 @@ namespace gui {
|
||||
|
||||
class TowerPlacePopup : public GuiWidget {
|
||||
private:
|
||||
Vec2f m_ClickWorldPos;
|
||||
Vec2f m_ClickWorldPos;
|
||||
public:
|
||||
TowerPlacePopup(client::Client* client);
|
||||
TowerPlacePopup(client::Client* client);
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
|
||||
void SetClickPos(const Vec2f& worldPos);
|
||||
void SetClickPos(const Vec2f& worldPos);
|
||||
private:
|
||||
static constexpr float m_TowerPopupTileWidth = 200.0f;
|
||||
static constexpr float m_TowerPopupTileHeight = 200.0f;
|
||||
static constexpr float m_TowerPopupTileWidth = 200.0f;
|
||||
static constexpr float m_TowerPopupTileHeight = 200.0f;
|
||||
|
||||
static constexpr float m_PlaceTowerButtonWidth = 150.0f;
|
||||
static constexpr float m_PlaceTowerButtonHeight = 35.0f;
|
||||
static constexpr float m_PlaceTowerButtonWidth = 150.0f;
|
||||
static constexpr float m_PlaceTowerButtonHeight = 35.0f;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -17,19 +17,19 @@ namespace gui {
|
||||
|
||||
class UpdateMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_Opened;
|
||||
std::string m_Error;
|
||||
std::unique_ptr<utils::Updater> m_Updater;
|
||||
std::shared_future<bool> m_UpdateAvailable;
|
||||
bool m_Opened;
|
||||
std::string m_Error;
|
||||
std::unique_ptr<utils::Updater> m_Updater;
|
||||
std::shared_future<bool> m_UpdateAvailable;
|
||||
public:
|
||||
UpdateMenu(client::Client* client);
|
||||
virtual ~UpdateMenu();
|
||||
UpdateMenu(client::Client* client);
|
||||
virtual ~UpdateMenu();
|
||||
|
||||
virtual void Render();
|
||||
virtual void Render();
|
||||
private:
|
||||
void CheckUpdates();
|
||||
bool IsUpdateChecked();
|
||||
void RenderErrorPopup();
|
||||
void CheckUpdates();
|
||||
bool IsUpdateChecked();
|
||||
void RenderErrorPopup();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace render {
|
||||
namespace WorldLoader {
|
||||
|
||||
struct RenderData {
|
||||
std::vector<float> positions;
|
||||
std::vector<float> colors;
|
||||
std::vector<float> positions;
|
||||
std::vector<float> colors;
|
||||
};
|
||||
|
||||
GL::VertexArray LoadMobModel();
|
||||
|
||||
@@ -9,35 +9,35 @@ namespace utils {
|
||||
|
||||
class Updater {
|
||||
private:
|
||||
float m_Progress;
|
||||
bool m_DownloadComplete;
|
||||
bool m_FileWrited;
|
||||
bool m_CancelDownload;
|
||||
DataBuffer m_FileBuffer;
|
||||
std::string m_LastVersion;
|
||||
float m_Progress;
|
||||
bool m_DownloadComplete;
|
||||
bool m_FileWrited;
|
||||
bool m_CancelDownload;
|
||||
DataBuffer m_FileBuffer;
|
||||
std::string m_LastVersion;
|
||||
public:
|
||||
Updater() : m_Progress(0), m_DownloadComplete(false), m_FileWrited(false), m_CancelDownload(false) {}
|
||||
Updater() : m_Progress(0), m_DownloadComplete(false), m_FileWrited(false), m_CancelDownload(false) {}
|
||||
|
||||
bool CheckUpdate();
|
||||
void DownloadUpdate();
|
||||
void CancelDownload() { m_CancelDownload = true; m_Progress = 0.0f; m_DownloadComplete = false; }
|
||||
bool WriteFile();
|
||||
bool CheckUpdate();
|
||||
void DownloadUpdate();
|
||||
void CancelDownload() { m_CancelDownload = true; m_Progress = 0.0f; m_DownloadComplete = false; }
|
||||
bool WriteFile();
|
||||
|
||||
void ClearCache() { m_FileBuffer.Clear(); }
|
||||
void ClearCache() { m_FileBuffer.Clear(); }
|
||||
|
||||
float GetDownloadProgress() { return m_Progress; }
|
||||
bool IsDownloadComplete() { return m_DownloadComplete; }
|
||||
bool IsFileWrited() { return m_FileWrited; }
|
||||
float GetDownloadProgress() { return m_Progress; }
|
||||
bool IsDownloadComplete() { return m_DownloadComplete; }
|
||||
bool IsFileWrited() { return m_FileWrited; }
|
||||
|
||||
static std::string GetLocalFilePath();
|
||||
static void RemoveOldFile();
|
||||
static std::string GetLocalFilePath();
|
||||
static void RemoveOldFile();
|
||||
|
||||
static std::string GetCurrentVersion() { return TD_VERSION; }
|
||||
std::string GetLastVersion() { return m_LastVersion; }
|
||||
static std::string GetCurrentVersion() { return TD_VERSION; }
|
||||
std::string GetLastVersion() { return m_LastVersion; }
|
||||
|
||||
bool CanUpdate();
|
||||
bool CanUpdate();
|
||||
private:
|
||||
std::string GetDownloadFileURL();
|
||||
std::string GetDownloadFileURL();
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -21,19 +21,19 @@ extern "C"
|
||||
|
||||
int main(int argc, const char* args[]) {
|
||||
#if !defined(NDEBUG)
|
||||
// setup signal handling
|
||||
backward::SignalHandling sh;
|
||||
// setup signal handling
|
||||
backward::SignalHandling sh;
|
||||
#endif
|
||||
|
||||
// remove the outdated binary
|
||||
td::utils::Updater::RemoveOldFile();
|
||||
// remove the outdated binary
|
||||
td::utils::Updater::RemoveOldFile();
|
||||
|
||||
Display::Create();
|
||||
while (!Display::IsCloseRequested()) {
|
||||
Display::PollEvents();
|
||||
Display::Render();
|
||||
Display::Update();
|
||||
}
|
||||
Display::Destroy();
|
||||
return 0;
|
||||
Display::Create();
|
||||
while (!Display::IsCloseRequested()) {
|
||||
Display::PollEvents();
|
||||
Display::Render();
|
||||
Display::Update();
|
||||
}
|
||||
Display::Destroy();
|
||||
return 0;
|
||||
}
|
||||
@@ -12,25 +12,25 @@ Game::~Game() {
|
||||
}
|
||||
|
||||
void Game::Tick(std::uint64_t delta) {
|
||||
if (m_GameState == GameState::Game) {
|
||||
m_World->Tick(delta);
|
||||
}
|
||||
if (m_GameState == GameState::Game) {
|
||||
m_World->Tick(delta);
|
||||
}
|
||||
}
|
||||
|
||||
Player* Game::GetPlayerById(PlayerID id) {
|
||||
auto it = m_Players.find(id);
|
||||
auto it = m_Players.find(id);
|
||||
|
||||
if (it == m_Players.end()) return nullptr;
|
||||
if (it == m_Players.end()) return nullptr;
|
||||
|
||||
return &it->second;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const Player* Game::GetPlayerById(PlayerID id) const {
|
||||
auto it = m_Players.find(id);
|
||||
auto it = m_Players.find(id);
|
||||
|
||||
if (it == m_Players.end()) return nullptr;
|
||||
if (it == m_Players.end()) return nullptr;
|
||||
|
||||
return &it->second;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -29,44 +29,44 @@ Connexion::Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket&
|
||||
}
|
||||
|
||||
bool Connexion::UpdateSocket() {
|
||||
if (m_Socket.GetStatus() != network::Socket::Connected)
|
||||
return false;
|
||||
if (m_Socket.GetStatus() != network::Socket::Connected)
|
||||
return false;
|
||||
|
||||
while (true) {
|
||||
DataBuffer buffer;
|
||||
m_Socket.Receive(buffer, sizeof(std::uint64_t));
|
||||
if (buffer.GetSize() == 0)
|
||||
break;
|
||||
std::uint64_t packetLenght;
|
||||
buffer >> packetLenght;
|
||||
while (true) {
|
||||
DataBuffer buffer;
|
||||
m_Socket.Receive(buffer, sizeof(std::uint64_t));
|
||||
if (buffer.GetSize() == 0)
|
||||
break;
|
||||
std::uint64_t packetLenght;
|
||||
buffer >> packetLenght;
|
||||
|
||||
m_Socket.Receive(buffer, packetLenght);
|
||||
m_Socket.Receive(buffer, packetLenght);
|
||||
|
||||
DataBuffer decompressed = utils::Decompress(buffer, packetLenght);
|
||||
DataBuffer decompressed = utils::Decompress(buffer, packetLenght);
|
||||
|
||||
protocol::PacketType packetType;
|
||||
decompressed >> packetType;
|
||||
protocol::PacketType packetType;
|
||||
decompressed >> packetType;
|
||||
|
||||
PacketPtr packet = protocol::PacketFactory::CreatePacket(packetType, decompressed);
|
||||
GetDispatcher()->Dispatch(packet);
|
||||
}
|
||||
return true;
|
||||
PacketPtr packet = protocol::PacketFactory::CreatePacket(packetType, decompressed);
|
||||
GetDispatcher()->Dispatch(packet);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Connexion::Connect(const std::string& address, std::uint16_t port) {
|
||||
if (!m_Socket.Connect(address, port)) {
|
||||
return false;
|
||||
}
|
||||
m_Socket.SetBlocking(false);
|
||||
return true;
|
||||
if (!m_Socket.Connect(address, port)) {
|
||||
return false;
|
||||
}
|
||||
m_Socket.SetBlocking(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Connexion::SendPacket(const protocol::Packet* packet) {
|
||||
network::SendPacket(packet->Serialize(), m_Socket);
|
||||
network::SendPacket(packet->Serialize(), m_Socket);
|
||||
}
|
||||
|
||||
void Connexion::CloseConnection() {
|
||||
m_Socket.Disconnect();
|
||||
m_Socket.Disconnect();
|
||||
}
|
||||
|
||||
Connexion::~Connexion() {
|
||||
|
||||
@@ -9,251 +9,251 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
bool Mob::IsImmuneTo(TowerType type) {
|
||||
return std::find(GetTowerImmunities().begin(), GetTowerImmunities().end(), type) != GetTowerImmunities().end();
|
||||
return std::find(GetTowerImmunities().begin(), GetTowerImmunities().end(), type) != GetTowerImmunities().end();
|
||||
}
|
||||
|
||||
bool Mob::IsImmuneTo(EffectType type) {
|
||||
return std::find(GetEffectImmunities().begin(), GetEffectImmunities().end(), type) != GetEffectImmunities().end();
|
||||
return std::find(GetEffectImmunities().begin(), GetEffectImmunities().end(), type) != GetEffectImmunities().end();
|
||||
}
|
||||
|
||||
EffectDuration& Mob::GetEffect(EffectType effectType) {
|
||||
return *std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect) { return effect.type == effectType;});
|
||||
return *std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect) { return effect.type == effectType;});
|
||||
}
|
||||
|
||||
void Mob::AddEffect(EffectType effectType, float durationSec, Tower* tower) {
|
||||
if (IsImmuneTo(effectType))
|
||||
return;
|
||||
if (HasEffect(effectType)) {
|
||||
EffectDuration& effect = GetEffect(effectType);
|
||||
if (effect.duration < durationSec)
|
||||
effect.duration = durationSec; // Setting new duration if it's greater then the actual
|
||||
} else {
|
||||
m_Effects.push_back({ effectType, durationSec, tower });
|
||||
}
|
||||
if (IsImmuneTo(effectType))
|
||||
return;
|
||||
if (HasEffect(effectType)) {
|
||||
EffectDuration& effect = GetEffect(effectType);
|
||||
if (effect.duration < durationSec)
|
||||
effect.duration = durationSec; // Setting new duration if it's greater then the actual
|
||||
} else {
|
||||
m_Effects.push_back({ effectType, durationSec, tower });
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::AttackCastle(std::uint64_t delta, World* world) {
|
||||
if (!HasReachedEnemyCastle()) return;
|
||||
if (!HasReachedEnemyCastle()) return;
|
||||
|
||||
if (m_AttackTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobCastleDamage, this, m_CastleTarget, GetStats()->GetDamage());
|
||||
m_AttackTimer.ApplyCooldown();
|
||||
}
|
||||
if (m_AttackTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobCastleDamage, this, m_CastleTarget, GetStats()->GetDamage());
|
||||
m_AttackTimer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::Walk(std::uint64_t delta, World* world) {
|
||||
float mobWalkSpeed = GetStats()->GetMovementSpeed();
|
||||
float mobWalkSpeed = GetStats()->GetMovementSpeed();
|
||||
|
||||
float walkAmount = mobWalkSpeed * (static_cast<float>(delta) / 1000.0f);
|
||||
float walkAmount = mobWalkSpeed * (static_cast<float>(delta) / 1000.0f);
|
||||
|
||||
if (HasEffect(EffectType::Slowness))
|
||||
walkAmount *= 0.70; // walk 30% slower
|
||||
if (HasEffect(EffectType::Slowness))
|
||||
walkAmount *= 0.70; // walk 30% slower
|
||||
|
||||
switch (GetDirection()) {
|
||||
case Direction::NegativeX: {
|
||||
SetCenterX(GetCenterX() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveX: {
|
||||
SetCenterX(GetCenterX() + walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::NegativeY: {
|
||||
SetCenterY(GetCenterY() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveY: {
|
||||
SetCenterY(GetCenterY() + walkAmount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (GetDirection()) {
|
||||
case Direction::NegativeX: {
|
||||
SetCenterX(GetCenterX() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveX: {
|
||||
SetCenterX(GetCenterX() + walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::NegativeY: {
|
||||
SetCenterY(GetCenterY() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveY: {
|
||||
SetCenterY(GetCenterY() + walkAmount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::Move(std::uint64_t delta, World* world) {
|
||||
TilePtr tile = world->GetTile(GetCenter().GetX(), GetCenter().GetY());
|
||||
TilePtr tile = world->GetTile(GetCenter().GetX(), GetCenter().GetY());
|
||||
|
||||
if (tile != nullptr && tile->GetType() == TileType::Walk) {
|
||||
WalkableTilePtr walkTile = std::static_pointer_cast<WalkableTile>(tile);
|
||||
ChangeDirection(*walkTile, world);
|
||||
}
|
||||
if (tile != nullptr && tile->GetType() == TileType::Walk) {
|
||||
WalkableTilePtr walkTile = std::static_pointer_cast<WalkableTile>(tile);
|
||||
ChangeDirection(*walkTile, world);
|
||||
}
|
||||
|
||||
if (HasReachedEnemyCastle()) return;
|
||||
if (HasReachedEnemyCastle()) return;
|
||||
|
||||
Walk(delta, world);
|
||||
Walk(delta, world);
|
||||
|
||||
TeamColor mobTeam = world->GetPlayerById(GetSender())->GetTeamColor();
|
||||
TeamColor mobTeam = world->GetPlayerById(GetSender())->GetTeamColor();
|
||||
|
||||
TeamCastle* enemyCastle = nullptr;
|
||||
TeamCastle* enemyCastle = nullptr;
|
||||
|
||||
if (mobTeam == TeamColor::Red) {
|
||||
enemyCastle = &world->GetBlueTeam().GetCastle();
|
||||
} else if (mobTeam == TeamColor::Blue) {
|
||||
enemyCastle = &world->GetRedTeam().GetCastle();
|
||||
}
|
||||
if (mobTeam == TeamColor::Red) {
|
||||
enemyCastle = &world->GetBlueTeam().GetCastle();
|
||||
} else if (mobTeam == TeamColor::Blue) {
|
||||
enemyCastle = &world->GetRedTeam().GetCastle();
|
||||
}
|
||||
|
||||
if (IsTouchingCastle(*enemyCastle)) {
|
||||
MoveBack(*enemyCastle, world);
|
||||
SetMobReachedCastle(enemyCastle);
|
||||
if (IsTouchingCastle(*enemyCastle)) {
|
||||
MoveBack(*enemyCastle, world);
|
||||
SetMobReachedCastle(enemyCastle);
|
||||
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobTouchCastle, this, enemyCastle);
|
||||
}
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobTouchCastle, this, enemyCastle);
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::MoveBack(const TeamCastle& enemyCastle, World* world) {
|
||||
switch (GetDirection()) {
|
||||
case Direction::NegativeX: {
|
||||
SetCenterX(enemyCastle.GetBottomRight().GetX() + GetWidth() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveX: {
|
||||
SetCenterX(enemyCastle.GetTopLeft().GetX() - GetWidth() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::NegativeY: {
|
||||
SetCenterY(enemyCastle.GetBottomRight().GetY() + GetHeight() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveY: {
|
||||
SetCenterY(enemyCastle.GetTopLeft().GetY() - GetHeight() / 2.0f);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (GetDirection()) {
|
||||
case Direction::NegativeX: {
|
||||
SetCenterX(enemyCastle.GetBottomRight().GetX() + GetWidth() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveX: {
|
||||
SetCenterX(enemyCastle.GetTopLeft().GetX() - GetWidth() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::NegativeY: {
|
||||
SetCenterY(enemyCastle.GetBottomRight().GetY() + GetHeight() / 2.0f);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveY: {
|
||||
SetCenterY(enemyCastle.GetTopLeft().GetY() - GetHeight() / 2.0f);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::ChangeDirection(const WalkableTile& tile, World* world) {
|
||||
if (GetDirection() == tile.direction) return;
|
||||
if (GetDirection() == tile.direction) return;
|
||||
|
||||
float tileX = static_cast<float>(static_cast<std::int32_t>(GetCenterX()));
|
||||
float tileY = static_cast<float>(static_cast<std::int32_t>(GetCenterY()));
|
||||
float tileX = static_cast<float>(static_cast<std::int32_t>(GetCenterX()));
|
||||
float tileY = static_cast<float>(static_cast<std::int32_t>(GetCenterY()));
|
||||
|
||||
switch (GetDirection()) {
|
||||
switch (GetDirection()) {
|
||||
|
||||
case Direction::PositiveY: {
|
||||
if (tile.direction == Direction::NegativeX) {
|
||||
if (GetTileY() > GetTileX()) {
|
||||
SetCenterY(tileY + GetTileX());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile->direction = Direction::PositiveX
|
||||
if (GetTileY() > 1 - GetTileX()) {
|
||||
SetCenterY(tileY + (1 - GetTileX()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case Direction::PositiveY: {
|
||||
if (tile.direction == Direction::NegativeX) {
|
||||
if (GetTileY() > GetTileX()) {
|
||||
SetCenterY(tileY + GetTileX());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile->direction = Direction::PositiveX
|
||||
if (GetTileY() > 1 - GetTileX()) {
|
||||
SetCenterY(tileY + (1 - GetTileX()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case Direction::NegativeY: {
|
||||
if (tile.direction == Direction::PositiveX) {
|
||||
if (GetTileY() < GetTileX()) {
|
||||
SetCenterY(tileY + GetTileX());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::NegativeX
|
||||
if (GetTileY() < 1 - GetTileX()) {
|
||||
SetCenterY(tileY + (1 - GetTileX()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case Direction::NegativeY: {
|
||||
if (tile.direction == Direction::PositiveX) {
|
||||
if (GetTileY() < GetTileX()) {
|
||||
SetCenterY(tileY + GetTileX());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::NegativeX
|
||||
if (GetTileY() < 1 - GetTileX()) {
|
||||
SetCenterY(tileY + (1 - GetTileX()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case Direction::PositiveX: {
|
||||
if (tile.direction == Direction::NegativeY) {
|
||||
if (GetTileX() > GetTileY()) {
|
||||
SetCenterX(tileX + GetTileY());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::PositiveY
|
||||
if (GetTileX() > 1 - GetTileY()) {
|
||||
SetCenterX(tileX + (1 - GetTileY()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case Direction::PositiveX: {
|
||||
if (tile.direction == Direction::NegativeY) {
|
||||
if (GetTileX() > GetTileY()) {
|
||||
SetCenterX(tileX + GetTileY());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::PositiveY
|
||||
if (GetTileX() > 1 - GetTileY()) {
|
||||
SetCenterX(tileX + (1 - GetTileY()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case Direction::NegativeX: {
|
||||
if (tile.direction == Direction::PositiveY) {
|
||||
if (GetTileX() < GetTileY()) {
|
||||
SetCenterX(tileX + GetTileY());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::NegativeY
|
||||
if (GetTileX() < 1 - GetTileY()) {
|
||||
SetCenterX(tileX + (1 - GetTileY()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case Direction::NegativeX: {
|
||||
if (tile.direction == Direction::PositiveY) {
|
||||
if (GetTileX() < GetTileY()) {
|
||||
SetCenterX(tileX + GetTileY());
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
} else { // tile.direction = Direction::NegativeY
|
||||
if (GetTileX() < 1 - GetTileY()) {
|
||||
SetCenterX(tileX + (1 - GetTileY()));
|
||||
SetDirection(tile.direction);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::IsTouchingCastle(const TeamCastle& enemyCastle) const {
|
||||
return enemyCastle.CollidesWith(*this);
|
||||
return enemyCastle.CollidesWith(*this);
|
||||
}
|
||||
|
||||
void Mob::Tick(std::uint64_t delta, World* world) {
|
||||
UpdateEffects(delta, world);
|
||||
Move(delta, world);
|
||||
AttackCastle(delta, world);
|
||||
UpdateEffects(delta, world);
|
||||
Move(delta, world);
|
||||
AttackCastle(delta, world);
|
||||
}
|
||||
|
||||
void Mob::UpdateEffects(std::uint64_t delta, World* world) {
|
||||
float deltaSec = static_cast<float>(delta / 1000.0f);
|
||||
for (std::size_t i = 0; i < m_Effects.size(); i++) {
|
||||
EffectDuration& effect = m_Effects[i];
|
||||
effect.duration -= deltaSec;
|
||||
if (effect.duration < 0) { // effect has gone
|
||||
m_Effects.erase(m_Effects.begin() + static_cast<int>(i));
|
||||
switch (effect.type) {
|
||||
case EffectType::Fire: {
|
||||
m_EffectFireTimer.Reset();
|
||||
break;
|
||||
}
|
||||
float deltaSec = static_cast<float>(delta / 1000.0f);
|
||||
for (std::size_t i = 0; i < m_Effects.size(); i++) {
|
||||
EffectDuration& effect = m_Effects[i];
|
||||
effect.duration -= deltaSec;
|
||||
if (effect.duration < 0) { // effect has gone
|
||||
m_Effects.erase(m_Effects.begin() + static_cast<int>(i));
|
||||
switch (effect.type) {
|
||||
case EffectType::Fire: {
|
||||
m_EffectFireTimer.Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
case EffectType::Poison: {
|
||||
m_EffectPoisonTimer.Reset();
|
||||
break;
|
||||
}
|
||||
case EffectType::Poison: {
|
||||
m_EffectPoisonTimer.Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
case EffectType::Heal: {
|
||||
m_EffectHealTimer.Reset();
|
||||
}
|
||||
case EffectType::Heal: {
|
||||
m_EffectHealTimer.Reset();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Fire)) {
|
||||
if (m_EffectFireTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, this, 3.0f, GetEffect(EffectType::Fire).tower);
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Poison)) {
|
||||
if (m_EffectPoisonTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, this, 1.0f, GetEffect(EffectType::Poison).tower);
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Heal)) {
|
||||
if (m_EffectFireTimer.Update(delta)) {
|
||||
Heal(10);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Fire)) {
|
||||
if (m_EffectFireTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, this, 3.0f, GetEffect(EffectType::Fire).tower);
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Poison)) {
|
||||
if (m_EffectPoisonTimer.Update(delta)) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, this, 1.0f, GetEffect(EffectType::Poison).tower);
|
||||
}
|
||||
}
|
||||
if (HasEffect(EffectType::Heal)) {
|
||||
if (m_EffectFireTimer.Update(delta)) {
|
||||
Heal(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::HasEffect(EffectType type) {
|
||||
return std::find_if(m_Effects.begin(), m_Effects.end(), [&type](EffectDuration effect) { return effect.type == type;}) != m_Effects.end();
|
||||
return std::find_if(m_Effects.begin(), m_Effects.end(), [&type](EffectDuration effect) { return effect.type == type;}) != m_Effects.end();
|
||||
}
|
||||
|
||||
|
||||
@@ -262,248 +262,248 @@ bool Mob::HasEffect(EffectType type) {
|
||||
typedef std::pair<MobType, std::uint8_t> MobKey;
|
||||
|
||||
static const std::map<MobKey, MobStats> MobConstants = {
|
||||
// damage speed size money_cost exp_cost exp_reward max_health
|
||||
{{MobType::Zombie, 1},{MobStats{1, 1.6, {1, 1}, 15, 0, 7, 40}}},
|
||||
{{MobType::Zombie, 2},{MobStats{1, 1.6, {1, 1}, 18, 88, 9, 56}}},
|
||||
{{MobType::Zombie, 3},{MobStats{1, 1.6, {1, 1}, 22, 153, 10, 78}}},
|
||||
{{MobType::Zombie, 4},{MobStats{1.5, 1.6, {1, 1}, 26, 268, 13, 110}}},
|
||||
{{MobType::Zombie, 5},{MobStats{2, 1.6, {1, 1}, 31, 469, 15, 154}}},
|
||||
// damage speed size money_cost exp_cost exp_reward max_health
|
||||
{{MobType::Zombie, 1},{MobStats{1, 1.6, {1, 1}, 15, 0, 7, 40}}},
|
||||
{{MobType::Zombie, 2},{MobStats{1, 1.6, {1, 1}, 18, 88, 9, 56}}},
|
||||
{{MobType::Zombie, 3},{MobStats{1, 1.6, {1, 1}, 22, 153, 10, 78}}},
|
||||
{{MobType::Zombie, 4},{MobStats{1.5, 1.6, {1, 1}, 26, 268, 13, 110}}},
|
||||
{{MobType::Zombie, 5},{MobStats{2, 1.6, {1, 1}, 31, 469, 15, 154}}},
|
||||
|
||||
{{MobType::Spider, 1},{MobStats{1, 1.6, {1, 1}, 25, 100, 15, 80}}},
|
||||
{{MobType::Spider, 2},{MobStats{1, 2, {1, 1}, 30, 175, 16, 112}}},
|
||||
{{MobType::Spider, 3},{MobStats{1.5, 2, {1, 1}, 36, 306, 18, 157}}},
|
||||
{{MobType::Spider, 4},{MobStats{2.5, 2, {1, 1}, 43, 536, 19, 222}}},
|
||||
{{MobType::Spider, 5},{MobStats{1.5, 2.5, {1, 1}, 52, 938, 22, 307}}},
|
||||
{{MobType::Spider, 1},{MobStats{1, 1.6, {1, 1}, 25, 100, 15, 80}}},
|
||||
{{MobType::Spider, 2},{MobStats{1, 2, {1, 1}, 30, 175, 16, 112}}},
|
||||
{{MobType::Spider, 3},{MobStats{1.5, 2, {1, 1}, 36, 306, 18, 157}}},
|
||||
{{MobType::Spider, 4},{MobStats{2.5, 2, {1, 1}, 43, 536, 19, 222}}},
|
||||
{{MobType::Spider, 5},{MobStats{1.5, 2.5, {1, 1}, 52, 938, 22, 307}}},
|
||||
|
||||
{{MobType::Skeleton, 1},{MobStats{1, 1.6, {1, 1}, 120, 200, 30, 350}}},
|
||||
{{MobType::Skeleton, 2},{MobStats{1, 1.6, {1, 1}, 144, 350, 33, 490}}},
|
||||
{{MobType::Skeleton, 3},{MobStats{1, 1.6, {1, 1}, 173, 613, 36, 686}}},
|
||||
{{MobType::Skeleton, 4},{MobStats{1.5, 1.6, {1, 1}, 225, 1072, 40, 960}}},
|
||||
{{MobType::Skeleton, 5},{MobStats{2, 1.6, {1, 1}, 255, 1876, 43, 1345}}},
|
||||
{{MobType::Skeleton, 1},{MobStats{1, 1.6, {1, 1}, 120, 200, 30, 350}}},
|
||||
{{MobType::Skeleton, 2},{MobStats{1, 1.6, {1, 1}, 144, 350, 33, 490}}},
|
||||
{{MobType::Skeleton, 3},{MobStats{1, 1.6, {1, 1}, 173, 613, 36, 686}}},
|
||||
{{MobType::Skeleton, 4},{MobStats{1.5, 1.6, {1, 1}, 225, 1072, 40, 960}}},
|
||||
{{MobType::Skeleton, 5},{MobStats{2, 1.6, {1, 1}, 255, 1876, 43, 1345}}},
|
||||
|
||||
{{MobType::Pigman, 1},{MobStats{1, 2, {1, 1}, 100, 150, 22, 150}}},
|
||||
{{MobType::Pigman, 2},{MobStats{1, 2, {1, 1}, 120, 263, 24, 210}}},
|
||||
{{MobType::Pigman, 3},{MobStats{1, 2, {1, 1}, 144, 459, 25, 297}}},
|
||||
{{MobType::Pigman, 4},{MobStats{1, 2, {1, 1}, 173, 804, 25, 412}}},
|
||||
{{MobType::Pigman, 5},{MobStats{1.5, 2, {1, 1}, 207, 1407, 27, 576}}},
|
||||
{{MobType::Pigman, 1},{MobStats{1, 2, {1, 1}, 100, 150, 22, 150}}},
|
||||
{{MobType::Pigman, 2},{MobStats{1, 2, {1, 1}, 120, 263, 24, 210}}},
|
||||
{{MobType::Pigman, 3},{MobStats{1, 2, {1, 1}, 144, 459, 25, 297}}},
|
||||
{{MobType::Pigman, 4},{MobStats{1, 2, {1, 1}, 173, 804, 25, 412}}},
|
||||
{{MobType::Pigman, 5},{MobStats{1.5, 2, {1, 1}, 207, 1407, 27, 576}}},
|
||||
|
||||
{{MobType::Creeper, 1},{MobStats{1, 2, {1, 1}, 250, 325, 46, 350}}},
|
||||
{{MobType::Creeper, 2},{MobStats{1, 2, {1, 1}, 290, 550, 49, 460}}},
|
||||
{{MobType::Creeper, 3},{MobStats{2, 2, {1, 1}, 350, 800, 55, 630}}},
|
||||
{{MobType::Creeper, 4},{MobStats{3, 2, {1, 1}, 420, 1300, 61, 900}}},
|
||||
{{MobType::Creeper, 5},{MobStats{4, 2, {1, 1}, 510, 1850, 67, 1250}}},
|
||||
{{MobType::Creeper, 1},{MobStats{1, 2, {1, 1}, 250, 325, 46, 350}}},
|
||||
{{MobType::Creeper, 2},{MobStats{1, 2, {1, 1}, 290, 550, 49, 460}}},
|
||||
{{MobType::Creeper, 3},{MobStats{2, 2, {1, 1}, 350, 800, 55, 630}}},
|
||||
{{MobType::Creeper, 4},{MobStats{3, 2, {1, 1}, 420, 1300, 61, 900}}},
|
||||
{{MobType::Creeper, 5},{MobStats{4, 2, {1, 1}, 510, 1850, 67, 1250}}},
|
||||
|
||||
{{MobType::Silverfish, 1},{MobStats{1, 1.6, {1, 1}, 38, 125, 18, 120}}},
|
||||
{{MobType::Silverfish, 2},{MobStats{1, 1.6, {1, 1}, 50, 230, 19, 170}}},
|
||||
{{MobType::Silverfish, 3},{MobStats{1, 1.6, {1, 1}, 75, 340, 25, 225}}},
|
||||
{{MobType::Silverfish, 4},{MobStats{1.5, 1.6, {1, 1}, 170, 700, 33, 310}}},
|
||||
{{MobType::Silverfish, 5},{MobStats{1.5, 1.6, {1, 1}, 200, 1800, 36, 390}}},
|
||||
{{MobType::Silverfish, 1},{MobStats{1, 1.6, {1, 1}, 38, 125, 18, 120}}},
|
||||
{{MobType::Silverfish, 2},{MobStats{1, 1.6, {1, 1}, 50, 230, 19, 170}}},
|
||||
{{MobType::Silverfish, 3},{MobStats{1, 1.6, {1, 1}, 75, 340, 25, 225}}},
|
||||
{{MobType::Silverfish, 4},{MobStats{1.5, 1.6, {1, 1}, 170, 700, 33, 310}}},
|
||||
{{MobType::Silverfish, 5},{MobStats{1.5, 1.6, {1, 1}, 200, 1800, 36, 390}}},
|
||||
|
||||
{{MobType::Blaze, 1},{MobStats{1, 1.6, {1, 1}, 500, 500, 105, 410}}},
|
||||
{{MobType::Blaze, 2},{MobStats{1, 1.6, {1, 1}, 600, 875, 111, 574}}},
|
||||
{{MobType::Blaze, 3},{MobStats{1, 1.6, {1, 1}, 720, 1531, 115, 804}}},
|
||||
{{MobType::Blaze, 4},{MobStats{1.5, 1.6, {1, 1}, 864, 2680, 121, 1125}}},
|
||||
{{MobType::Blaze, 5},{MobStats{2, 1.6, {1, 1}, 1037, 4689, 127, 1575}}},
|
||||
{{MobType::Blaze, 1},{MobStats{1, 1.6, {1, 1}, 500, 500, 105, 410}}},
|
||||
{{MobType::Blaze, 2},{MobStats{1, 1.6, {1, 1}, 600, 875, 111, 574}}},
|
||||
{{MobType::Blaze, 3},{MobStats{1, 1.6, {1, 1}, 720, 1531, 115, 804}}},
|
||||
{{MobType::Blaze, 4},{MobStats{1.5, 1.6, {1, 1}, 864, 2680, 121, 1125}}},
|
||||
{{MobType::Blaze, 5},{MobStats{2, 1.6, {1, 1}, 1037, 4689, 127, 1575}}},
|
||||
|
||||
{{MobType::Witch, 1},{MobStats{1, 1.6, {1, 1}, 150, 300, 37, 300}}},
|
||||
{{MobType::Witch, 2},{MobStats{1, 1.6, {1, 1}, 165, 525, 39, 405}}},
|
||||
{{MobType::Witch, 3},{MobStats{1, 1.6, {1, 1}, 182, 918, 42, 547}}},
|
||||
{{MobType::Witch, 4},{MobStats{1.5, 1.6, {1, 1}, 200, 1606, 43, 738}}},
|
||||
{{MobType::Witch, 5},{MobStats{2, 1.6, {1, 1}, 220, 2810, 45, 996}}},
|
||||
{{MobType::Witch, 1},{MobStats{1, 1.6, {1, 1}, 150, 300, 37, 300}}},
|
||||
{{MobType::Witch, 2},{MobStats{1, 1.6, {1, 1}, 165, 525, 39, 405}}},
|
||||
{{MobType::Witch, 3},{MobStats{1, 1.6, {1, 1}, 182, 918, 42, 547}}},
|
||||
{{MobType::Witch, 4},{MobStats{1.5, 1.6, {1, 1}, 200, 1606, 43, 738}}},
|
||||
{{MobType::Witch, 5},{MobStats{2, 1.6, {1, 1}, 220, 2810, 45, 996}}},
|
||||
|
||||
{{MobType::Slime, 1},{MobStats{1, 0.8, {1, 1}, 1500, 1000, 300, 800}}},
|
||||
{{MobType::Slime, 2},{MobStats{1.5, 0.8, {1, 1}, 1800, 1750, 314, 880}}},
|
||||
{{MobType::Slime, 3},{MobStats{2, 0.8, {1, 1}, 2160, 3063, 330, 968}}},
|
||||
{{MobType::Slime, 4},{MobStats{2.5, 0.8, {1, 1}, 2592, 5359, 348, 1065}}},
|
||||
{{MobType::Slime, 5},{MobStats{3, 0.8, {1, 1}, 3110, 9379, 366, 1171}}},
|
||||
{{MobType::Slime, 1},{MobStats{1, 0.8, {1, 1}, 1500, 1000, 300, 800}}},
|
||||
{{MobType::Slime, 2},{MobStats{1.5, 0.8, {1, 1}, 1800, 1750, 314, 880}}},
|
||||
{{MobType::Slime, 3},{MobStats{2, 0.8, {1, 1}, 2160, 3063, 330, 968}}},
|
||||
{{MobType::Slime, 4},{MobStats{2.5, 0.8, {1, 1}, 2592, 5359, 348, 1065}}},
|
||||
{{MobType::Slime, 5},{MobStats{3, 0.8, {1, 1}, 3110, 9379, 366, 1171}}},
|
||||
|
||||
{{MobType::Giant, 1},{MobStats{10, 0.8, {1, 1}, 4000, 2250, 600, 6250}}},
|
||||
{{MobType::Giant, 2},{MobStats{20, 0.8, {1, 1}, 4500, 4000, 612, 9375}}},
|
||||
{{MobType::Giant, 3},{MobStats{30, 0.8, {1, 1}, 5062, 7250, 624, 14062}}},
|
||||
{{MobType::Giant, 4},{MobStats{40, 0.8, {1, 1}, 5695, 12500, 636, 21093}}},
|
||||
{{MobType::Giant, 5},{MobStats{50, 0.8, {1, 1}, 6407, 22000, 648, 31640}}},
|
||||
{{MobType::Giant, 1},{MobStats{10, 0.8, {1, 1}, 4000, 2250, 600, 6250}}},
|
||||
{{MobType::Giant, 2},{MobStats{20, 0.8, {1, 1}, 4500, 4000, 612, 9375}}},
|
||||
{{MobType::Giant, 3},{MobStats{30, 0.8, {1, 1}, 5062, 7250, 624, 14062}}},
|
||||
{{MobType::Giant, 4},{MobStats{40, 0.8, {1, 1}, 5695, 12500, 636, 21093}}},
|
||||
{{MobType::Giant, 5},{MobStats{50, 0.8, {1, 1}, 6407, 22000, 648, 31640}}},
|
||||
};
|
||||
|
||||
const MobStats* GetMobStats(MobType type, std::uint8_t level) {
|
||||
return &MobConstants.at(MobKey{ type, level });
|
||||
return &MobConstants.at(MobKey{ type, level });
|
||||
}
|
||||
|
||||
static const std::map<MobKey, TowerImmunities> MobsTowerImmunities = {
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
{{MobType::Spider, 5},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
{{MobType::Spider, 5},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{}},
|
||||
{{MobType::Skeleton, 4},{}},
|
||||
{{MobType::Skeleton, 5},{}},
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{}},
|
||||
{{MobType::Skeleton, 4},{}},
|
||||
{{MobType::Skeleton, 5},{}},
|
||||
|
||||
{{MobType::Pigman, 1},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 2},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 3},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 4},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 5},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 1},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 2},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 3},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 4},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 5},{TowerType::Zeus}},
|
||||
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{}},
|
||||
{{MobType::Silverfish, 5},{}},
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{}},
|
||||
{{MobType::Silverfish, 5},{}},
|
||||
|
||||
{{MobType::Blaze, 1},{}},
|
||||
{{MobType::Blaze, 2},{}},
|
||||
{{MobType::Blaze, 3},{}},
|
||||
{{MobType::Blaze, 4},{}},
|
||||
{{MobType::Blaze, 5},{}},
|
||||
{{MobType::Blaze, 1},{}},
|
||||
{{MobType::Blaze, 2},{}},
|
||||
{{MobType::Blaze, 3},{}},
|
||||
{{MobType::Blaze, 4},{}},
|
||||
{{MobType::Blaze, 5},{}},
|
||||
|
||||
{{MobType::Witch, 1},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 2},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 3},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 4},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 5},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 1},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 2},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 3},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 4},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 5},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{}},
|
||||
{{MobType::Slime, 5},{}},
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{}},
|
||||
{{MobType::Slime, 5},{}},
|
||||
|
||||
{{MobType::Giant, 1},{}},
|
||||
{{MobType::Giant, 2},{}},
|
||||
{{MobType::Giant, 3},{}},
|
||||
{{MobType::Giant, 4},{}},
|
||||
{{MobType::Giant, 5},{}},
|
||||
{{MobType::Giant, 1},{}},
|
||||
{{MobType::Giant, 2},{}},
|
||||
{{MobType::Giant, 3},{}},
|
||||
{{MobType::Giant, 4},{}},
|
||||
{{MobType::Giant, 5},{}},
|
||||
};
|
||||
|
||||
const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level) {
|
||||
return MobsTowerImmunities.at({ type, level });
|
||||
return MobsTowerImmunities.at({ type, level });
|
||||
}
|
||||
|
||||
static const std::map<MobKey, EffectImmunities> MobsEffectImmunities = {
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{}},
|
||||
{{MobType::Spider, 5},{}},
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{}},
|
||||
{{MobType::Spider, 5},{}},
|
||||
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{}},
|
||||
{{MobType::Skeleton, 4},{EffectType::Fire}},
|
||||
{{MobType::Skeleton, 5},{EffectType::Fire}},
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{}},
|
||||
{{MobType::Skeleton, 4},{EffectType::Fire}},
|
||||
{{MobType::Skeleton, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Pigman, 1},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 2},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 3},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 4},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 5},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 1},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 2},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 3},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 4},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{EffectType::Fire}},
|
||||
{{MobType::Silverfish, 5},{EffectType::Fire}},
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{EffectType::Fire}},
|
||||
{{MobType::Silverfish, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Blaze, 1},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 2},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 3},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 4},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 5},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 1},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 2},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 3},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 4},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Witch, 1},{}},
|
||||
{{MobType::Witch, 2},{}},
|
||||
{{MobType::Witch, 3},{}},
|
||||
{{MobType::Witch, 4},{}},
|
||||
{{MobType::Witch, 5},{}},
|
||||
{{MobType::Witch, 1},{}},
|
||||
{{MobType::Witch, 2},{}},
|
||||
{{MobType::Witch, 3},{}},
|
||||
{{MobType::Witch, 4},{}},
|
||||
{{MobType::Witch, 5},{}},
|
||||
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{EffectType::Fire}},
|
||||
{{MobType::Slime, 5},{EffectType::Fire}},
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{EffectType::Fire}},
|
||||
{{MobType::Slime, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Giant, 1},{EffectType::Stun}},
|
||||
{{MobType::Giant, 2},{EffectType::Stun}},
|
||||
{{MobType::Giant, 3},{EffectType::Stun}},
|
||||
{{MobType::Giant, 4},{EffectType::Stun}},
|
||||
{{MobType::Giant, 5},{EffectType::Stun}},
|
||||
{{MobType::Giant, 1},{EffectType::Stun}},
|
||||
{{MobType::Giant, 2},{EffectType::Stun}},
|
||||
{{MobType::Giant, 3},{EffectType::Stun}},
|
||||
{{MobType::Giant, 4},{EffectType::Stun}},
|
||||
{{MobType::Giant, 5},{EffectType::Stun}},
|
||||
};
|
||||
|
||||
const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level) {
|
||||
return MobsEffectImmunities.at({ type, level });
|
||||
return MobsEffectImmunities.at({ type, level });
|
||||
}
|
||||
|
||||
MobPtr MobFactory::CreateMob(MobID mobId, MobType mobType, std::uint8_t mobLevel, PlayerID mobSender) {
|
||||
using MobCreator = std::function<std::shared_ptr<Mob>(MobID, std::uint8_t, PlayerID)>;
|
||||
using MobCreator = std::function<std::shared_ptr<Mob>(MobID, std::uint8_t, PlayerID)>;
|
||||
|
||||
static const std::map<MobType, MobCreator> mobFactory = {
|
||||
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
||||
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
||||
{MobType::Skeleton, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Skeleton>(id, level, sender);} },
|
||||
{MobType::Pigman, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<PigMan>(id, level, sender);} },
|
||||
{MobType::Creeper, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Creeper>(id, level, sender);} },
|
||||
{MobType::Silverfish, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Silverfish>(id, level, sender);} },
|
||||
{MobType::Blaze, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Blaze>(id, level, sender);} },
|
||||
{MobType::Witch, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Witch>(id, level, sender);} },
|
||||
{MobType::Slime, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Slime>(id, level, sender);} },
|
||||
{MobType::Giant, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Giant>(id, level, sender);} },
|
||||
};
|
||||
static const std::map<MobType, MobCreator> mobFactory = {
|
||||
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
||||
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
||||
{MobType::Skeleton, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Skeleton>(id, level, sender);} },
|
||||
{MobType::Pigman, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<PigMan>(id, level, sender);} },
|
||||
{MobType::Creeper, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Creeper>(id, level, sender);} },
|
||||
{MobType::Silverfish, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Silverfish>(id, level, sender);} },
|
||||
{MobType::Blaze, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Blaze>(id, level, sender);} },
|
||||
{MobType::Witch, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Witch>(id, level, sender);} },
|
||||
{MobType::Slime, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Slime>(id, level, sender);} },
|
||||
{MobType::Giant, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Giant>(id, level, sender);} },
|
||||
};
|
||||
|
||||
return mobFactory.at(mobType)(mobId, mobLevel, mobSender);
|
||||
return mobFactory.at(mobType)(mobId, mobLevel, mobSender);
|
||||
}
|
||||
|
||||
std::string MobFactory::GetMobName(MobType type) {
|
||||
switch (type) {
|
||||
case MobType::Zombie:
|
||||
return "Zombie";
|
||||
case MobType::Spider:
|
||||
return "Spider";
|
||||
case MobType::Skeleton:
|
||||
return "Skeleton";
|
||||
case MobType::Pigman:
|
||||
return "Pigman";
|
||||
case MobType::Creeper:
|
||||
return "Creeper";
|
||||
case MobType::Silverfish:
|
||||
return "Silverfish";
|
||||
case MobType::Blaze:
|
||||
return "Blaze";
|
||||
case MobType::Witch:
|
||||
return "Witch";
|
||||
case MobType::Slime:
|
||||
return "Slime";
|
||||
case MobType::Giant:
|
||||
return "Giant";
|
||||
default:
|
||||
return "Unknow";
|
||||
}
|
||||
switch (type) {
|
||||
case MobType::Zombie:
|
||||
return "Zombie";
|
||||
case MobType::Spider:
|
||||
return "Spider";
|
||||
case MobType::Skeleton:
|
||||
return "Skeleton";
|
||||
case MobType::Pigman:
|
||||
return "Pigman";
|
||||
case MobType::Creeper:
|
||||
return "Creeper";
|
||||
case MobType::Silverfish:
|
||||
return "Silverfish";
|
||||
case MobType::Blaze:
|
||||
return "Blaze";
|
||||
case MobType::Witch:
|
||||
return "Witch";
|
||||
case MobType::Slime:
|
||||
return "Slime";
|
||||
case MobType::Giant:
|
||||
return "Giant";
|
||||
default:
|
||||
return "Unknow";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -8,19 +8,19 @@ namespace game {
|
||||
Team::Team(TeamColor color) : m_Color(color), m_TeamCastle(this) {}
|
||||
|
||||
void Team::AddPlayer(Player* newPlayer) {
|
||||
m_Players.push_back(newPlayer);
|
||||
m_Players.push_back(newPlayer);
|
||||
}
|
||||
|
||||
void Team::RemovePlayer(const Player* player) {
|
||||
m_Players.erase(std::find(m_Players.begin(), m_Players.end(), player));
|
||||
m_Players.erase(std::find(m_Players.begin(), m_Players.end(), player));
|
||||
}
|
||||
|
||||
TeamColor Team::GetColor() const {
|
||||
return m_Color;
|
||||
return m_Color;
|
||||
}
|
||||
|
||||
std::uint8_t Team::GetPlayerCount() const {
|
||||
return m_Players.size();
|
||||
return m_Players.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,118 +7,118 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
bool Tower::IsMobInRange(MobPtr mob) {
|
||||
if (mob->IsDead())
|
||||
return false;
|
||||
return mob->CollidesWith(*this);
|
||||
if (mob->IsDead())
|
||||
return false;
|
||||
return mob->CollidesWith(*this);
|
||||
}
|
||||
|
||||
const std::map<std::pair<TowerType, TowerLevel>, TowerStats> TowerConstants = {
|
||||
// // rate damage range
|
||||
{{TowerType::Archer, {1, TowerPath::Base}}, {2, 5, 10}},
|
||||
// // rate damage range
|
||||
{{TowerType::Archer, {1, TowerPath::Base}}, {2, 5, 10}},
|
||||
|
||||
{{TowerType::Archer, {2, TowerPath::Top}}, {1, 0, 12}},
|
||||
{{TowerType::Archer, {3, TowerPath::Top}}, {1, 0, 13}},
|
||||
{{TowerType::Archer, {4, TowerPath::Top}}, {0.8, 0, 15}},
|
||||
{{TowerType::Archer, {2, TowerPath::Top}}, {1, 0, 12}},
|
||||
{{TowerType::Archer, {3, TowerPath::Top}}, {1, 0, 13}},
|
||||
{{TowerType::Archer, {4, TowerPath::Top}}, {0.8, 0, 15}},
|
||||
|
||||
{{TowerType::Archer, {2, TowerPath::Bottom}}, {2, 10, 12}},
|
||||
{{TowerType::Archer, {3, TowerPath::Bottom}}, {2, 10, 13}},
|
||||
{{TowerType::Archer, {4, TowerPath::Bottom}}, {2, 10, 15}},
|
||||
{{TowerType::Archer, {2, TowerPath::Bottom}}, {2, 10, 12}},
|
||||
{{TowerType::Archer, {3, TowerPath::Bottom}}, {2, 10, 13}},
|
||||
{{TowerType::Archer, {4, TowerPath::Bottom}}, {2, 10, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Ice, {1, TowerPath::Base}}, {1, 0, 10}},
|
||||
{{TowerType::Ice, {2, TowerPath::Base}}, {1, 0, 12}},
|
||||
{{TowerType::Ice, {3, TowerPath::Base}}, {1, 0, 13}},
|
||||
{{TowerType::Ice, {4, TowerPath::Base}}, {1, 1, 15}},
|
||||
{{TowerType::Ice, {1, TowerPath::Base}}, {1, 0, 10}},
|
||||
{{TowerType::Ice, {2, TowerPath::Base}}, {1, 0, 12}},
|
||||
{{TowerType::Ice, {3, TowerPath::Base}}, {1, 0, 13}},
|
||||
{{TowerType::Ice, {4, TowerPath::Base}}, {1, 1, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Sorcerer, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Sorcerer, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
{{TowerType::Sorcerer, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Sorcerer, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Top}}, {4, 0, 14}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Top}}, {4, 0, 15}},
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Top}}, {4, 0, 14}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Top}}, {4, 0, 15}},
|
||||
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Bottom}}, {4, 0, 14}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Bottom}}, {4, 0, 15}},
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Bottom}}, {4, 0, 14}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Bottom}}, {4, 0, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Zeus, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Zeus, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
{{TowerType::Zeus, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Zeus, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
|
||||
{{TowerType::Zeus, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Zeus, {3, TowerPath::Bottom}}, {1.2, 0, 14}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Bottom}}, {0.8, 0, 15}},
|
||||
{{TowerType::Zeus, {3, TowerPath::Bottom}}, {1.2, 0, 14}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Bottom}}, {0.8, 0, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Mage, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Mage, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
{{TowerType::Mage, {3, TowerPath::Base}}, {3, 0, 13}},
|
||||
{{TowerType::Mage, {4, TowerPath::Base}}, {1, 30, 15}},
|
||||
{{TowerType::Mage, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Mage, {2, TowerPath::Base}}, {4, 0, 12}},
|
||||
{{TowerType::Mage, {3, TowerPath::Base}}, {3, 0, 13}},
|
||||
{{TowerType::Mage, {4, TowerPath::Base}}, {1, 30, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Artillery, {1, TowerPath::Base}}, {7, 0, 10}},
|
||||
{{TowerType::Artillery, {2, TowerPath::Base}}, {7, 0, 12}},
|
||||
{{TowerType::Artillery, {1, TowerPath::Base}}, {7, 0, 10}},
|
||||
{{TowerType::Artillery, {2, TowerPath::Base}}, {7, 0, 12}},
|
||||
|
||||
{{TowerType::Artillery, {3, TowerPath::Top}}, {7, 0, 13}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Top}}, {7, 0, 15}},
|
||||
{{TowerType::Artillery, {3, TowerPath::Top}}, {7, 0, 13}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Top}}, {7, 0, 15}},
|
||||
|
||||
{{TowerType::Artillery, {3, TowerPath::Bottom}}, {5, 0, 13}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Bottom}}, {4, 0, 15}},
|
||||
{{TowerType::Artillery, {3, TowerPath::Bottom}}, {5, 0, 13}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Bottom}}, {4, 0, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Quake, {1, TowerPath::Base}}, {5, 5, 10}},
|
||||
{{TowerType::Quake, {2, TowerPath::Base}}, {4, 7, 12}},
|
||||
{{TowerType::Quake, {3, TowerPath::Base}}, {3, 9, 13}},
|
||||
{{TowerType::Quake, {4, TowerPath::Base}}, {2, 11, 15}},
|
||||
{{TowerType::Quake, {1, TowerPath::Base}}, {5, 5, 10}},
|
||||
{{TowerType::Quake, {2, TowerPath::Base}}, {4, 7, 12}},
|
||||
{{TowerType::Quake, {3, TowerPath::Base}}, {3, 9, 13}},
|
||||
{{TowerType::Quake, {4, TowerPath::Base}}, {2, 11, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Poison, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Poison, {2, TowerPath::Base}}, {5, 0, 12}},
|
||||
{{TowerType::Poison, {1, TowerPath::Base}}, {5, 0, 10}},
|
||||
{{TowerType::Poison, {2, TowerPath::Base}}, {5, 0, 12}},
|
||||
|
||||
{{TowerType::Poison, {3, TowerPath::Top}}, {6, 0, 13}},
|
||||
{{TowerType::Poison, {4, TowerPath::Top}}, {5, 0, 15}},
|
||||
{{TowerType::Poison, {3, TowerPath::Top}}, {6, 0, 13}},
|
||||
{{TowerType::Poison, {4, TowerPath::Top}}, {5, 0, 15}},
|
||||
|
||||
{{TowerType::Poison, {3, TowerPath::Bottom}}, {5, 10, 13}},
|
||||
{{TowerType::Poison, {4, TowerPath::Bottom}}, {6, 20, 15}},
|
||||
{{TowerType::Poison, {3, TowerPath::Bottom}}, {5, 10, 13}},
|
||||
{{TowerType::Poison, {4, TowerPath::Bottom}}, {6, 20, 15}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Leach, {1, TowerPath::Base}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {2, TowerPath::Base}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {3, TowerPath::Base}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {1, TowerPath::Base}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {2, TowerPath::Base}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {3, TowerPath::Base}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Turret, {1, TowerPath::Base}}, {0.5, 0, 0}},
|
||||
{{TowerType::Turret, {1, TowerPath::Base}}, {0.5, 0, 0}},
|
||||
|
||||
{{TowerType::Turret, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Turret, {2, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {2, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Necromancer, {1, TowerPath::Base}}, {2, 0, 11}},
|
||||
{{TowerType::Necromancer, {2, TowerPath::Base}}, {1, 0, 14}},
|
||||
{{TowerType::Necromancer, {1, TowerPath::Base}}, {2, 0, 11}},
|
||||
{{TowerType::Necromancer, {2, TowerPath::Base}}, {1, 0, 14}},
|
||||
|
||||
{{TowerType::Necromancer, {3, TowerPath::Top}}, {1, 0, 15}},
|
||||
{{TowerType::Necromancer, {3, TowerPath::Top}}, {1, 0, 15}},
|
||||
|
||||
{{TowerType::Necromancer, {3, TowerPath::Bottom}}, {0, 30, 0}},
|
||||
{{TowerType::Necromancer, {3, TowerPath::Bottom}}, {0, 30, 0}},
|
||||
};
|
||||
|
||||
const TowerStats* GetTowerStats(TowerType type, TowerLevel level) {
|
||||
auto it = TowerConstants.find({ type, level });
|
||||
if (it == TowerConstants.end()) return nullptr;
|
||||
return &it->second;
|
||||
auto it = TowerConstants.find({ type, level });
|
||||
if (it == TowerConstants.end()) return nullptr;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,21 +126,21 @@ const TowerStats* GetTowerStats(TowerType type, TowerLevel level) {
|
||||
|
||||
|
||||
static const std::map<TowerType, TowerInfo> TowerInfoConstants = {
|
||||
{TowerType::Archer, {"Archer", "Shoot projectiles", false}},
|
||||
{TowerType::Artillery, {"Artillery", "Explosion", false}},
|
||||
{TowerType::Ice, {"Ice", "Slow down enemies", false}},
|
||||
{TowerType::Leach, {"Leach", "Shoot projectiles", true}},
|
||||
{TowerType::Mage, {"Mage", "Set enemies on fire", false}},
|
||||
{TowerType::Necromancer, {"Necromancer", "Summon troops", true}},
|
||||
{TowerType::Poison, {"Poison", "Poison enemies", false}},
|
||||
{TowerType::Quake, {"Quake", "Shoot projectiles", false}},
|
||||
{TowerType::Sorcerer, {"Sorcerer", "Summon friendly troops", false}},
|
||||
{TowerType::Turret, {"Turret", "Shoot arrow very fast", true}},
|
||||
{TowerType::Zeus, {"Zeus", "Strike lightning", false}},
|
||||
{TowerType::Archer, {"Archer", "Shoot projectiles", false}},
|
||||
{TowerType::Artillery, {"Artillery", "Explosion", false}},
|
||||
{TowerType::Ice, {"Ice", "Slow down enemies", false}},
|
||||
{TowerType::Leach, {"Leach", "Shoot projectiles", true}},
|
||||
{TowerType::Mage, {"Mage", "Set enemies on fire", false}},
|
||||
{TowerType::Necromancer, {"Necromancer", "Summon troops", true}},
|
||||
{TowerType::Poison, {"Poison", "Poison enemies", false}},
|
||||
{TowerType::Quake, {"Quake", "Shoot projectiles", false}},
|
||||
{TowerType::Sorcerer, {"Sorcerer", "Summon friendly troops", false}},
|
||||
{TowerType::Turret, {"Turret", "Shoot arrow very fast", true}},
|
||||
{TowerType::Zeus, {"Zeus", "Strike lightning", false}},
|
||||
};
|
||||
|
||||
const TowerInfo& GetTowerInfo(TowerType type) {
|
||||
return TowerInfoConstants.at(type);
|
||||
return TowerInfoConstants.at(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,52 +152,52 @@ namespace TowerFactory {
|
||||
using TowerCreator = std::function<std::shared_ptr<Tower>(TowerID, std::int32_t, std::int32_t, PlayerID)>;
|
||||
|
||||
static const std::map<TowerType, TowerCreator> towerFactory = {
|
||||
{TowerType::Archer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ArcherTower>(id, x, y , builder);} },
|
||||
{TowerType::Artillery, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ArtilleryTower>(id, x, y , builder);} },
|
||||
{TowerType::Ice, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<IceTower>(id, x, y , builder);} },
|
||||
{TowerType::Mage, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<MageTower>(id, x, y , builder);} },
|
||||
{TowerType::Poison, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<PoisonTower>(id, x, y , builder);} },
|
||||
{TowerType::Quake, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<QuakeTower>(id, x, y , builder);} },
|
||||
{TowerType::Sorcerer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<SorcererTower>(id, x, y , builder);} },
|
||||
{TowerType::Zeus, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ZeusTower>(id, x, y , builder);} },
|
||||
{TowerType::Leach, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<LeachTower>(id, x, y , builder);} },
|
||||
{TowerType::Necromancer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<NecromancerTower>(id, x, y , builder);} },
|
||||
{TowerType::Turret, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<TurretTower>(id, x, y , builder);} },
|
||||
{TowerType::Archer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ArcherTower>(id, x, y , builder);} },
|
||||
{TowerType::Artillery, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ArtilleryTower>(id, x, y , builder);} },
|
||||
{TowerType::Ice, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<IceTower>(id, x, y , builder);} },
|
||||
{TowerType::Mage, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<MageTower>(id, x, y , builder);} },
|
||||
{TowerType::Poison, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<PoisonTower>(id, x, y , builder);} },
|
||||
{TowerType::Quake, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<QuakeTower>(id, x, y , builder);} },
|
||||
{TowerType::Sorcerer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<SorcererTower>(id, x, y , builder);} },
|
||||
{TowerType::Zeus, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<ZeusTower>(id, x, y , builder);} },
|
||||
{TowerType::Leach, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<LeachTower>(id, x, y , builder);} },
|
||||
{TowerType::Necromancer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<NecromancerTower>(id, x, y , builder);} },
|
||||
{TowerType::Turret, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared<TurretTower>(id, x, y , builder);} },
|
||||
};
|
||||
|
||||
TowerPtr CreateTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) {
|
||||
return towerFactory.at(type)(id, x, y, builder);
|
||||
return towerFactory.at(type)(id, x, y, builder);
|
||||
}
|
||||
|
||||
std::string GetTowerName(TowerType type) {
|
||||
switch (type) {
|
||||
switch (type) {
|
||||
|
||||
case TowerType::Archer:
|
||||
return "Archer";
|
||||
case TowerType::Artillery:
|
||||
return "Artillery";
|
||||
case TowerType::Ice:
|
||||
return "Ice";
|
||||
case TowerType::Mage:
|
||||
return "Mage";
|
||||
case TowerType::Poison:
|
||||
return "Poison";
|
||||
case TowerType::Quake:
|
||||
return "Quake";
|
||||
case TowerType::Sorcerer:
|
||||
return "Sorcerer";
|
||||
case TowerType::Zeus:
|
||||
return "Zeus";
|
||||
case TowerType::Leach:
|
||||
return "Leach";
|
||||
case TowerType::Necromancer:
|
||||
return "Necromancer";
|
||||
case TowerType::Turret:
|
||||
return "Turret";
|
||||
default:
|
||||
return "Unknow";
|
||||
case TowerType::Archer:
|
||||
return "Archer";
|
||||
case TowerType::Artillery:
|
||||
return "Artillery";
|
||||
case TowerType::Ice:
|
||||
return "Ice";
|
||||
case TowerType::Mage:
|
||||
return "Mage";
|
||||
case TowerType::Poison:
|
||||
return "Poison";
|
||||
case TowerType::Quake:
|
||||
return "Quake";
|
||||
case TowerType::Sorcerer:
|
||||
return "Sorcerer";
|
||||
case TowerType::Zeus:
|
||||
return "Zeus";
|
||||
case TowerType::Leach:
|
||||
return "Leach";
|
||||
case TowerType::Necromancer:
|
||||
return "Necromancer";
|
||||
case TowerType::Turret:
|
||||
return "Turret";
|
||||
default:
|
||||
return "Unknow";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TowerFactory
|
||||
@@ -207,82 +207,82 @@ std::string GetTowerName(TowerType type) {
|
||||
|
||||
|
||||
void ArcherTower::Tick(std::uint64_t delta, World* world) {
|
||||
if (m_Timer.Update(delta)) {
|
||||
std::uint8_t arrowsShot = 0;
|
||||
bool explosiveArrows = GetLevel().GetPath() == TowerPath::Bottom;
|
||||
std::uint8_t arrows = explosiveArrows ? 2 : GetLevel().GetLevel();
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
world->GetWorldNotifier().NotifyListeners(&WorldListener::OnArcherTowerShot, mob, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
arrowsShot++;
|
||||
if (arrowsShot >= arrows)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_Timer.Update(delta)) {
|
||||
std::uint8_t arrowsShot = 0;
|
||||
bool explosiveArrows = GetLevel().GetPath() == TowerPath::Bottom;
|
||||
std::uint8_t arrows = explosiveArrows ? 2 : GetLevel().GetLevel();
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
world->GetWorldNotifier().NotifyListeners(&WorldListener::OnArcherTowerShot, mob, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
arrowsShot++;
|
||||
if (arrowsShot >= arrows)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IceTower::Tick(std::uint64_t delta, World* world) {
|
||||
if (m_Timer.Update(delta)) {
|
||||
float damage = GetStats()->GetDamage();
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
mob->AddEffect(EffectType::Slowness, 1, this); // slowness for 1s every second
|
||||
if (damage > 0)
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), damage, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_Timer.Update(delta)) {
|
||||
float damage = GetStats()->GetDamage();
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
mob->AddEffect(EffectType::Slowness, 1, this); // slowness for 1s every second
|
||||
if (damage > 0)
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), damage, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MageTower::Tick(std::uint64_t delta, World* world) {
|
||||
if (m_Timer.Update(delta)) {
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
mob->AddEffect(EffectType::Fire, GetLevel().GetLevel() * 3, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_Timer.Update(delta)) {
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
mob->AddEffect(EffectType::Fire, GetLevel().GetLevel() * 3, this);
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PoisonTower::Tick(std::uint64_t delta, World* world) {
|
||||
if (m_Timer.Update(delta)) {
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
if (GetLevel().GetPath() == TowerPath::Bottom) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), GetStats()->GetDamage(), this);
|
||||
} else {
|
||||
float durationSec;
|
||||
switch (GetLevel().GetLevel()) {
|
||||
case 1:
|
||||
durationSec = 5;
|
||||
break;
|
||||
if (m_Timer.Update(delta)) {
|
||||
for (MobPtr mob : world->GetMobList()) {
|
||||
if (IsMobInRange(mob)) {
|
||||
if (GetLevel().GetPath() == TowerPath::Bottom) {
|
||||
world->GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), GetStats()->GetDamage(), this);
|
||||
} else {
|
||||
float durationSec;
|
||||
switch (GetLevel().GetLevel()) {
|
||||
case 1:
|
||||
durationSec = 5;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
durationSec = 15;
|
||||
break;
|
||||
case 2:
|
||||
durationSec = 15;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
durationSec = 30;
|
||||
break;
|
||||
case 3:
|
||||
durationSec = 30;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
durationSec = 1e10; // about 3 million hours. It should be enough
|
||||
break;
|
||||
case 4:
|
||||
durationSec = 1e10; // about 3 million hours. It should be enough
|
||||
break;
|
||||
|
||||
default:
|
||||
durationSec = 0; // how did we get there ?
|
||||
break;
|
||||
}
|
||||
mob->AddEffect(EffectType::Poison, durationSec, this);
|
||||
}
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
durationSec = 0; // how did we get there ?
|
||||
break;
|
||||
}
|
||||
mob->AddEffect(EffectType::Poison, durationSec, this);
|
||||
}
|
||||
m_Timer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuakeTower::Tick(std::uint64_t delta, World* world) {
|
||||
|
||||
@@ -12,312 +12,312 @@ namespace td {
|
||||
namespace game {
|
||||
|
||||
World::World(Game* game) : m_Game(game) {
|
||||
GetWorldNotifier().BindListener(this);
|
||||
GetMobNotifier().BindListener(this);
|
||||
GetWorldNotifier().BindListener(this);
|
||||
GetMobNotifier().BindListener(this);
|
||||
}
|
||||
|
||||
TilePtr World::GetTile(std::int32_t x, std::int32_t y) const {
|
||||
std::int16_t chunkX = x / Chunk::ChunkWidth;
|
||||
std::int16_t chunkY = y / Chunk::ChunkHeight;
|
||||
std::int16_t chunkX = x / Chunk::ChunkWidth;
|
||||
std::int16_t chunkY = y / Chunk::ChunkHeight;
|
||||
|
||||
std::uint16_t subChunkX = std::abs(x % Chunk::ChunkWidth);
|
||||
std::uint16_t subChunkY = std::abs(y % Chunk::ChunkHeight);
|
||||
std::uint16_t subChunkX = std::abs(x % Chunk::ChunkWidth);
|
||||
std::uint16_t subChunkY = std::abs(y % Chunk::ChunkHeight);
|
||||
|
||||
auto chunkIt = m_Chunks.find({ chunkX, chunkY });
|
||||
if (chunkIt == m_Chunks.end())
|
||||
return nullptr;
|
||||
auto chunkIt = m_Chunks.find({ chunkX, chunkY });
|
||||
if (chunkIt == m_Chunks.end())
|
||||
return nullptr;
|
||||
|
||||
ChunkPtr chunk = chunkIt->second;
|
||||
ChunkPtr chunk = chunkIt->second;
|
||||
|
||||
return GetTilePtr(chunk->GetTileIndex(subChunkY * Chunk::ChunkWidth + subChunkX));
|
||||
return GetTilePtr(chunk->GetTileIndex(subChunkY * Chunk::ChunkWidth + subChunkX));
|
||||
}
|
||||
|
||||
bool World::LoadMap(const protocol::WorldBeginDataPacket* worldHeader) {
|
||||
m_TowerPlacePalette = worldHeader->GetTowerTilePalette();
|
||||
m_WalkablePalette = worldHeader->GetWalkableTileColor();
|
||||
m_DecorationPalette = worldHeader->GetDecorationPalette();
|
||||
m_Background = worldHeader->GetBackgroundColor();
|
||||
m_TowerPlacePalette = worldHeader->GetTowerTilePalette();
|
||||
m_WalkablePalette = worldHeader->GetWalkableTileColor();
|
||||
m_DecorationPalette = worldHeader->GetDecorationPalette();
|
||||
m_Background = worldHeader->GetBackgroundColor();
|
||||
|
||||
GetRedTeam().GetSpawn() = worldHeader->GetRedSpawn();
|
||||
GetBlueTeam().GetSpawn() = worldHeader->GetBlueSpawn();
|
||||
GetRedTeam().GetSpawn() = worldHeader->GetRedSpawn();
|
||||
GetBlueTeam().GetSpawn() = worldHeader->GetBlueSpawn();
|
||||
|
||||
m_SpawnColorPalette = worldHeader->GetSpawnPalette();
|
||||
m_SpawnColorPalette = worldHeader->GetSpawnPalette();
|
||||
|
||||
GetRedTeam().GetCastle() = worldHeader->GetRedCastle();
|
||||
GetRedTeam().GetCastle().SetTeam(&GetRedTeam());
|
||||
GetRedTeam().GetCastle() = worldHeader->GetRedCastle();
|
||||
GetRedTeam().GetCastle().SetTeam(&GetRedTeam());
|
||||
|
||||
GetBlueTeam().GetCastle() = worldHeader->GetBlueCastle();
|
||||
GetBlueTeam().GetCastle().SetTeam(&GetBlueTeam());
|
||||
GetBlueTeam().GetCastle() = worldHeader->GetBlueCastle();
|
||||
GetBlueTeam().GetCastle().SetTeam(&GetBlueTeam());
|
||||
|
||||
m_TilePalette = worldHeader->GetTilePalette();
|
||||
m_TilePalette = worldHeader->GetTilePalette();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool World::LoadMap(const protocol::WorldDataPacket* worldData) {
|
||||
m_Chunks = worldData->GetChunks();
|
||||
return true;
|
||||
m_Chunks = worldData->GetChunks();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool World::LoadMapFromFile(const std::string& fileName) {
|
||||
DataBuffer buffer;
|
||||
if (!buffer.ReadFile(fileName)) {
|
||||
utils::LOGE(utils::format("Failed to load map from file %s", fileName.c_str()));
|
||||
return false;
|
||||
}
|
||||
DataBuffer buffer;
|
||||
if (!buffer.ReadFile(fileName)) {
|
||||
utils::LOGE(utils::format("Failed to load map from file %s", fileName.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::LOG(utils::format("Read file : %s (File size : %u)", fileName.c_str(), buffer.GetSize()));
|
||||
utils::LOG(utils::format("Read file : %s (File size : %u)", fileName.c_str(), buffer.GetSize()));
|
||||
|
||||
DataBuffer mapHeaderPacketBuffer = utils::Decompress(buffer);
|
||||
DataBuffer mapDataPacketBuffer = utils::Decompress(buffer);
|
||||
DataBuffer mapHeaderPacketBuffer = utils::Decompress(buffer);
|
||||
DataBuffer mapDataPacketBuffer = utils::Decompress(buffer);
|
||||
|
||||
protocol::WorldBeginDataPacket headerPacket;
|
||||
headerPacket.Deserialize(mapHeaderPacketBuffer);
|
||||
protocol::WorldBeginDataPacket headerPacket;
|
||||
headerPacket.Deserialize(mapHeaderPacketBuffer);
|
||||
|
||||
protocol::WorldDataPacket dataPacket;
|
||||
dataPacket.Deserialize(mapDataPacketBuffer);
|
||||
protocol::WorldDataPacket dataPacket;
|
||||
dataPacket.Deserialize(mapDataPacketBuffer);
|
||||
|
||||
LoadMap(&headerPacket);
|
||||
LoadMap(&dataPacket);
|
||||
LoadMap(&headerPacket);
|
||||
LoadMap(&dataPacket);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool World::SaveMap(const std::string& fileName) const {
|
||||
protocol::WorldBeginDataPacket headerPacket(this);
|
||||
protocol::WorldDataPacket dataPacket(this);
|
||||
protocol::WorldBeginDataPacket headerPacket(this);
|
||||
protocol::WorldDataPacket dataPacket(this);
|
||||
|
||||
DataBuffer mapHeaderCompressed = utils::Compress(headerPacket.Serialize(false));
|
||||
DataBuffer mapDataCompressed = utils::Compress(dataPacket.Serialize(false));
|
||||
DataBuffer mapHeaderCompressed = utils::Compress(headerPacket.Serialize(false));
|
||||
DataBuffer mapDataCompressed = utils::Compress(dataPacket.Serialize(false));
|
||||
|
||||
utils::LOG(utils::format("Header Packet Size : %u", mapHeaderCompressed.GetSize()));
|
||||
utils::LOG(utils::format("World Data Packet Size : %u", mapDataCompressed.GetSize()));
|
||||
utils::LOG(utils::format("Header Packet Size : %u", mapHeaderCompressed.GetSize()));
|
||||
utils::LOG(utils::format("World Data Packet Size : %u", mapDataCompressed.GetSize()));
|
||||
|
||||
DataBuffer buffer = mapHeaderCompressed << mapDataCompressed;
|
||||
utils::LOG(utils::format("Total Size : %u", buffer.GetSize()));
|
||||
return buffer.WriteFile(fileName);
|
||||
DataBuffer buffer = mapHeaderCompressed << mapDataCompressed;
|
||||
utils::LOG(utils::format("Total Size : %u", buffer.GetSize()));
|
||||
return buffer.WriteFile(fileName);
|
||||
}
|
||||
|
||||
void World::Tick(std::uint64_t delta) {
|
||||
if (m_Game->GetGameState() != GameState::Game) return;
|
||||
if (m_Game->GetGameState() != GameState::Game) return;
|
||||
|
||||
TickMobs(delta);
|
||||
for (TowerPtr tower : m_Towers) {
|
||||
tower->Tick(delta, this);
|
||||
}
|
||||
CleanDeadMobs();
|
||||
TickMobs(delta);
|
||||
for (TowerPtr tower : m_Towers) {
|
||||
tower->Tick(delta, this);
|
||||
}
|
||||
CleanDeadMobs();
|
||||
}
|
||||
|
||||
void World::SpawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir) {
|
||||
MobPtr mob = MobFactory::CreateMob(id, type, level, sender);
|
||||
mob->SetCenter({ x, y });
|
||||
mob->SetDirection(dir);
|
||||
m_Mobs.push_back(mob);
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobSpawn, mob.get());
|
||||
MobPtr mob = MobFactory::CreateMob(id, type, level, sender);
|
||||
mob->SetCenter({ x, y });
|
||||
mob->SetDirection(dir);
|
||||
m_Mobs.push_back(mob);
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobSpawn, mob.get());
|
||||
}
|
||||
|
||||
TowerPtr World::PlaceTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) {
|
||||
TowerPtr tower = TowerFactory::CreateTower(type, id, x, y, builder);
|
||||
m_Towers.push_back(tower);
|
||||
return tower;
|
||||
TowerPtr tower = TowerFactory::CreateTower(type, id, x, y, builder);
|
||||
m_Towers.push_back(tower);
|
||||
return tower;
|
||||
}
|
||||
|
||||
TowerPtr World::RemoveTower(TowerID towerId) {
|
||||
auto it = std::find_if(m_Towers.begin(), m_Towers.end(), [towerId](TowerPtr tower) { return tower->GetID() == towerId;});
|
||||
if (it == m_Towers.end()) return nullptr;
|
||||
auto it = std::find_if(m_Towers.begin(), m_Towers.end(), [towerId](TowerPtr tower) { return tower->GetID() == towerId;});
|
||||
if (it == m_Towers.end()) return nullptr;
|
||||
|
||||
TowerPtr tower = *it;
|
||||
TowerPtr tower = *it;
|
||||
|
||||
m_Towers.erase(it);
|
||||
m_Towers.erase(it);
|
||||
|
||||
return tower;
|
||||
return tower;
|
||||
}
|
||||
|
||||
void World::TickMobs(std::uint64_t delta) {
|
||||
for (MobPtr mob : m_Mobs) {
|
||||
mob->Tick(delta, this);
|
||||
}
|
||||
for (MobPtr mob : m_Mobs) {
|
||||
mob->Tick(delta, this);
|
||||
}
|
||||
}
|
||||
|
||||
const Color* World::GetTileColor(TilePtr tile) const {
|
||||
switch (tile->GetType()) {
|
||||
case TileType::Tower: {
|
||||
TowerTile* towerTile = dynamic_cast<TowerTile*>(tile.get());
|
||||
return &m_TowerPlacePalette[towerTile->color_palette_ref];
|
||||
}
|
||||
case TileType::Walk: {
|
||||
return &m_WalkablePalette;
|
||||
}
|
||||
case TileType::Decoration: {
|
||||
DecorationTile* towerTile = dynamic_cast<DecorationTile*>(tile.get());
|
||||
return &m_DecorationPalette[towerTile->color_palette_ref];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
switch (tile->GetType()) {
|
||||
case TileType::Tower: {
|
||||
TowerTile* towerTile = dynamic_cast<TowerTile*>(tile.get());
|
||||
return &m_TowerPlacePalette[towerTile->color_palette_ref];
|
||||
}
|
||||
case TileType::Walk: {
|
||||
return &m_WalkablePalette;
|
||||
}
|
||||
case TileType::Decoration: {
|
||||
DecorationTile* towerTile = dynamic_cast<DecorationTile*>(tile.get());
|
||||
return &m_DecorationPalette[towerTile->color_palette_ref];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool World::CanPlaceLittleTower(const Vec2f& worldPos, PlayerID playerID) const {
|
||||
TilePtr tile = GetTile(worldPos.x, worldPos.y);
|
||||
const Player& player = m_Game->GetPlayers()[playerID];
|
||||
TilePtr tile = GetTile(worldPos.x, worldPos.y);
|
||||
const Player& player = m_Game->GetPlayers()[playerID];
|
||||
|
||||
if (tile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (tile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tile->GetType() == game::TileType::Tower) {
|
||||
const TowerTile* towerTile = dynamic_cast<TowerTile*>(tile.get());
|
||||
if (towerTile->team_owner != player.GetTeamColor())
|
||||
return false;
|
||||
for (int x = -1; x < 2; x++) {
|
||||
for (int y = -1; y < 2; y++) {
|
||||
game::TilePtr adjacentTile = GetTile(worldPos.x + x, worldPos.y + y);
|
||||
if (adjacentTile == nullptr || adjacentTile->GetType() != game::TileType::Tower || GetTower({ worldPos.x + x, worldPos.y + y }) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (tile->GetType() == game::TileType::Tower) {
|
||||
const TowerTile* towerTile = dynamic_cast<TowerTile*>(tile.get());
|
||||
if (towerTile->team_owner != player.GetTeamColor())
|
||||
return false;
|
||||
for (int x = -1; x < 2; x++) {
|
||||
for (int y = -1; y < 2; y++) {
|
||||
game::TilePtr adjacentTile = GetTile(worldPos.x + x, worldPos.y + y);
|
||||
if (adjacentTile == nullptr || adjacentTile->GetType() != game::TileType::Tower || GetTower({ worldPos.x + x, worldPos.y + y }) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool World::CanPlaceBigTower(const Vec2f& worldPos, PlayerID playerID) const {
|
||||
if (!CanPlaceLittleTower(worldPos, playerID)) return false;
|
||||
if (!CanPlaceLittleTower(worldPos, playerID)) return false;
|
||||
|
||||
TilePtr tile = GetTile(worldPos.x, worldPos.y);
|
||||
const Player& player = m_Game->GetPlayers()[playerID];
|
||||
TilePtr tile = GetTile(worldPos.x, worldPos.y);
|
||||
const Player& player = m_Game->GetPlayers()[playerID];
|
||||
|
||||
if (tile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (tile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tile->GetType() == game::TileType::Tower) {
|
||||
const TowerTile* towerTile = dynamic_cast<const TowerTile*>(tile.get());
|
||||
if (towerTile->team_owner != player.GetTeamColor())
|
||||
return false;
|
||||
for (int x = -2; x < 3; x++) {
|
||||
for (int y = -2; y < 3; y++) {
|
||||
game::TilePtr adjacentTile = GetTile(worldPos.x + x, worldPos.y + y);
|
||||
if (adjacentTile == nullptr || adjacentTile->GetType() != game::TileType::Tower || GetTower({ worldPos.x + x, worldPos.y + y }) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (tile->GetType() == game::TileType::Tower) {
|
||||
const TowerTile* towerTile = dynamic_cast<const TowerTile*>(tile.get());
|
||||
if (towerTile->team_owner != player.GetTeamColor())
|
||||
return false;
|
||||
for (int x = -2; x < 3; x++) {
|
||||
for (int y = -2; y < 3; y++) {
|
||||
game::TilePtr adjacentTile = GetTile(worldPos.x + x, worldPos.y + y);
|
||||
if (adjacentTile == nullptr || adjacentTile->GetType() != game::TileType::Tower || GetTower({ worldPos.x + x, worldPos.y + y }) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void World::CleanDeadMobs() {
|
||||
// safely remove mobs when unused
|
||||
for (std::size_t i = 0; i < m_Mobs.size(); i++) {
|
||||
MobPtr mob = m_Mobs[i];
|
||||
if (mob->IsDead()) {
|
||||
m_Mobs.erase(m_Mobs.begin() + static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
// safely remove mobs when unused
|
||||
for (std::size_t i = 0; i < m_Mobs.size(); i++) {
|
||||
MobPtr mob = m_Mobs[i];
|
||||
if (mob->IsDead()) {
|
||||
m_Mobs.erase(m_Mobs.begin() + static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TowerPtr World::GetTower(const Vec2f& position) const {
|
||||
for (TowerPtr tower : m_Towers) {
|
||||
if (tower->GetSize() == TowerSize::Big) {
|
||||
if (tower->GetCenterX() - 2.5f < position.x && tower->GetCenterX() + 2.5f > position.x &&
|
||||
tower->GetCenterY() - 2.5f < position.y && tower->GetCenterY() + 2.5f > position.y) {
|
||||
return tower;
|
||||
}
|
||||
} else { // little tower
|
||||
if (tower->GetCenterX() - 1.5f < position.x && tower->GetCenterX() + 1.5f > position.x &&
|
||||
tower->GetCenterY() - 1.5f < position.y && tower->GetCenterY() + 1.5f > position.y) {
|
||||
return tower;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
for (TowerPtr tower : m_Towers) {
|
||||
if (tower->GetSize() == TowerSize::Big) {
|
||||
if (tower->GetCenterX() - 2.5f < position.x && tower->GetCenterX() + 2.5f > position.x &&
|
||||
tower->GetCenterY() - 2.5f < position.y && tower->GetCenterY() + 2.5f > position.y) {
|
||||
return tower;
|
||||
}
|
||||
} else { // little tower
|
||||
if (tower->GetCenterX() - 1.5f < position.x && tower->GetCenterX() + 1.5f > position.x &&
|
||||
tower->GetCenterY() - 1.5f < position.y && tower->GetCenterY() + 1.5f > position.y) {
|
||||
return tower;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TowerPtr World::GetTowerById(TowerID towerID) {
|
||||
auto it = std::find_if(m_Towers.begin(), m_Towers.end(), [towerID](TowerPtr tower) { return tower->GetID() == towerID;});
|
||||
if (it == m_Towers.end()) return nullptr;
|
||||
return *it;
|
||||
auto it = std::find_if(m_Towers.begin(), m_Towers.end(), [towerID](TowerPtr tower) { return tower->GetID() == towerID;});
|
||||
if (it == m_Towers.end()) return nullptr;
|
||||
return *it;
|
||||
}
|
||||
|
||||
void World::OnArcherTowerShot(MobPtr tarGet, ArcherTower* shooter) {
|
||||
bool fireArrows = shooter->GetLevel().GetPath() == TowerPath::Bottom;
|
||||
bool explosiveArrows = shooter->GetLevel().GetLevel() == 4 && fireArrows;
|
||||
bool fireArrows = shooter->GetLevel().GetPath() == TowerPath::Bottom;
|
||||
bool explosiveArrows = shooter->GetLevel().GetLevel() == 4 && fireArrows;
|
||||
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnArrowShot, tarGet, fireArrows, shooter);
|
||||
if (explosiveArrows) {
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnExplosion, utils::shape::Circle{ tarGet->GetCenterX(), tarGet->GetCenterY(), ArcherTower::ExplosionRadius }, shooter->GetStats()->GetDamage(), shooter);
|
||||
}
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnArrowShot, tarGet, fireArrows, shooter);
|
||||
if (explosiveArrows) {
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnExplosion, utils::shape::Circle{ tarGet->GetCenterX(), tarGet->GetCenterY(), ArcherTower::ExplosionRadius }, shooter->GetStats()->GetDamage(), shooter);
|
||||
}
|
||||
}
|
||||
|
||||
void World::OnArrowShot(MobPtr tarGet, bool fireArrow, Tower* shooter) {
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, tarGet.get(), shooter->GetStats()->GetDamage(), shooter);
|
||||
if (fireArrow) {
|
||||
tarGet->AddEffect(EffectType::Fire, ArcherTower::FireDurationSec, shooter);
|
||||
}
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, tarGet.get(), shooter->GetStats()->GetDamage(), shooter);
|
||||
if (fireArrow) {
|
||||
tarGet->AddEffect(EffectType::Fire, ArcherTower::FireDurationSec, shooter);
|
||||
}
|
||||
}
|
||||
|
||||
void World::OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {
|
||||
for (MobPtr mob : m_Mobs) {
|
||||
if (mob->IsAlive() && mob->CollidesWith(explosion)) {
|
||||
// linear distance damage reduction
|
||||
float explosionDamage = mob->Distance(explosion) / explosion.GetRadius() * centerDamage;
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), explosionDamage, shooter);
|
||||
}
|
||||
}
|
||||
for (MobPtr mob : m_Mobs) {
|
||||
if (mob->IsAlive() && mob->CollidesWith(explosion)) {
|
||||
// linear distance damage reduction
|
||||
float explosionDamage = mob->Distance(explosion) / explosion.GetRadius() * centerDamage;
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDamage, mob.get(), explosionDamage, shooter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {
|
||||
enemyCastle->Damage(damage);
|
||||
if (enemyCastle->GetLife() <= 0) {
|
||||
m_Game->NotifyListeners(&GameListener::OnGameEnd);
|
||||
}
|
||||
enemyCastle->Damage(damage);
|
||||
if (enemyCastle->GetLife() <= 0) {
|
||||
m_Game->NotifyListeners(&GameListener::OnGameEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void World::OnMobDamage(Mob* tarGet, float damage, Tower* source) {
|
||||
tarGet->Damage(damage, source);
|
||||
if (tarGet->IsDead()) {
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDie, tarGet);
|
||||
}
|
||||
tarGet->Damage(damage, source);
|
||||
if (tarGet->IsDead()) {
|
||||
GetMobNotifier().NotifyListeners(&MobListener::OnMobDie, tarGet);
|
||||
}
|
||||
}
|
||||
|
||||
Team& World::GetRedTeam() {
|
||||
return m_Game->GetRedTeam();
|
||||
return m_Game->GetRedTeam();
|
||||
}
|
||||
|
||||
const Team& World::GetRedTeam() const {
|
||||
return m_Game->GetRedTeam();
|
||||
return m_Game->GetRedTeam();
|
||||
}
|
||||
|
||||
Team& World::GetBlueTeam() {
|
||||
return m_Game->GetBlueTeam();
|
||||
return m_Game->GetBlueTeam();
|
||||
}
|
||||
|
||||
const Team& World::GetBlueTeam() const {
|
||||
return m_Game->GetBlueTeam();
|
||||
return m_Game->GetBlueTeam();
|
||||
}
|
||||
|
||||
Team& World::GetTeam(TeamColor team) {
|
||||
return m_Game->GetTeam(team);
|
||||
return m_Game->GetTeam(team);
|
||||
}
|
||||
|
||||
const Team& World::GetTeam(TeamColor team) const {
|
||||
return m_Game->GetTeam(team);
|
||||
return m_Game->GetTeam(team);
|
||||
}
|
||||
|
||||
const Player* World::GetPlayerById(PlayerID id) const {
|
||||
return m_Game->GetPlayerById(id);
|
||||
return m_Game->GetPlayerById(id);
|
||||
}
|
||||
|
||||
const TeamList& World::GetTeams() const {
|
||||
return m_Game->GetTeams();
|
||||
return m_Game->GetTeams();
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -5,73 +5,73 @@ namespace td {
|
||||
namespace client {
|
||||
|
||||
bool Client::Connect(const network::IPAddresses& addresses, std::uint16_t port) {
|
||||
for (const network::IPAddress& address : addresses) {
|
||||
if (address.IsValid() && m_Connexion.Connect(address.ToString(), port)) {
|
||||
m_Connected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
utils::LOGE("Failed to connect !");
|
||||
return false;
|
||||
for (const network::IPAddress& address : addresses) {
|
||||
if (address.IsValid() && m_Connexion.Connect(address.ToString(), port)) {
|
||||
m_Connected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
utils::LOGE("Failed to connect !");
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::SelectTeam(game::TeamColor team) {
|
||||
if (!m_Connected)
|
||||
return;
|
||||
if (!m_Connected)
|
||||
return;
|
||||
|
||||
protocol::SelectTeamPacket packet(team);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::SelectTeamPacket packet(team);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::CloseConnection() {
|
||||
if (!m_Connected)
|
||||
return;
|
||||
if (!m_Connected)
|
||||
return;
|
||||
|
||||
m_Connected = false;
|
||||
m_Connected = false;
|
||||
|
||||
protocol::DisconnectPacket packet;
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::DisconnectPacket packet;
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::Tick(std::uint64_t delta) {
|
||||
if (!m_Connected)
|
||||
return;
|
||||
m_Connected = m_Connexion.UpdateSocket();
|
||||
if (!m_Connected) {
|
||||
utils::LOG(utils::format("Disconnected ! (Reason : %s)", m_Connexion.GetDisconnectReason().c_str()));
|
||||
Reset();
|
||||
} else {
|
||||
m_Game->Tick(delta);
|
||||
}
|
||||
if (!m_Connected)
|
||||
return;
|
||||
m_Connected = m_Connexion.UpdateSocket();
|
||||
if (!m_Connected) {
|
||||
utils::LOG(utils::format("Disconnected ! (Reason : %s)", m_Connexion.GetDisconnectReason().c_str()));
|
||||
Reset();
|
||||
} else {
|
||||
m_Game->Tick(delta);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Render() {
|
||||
m_Game->RenderWorld();
|
||||
m_Game->RenderWorld();
|
||||
}
|
||||
|
||||
void Client::Reset() {
|
||||
m_Game.reset(0);
|
||||
m_Game = std::make_unique<ClientGame>(this);
|
||||
m_Game.reset(0);
|
||||
m_Game = std::make_unique<ClientGame>(this);
|
||||
}
|
||||
|
||||
void Client::SendMobs(const std::vector<protocol::MobSend>& mobSends) {
|
||||
protocol::SendMobsPacket packet(mobSends);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::SendMobsPacket packet(mobSends);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::PlaceTower(game::TowerType type, const Vec2f& position) {
|
||||
protocol::PlaceTowerPacket packet(position.x, position.y, type);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::PlaceTowerPacket packet(position.x, position.y, type);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::UpgradeTower(game::TowerID tower, game::TowerLevel level) {
|
||||
protocol::UpgradeTowerPacket packet(tower, level);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::UpgradeTowerPacket packet(tower, level);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::RemoveTower(game::TowerID tower) {
|
||||
protocol::RemoveTowerPacket packet(tower);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
protocol::RemoveTowerPacket packet(tower);
|
||||
m_Connexion.SendPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -5,43 +5,43 @@ namespace td {
|
||||
namespace client {
|
||||
|
||||
ClientConnexion::ClientConnexion() : Connexion(&m_Dispatcher), m_ServerTPS(0) {
|
||||
RegisterHandlers();
|
||||
RegisterHandlers();
|
||||
}
|
||||
|
||||
void ClientConnexion::RegisterHandlers() {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ServerTps, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ServerTps, this);
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
|
||||
protocol::KeepAlivePacket keepAlivePacket(packet->GetAliveID());
|
||||
SendPacket(&keepAlivePacket);
|
||||
protocol::KeepAlivePacket keepAlivePacket(packet->GetAliveID());
|
||||
SendPacket(&keepAlivePacket);
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::ConnexionInfoPacket* packet) {
|
||||
m_ConnectionID = packet->GetConnectionID();
|
||||
Login();
|
||||
m_ConnectionID = packet->GetConnectionID();
|
||||
Login();
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::ServerTpsPacket* packet) {
|
||||
m_ServerTPS = packet->GetTPS();
|
||||
m_Ping = utils::GetTime() - packet->GetPacketSendTime();
|
||||
m_ServerTPS = packet->GetTPS();
|
||||
m_Ping = utils::GetTime() - packet->GetPacketSendTime();
|
||||
}
|
||||
|
||||
void ClientConnexion::Login() {
|
||||
td::protocol::PlayerLoginPacket loginPacket("Persson" + std::to_string(m_ConnectionID));
|
||||
SendPacket(&loginPacket);
|
||||
td::protocol::PlayerLoginPacket loginPacket("Persson" + std::to_string(m_ConnectionID));
|
||||
SendPacket(&loginPacket);
|
||||
}
|
||||
|
||||
bool ClientConnexion::UpdateSocket() {
|
||||
return Connexion::UpdateSocket();
|
||||
return Connexion::UpdateSocket();
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::DisconnectPacket* packet) {
|
||||
m_DisconnectReason = packet->GetReason();
|
||||
CloseConnection();
|
||||
m_DisconnectReason = packet->GetReason();
|
||||
CloseConnection();
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -8,110 +8,110 @@ namespace client {
|
||||
ClientGame::ClientGame(Client* client) : protocol::PacketHandler(client->GetConnexion().GetDispatcher()),
|
||||
game::Game(&m_WorldClient), m_Client(client), m_Renderer(client->GetRenderer()), m_WorldClient(this),
|
||||
m_WorldRenderer(&m_WorldClient, this) {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerJoin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerList, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLeave, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdatePlayerTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateLobbyTime, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateGameState, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMoney, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateEXP, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerJoin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerList, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLeave, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdatePlayerTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateLobbyTime, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateGameState, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMoney, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateEXP, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
|
||||
}
|
||||
|
||||
ClientGame::~ClientGame() {
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
}
|
||||
|
||||
void ClientGame::Tick(std::uint64_t delta) {
|
||||
game::Game::Tick(delta);
|
||||
m_WorldRenderer.Update();
|
||||
if (m_GameState == game::GameState::Lobby && m_LobbyTime > 0) {
|
||||
m_LobbyTime -= delta;
|
||||
}
|
||||
game::Game::Tick(delta);
|
||||
m_WorldRenderer.Update();
|
||||
if (m_GameState == game::GameState::Lobby && m_LobbyTime > 0) {
|
||||
m_LobbyTime -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerJoinPacket* packet) {
|
||||
game::Player player(packet->GetPlayerID());
|
||||
player.SetName(packet->GetPlayerName());
|
||||
game::Player player(packet->GetPlayerID());
|
||||
player.SetName(packet->GetPlayerName());
|
||||
|
||||
m_Players.insert({ player.GetID(), player });
|
||||
m_Players.insert({ player.GetID(), player });
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerLeavePacket* packet) {
|
||||
game::Player* player = &m_Players[packet->GetPlayerID()];
|
||||
if (player->GetTeamColor() != game::TeamColor::None) {
|
||||
m_Teams[(std::size_t)player->GetTeamColor()].RemovePlayer(player);
|
||||
}
|
||||
m_Players.erase(player->GetID());
|
||||
game::Player* player = &m_Players[packet->GetPlayerID()];
|
||||
if (player->GetTeamColor() != game::TeamColor::None) {
|
||||
m_Teams[(std::size_t)player->GetTeamColor()].RemovePlayer(player);
|
||||
}
|
||||
m_Players.erase(player->GetID());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerListPacket* packet) {
|
||||
for (auto pair : packet->GetPlayers()) {
|
||||
std::uint8_t playerID = pair.first;
|
||||
protocol::PlayerInfo playerInfo = pair.second;
|
||||
game::Player player(playerID);
|
||||
player.SetName(playerInfo.name);
|
||||
player.SetTeamColor(playerInfo.team);
|
||||
m_Players.insert({ playerID, player });
|
||||
if (player.GetTeamColor() != game::TeamColor::None) {
|
||||
m_Teams[(std::size_t)player.GetTeamColor()].AddPlayer(&m_Players[playerID]);
|
||||
}
|
||||
}
|
||||
m_Player = &m_Players[m_ConnexionID];
|
||||
for (auto pair : packet->GetPlayers()) {
|
||||
std::uint8_t playerID = pair.first;
|
||||
protocol::PlayerInfo playerInfo = pair.second;
|
||||
game::Player player(playerID);
|
||||
player.SetName(playerInfo.name);
|
||||
player.SetTeamColor(playerInfo.team);
|
||||
m_Players.insert({ playerID, player });
|
||||
if (player.GetTeamColor() != game::TeamColor::None) {
|
||||
m_Teams[(std::size_t)player.GetTeamColor()].AddPlayer(&m_Players[playerID]);
|
||||
}
|
||||
}
|
||||
m_Player = &m_Players[m_ConnexionID];
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdatePlayerTeamPacket* packet) {
|
||||
game::Player* player = &m_Players[packet->GetPlayerID()];
|
||||
if (player->GetTeamColor() == game::TeamColor::None) { //join a team
|
||||
GetTeam(packet->GetSelectedTeam()).AddPlayer(player);
|
||||
} else if (packet->GetSelectedTeam() == game::TeamColor::None) { // leave a team
|
||||
GetTeam(player->GetTeamColor()).RemovePlayer(player);
|
||||
} else { // change team
|
||||
GetTeam(player->GetTeamColor()).RemovePlayer(player);
|
||||
GetTeam(packet->GetSelectedTeam()).AddPlayer(player);
|
||||
}
|
||||
player->SetTeamColor(packet->GetSelectedTeam());
|
||||
game::Player* player = &m_Players[packet->GetPlayerID()];
|
||||
if (player->GetTeamColor() == game::TeamColor::None) { //join a team
|
||||
GetTeam(packet->GetSelectedTeam()).AddPlayer(player);
|
||||
} else if (packet->GetSelectedTeam() == game::TeamColor::None) { // leave a team
|
||||
GetTeam(player->GetTeamColor()).RemovePlayer(player);
|
||||
} else { // change team
|
||||
GetTeam(player->GetTeamColor()).RemovePlayer(player);
|
||||
GetTeam(packet->GetSelectedTeam()).AddPlayer(player);
|
||||
}
|
||||
player->SetTeamColor(packet->GetSelectedTeam());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateGameStatePacket* packet) {
|
||||
SetGameState(packet->GetGameState());
|
||||
SetGameState(packet->GetGameState());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::ConnexionInfoPacket* packet) {
|
||||
m_ConnexionID = packet->GetConnectionID();
|
||||
m_ConnexionID = packet->GetConnectionID();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateLobbyTimePacket* packet) {
|
||||
m_LobbyTime = packet->GetRemainingTime();
|
||||
m_LobbyTime = packet->GetRemainingTime();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateMoneyPacket* packet) {
|
||||
m_Player->SetGold(packet->GetGold());
|
||||
m_Player->SetGold(packet->GetGold());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateExpPacket* packet) {
|
||||
m_Player->SetExp(packet->GetExp());
|
||||
m_Player->SetExp(packet->GetExp());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::DisconnectPacket* packet) {
|
||||
m_GameState = game::GameState::Disconnected;
|
||||
m_Renderer->SetBackgroundColor({ 0, 0, 0 });
|
||||
m_GameState = game::GameState::Disconnected;
|
||||
m_Renderer->SetBackgroundColor({ 0, 0, 0 });
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::WorldDataPacket* packet) {
|
||||
m_WorldRenderer.LoadModels();
|
||||
// set cam pos to player spawn
|
||||
const game::Spawn& spawn = m_World->GetTeam(m_Player->GetTeamColor()).GetSpawn();
|
||||
m_WorldRenderer.SetCamPos(spawn.GetCenterX(), spawn.GetCenterY());
|
||||
m_WorldRenderer.LoadModels();
|
||||
// set cam pos to player spawn
|
||||
const game::Spawn& spawn = m_World->GetTeam(m_Player->GetTeamColor()).GetSpawn();
|
||||
m_WorldRenderer.SetCamPos(spawn.GetCenterX(), spawn.GetCenterY());
|
||||
}
|
||||
|
||||
void ClientGame::RenderWorld() {
|
||||
if (m_GameState == game::GameState::Game || m_GameState == game::GameState::EndGame) {
|
||||
m_WorldRenderer.Render();
|
||||
}
|
||||
if (m_GameState == game::GameState::Game || m_GameState == game::GameState::EndGame) {
|
||||
m_WorldRenderer.Render();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -7,69 +7,69 @@ namespace td {
|
||||
namespace client {
|
||||
|
||||
WorldClient::WorldClient(ClientGame* game) : game::World(game), protocol::PacketHandler(game->GetDispatcher()), m_Game(game) {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldAddTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldBeginData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateCastleLife, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMobStates, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldAddTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldBeginData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, 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) {
|
||||
LoadMap(packet);
|
||||
if (m_Game->GetGameState() == game::GameState::Game) {
|
||||
const Color& backgroundColor = GetBackgroundColor();
|
||||
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) });
|
||||
}
|
||||
LoadMap(packet);
|
||||
if (m_Game->GetGameState() == game::GameState::Game) {
|
||||
const Color& backgroundColor = GetBackgroundColor();
|
||||
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) });
|
||||
}
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(const protocol::WorldDataPacket* packet) {
|
||||
LoadMap(packet);
|
||||
LoadMap(packet);
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(const protocol::SpawnMobPacket* packet) {
|
||||
SpawnMobAt(packet->GetMobID(), packet->GetMobType(), packet->GetMobLevel(), packet->GetSender(),
|
||||
packet->GetMobX(), packet->GetMobY(), packet->GetMobDirection());
|
||||
SpawnMobAt(packet->GetMobID(), packet->GetMobType(), packet->GetMobLevel(), packet->GetSender(),
|
||||
packet->GetMobX(), packet->GetMobY(), packet->GetMobDirection());
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(const protocol::UpgradeTowerPacket* packet) {
|
||||
game::TowerPtr tower = GetTowerById(packet->GetTowerID());
|
||||
if (tower == nullptr) return; // this should not happen but who knows ?
|
||||
tower->Upgrade(packet->GetTowerLevel().GetLevel(), packet->GetTowerLevel().GetPath());
|
||||
game::TowerPtr tower = GetTowerById(packet->GetTowerID());
|
||||
if (tower == nullptr) return; // this should not happen but who knows ?
|
||||
tower->Upgrade(packet->GetTowerLevel().GetLevel(), packet->GetTowerLevel().GetPath());
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(const protocol::WorldAddTowerPacket* packet) {
|
||||
game::TowerPtr newTower = PlaceTowerAt(packet->GetTowerID(), packet->GetTowerType(), packet->GetTowerX(), packet->GetTowerY(), packet->GetBuilder());
|
||||
game::TowerPtr newTower = PlaceTowerAt(packet->GetTowerID(), packet->GetTowerType(), packet->GetTowerX(), packet->GetTowerY(), packet->GetBuilder());
|
||||
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnTowerAdd, newTower);
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnTowerAdd, newTower);
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(const protocol::RemoveTowerPacket* packet) {
|
||||
game::TowerPtr tower = RemoveTower(packet->GetTowerID());
|
||||
game::TowerPtr tower = RemoveTower(packet->GetTowerID());
|
||||
|
||||
if (tower != nullptr) {
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnTowerRemove, tower);
|
||||
}
|
||||
if (tower != nullptr) {
|
||||
GetWorldNotifier().NotifyListeners(&WorldListener::OnTowerRemove, tower);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
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());
|
||||
GetTeam(packet->GetTeamColor()).GetCastle().SetLife(packet->GetCastleLife());
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -13,17 +13,17 @@ namespace td {
|
||||
namespace server {
|
||||
|
||||
/*static constexpr std::uint8_t timeNotifications[] = {
|
||||
2 * 60, // 2 min
|
||||
60 + 30, // 1 min 30 s
|
||||
60, // 1 min
|
||||
30, // 30 s
|
||||
15, // 15 s
|
||||
10, // 10 s
|
||||
5, // 5 s
|
||||
4, // 4 s
|
||||
3, // 3 s
|
||||
2, // 2 s
|
||||
1, // 1 s
|
||||
2 * 60, // 2 min
|
||||
60 + 30, // 1 min 30 s
|
||||
60, // 1 min
|
||||
30, // 30 s
|
||||
15, // 15 s
|
||||
10, // 10 s
|
||||
5, // 5 s
|
||||
4, // 4 s
|
||||
3, // 3 s
|
||||
2, // 2 s
|
||||
1, // 1 s
|
||||
};*/
|
||||
|
||||
Lobby::Lobby(Server* server) : m_Server(server), m_Timer(1000, std::bind(&Lobby::SendTimeRemaining, this)) {
|
||||
@@ -31,50 +31,50 @@ Lobby::Lobby(Server* server) : m_Server(server), m_Timer(1000, std::bind(&Lobby:
|
||||
}
|
||||
|
||||
void Lobby::Tick() {
|
||||
if (m_GameStarted || m_StartTimerTime == 0)
|
||||
return;
|
||||
if (m_GameStarted || m_StartTimerTime == 0)
|
||||
return;
|
||||
|
||||
if (utils::GetTime() - m_StartTimerTime >= LobbyWaitingTime) {
|
||||
m_Server->GetGame().NotifyListeners(&game::GameListener::OnGameBegin);
|
||||
m_GameStarted = true;
|
||||
return;
|
||||
}
|
||||
if (utils::GetTime() - m_StartTimerTime >= LobbyWaitingTime) {
|
||||
m_Server->GetGame().NotifyListeners(&game::GameListener::OnGameBegin);
|
||||
m_GameStarted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_Timer.Update();
|
||||
m_Timer.Update();
|
||||
}
|
||||
|
||||
void Lobby::SendTimeRemaining() {
|
||||
protocol::UpdateLobbyTimePacket packet(LobbyWaitingTime - (utils::GetTime() - m_StartTimerTime)); // converting second to millis
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
protocol::UpdateLobbyTimePacket packet(LobbyWaitingTime - (utils::GetTime() - m_StartTimerTime)); // converting second to millis
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerJoin(std::uint8_t playerID) {
|
||||
if (m_GameStarted)
|
||||
return;
|
||||
utils::LOG("(Server) Player Joined Lobby !");
|
||||
m_Players.push_back(playerID);
|
||||
if (m_Players.size() == MIN_PLAYER_WAITING) { // start timer if a second player join the match
|
||||
m_StartTimerTime = utils::GetTime();
|
||||
m_Timer.Reset();
|
||||
SendTimeRemaining();
|
||||
}
|
||||
if (m_GameStarted)
|
||||
return;
|
||||
utils::LOG("(Server) Player Joined Lobby !");
|
||||
m_Players.push_back(playerID);
|
||||
if (m_Players.size() == MIN_PLAYER_WAITING) { // start timer if a second player join the match
|
||||
m_StartTimerTime = utils::GetTime();
|
||||
m_Timer.Reset();
|
||||
SendTimeRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerLeave(std::uint8_t playerID) {
|
||||
if (m_GameStarted)
|
||||
return;
|
||||
utils::LOG("(Server) Player Leaved Lobby !");
|
||||
if (m_GameStarted)
|
||||
return;
|
||||
utils::LOG("(Server) Player Leaved Lobby !");
|
||||
|
||||
auto it = std::find(m_Players.begin(), m_Players.end(), playerID);
|
||||
if (it == m_Players.end())
|
||||
return;
|
||||
m_Players.erase(it);
|
||||
auto it = std::find(m_Players.begin(), m_Players.end(), playerID);
|
||||
if (it == m_Players.end())
|
||||
return;
|
||||
m_Players.erase(it);
|
||||
|
||||
if (m_Players.size() == 1) {
|
||||
protocol::UpdateLobbyTimePacket packet(0);
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
m_StartTimerTime = 0; // reset timer if there is only one player left
|
||||
}
|
||||
if (m_Players.size() == 1) {
|
||||
protocol::UpdateLobbyTimePacket packet(0);
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
m_StartTimerTime = 0; // reset timer if there is only one player left
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -7,139 +7,139 @@ namespace td {
|
||||
namespace server {
|
||||
|
||||
Server::Server(const std::string& worldFilePath) : m_ServerRunning(false) {
|
||||
m_Game.GetWorld()->LoadMapFromFile(worldFilePath);
|
||||
m_Game.GetWorld()->LoadMapFromFile(worldFilePath);
|
||||
}
|
||||
|
||||
Server::~Server() {
|
||||
if (m_Thread.joinable())
|
||||
m_Thread.join();
|
||||
if (m_Thread.joinable())
|
||||
m_Thread.join();
|
||||
}
|
||||
|
||||
void Server::StartThread() {
|
||||
m_Thread = std::thread([this]() {
|
||||
std::uint64_t lastTime = td::utils::GetTime();
|
||||
while (m_ServerRunning) {
|
||||
std::uint64_t time = td::utils::GetTime();
|
||||
m_Thread = std::thread([this]() {
|
||||
std::uint64_t lastTime = td::utils::GetTime();
|
||||
while (m_ServerRunning) {
|
||||
std::uint64_t time = td::utils::GetTime();
|
||||
|
||||
std::uint64_t delta = time - lastTime;
|
||||
std::uint64_t delta = time - lastTime;
|
||||
|
||||
if (delta >= SERVER_TICK) {
|
||||
Tick(delta);
|
||||
lastTime = td::utils::GetTime();
|
||||
std::uint64_t sleepTime = SERVER_TICK - (delta - SERVER_TICK);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
|
||||
}
|
||||
if (delta >= SERVER_TICK) {
|
||||
Tick(delta);
|
||||
lastTime = td::utils::GetTime();
|
||||
std::uint64_t sleepTime = SERVER_TICK - (delta - SERVER_TICK);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
|
||||
}
|
||||
|
||||
}
|
||||
Clean();
|
||||
});
|
||||
}
|
||||
Clean();
|
||||
});
|
||||
}
|
||||
|
||||
void Server::Close() {
|
||||
StopThread();
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void Server::StopThread() {
|
||||
m_ServerRunning = false;
|
||||
m_ServerRunning = false;
|
||||
}
|
||||
|
||||
bool Server::Start(std::uint16_t port) {
|
||||
if (!m_Listener.Listen(port, 10)) {
|
||||
utils::LOGE(utils::format("Failed to bind port %u !", port));
|
||||
return false;
|
||||
}
|
||||
if (!m_Listener.SetBlocking(false)) {
|
||||
utils::LOGE("Failed to block server socket !");
|
||||
return false;
|
||||
}
|
||||
utils::LOG(utils::format("Server started at port %u !", port));
|
||||
m_TickCounter.Reset();
|
||||
m_ServerRunning = true;
|
||||
StartThread();
|
||||
return true;
|
||||
if (!m_Listener.Listen(port, 10)) {
|
||||
utils::LOGE(utils::format("Failed to bind port %u !", port));
|
||||
return false;
|
||||
}
|
||||
if (!m_Listener.SetBlocking(false)) {
|
||||
utils::LOGE("Failed to block server socket !");
|
||||
return false;
|
||||
}
|
||||
utils::LOG(utils::format("Server started at port %u !", port));
|
||||
m_TickCounter.Reset();
|
||||
m_ServerRunning = true;
|
||||
StartThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::Clean() {
|
||||
m_Listener.Close();
|
||||
m_Listener.Destroy();
|
||||
m_Listener.Close();
|
||||
m_Listener.Destroy();
|
||||
|
||||
m_Connections.clear();
|
||||
GetPlayers().clear();
|
||||
m_Connections.clear();
|
||||
GetPlayers().clear();
|
||||
|
||||
utils::LOG("Server successfully stopped !");
|
||||
utils::LOG("Server successfully stopped !");
|
||||
}
|
||||
|
||||
void Server::Stop() {
|
||||
if (!m_ServerRunning)
|
||||
return;
|
||||
if (!m_ServerRunning)
|
||||
return;
|
||||
|
||||
protocol::DisconnectPacket packet("Server closed");
|
||||
BroadcastPacket(&packet);
|
||||
protocol::DisconnectPacket packet("Server closed");
|
||||
BroadcastPacket(&packet);
|
||||
|
||||
StopThread();
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void Server::Tick(std::uint64_t delta) {
|
||||
Accept();
|
||||
UpdateSockets();
|
||||
m_Lobby.Tick();
|
||||
m_Game.Tick(delta);
|
||||
if (m_TickCounter.Update()) {
|
||||
protocol::ServerTpsPacket packet(m_TickCounter.GetTPS(), utils::GetTime());
|
||||
BroadcastPacket(&packet);
|
||||
}
|
||||
Accept();
|
||||
UpdateSockets();
|
||||
m_Lobby.Tick();
|
||||
m_Game.Tick(delta);
|
||||
if (m_TickCounter.Update()) {
|
||||
protocol::ServerTpsPacket packet(m_TickCounter.GetTPS(), utils::GetTime());
|
||||
BroadcastPacket(&packet);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::Accept() {
|
||||
static std::uint8_t newPlayerID = 0;
|
||||
network::TCPSocket newSocket;
|
||||
if (m_Listener.Accept(newSocket)) {
|
||||
ServerConnexion con(newSocket, newPlayerID);
|
||||
m_Connections.insert(std::move(ConnexionMap::value_type{ newPlayerID, std::move(con) }));
|
||||
OnPlayerJoin(newPlayerID);
|
||||
m_Connections[newPlayerID].SetServer(this);
|
||||
newPlayerID++;
|
||||
}
|
||||
static std::uint8_t newPlayerID = 0;
|
||||
network::TCPSocket newSocket;
|
||||
if (m_Listener.Accept(newSocket)) {
|
||||
ServerConnexion con(newSocket, newPlayerID);
|
||||
m_Connections.insert(std::move(ConnexionMap::value_type{ newPlayerID, std::move(con) }));
|
||||
OnPlayerJoin(newPlayerID);
|
||||
m_Connections[newPlayerID].SetServer(this);
|
||||
newPlayerID++;
|
||||
}
|
||||
}
|
||||
|
||||
void Server::UpdateSockets() {
|
||||
std::int16_t closedConnexionID = -1;
|
||||
for (auto& connection : m_Connections) {
|
||||
ServerConnexion& con = connection.second;
|
||||
if (con.GetSocketStatus() != network::Socket::Status::Connected) {
|
||||
closedConnexionID = connection.first;
|
||||
} else {
|
||||
con.UpdateSocket();
|
||||
}
|
||||
}
|
||||
if (closedConnexionID != -1) {
|
||||
RemoveConnexion(closedConnexionID);
|
||||
}
|
||||
std::int16_t closedConnexionID = -1;
|
||||
for (auto& connection : m_Connections) {
|
||||
ServerConnexion& con = connection.second;
|
||||
if (con.GetSocketStatus() != network::Socket::Status::Connected) {
|
||||
closedConnexionID = connection.first;
|
||||
} else {
|
||||
con.UpdateSocket();
|
||||
}
|
||||
}
|
||||
if (closedConnexionID != -1) {
|
||||
RemoveConnexion(closedConnexionID);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::BroadcastPacket(const protocol::Packet* packet) {
|
||||
for (auto& connection : m_Connections) {
|
||||
ServerConnexion& con = connection.second;
|
||||
con.SendPacket(packet);
|
||||
}
|
||||
for (auto& connection : m_Connections) {
|
||||
ServerConnexion& con = connection.second;
|
||||
con.SendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::RemoveConnexion(std::uint8_t connexionID) {
|
||||
GetPlayers().erase(GetPlayers().find(connexionID));
|
||||
m_Connections.erase(connexionID);
|
||||
m_Lobby.OnPlayerLeave(connexionID);
|
||||
OnPlayerLeave(connexionID);
|
||||
GetPlayers().erase(GetPlayers().find(connexionID));
|
||||
m_Connections.erase(connexionID);
|
||||
m_Lobby.OnPlayerLeave(connexionID);
|
||||
OnPlayerLeave(connexionID);
|
||||
}
|
||||
|
||||
void Server::OnPlayerJoin(std::uint8_t id) {
|
||||
m_Lobby.OnPlayerJoin(id);
|
||||
m_Lobby.OnPlayerJoin(id);
|
||||
|
||||
GetPlayers().insert({ id, game::Player{id} });
|
||||
GetPlayers().insert({ id, game::Player{id} });
|
||||
}
|
||||
|
||||
void Server::OnPlayerLeave(std::uint8_t id) {
|
||||
protocol::PlayerLeavePacket packet(id);
|
||||
BroadcastPacket(&packet);
|
||||
protocol::PlayerLeavePacket packet(id);
|
||||
BroadcastPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace td {
|
||||
namespace server {
|
||||
|
||||
/*
|
||||
NEVER TRUST USER INPUT
|
||||
NEVER TRUST USER INPUT
|
||||
*/
|
||||
|
||||
|
||||
@@ -23,176 +23,176 @@ ServerConnexion::ServerConnexion() : m_Player(0) {
|
||||
}
|
||||
|
||||
ServerConnexion::ServerConnexion(network::TCPSocket& socket, std::uint8_t id) : Connexion::Connexion(&m_Dispatcher, socket), m_ID(id), m_Player(0) {
|
||||
Connexion::UpdateSocket();
|
||||
Connexion::UpdateSocket();
|
||||
}
|
||||
|
||||
ServerConnexion::ServerConnexion(ServerConnexion&& move) : Connexion::Connexion(std::move(move)), m_Server(move.m_Server),
|
||||
m_ID(move.m_ID), m_KeepAlive(move.m_KeepAlive), m_Player(move.m_Player) {
|
||||
|
||||
move.m_Server = nullptr;
|
||||
RegisterHandlers();
|
||||
move.m_Server = nullptr;
|
||||
RegisterHandlers();
|
||||
}
|
||||
|
||||
void ServerConnexion::RegisterHandlers() {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
|
||||
}
|
||||
|
||||
bool ServerConnexion::UpdateSocket() {
|
||||
CheckKeepAlive();
|
||||
return Connexion::UpdateSocket();
|
||||
CheckKeepAlive();
|
||||
return Connexion::UpdateSocket();
|
||||
}
|
||||
|
||||
void ServerConnexion::CheckKeepAlive() {
|
||||
std::uint64_t time = utils::GetTime();
|
||||
if (time - m_KeepAlive.sendTime > KEEP_ALIVE_TIMEOUT) {
|
||||
if (m_KeepAlive.recievedResponse) {
|
||||
SendKeepAlive();
|
||||
} else {
|
||||
protocol::DisconnectPacket packet("Time out");
|
||||
SendPacket(&packet);
|
||||
CloseConnection();
|
||||
}
|
||||
}
|
||||
std::uint64_t time = utils::GetTime();
|
||||
if (time - m_KeepAlive.sendTime > KEEP_ALIVE_TIMEOUT) {
|
||||
if (m_KeepAlive.recievedResponse) {
|
||||
SendKeepAlive();
|
||||
} else {
|
||||
protocol::DisconnectPacket packet("Time out");
|
||||
SendPacket(&packet);
|
||||
CloseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::SendKeepAlive() {
|
||||
m_KeepAlive.keepAliveID = utils::GetRandomInt<std::uint64_t>(0, RAND_MAX);
|
||||
m_KeepAlive.recievedResponse = false;
|
||||
m_KeepAlive.keepAliveID = utils::GetRandomInt<std::uint64_t>(0, RAND_MAX);
|
||||
m_KeepAlive.recievedResponse = false;
|
||||
|
||||
protocol::KeepAlivePacket keepAlivePacket(m_KeepAlive.keepAliveID);
|
||||
SendPacket(&keepAlivePacket);
|
||||
protocol::KeepAlivePacket keepAlivePacket(m_KeepAlive.keepAliveID);
|
||||
SendPacket(&keepAlivePacket);
|
||||
|
||||
std::uint64_t time = utils::GetTime();
|
||||
m_KeepAlive.sendTime = time;
|
||||
std::uint64_t time = utils::GetTime();
|
||||
m_KeepAlive.sendTime = time;
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::PlayerLoginPacket* packet) {
|
||||
if (m_Player->GetName().empty() && !packet->GetPlayerName().empty()) {
|
||||
m_Player->SetName(packet->GetPlayerName());
|
||||
if (m_Player->GetName().empty() && !packet->GetPlayerName().empty()) {
|
||||
m_Player->SetName(packet->GetPlayerName());
|
||||
|
||||
protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->GetName());
|
||||
m_Server->BroadcastPacket(&joinPacket);
|
||||
protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->GetName());
|
||||
m_Server->BroadcastPacket(&joinPacket);
|
||||
|
||||
std::map<std::uint8_t, protocol::PlayerInfo> playerNames;
|
||||
for (const auto& pair : m_Server->GetPlayers()) {
|
||||
const game::Player& player = pair.second;
|
||||
if (!player.GetName().empty()) {
|
||||
protocol::PlayerInfo playerInfo;
|
||||
playerInfo.name = player.GetName();
|
||||
playerInfo.team = player.GetTeamColor();
|
||||
playerNames.insert({ player.GetID(), playerInfo });
|
||||
}
|
||||
}
|
||||
std::map<std::uint8_t, protocol::PlayerInfo> playerNames;
|
||||
for (const auto& pair : m_Server->GetPlayers()) {
|
||||
const game::Player& player = pair.second;
|
||||
if (!player.GetName().empty()) {
|
||||
protocol::PlayerInfo playerInfo;
|
||||
playerInfo.name = player.GetName();
|
||||
playerInfo.team = player.GetTeamColor();
|
||||
playerNames.insert({ player.GetID(), playerInfo });
|
||||
}
|
||||
}
|
||||
|
||||
protocol::PlayerListPacket listPacket(playerNames);
|
||||
SendPacket(&listPacket);
|
||||
}
|
||||
protocol::PlayerListPacket listPacket(playerNames);
|
||||
SendPacket(&listPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::SelectTeamPacket* packet) {
|
||||
if (m_Server->GetGame().GetGameState() != game::GameState::Lobby)
|
||||
return;
|
||||
if (static_cast<std::int8_t>(packet->GetSelectedTeam()) >= -1 || static_cast<std::int8_t>(packet->GetSelectedTeam()) <= 1) {
|
||||
if (m_Player->GetTeamColor() == game::TeamColor::None) { // join a team
|
||||
m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player);
|
||||
} else if (packet->GetSelectedTeam() == game::TeamColor::None) { // leave a team
|
||||
m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player);
|
||||
m_Player->SetTeamColor(game::TeamColor::None);
|
||||
} else { // change team
|
||||
m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player);
|
||||
m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player);
|
||||
}
|
||||
m_Player->SetTeamColor(packet->GetSelectedTeam());
|
||||
protocol::UpdatePlayerTeamPacket updateTeamPacket(m_ID, packet->GetSelectedTeam());
|
||||
m_Server->BroadcastPacket(&updateTeamPacket);
|
||||
}
|
||||
if (m_Server->GetGame().GetGameState() != game::GameState::Lobby)
|
||||
return;
|
||||
if (static_cast<std::int8_t>(packet->GetSelectedTeam()) >= -1 || static_cast<std::int8_t>(packet->GetSelectedTeam()) <= 1) {
|
||||
if (m_Player->GetTeamColor() == game::TeamColor::None) { // join a team
|
||||
m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player);
|
||||
} else if (packet->GetSelectedTeam() == game::TeamColor::None) { // leave a team
|
||||
m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player);
|
||||
m_Player->SetTeamColor(game::TeamColor::None);
|
||||
} else { // change team
|
||||
m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player);
|
||||
m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player);
|
||||
}
|
||||
m_Player->SetTeamColor(packet->GetSelectedTeam());
|
||||
protocol::UpdatePlayerTeamPacket updateTeamPacket(m_ID, packet->GetSelectedTeam());
|
||||
m_Server->BroadcastPacket(&updateTeamPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
|
||||
if (packet->GetAliveID() == m_KeepAlive.keepAliveID)
|
||||
m_KeepAlive.recievedResponse = true;
|
||||
if (packet->GetAliveID() == m_KeepAlive.keepAliveID)
|
||||
m_KeepAlive.recievedResponse = true;
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::DisconnectPacket* packet) {
|
||||
CloseConnection();
|
||||
CloseConnection();
|
||||
}
|
||||
|
||||
void ServerConnexion::SetServer(Server* server) {
|
||||
m_Server = server;
|
||||
m_Player = &m_Server->GetPlayers().at(m_ID);
|
||||
InitConnection();
|
||||
SendKeepAlive();
|
||||
m_Server = server;
|
||||
m_Player = &m_Server->GetPlayers().at(m_ID);
|
||||
InitConnection();
|
||||
SendKeepAlive();
|
||||
}
|
||||
|
||||
void ServerConnexion::InitConnection() {
|
||||
protocol::UpdateGameStatePacket statePacket(m_Server->GetGame().GetGameState());
|
||||
SendPacket(&statePacket);
|
||||
protocol::UpdateGameStatePacket statePacket(m_Server->GetGame().GetGameState());
|
||||
SendPacket(&statePacket);
|
||||
|
||||
protocol::ConnexionInfoPacket conPacket(m_ID);
|
||||
SendPacket(&conPacket);
|
||||
protocol::ConnexionInfoPacket conPacket(m_ID);
|
||||
SendPacket(&conPacket);
|
||||
|
||||
if (m_Server->GetGame().GetGameState() == game::GameState::Game) {
|
||||
protocol::WorldBeginDataPacket headerDataPacket(m_Server->GetGame().GetWorld());
|
||||
protocol::WorldBeginDataPacket dataPacket(m_Server->GetGame().GetWorld());
|
||||
SendPacket(&headerDataPacket);
|
||||
SendPacket(&dataPacket);
|
||||
}
|
||||
if (m_Server->GetGame().GetGameState() == game::GameState::Game) {
|
||||
protocol::WorldBeginDataPacket headerDataPacket(m_Server->GetGame().GetWorld());
|
||||
protocol::WorldBeginDataPacket dataPacket(m_Server->GetGame().GetWorld());
|
||||
SendPacket(&headerDataPacket);
|
||||
SendPacket(&dataPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::PlaceTowerPacket* packet) {
|
||||
game::TowerType towerType = packet->GetTowerType();
|
||||
const game::TowerInfo& towerInfo = game::GetTowerInfo(towerType);
|
||||
server::ServerWorld* world = m_Server->GetGame().GetServerWorld();
|
||||
game::TowerType towerType = packet->GetTowerType();
|
||||
const game::TowerInfo& towerInfo = game::GetTowerInfo(towerType);
|
||||
server::ServerWorld* world = m_Server->GetGame().GetServerWorld();
|
||||
|
||||
Vec2f towerPos = { static_cast<float>(packet->GetTowerX()), static_cast<float>(packet->GetTowerY()) };
|
||||
Vec2f towerPos = { static_cast<float>(packet->GetTowerX()), static_cast<float>(packet->GetTowerY()) };
|
||||
|
||||
if (!world->CanPlaceLittleTower(towerPos, m_ID))
|
||||
return;
|
||||
if (!world->CanPlaceLittleTower(towerPos, m_ID))
|
||||
return;
|
||||
|
||||
if (towerInfo.IsBigTower())
|
||||
if (!world->CanPlaceBigTower(towerPos, m_ID))
|
||||
return;
|
||||
if (towerInfo.IsBigTower())
|
||||
if (!world->CanPlaceBigTower(towerPos, m_ID))
|
||||
return;
|
||||
|
||||
game::TowerPtr tower = world->PlaceTowerAt(towerType, packet->GetTowerX(), packet->GetTowerY(), m_ID);
|
||||
game::TowerPtr tower = world->PlaceTowerAt(towerType, packet->GetTowerX(), packet->GetTowerY(), m_ID);
|
||||
|
||||
world->GetWorldNotifier().NotifyListeners(&game::WorldListener::OnTowerAdd, tower);
|
||||
world->GetWorldNotifier().NotifyListeners(&game::WorldListener::OnTowerAdd, tower);
|
||||
|
||||
protocol::WorldAddTowerPacket addTowerPacket(tower->GetID(), packet->GetTowerX(), packet->GetTowerY(), packet->GetTowerType(), m_ID);
|
||||
m_Server->BroadcastPacket(&addTowerPacket);
|
||||
protocol::WorldAddTowerPacket addTowerPacket(tower->GetID(), packet->GetTowerX(), packet->GetTowerY(), packet->GetTowerType(), m_ID);
|
||||
m_Server->BroadcastPacket(&addTowerPacket);
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::SendMobsPacket* packet) {
|
||||
const std::vector<protocol::MobSend>& mobSent = packet->GetMobSends();
|
||||
const std::vector<protocol::MobSend>& mobSent = packet->GetMobSends();
|
||||
|
||||
//TODO: verify the packet
|
||||
//TODO: verify the packet
|
||||
|
||||
for (protocol::MobSend mobSend : mobSent) {
|
||||
m_Server->GetGame().GetServerWorld()->SpawnMobs(mobSend.mobType, mobSend.mobLevel, m_ID, mobSend.mobCount);
|
||||
}
|
||||
for (protocol::MobSend mobSend : mobSent) {
|
||||
m_Server->GetGame().GetServerWorld()->SpawnMobs(mobSend.mobType, mobSend.mobLevel, m_ID, mobSend.mobCount);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::UpgradeTowerPacket* packet) {
|
||||
//TODO: verify the packet
|
||||
//TODO: verify the packet
|
||||
|
||||
m_Server->BroadcastPacket(packet);
|
||||
m_Server->BroadcastPacket(packet);
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::RemoveTowerPacket* packet) {
|
||||
//TODO: verify the packet
|
||||
//TODO: verify the packet
|
||||
|
||||
m_Server->BroadcastPacket(packet);
|
||||
m_Server->BroadcastPacket(packet);
|
||||
}
|
||||
|
||||
ServerConnexion::~ServerConnexion() {
|
||||
if (GetDispatcher() != nullptr)
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
if (GetDispatcher() != nullptr)
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -8,113 +8,113 @@ ServerGame::ServerGame(server::Server* server) : game::Game(&m_ServerWorld), m_S
|
||||
m_GoldMineTimer{ 1000, std::bind(&ServerGame::UpdateGoldMines, this) },
|
||||
m_MobStatesTimer{ 5000, std::bind(&ServerGame::UpdateMobStates, this) },
|
||||
m_EndGameCooldown{ 1000 * 10 } {
|
||||
BindListener(this);
|
||||
BindListener(this);
|
||||
}
|
||||
|
||||
void ServerGame::Tick(std::uint64_t delta) {
|
||||
if (m_GameState == game::GameState::Game) {
|
||||
Game::Tick(delta);
|
||||
m_MobStatesTimer.Update(delta);
|
||||
UpdatePlayerStats();
|
||||
} else if (m_GameState == game::GameState::EndGame) {
|
||||
if (m_EndGameCooldown.Update(delta)) {
|
||||
NotifyListeners(&game::GameListener::OnGameClose);
|
||||
}
|
||||
}
|
||||
if (m_GameState == game::GameState::Game) {
|
||||
Game::Tick(delta);
|
||||
m_MobStatesTimer.Update(delta);
|
||||
UpdatePlayerStats();
|
||||
} else if (m_GameState == game::GameState::EndGame) {
|
||||
if (m_EndGameCooldown.Update(delta)) {
|
||||
NotifyListeners(&game::GameListener::OnGameClose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::StartGame() {
|
||||
BalanceTeams();
|
||||
BalanceTeams();
|
||||
|
||||
protocol::WorldBeginDataPacket headerMapData(m_World);
|
||||
m_Server->BroadcastPacket(&headerMapData);
|
||||
protocol::WorldBeginDataPacket headerMapData(m_World);
|
||||
m_Server->BroadcastPacket(&headerMapData);
|
||||
|
||||
protocol::WorldDataPacket mapData(m_World);
|
||||
m_Server->BroadcastPacket(&mapData);
|
||||
protocol::WorldDataPacket mapData(m_World);
|
||||
m_Server->BroadcastPacket(&mapData);
|
||||
|
||||
InitPlayerStats();
|
||||
InitPlayerStats();
|
||||
|
||||
m_GameState = game::GameState::Game;
|
||||
m_GameState = game::GameState::Game;
|
||||
}
|
||||
|
||||
void ServerGame::InitPlayerStats() {
|
||||
static const unsigned int START_GOLD = 100;
|
||||
static const unsigned int START_EXP = 0;
|
||||
for (auto& [id, player] : m_Server->GetPlayers()) {
|
||||
player.SetGold(START_GOLD);
|
||||
player.SetExp(START_EXP);
|
||||
player.getUpgrades().SetGoldPerSecond(5);
|
||||
}
|
||||
static const unsigned int START_GOLD = 100;
|
||||
static const unsigned int START_EXP = 0;
|
||||
for (auto& [id, player] : m_Server->GetPlayers()) {
|
||||
player.SetGold(START_GOLD);
|
||||
player.SetExp(START_EXP);
|
||||
player.getUpgrades().SetGoldPerSecond(5);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::UpdatePlayerStats() {
|
||||
m_GoldMineTimer.Update();
|
||||
m_GoldMineTimer.Update();
|
||||
}
|
||||
|
||||
void ServerGame::UpdateGoldMines() {
|
||||
for (auto& [id, player] : m_Server->GetPlayers()) {
|
||||
player.AddGold(player.getUpgrades().GetGoldPerSecond());
|
||||
for (auto& [id, player] : m_Server->GetPlayers()) {
|
||||
player.AddGold(player.getUpgrades().GetGoldPerSecond());
|
||||
|
||||
// Update player money and exp every second
|
||||
protocol::UpdateMoneyPacket moneyPacket(player.GetGold());
|
||||
m_Server->GetConnexions()[player.GetID()].SendPacket(&moneyPacket);
|
||||
// Update player money and exp every second
|
||||
protocol::UpdateMoneyPacket moneyPacket(player.GetGold());
|
||||
m_Server->GetConnexions()[player.GetID()].SendPacket(&moneyPacket);
|
||||
|
||||
protocol::UpdateExpPacket expPacket(player.GetExp());
|
||||
m_Server->GetConnexions()[player.GetID()].SendPacket(&expPacket);
|
||||
}
|
||||
protocol::UpdateExpPacket expPacket(player.GetExp());
|
||||
m_Server->GetConnexions()[player.GetID()].SendPacket(&expPacket);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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() {
|
||||
for (auto& playerInfo : Game::m_Players) {
|
||||
game::Player& player = playerInfo.second;
|
||||
if (player.GetTeamColor() == game::TeamColor::None) {
|
||||
game::Team& redTeam = GetRedTeam();
|
||||
game::Team& blueTeam = GetBlueTeam();
|
||||
if (blueTeam.GetPlayerCount() > redTeam.GetPlayerCount()) {
|
||||
player.SetTeamColor(game::TeamColor::Red);
|
||||
redTeam.AddPlayer(&player);
|
||||
} else {
|
||||
player.SetTeamColor(game::TeamColor::Blue);
|
||||
blueTeam.AddPlayer(&player);
|
||||
}
|
||||
protocol::UpdatePlayerTeamPacket packet(player.GetID(), player.GetTeamColor());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
}
|
||||
for (auto& playerInfo : Game::m_Players) {
|
||||
game::Player& player = playerInfo.second;
|
||||
if (player.GetTeamColor() == game::TeamColor::None) {
|
||||
game::Team& redTeam = GetRedTeam();
|
||||
game::Team& blueTeam = GetBlueTeam();
|
||||
if (blueTeam.GetPlayerCount() > redTeam.GetPlayerCount()) {
|
||||
player.SetTeamColor(game::TeamColor::Red);
|
||||
redTeam.AddPlayer(&player);
|
||||
} else {
|
||||
player.SetTeamColor(game::TeamColor::Blue);
|
||||
blueTeam.AddPlayer(&player);
|
||||
}
|
||||
protocol::UpdatePlayerTeamPacket packet(player.GetID(), player.GetTeamColor());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::OnGameStateUpdate(game::GameState newState) {
|
||||
SetGameState(newState);
|
||||
protocol::UpdateGameStatePacket packet(newState);
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
SetGameState(newState);
|
||||
protocol::UpdateGameStatePacket packet(newState);
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
|
||||
void ServerGame::OnGameBegin() {
|
||||
NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Game);
|
||||
StartGame();
|
||||
NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Game);
|
||||
StartGame();
|
||||
}
|
||||
|
||||
void ServerGame::OnGameEnd() {
|
||||
NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::EndGame);
|
||||
m_EndGameCooldown.ApplyCooldown();
|
||||
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);
|
||||
NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Closed);
|
||||
// Disconnect clients
|
||||
protocol::DisconnectPacket packet("Game finished");
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
|
||||
// Closing server
|
||||
m_Server->Close();
|
||||
// Closing server
|
||||
m_Server->Close();
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -12,66 +12,66 @@ ServerWorld::ServerWorld(Server* server, ServerGame* game) : game::World(game),
|
||||
}
|
||||
|
||||
void ServerWorld::SpawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
game::TeamColor senderTeam = m_Game->GetPlayers().at(sender).GetTeamColor();
|
||||
game::Spawn* enemyMobSpawn;
|
||||
for (int i = 0; i < count; i++) {
|
||||
game::TeamColor senderTeam = m_Game->GetPlayers().at(sender).GetTeamColor();
|
||||
game::Spawn* enemyMobSpawn;
|
||||
|
||||
if (senderTeam == game::TeamColor::Red) {
|
||||
enemyMobSpawn = &GetTeam(game::TeamColor::Blue).GetSpawn();
|
||||
} else {
|
||||
enemyMobSpawn = &GetTeam(game::TeamColor::Red).GetSpawn();
|
||||
}
|
||||
if (senderTeam == game::TeamColor::Red) {
|
||||
enemyMobSpawn = &GetTeam(game::TeamColor::Blue).GetSpawn();
|
||||
} else {
|
||||
enemyMobSpawn = &GetTeam(game::TeamColor::Red).GetSpawn();
|
||||
}
|
||||
|
||||
float spawnWidth = enemyMobSpawn->GetWidth();
|
||||
float spawnHeight = enemyMobSpawn->GetHeight();
|
||||
float spawnWidth = enemyMobSpawn->GetWidth();
|
||||
float spawnHeight = enemyMobSpawn->GetHeight();
|
||||
|
||||
float spawnCenterX = enemyMobSpawn->GetCenterX();
|
||||
float spawnCenterY = enemyMobSpawn->GetCenterY();
|
||||
float spawnCenterX = enemyMobSpawn->GetCenterX();
|
||||
float spawnCenterY = enemyMobSpawn->GetCenterY();
|
||||
|
||||
auto mobStats = GetMobStats(type, level);
|
||||
auto mobSize = mobStats->GetSize();
|
||||
auto mobStats = GetMobStats(type, level);
|
||||
auto mobSize = mobStats->GetSize();
|
||||
|
||||
float minSpawnX = spawnCenterX - spawnWidth / 2.0f + mobSize.x / 2.0f;
|
||||
float maxSpawnX = spawnCenterX + spawnWidth / 2.0f - mobSize.x / 2.0f;
|
||||
float minSpawnX = spawnCenterX - spawnWidth / 2.0f + mobSize.x / 2.0f;
|
||||
float maxSpawnX = spawnCenterX + spawnWidth / 2.0f - mobSize.x / 2.0f;
|
||||
|
||||
float minSpawnY = spawnCenterY - spawnHeight / 2.0f + mobSize.y / 2.0f;
|
||||
float maxSpawnY = spawnCenterY + spawnHeight / 2.0f - mobSize.y / 2.0f;
|
||||
float minSpawnY = spawnCenterY - spawnHeight / 2.0f + mobSize.y / 2.0f;
|
||||
float maxSpawnY = spawnCenterY + spawnHeight / 2.0f - mobSize.y / 2.0f;
|
||||
|
||||
float mobX = utils::GetRandomReal<float>(minSpawnX + MobSpawnBorder, maxSpawnX - MobSpawnBorder);
|
||||
float mobY = utils::GetRandomReal<float>(minSpawnY + MobSpawnBorder, maxSpawnY - MobSpawnBorder);
|
||||
float mobX = utils::GetRandomReal<float>(minSpawnX + MobSpawnBorder, maxSpawnX - MobSpawnBorder);
|
||||
float mobY = utils::GetRandomReal<float>(minSpawnY + MobSpawnBorder, maxSpawnY - MobSpawnBorder);
|
||||
|
||||
SpawnMobAt(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->GetDirection());
|
||||
SpawnMobAt(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->GetDirection());
|
||||
|
||||
protocol::SpawnMobPacket packet(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->GetDirection());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
protocol::SpawnMobPacket packet(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->GetDirection());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
|
||||
m_CurrentMobID++;
|
||||
}
|
||||
m_CurrentMobID++;
|
||||
}
|
||||
}
|
||||
|
||||
game::TowerPtr ServerWorld::PlaceTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder) {
|
||||
game::TowerPtr tower = World::PlaceTowerAt(m_CurrentTowerID, type, x, y, builder);
|
||||
m_CurrentTowerID++;
|
||||
return tower;
|
||||
game::TowerPtr tower = World::PlaceTowerAt(m_CurrentTowerID, type, x, y, builder);
|
||||
m_CurrentTowerID++;
|
||||
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());
|
||||
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());
|
||||
}
|
||||
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);
|
||||
// calling base class event
|
||||
World::OnMobCastleDamage(damager, enemyCastle, damage);
|
||||
|
||||
protocol::UpdateCastleLifePacket packet(enemyCastle->GetLife(), enemyCastle->GetTeam()->GetColor());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
protocol::UpdateCastleLifePacket packet(enemyCastle->GetLife(), enemyCastle->GetTeam()->GetColor());
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -9,79 +9,79 @@ namespace td {
|
||||
namespace utils {
|
||||
|
||||
std::uint64_t Inflate(const std::string& source, std::string& dest) {
|
||||
uLongf size = dest.size();
|
||||
uncompress(reinterpret_cast<Bytef*>(dest.data()), reinterpret_cast<uLongf*>(&size), reinterpret_cast<const Bytef*>(source.c_str()), source.length());
|
||||
return size;
|
||||
uLongf size = dest.size();
|
||||
uncompress(reinterpret_cast<Bytef*>(dest.data()), reinterpret_cast<uLongf*>(&size), reinterpret_cast<const Bytef*>(source.c_str()), source.length());
|
||||
return size;
|
||||
}
|
||||
|
||||
std::uint64_t Deflate(const std::string& source, std::string& dest) {
|
||||
uLongf size = source.length();
|
||||
dest.resize(source.size()); // Resize for the compressed data to fit into
|
||||
compress(reinterpret_cast<Bytef*>(dest.data()), reinterpret_cast<uLongf*>(&size), reinterpret_cast<const Bytef*>(source.c_str()), source.length());
|
||||
dest.resize(size); // Resize to cut useless data
|
||||
return size;
|
||||
uLongf size = source.length();
|
||||
dest.resize(source.size()); // Resize for the compressed data to fit into
|
||||
compress(reinterpret_cast<Bytef*>(dest.data()), reinterpret_cast<uLongf*>(&size), reinterpret_cast<const Bytef*>(source.c_str()), source.length());
|
||||
dest.resize(size); // Resize to cut useless data
|
||||
return size;
|
||||
}
|
||||
|
||||
DataBuffer Compress(const DataBuffer& buffer) {
|
||||
std::string compressedData;
|
||||
DataBuffer packet;
|
||||
std::string compressedData;
|
||||
DataBuffer packet;
|
||||
|
||||
if (buffer.GetSize() < COMPRESSION_THRESHOLD) {
|
||||
// Don't compress since it's a small packet
|
||||
std::uint64_t dataLength = 0;
|
||||
std::uint64_t packetLength = buffer.GetSize() + sizeof(dataLength);
|
||||
if (buffer.GetSize() < COMPRESSION_THRESHOLD) {
|
||||
// Don't compress since it's a small packet
|
||||
std::uint64_t dataLength = 0;
|
||||
std::uint64_t packetLength = buffer.GetSize() + sizeof(dataLength);
|
||||
|
||||
packet << packetLength;
|
||||
packet << dataLength;
|
||||
packet << buffer;
|
||||
return packet;
|
||||
}
|
||||
packet << packetLength;
|
||||
packet << dataLength;
|
||||
packet << buffer;
|
||||
return packet;
|
||||
}
|
||||
|
||||
Deflate(buffer.ToString(), compressedData);
|
||||
Deflate(buffer.ToString(), compressedData);
|
||||
|
||||
std::uint64_t dataLength = buffer.GetSize();
|
||||
std::uint64_t packetLength = compressedData.length() + sizeof(dataLength);
|
||||
std::uint64_t dataLength = buffer.GetSize();
|
||||
std::uint64_t packetLength = compressedData.length() + sizeof(dataLength);
|
||||
|
||||
packet << packetLength;
|
||||
packet << dataLength;
|
||||
packet << compressedData;
|
||||
return packet;
|
||||
packet << packetLength;
|
||||
packet << dataLength;
|
||||
packet << compressedData;
|
||||
return packet;
|
||||
}
|
||||
|
||||
DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) {
|
||||
std::uint64_t uncompressedLength;
|
||||
std::uint64_t uncompressedLength;
|
||||
|
||||
buffer >> uncompressedLength;
|
||||
buffer >> uncompressedLength;
|
||||
|
||||
std::uint64_t compressedLength = packetLength - sizeof(uncompressedLength);
|
||||
std::uint64_t compressedLength = packetLength - sizeof(uncompressedLength);
|
||||
|
||||
if (uncompressedLength == 0) {
|
||||
// Uncompressed
|
||||
DataBuffer ret;
|
||||
buffer.ReadSome(ret, compressedLength);
|
||||
return ret;
|
||||
}
|
||||
if (uncompressedLength == 0) {
|
||||
// Uncompressed
|
||||
DataBuffer ret;
|
||||
buffer.ReadSome(ret, compressedLength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize());
|
||||
assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize());
|
||||
|
||||
std::string deflatedData;
|
||||
buffer.ReadSome(deflatedData, compressedLength);
|
||||
std::string deflatedData;
|
||||
buffer.ReadSome(deflatedData, compressedLength);
|
||||
|
||||
std::string inflated;
|
||||
inflated.resize(uncompressedLength);
|
||||
std::string inflated;
|
||||
inflated.resize(uncompressedLength);
|
||||
|
||||
Inflate(deflatedData, inflated);
|
||||
Inflate(deflatedData, inflated);
|
||||
|
||||
assert(inflated.length() == uncompressedLength);
|
||||
return DataBuffer(inflated);
|
||||
assert(inflated.length() == uncompressedLength);
|
||||
return DataBuffer(inflated);
|
||||
}
|
||||
|
||||
DataBuffer Decompress(DataBuffer& buffer) {
|
||||
std::uint64_t packetLength;
|
||||
std::uint64_t packetLength;
|
||||
|
||||
buffer >> packetLength;
|
||||
buffer >> packetLength;
|
||||
|
||||
return Decompress(buffer, packetLength);
|
||||
return Decompress(buffer, packetLength);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -7,88 +7,88 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
DataBuffer::DataBuffer() : m_ReadOffset(0) { }
|
||||
DataBuffer::DataBuffer(const DataBuffer& other) : m_Buffer(other.m_Buffer), m_ReadOffset(other.m_ReadOffset) { }
|
||||
DataBuffer::DataBuffer(DataBuffer&& other) : m_Buffer(std::move(other.m_Buffer)), m_ReadOffset(std::move(other.m_ReadOffset)) { }
|
||||
DataBuffer::DataBuffer(const std::string& str) : m_Buffer(str.begin(), str.end()), m_ReadOffset(0) { }
|
||||
DataBuffer::DataBuffer() : m_ReadOffset(0) {}
|
||||
DataBuffer::DataBuffer(const DataBuffer& other) : m_Buffer(other.m_Buffer), m_ReadOffset(other.m_ReadOffset) {}
|
||||
DataBuffer::DataBuffer(DataBuffer&& other) : m_Buffer(std::move(other.m_Buffer)), m_ReadOffset(std::move(other.m_ReadOffset)) {}
|
||||
DataBuffer::DataBuffer(const std::string& str) : m_Buffer(str.begin(), str.end()), m_ReadOffset(0) {}
|
||||
|
||||
DataBuffer::DataBuffer(const DataBuffer& other, Data::difference_type offset) : m_ReadOffset(0) {
|
||||
m_Buffer.reserve(other.GetSize() - static_cast<std::size_t>(offset));
|
||||
std::copy(other.m_Buffer.begin() + offset, other.m_Buffer.end(), std::back_inserter(m_Buffer));
|
||||
m_Buffer.reserve(other.GetSize() - static_cast<std::size_t>(offset));
|
||||
std::copy(other.m_Buffer.begin() + offset, other.m_Buffer.end(), std::back_inserter(m_Buffer));
|
||||
}
|
||||
|
||||
DataBuffer& DataBuffer::operator=(const DataBuffer& other) {
|
||||
m_Buffer = other.m_Buffer;
|
||||
m_ReadOffset = other.m_ReadOffset;
|
||||
return *this;
|
||||
m_Buffer = other.m_Buffer;
|
||||
m_ReadOffset = other.m_ReadOffset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DataBuffer& DataBuffer::operator=(DataBuffer&& other) {
|
||||
m_Buffer = std::move(other.m_Buffer);
|
||||
m_ReadOffset = std::move(other.m_ReadOffset);
|
||||
return *this;
|
||||
m_Buffer = std::move(other.m_Buffer);
|
||||
m_ReadOffset = std::move(other.m_ReadOffset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DataBuffer::SetReadOffset(std::size_t pos) {
|
||||
assert(pos <= GetSize());
|
||||
m_ReadOffset = pos;
|
||||
assert(pos <= GetSize());
|
||||
m_ReadOffset = pos;
|
||||
}
|
||||
|
||||
std::string DataBuffer::ToString() const {
|
||||
return std::string(m_Buffer.begin(), m_Buffer.end());
|
||||
return std::string(m_Buffer.begin(), m_Buffer.end());
|
||||
}
|
||||
|
||||
std::size_t DataBuffer::GetSize() const { return m_Buffer.size(); }
|
||||
bool DataBuffer::IsEmpty() const { return m_Buffer.empty(); }
|
||||
std::size_t DataBuffer::GetRemaining() const {
|
||||
return m_Buffer.size() - m_ReadOffset;
|
||||
return m_Buffer.size() - m_ReadOffset;
|
||||
}
|
||||
|
||||
DataBuffer::iterator DataBuffer::begin() {
|
||||
return m_Buffer.begin();
|
||||
return m_Buffer.begin();
|
||||
}
|
||||
DataBuffer::iterator DataBuffer::end() {
|
||||
return m_Buffer.end();
|
||||
return m_Buffer.end();
|
||||
}
|
||||
DataBuffer::const_iterator DataBuffer::begin() const {
|
||||
return m_Buffer.begin();
|
||||
return m_Buffer.begin();
|
||||
}
|
||||
DataBuffer::const_iterator DataBuffer::end() const {
|
||||
return m_Buffer.end();
|
||||
return m_Buffer.end();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer) {
|
||||
for (unsigned char u : buffer)
|
||||
os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(u) << " ";
|
||||
os << std::dec;
|
||||
return os;
|
||||
for (unsigned char u : buffer)
|
||||
os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(u) << " ";
|
||||
os << std::dec;
|
||||
return os;
|
||||
}
|
||||
|
||||
bool DataBuffer::ReadFile(const std::string& fileName) {
|
||||
try {
|
||||
std::ifstream file(fileName, std::istream::binary);
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
const std::string& s = ss.str();
|
||||
m_Buffer = DataBuffer::Data(s.begin(), s.end());
|
||||
m_ReadOffset = 0;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Failed to read file \"" << fileName << "\" reason : " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return m_Buffer.size() > 0;
|
||||
try {
|
||||
std::ifstream file(fileName, std::istream::binary);
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
const std::string& s = ss.str();
|
||||
m_Buffer = DataBuffer::Data(s.begin(), s.end());
|
||||
m_ReadOffset = 0;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Failed to read file \"" << fileName << "\" reason : " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return m_Buffer.size() > 0;
|
||||
}
|
||||
|
||||
bool DataBuffer::WriteFile(const std::string& fileName) {
|
||||
try {
|
||||
std::ofstream file(fileName, std::ostream::binary);
|
||||
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));
|
||||
file.flush();
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Failed to write file \"" << fileName << "\" reason : " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
try {
|
||||
std::ofstream file(fileName, std::ostream::binary);
|
||||
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));
|
||||
file.flush();
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Failed to write file \"" << fileName << "\" reason : " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // td
|
||||
|
||||
@@ -10,195 +10,195 @@ namespace utils {
|
||||
/* Sine functions */
|
||||
|
||||
float EaseInSine(float x) {
|
||||
return 1.0f - std::cos((x * PI) / 2.0f);
|
||||
return 1.0f - std::cos((x * PI) / 2.0f);
|
||||
}
|
||||
|
||||
float EaseOutSine(float x) {
|
||||
return std::sin((x * PI) / 2.0f);
|
||||
return std::sin((x * PI) / 2.0f);
|
||||
}
|
||||
|
||||
float EaseInOutSine(float x) {
|
||||
return -(std::cos(PI * x) - 1.0f) / 2.0f;
|
||||
return -(std::cos(PI * x) - 1.0f) / 2.0f;
|
||||
}
|
||||
|
||||
/* Cubic functions */
|
||||
|
||||
float EaseInCubic(float x) {
|
||||
return x * EaseInQuad(x);
|
||||
return x * EaseInQuad(x);
|
||||
}
|
||||
|
||||
float EaseOutCubic(float x) {
|
||||
return 1 - std::pow(1 - x, 3);
|
||||
return 1 - std::pow(1 - x, 3);
|
||||
}
|
||||
|
||||
float EaseInOutCubic(float x) {
|
||||
return x < 0.5 ? 4 * EaseInCubic(x) : 1 - std::pow(-2 * x + 2, 3) / 2.0f;
|
||||
return x < 0.5 ? 4 * EaseInCubic(x) : 1 - std::pow(-2 * x + 2, 3) / 2.0f;
|
||||
}
|
||||
|
||||
/* Quint functions */
|
||||
|
||||
float EaseInQuint(float x) {
|
||||
return x * EaseInQuart(x);
|
||||
return x * EaseInQuart(x);
|
||||
}
|
||||
|
||||
float EaseOutQuint(float x) {
|
||||
return 1 - std::pow(1 - x, 5);
|
||||
return 1 - std::pow(1 - x, 5);
|
||||
}
|
||||
|
||||
float EaseInOutQuint(float x) {
|
||||
return x < 0.5 ? 16 * EaseInQuint(x) : 1 - std::pow(-2 * x + 2, 5) / 2.0f;
|
||||
return x < 0.5 ? 16 * EaseInQuint(x) : 1 - std::pow(-2 * x + 2, 5) / 2.0f;
|
||||
}
|
||||
|
||||
/* Circ functions */
|
||||
|
||||
float EaseInCirc(float x) {
|
||||
return 1 - std::sqrt(1 - std::pow(x, 2));
|
||||
return 1 - std::sqrt(1 - std::pow(x, 2));
|
||||
}
|
||||
|
||||
float EaseOutCirc(float x) {
|
||||
return std::sqrt(1 - std::pow(x - 1, 2));
|
||||
return std::sqrt(1 - std::pow(x - 1, 2));
|
||||
}
|
||||
|
||||
float EaseInOutCirc(float x) {
|
||||
return x < 0.5
|
||||
? (1 - std::sqrt(1 - std::pow(2 * x, 2))) / 2.0f
|
||||
: (std::sqrt(1 - std::pow(-2 * x + 2, 2)) + 1) / 2.0f;
|
||||
return x < 0.5
|
||||
? (1 - std::sqrt(1 - std::pow(2 * x, 2))) / 2.0f
|
||||
: (std::sqrt(1 - std::pow(-2 * x + 2, 2)) + 1) / 2.0f;
|
||||
}
|
||||
|
||||
/* Elastic functions */
|
||||
|
||||
float EaseInElastic(float x) {
|
||||
const float c4 = (2 * PI) / 3.0f;
|
||||
const float c4 = (2 * PI) / 3.0f;
|
||||
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: -std::pow(2, 10 * x - 10) * std::sin((x * 10 - 10.75) * c4);
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: -std::pow(2, 10 * x - 10) * std::sin((x * 10 - 10.75) * c4);
|
||||
}
|
||||
|
||||
float EaseOutElastic(float x) {
|
||||
const float c4 = (2 * PI) / 3.0f;
|
||||
const float c4 = (2 * PI) / 3.0f;
|
||||
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: std::pow(2, -10 * x) * std::sin((x * 10 - 0.75) * c4) + 1;
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: std::pow(2, -10 * x) * std::sin((x * 10 - 0.75) * c4) + 1;
|
||||
}
|
||||
|
||||
float EaseInOutElastic(float x) {
|
||||
const float c5 = (2 * PI) / 4.5;
|
||||
const float c5 = (2 * PI) / 4.5;
|
||||
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5
|
||||
? -(std::pow(2, 20 * x - 10) * std::sin((20 * x - 11.125) * c5)) / 2.0f
|
||||
: (std::pow(2, -20 * x + 10) * std::sin((20 * x - 11.125) * c5)) / 2.0f + 1;
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5
|
||||
? -(std::pow(2, 20 * x - 10) * std::sin((20 * x - 11.125) * c5)) / 2.0f
|
||||
: (std::pow(2, -20 * x + 10) * std::sin((20 * x - 11.125) * c5)) / 2.0f + 1;
|
||||
}
|
||||
|
||||
/* Quad functions */
|
||||
|
||||
float EaseInQuad(float x) {
|
||||
return x * x;
|
||||
return x * x;
|
||||
}
|
||||
|
||||
float EaseOutQuad(float x) {
|
||||
return 1 - (1 - x) * (1 - x);
|
||||
return 1 - (1 - x) * (1 - x);
|
||||
}
|
||||
|
||||
float EaseInOutQuad(float x) {
|
||||
return x < 0.5 ? 2 * x * x : 1 - std::pow(-2 * x + 2, 2) / 2.0f;
|
||||
return x < 0.5 ? 2 * x * x : 1 - std::pow(-2 * x + 2, 2) / 2.0f;
|
||||
}
|
||||
|
||||
/* Quart functions */
|
||||
|
||||
float EaseInQuart(float x) {
|
||||
return x * EaseInCubic(x);
|
||||
return x * EaseInCubic(x);
|
||||
}
|
||||
|
||||
float EaseOutQuart(float x) {
|
||||
return 1 - std::pow(1 - x, 4);
|
||||
return 1 - std::pow(1 - x, 4);
|
||||
}
|
||||
|
||||
float EaseInOutQuart(float x) {
|
||||
return x < 0.5 ? 8 * EaseInQuart(x) : 1 - std::pow(-2 * x + 2, 4) / 2.0f;
|
||||
return x < 0.5 ? 8 * EaseInQuart(x) : 1 - std::pow(-2 * x + 2, 4) / 2.0f;
|
||||
}
|
||||
|
||||
/* Expo functions */
|
||||
|
||||
float EaseInExpo(float x) {
|
||||
return x == 0 ? 0 : std::pow(2, 10 * x - 10);
|
||||
return x == 0 ? 0 : std::pow(2, 10 * x - 10);
|
||||
}
|
||||
|
||||
float EaseOutExpo(float x) {
|
||||
return x == 1 ? 1 : 1 - std::pow(2, -10 * x);
|
||||
return x == 1 ? 1 : 1 - std::pow(2, -10 * x);
|
||||
}
|
||||
|
||||
float EaseInOutExpo(float x) {
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5 ? std::pow(2, 20 * x - 10) / 2.0f
|
||||
: (2 - std::pow(2, -20 * x + 10)) / 2.0f;
|
||||
return x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5 ? std::pow(2, 20 * x - 10) / 2.0f
|
||||
: (2 - std::pow(2, -20 * x + 10)) / 2.0f;
|
||||
}
|
||||
|
||||
/* Back functions */
|
||||
|
||||
float EaseInBack(float x) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1;
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1;
|
||||
|
||||
return c3 * EaseInCubic(x) - c1 * EaseInQuad(x);
|
||||
return c3 * EaseInCubic(x) - c1 * EaseInQuad(x);
|
||||
}
|
||||
|
||||
float EaseOutBack(float x) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1;
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1;
|
||||
|
||||
return 1 + c3 * std::pow(x - 1, 3) + c1 * std::pow(x - 1, 2);
|
||||
return 1 + c3 * std::pow(x - 1, 3) + c1 * std::pow(x - 1, 2);
|
||||
}
|
||||
|
||||
float EaseInOutBack(float x) {
|
||||
const float c1 = 1.70158;
|
||||
const float c2 = c1 * 1.525;
|
||||
const float c1 = 1.70158;
|
||||
const float c2 = c1 * 1.525;
|
||||
|
||||
return x < 0.5
|
||||
? (std::pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2.0f
|
||||
: (std::pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2.0f;
|
||||
return x < 0.5
|
||||
? (std::pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2.0f
|
||||
: (std::pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2.0f;
|
||||
}
|
||||
|
||||
/* Bounce functions */
|
||||
|
||||
float EaseInBounce(float x) {
|
||||
return 1 - EaseOutBounce(1 - x);
|
||||
return 1 - EaseOutBounce(1 - x);
|
||||
}
|
||||
|
||||
float EaseOutBounce(float x) {
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
|
||||
if (x < 1 / d1) {
|
||||
return n1 * EaseInQuad(x);
|
||||
} else if (x < 2 / d1) {
|
||||
x -= 1.5;
|
||||
return n1 * (x / d1) * x + 0.75;
|
||||
} else if (x < 2.5 / d1) {
|
||||
x -= 2.25;
|
||||
return n1 * (x / d1) * x + 0.9375;
|
||||
} else {
|
||||
x -= 2.625;
|
||||
return n1 * (x / d1) * x + 0.984375;
|
||||
}
|
||||
if (x < 1 / d1) {
|
||||
return n1 * EaseInQuad(x);
|
||||
} else if (x < 2 / d1) {
|
||||
x -= 1.5;
|
||||
return n1 * (x / d1) * x + 0.75;
|
||||
} else if (x < 2.5 / d1) {
|
||||
x -= 2.25;
|
||||
return n1 * (x / d1) * x + 0.9375;
|
||||
} else {
|
||||
x -= 2.625;
|
||||
return n1 * (x / d1) * x + 0.984375;
|
||||
}
|
||||
}
|
||||
|
||||
float EaseInOutBounce(float x) {
|
||||
return x < 0.5
|
||||
? (1 - EaseOutBounce(1 - 2 * x)) / 2.0f
|
||||
: (1 + EaseOutBounce(2 * x - 1)) / 2.0f;
|
||||
return x < 0.5
|
||||
? (1 - EaseOutBounce(1 - 2 * x)) / 2.0f
|
||||
: (1 + EaseOutBounce(2 * x - 1)) / 2.0f;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -8,44 +8,44 @@ namespace utils {
|
||||
namespace shape {
|
||||
|
||||
float Point::Distance(const Point& point) const {
|
||||
return std::sqrt(DistanceSquared(point));
|
||||
return std::sqrt(DistanceSquared(point));
|
||||
}
|
||||
|
||||
float Point::DistanceSquared(const Point& point) const {
|
||||
return (m_X - point.GetX()) * (m_X - point.GetX()) + (m_Y - point.GetY()) * (m_Y - point.GetY());
|
||||
return (m_X - point.GetX()) * (m_X - point.GetX()) + (m_Y - point.GetY()) * (m_Y - point.GetY());
|
||||
}
|
||||
|
||||
|
||||
bool Rectangle::CollidesWith(const Point& point) const {
|
||||
return point.GetX() > GetTopLeft().GetX() && point.GetX() < GetBottomRight().GetX() &&
|
||||
point.GetY() > GetTopLeft().GetY() && point.GetY() < GetBottomRight().GetY();
|
||||
return point.GetX() > GetTopLeft().GetX() && point.GetX() < GetBottomRight().GetX() &&
|
||||
point.GetY() > GetTopLeft().GetY() && point.GetY() < GetBottomRight().GetY();
|
||||
}
|
||||
|
||||
bool Rectangle::CollidesWith(const Rectangle& rect) const {
|
||||
|
||||
Point point1{ rect.GetTopLeft().GetX(), rect.GetTopLeft().GetY() };
|
||||
Point point2{ rect.GetTopLeft().GetX(), rect.GetBottomRight().GetY() };
|
||||
Point point3{ rect.GetBottomRight().GetX(), rect.GetTopLeft().GetY() };
|
||||
Point point4{ rect.GetBottomRight().GetX(), rect.GetBottomRight().GetY() };
|
||||
Point point1{ rect.GetTopLeft().GetX(), rect.GetTopLeft().GetY() };
|
||||
Point point2{ rect.GetTopLeft().GetX(), rect.GetBottomRight().GetY() };
|
||||
Point point3{ rect.GetBottomRight().GetX(), rect.GetTopLeft().GetY() };
|
||||
Point point4{ rect.GetBottomRight().GetX(), rect.GetBottomRight().GetY() };
|
||||
|
||||
if (CollidesWith(point1)) return true;
|
||||
if (CollidesWith(point2)) return true;
|
||||
if (CollidesWith(point3)) return true;
|
||||
if (CollidesWith(point4)) return true;
|
||||
if (CollidesWith(point1)) return true;
|
||||
if (CollidesWith(point2)) return true;
|
||||
if (CollidesWith(point3)) return true;
|
||||
if (CollidesWith(point4)) return true;
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Rectangle::CollidesWith(const Circle& circle) const {
|
||||
return circle.CollidesWith(*this);
|
||||
return circle.CollidesWith(*this);
|
||||
}
|
||||
|
||||
float Rectangle::Distance(const Circle& circle) const {
|
||||
return circle.Distance(*this);
|
||||
return circle.Distance(*this);
|
||||
}
|
||||
|
||||
float Rectangle::DistanceSquared(const Circle& circle) const {
|
||||
return circle.DistanceSquared(*this);
|
||||
return circle.DistanceSquared(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,31 +53,31 @@ float Rectangle::DistanceSquared(const Circle& circle) const {
|
||||
|
||||
|
||||
bool Circle::CollidesWith(const Point& point) const {
|
||||
return m_Radius * m_Radius > m_Center.DistanceSquared(point);
|
||||
return m_Radius * m_Radius > m_Center.DistanceSquared(point);
|
||||
}
|
||||
|
||||
bool Circle::CollidesWith(const Rectangle& rect) const {
|
||||
float DistanceSquared_ = DistanceSquared(rect);
|
||||
float DistanceSquared_ = DistanceSquared(rect);
|
||||
|
||||
return DistanceSquared_ < m_Radius* m_Radius;
|
||||
return DistanceSquared_ < m_Radius* m_Radius;
|
||||
}
|
||||
|
||||
bool Circle::CollidesWith(const Circle& circle) const {
|
||||
return m_Radius + circle.GetRadius() > m_Center.DistanceSquared(circle.GetCenter());
|
||||
return m_Radius + circle.GetRadius() > m_Center.DistanceSquared(circle.GetCenter());
|
||||
}
|
||||
|
||||
float Circle::Distance(const Rectangle& rect) const {
|
||||
return std::sqrt(DistanceSquared(rect));
|
||||
return std::sqrt(DistanceSquared(rect));
|
||||
}
|
||||
|
||||
float Circle::DistanceSquared(const Rectangle& rect) const {
|
||||
float closestX = std::clamp(m_Center.GetX(), rect.GetTopLeft().GetX(), rect.GetBottomRight().GetX());
|
||||
float closestY = std::clamp(m_Center.GetY(), rect.GetTopLeft().GetY(), rect.GetBottomRight().GetY());
|
||||
float closestX = std::clamp(m_Center.GetX(), rect.GetTopLeft().GetX(), rect.GetBottomRight().GetX());
|
||||
float closestY = std::clamp(m_Center.GetY(), rect.GetTopLeft().GetY(), rect.GetBottomRight().GetY());
|
||||
|
||||
float DistanceX = m_Center.GetX() - closestX;
|
||||
float DistanceY = m_Center.GetY() - closestY;
|
||||
float DistanceX = m_Center.GetX() - closestX;
|
||||
float DistanceY = m_Center.GetY() - closestY;
|
||||
|
||||
return (DistanceX * DistanceX) + (DistanceY * DistanceY);
|
||||
return (DistanceX * DistanceX) + (DistanceY * DistanceY);
|
||||
}
|
||||
|
||||
} // namespace shape
|
||||
|
||||
@@ -7,60 +7,60 @@ namespace td {
|
||||
namespace utils {
|
||||
|
||||
void AutoTimer::Update() {
|
||||
m_InternalTime += GetTime() - m_LastTime;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
if (m_Function != nullptr)
|
||||
m_Function();
|
||||
m_InternalTime %= m_Interval;
|
||||
}
|
||||
m_LastTime = GetTime();
|
||||
m_InternalTime += GetTime() - m_LastTime;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
if (m_Function != nullptr)
|
||||
m_Function();
|
||||
m_InternalTime %= m_Interval;
|
||||
}
|
||||
m_LastTime = GetTime();
|
||||
}
|
||||
|
||||
void AutoTimer::Update(std::uint64_t delta) {
|
||||
m_InternalTime += delta;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
if (m_Function != nullptr)
|
||||
m_Function();
|
||||
m_InternalTime %= m_Interval;
|
||||
}
|
||||
m_LastTime = GetTime();
|
||||
m_InternalTime += delta;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
if (m_Function != nullptr)
|
||||
m_Function();
|
||||
m_InternalTime %= m_Interval;
|
||||
}
|
||||
m_LastTime = GetTime();
|
||||
}
|
||||
|
||||
void AutoTimer::Reset() {
|
||||
m_InternalTime = 0;
|
||||
m_LastTime = GetTime();
|
||||
m_InternalTime = 0;
|
||||
m_LastTime = GetTime();
|
||||
}
|
||||
|
||||
bool Timer::Update(std::uint64_t delta) {
|
||||
m_InternalTime += delta;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
m_InternalTime %= m_Interval;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
m_InternalTime += delta;
|
||||
if (m_InternalTime >= m_Interval) {
|
||||
m_InternalTime %= m_Interval;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Timer::Reset() {
|
||||
m_InternalTime = 0; // let the timer active once at the beginning
|
||||
m_InternalTime = 0; // let the timer active once at the beginning
|
||||
}
|
||||
|
||||
bool CooldownTimer::Update(std::uint64_t delta) {
|
||||
if (m_Cooldown > 0) {
|
||||
m_Cooldown = static_cast<std::uint64_t>(std::max(static_cast<std::int64_t>(0), static_cast<std::int64_t>(m_Cooldown - delta)));
|
||||
}
|
||||
return m_Cooldown == 0;
|
||||
if (m_Cooldown > 0) {
|
||||
m_Cooldown = static_cast<std::uint64_t>(std::max(static_cast<std::int64_t>(0), static_cast<std::int64_t>(m_Cooldown - delta)));
|
||||
}
|
||||
return m_Cooldown == 0;
|
||||
}
|
||||
|
||||
void CooldownTimer::Reset() {
|
||||
m_Cooldown = 0; // let the timer active once at the beginning
|
||||
m_Cooldown = 0; // let the timer active once at the beginning
|
||||
}
|
||||
|
||||
void CooldownTimer::ApplyCooldown() {
|
||||
m_Cooldown = m_CooldownTime;
|
||||
m_Cooldown = m_CooldownTime;
|
||||
}
|
||||
|
||||
std::uint64_t GetTime() {
|
||||
return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
|
||||
return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -16,109 +16,109 @@ namespace network {
|
||||
|
||||
/* Create an invalid address */
|
||||
IPAddress::IPAddress() noexcept
|
||||
: m_Address(0), m_Valid(false) {
|
||||
: m_Address(0), m_Valid(false) {
|
||||
|
||||
}
|
||||
|
||||
/* Initialize by string IP */
|
||||
IPAddress::IPAddress(const std::string& ip)
|
||||
: m_Address(0), m_Valid(false) {
|
||||
: m_Address(0), m_Valid(false) {
|
||||
|
||||
std::sregex_iterator begin(ip.begin(), ip.end(), IPRegex);
|
||||
std::sregex_iterator end;
|
||||
std::sregex_iterator begin(ip.begin(), ip.end(), IPRegex);
|
||||
std::sregex_iterator end;
|
||||
|
||||
if (begin == end) return; // m_Valid = false
|
||||
if (begin == end) return; // m_Valid = false
|
||||
|
||||
std::smatch match = *begin;
|
||||
std::smatch match = *begin;
|
||||
|
||||
std::uint8_t octet1 = std::stoul(std::string(match[1]));
|
||||
std::uint8_t octet2 = std::stoul(std::string(match[2]));
|
||||
std::uint8_t octet3 = std::stoul(std::string(match[3]));
|
||||
std::uint8_t octet4 = std::stoul(std::string(match[4]));
|
||||
std::uint8_t octet1 = std::stoul(std::string(match[1]));
|
||||
std::uint8_t octet2 = std::stoul(std::string(match[2]));
|
||||
std::uint8_t octet3 = std::stoul(std::string(match[3]));
|
||||
std::uint8_t octet4 = std::stoul(std::string(match[4]));
|
||||
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
m_Valid = true;
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
m_Valid = true;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(const std::wstring& ip)
|
||||
: m_Address(0), m_Valid(false) {
|
||||
: m_Address(0), m_Valid(false) {
|
||||
|
||||
std::wsregex_iterator begin(ip.begin(), ip.end(), IPRegexW);
|
||||
std::wsregex_iterator end;
|
||||
std::wsregex_iterator begin(ip.begin(), ip.end(), IPRegexW);
|
||||
std::wsregex_iterator end;
|
||||
|
||||
if (begin == end) return; // m_Valid = false
|
||||
if (begin == end) return; // m_Valid = false
|
||||
|
||||
std::wsmatch match = *begin;
|
||||
std::wsmatch match = *begin;
|
||||
|
||||
std::uint8_t octet1 = std::stoul(match[1]);
|
||||
std::uint8_t octet2 = std::stoul(match[2]);
|
||||
std::uint8_t octet3 = std::stoul(match[3]);
|
||||
std::uint8_t octet4 = std::stoul(match[4]);
|
||||
std::uint8_t octet1 = std::stoul(match[1]);
|
||||
std::uint8_t octet2 = std::stoul(match[2]);
|
||||
std::uint8_t octet3 = std::stoul(match[3]);
|
||||
std::uint8_t octet4 = std::stoul(match[4]);
|
||||
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
m_Valid = true;
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
m_Valid = true;
|
||||
}
|
||||
|
||||
/* Initialize by octets */
|
||||
IPAddress::IPAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) noexcept
|
||||
: m_Valid(true) {
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
: m_Valid(true) {
|
||||
m_Address = static_cast<std::uint32_t>((octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4);
|
||||
}
|
||||
|
||||
/* Get the specific octet */
|
||||
uint8_t IPAddress::GetOctet(uint8_t num) const {
|
||||
if (num == 0 || num > 4) throw std::invalid_argument("Invalid argument in IPAddress:GetOctet.");
|
||||
if (num == 0 || num > 4) throw std::invalid_argument("Invalid argument in IPAddress:GetOctet.");
|
||||
|
||||
return (m_Address >> (8 * (4 - num))) & 0xFF;
|
||||
return (m_Address >> (8 * (4 - num))) & 0xFF;
|
||||
}
|
||||
|
||||
/* Set the specific octet. 1-4 */
|
||||
void IPAddress::SetOctet(uint8_t num, uint8_t value) {
|
||||
if (num == 0 || num > 4) throw std::invalid_argument("Invalid argument in IPAddress:GetOctet.");
|
||||
uint8_t octets[4];
|
||||
if (num == 0 || num > 4) throw std::invalid_argument("Invalid argument in IPAddress:GetOctet.");
|
||||
uint8_t octets[4];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
octets[i] = (m_Address >> ((3 - i) * 8)) & 0xFF;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
octets[i] = (m_Address >> ((3 - i) * 8)) & 0xFF;
|
||||
|
||||
octets[num - 1] = value;
|
||||
octets[num - 1] = value;
|
||||
|
||||
m_Address = static_cast<std::uint32_t>((octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | octets[3]);
|
||||
m_Address = static_cast<std::uint32_t>((octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | octets[3]);
|
||||
}
|
||||
|
||||
IPAddress IPAddress::LocalAddress() {
|
||||
return IPAddress(127, 0, 0, 1);
|
||||
return IPAddress(127, 0, 0, 1);
|
||||
}
|
||||
|
||||
std::string IPAddress::ToString() const {
|
||||
std::stringstream ss;
|
||||
std::stringstream ss;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i != 0) ss << ".";
|
||||
ss << static_cast<unsigned int>(GetOctet(i + 1));
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i != 0) ss << ".";
|
||||
ss << static_cast<unsigned int>(GetOctet(i + 1));
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(const IPAddress& right) {
|
||||
return m_Address == right.m_Address;
|
||||
return m_Address == right.m_Address;
|
||||
}
|
||||
|
||||
bool IPAddress::operator!=(const IPAddress& right) {
|
||||
return !(*this == right);
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(bool b) {
|
||||
return IsValid() == b;
|
||||
return IsValid() == b;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const IPAddress& addr) {
|
||||
return os << addr.ToString();
|
||||
return os << addr.ToString();
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& os, const IPAddress& addr) {
|
||||
std::string str = addr.ToString();
|
||||
return os << std::wstring(str.begin(), str.end());
|
||||
std::string str = addr.ToString();
|
||||
return os << std::wstring(str.begin(), str.end());
|
||||
}
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -5,20 +5,20 @@ namespace network {
|
||||
|
||||
class NetworkInitializer {
|
||||
public:
|
||||
NetworkInitializer();
|
||||
~NetworkInitializer();
|
||||
NetworkInitializer();
|
||||
~NetworkInitializer();
|
||||
|
||||
NetworkInitializer(const NetworkInitializer& rhs) = delete;
|
||||
NetworkInitializer& operator=(const NetworkInitializer& rhs) = delete;
|
||||
NetworkInitializer(const NetworkInitializer& rhs) = delete;
|
||||
NetworkInitializer& operator=(const NetworkInitializer& rhs) = delete;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
NetworkInitializer::NetworkInitializer() {
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
}
|
||||
NetworkInitializer::~NetworkInitializer() {
|
||||
WSACleanup();
|
||||
WSACleanup();
|
||||
}
|
||||
#else
|
||||
NetworkInitializer::NetworkInitializer() {
|
||||
@@ -32,36 +32,36 @@ NetworkInitializer::~NetworkInitializer() {
|
||||
NetworkInitializer initializer;
|
||||
|
||||
IPAddresses Dns::Resolve(const std::string& host) {
|
||||
IPAddresses list;
|
||||
addrinfo hints{};
|
||||
addrinfo* addresses = nullptr;
|
||||
IPAddresses list;
|
||||
addrinfo hints{};
|
||||
addrinfo* addresses = nullptr;
|
||||
|
||||
//hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
//hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
getaddrinfo(host.c_str(), NULL, &hints, &addresses);
|
||||
getaddrinfo(host.c_str(), NULL, &hints, &addresses);
|
||||
|
||||
for (addrinfo* p = addresses; p != NULL; p = p->ai_next) {
|
||||
for (addrinfo* p = addresses; p != NULL; p = p->ai_next) {
|
||||
#ifdef _WIN32
|
||||
//wchar_t straddr[35];
|
||||
//char straddr[512];
|
||||
//DWORD len;
|
||||
//WSAAddressToStringA(p->ai_addr, p->ai_addrlen, NULL, straddr, &len);
|
||||
//wchar_t straddr[35];
|
||||
//char straddr[512];
|
||||
//DWORD len;
|
||||
//WSAAddressToStringA(p->ai_addr, p->ai_addrlen, NULL, straddr, &len);
|
||||
|
||||
char* straddr = inet_ntoa(((sockaddr_in*)p->ai_addr)->sin_addr);
|
||||
char* straddr = inet_ntoa(((sockaddr_in*)p->ai_addr)->sin_addr);
|
||||
|
||||
#else
|
||||
char straddr[512];
|
||||
char straddr[512];
|
||||
|
||||
inet_ntop(p->ai_family, &(reinterpret_cast<sockaddr_in*>(p->ai_addr))->sin_addr, straddr, sizeof(straddr));
|
||||
inet_ntop(p->ai_family, &(reinterpret_cast<sockaddr_in*>(p->ai_addr))->sin_addr, straddr, sizeof(straddr));
|
||||
#endif
|
||||
|
||||
list.push_back(IPAddress(straddr));
|
||||
}
|
||||
list.push_back(IPAddress(straddr));
|
||||
}
|
||||
|
||||
return list;
|
||||
return list;
|
||||
}
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -13,68 +13,67 @@ namespace td {
|
||||
namespace network {
|
||||
|
||||
Socket::Socket(Type type)
|
||||
: m_Blocking(false),
|
||||
m_Type(type),
|
||||
m_Status(Disconnected),
|
||||
m_Handle(static_cast<SocketHandle>(INVALID_SOCKET))
|
||||
{
|
||||
: m_Blocking(false),
|
||||
m_Type(type),
|
||||
m_Status(Disconnected),
|
||||
m_Handle(static_cast<SocketHandle>(INVALID_SOCKET)) {
|
||||
|
||||
}
|
||||
|
||||
Socket::~Socket() {
|
||||
Disconnect();
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool Socket::SetBlocking(bool block) {
|
||||
unsigned long mode = block ? 0 : 1;
|
||||
unsigned long mode = block ? 0 : 1;
|
||||
|
||||
if (ioctl(m_Handle, FIONBIO, &mode) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (ioctl(m_Handle, FIONBIO, &mode) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Blocking = block;
|
||||
m_Blocking = block;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Socket::IsBlocking() const noexcept {
|
||||
return m_Blocking;
|
||||
return m_Blocking;
|
||||
}
|
||||
|
||||
Socket::Type Socket::GetType() const noexcept {
|
||||
return m_Type;
|
||||
return m_Type;
|
||||
}
|
||||
|
||||
SocketHandle Socket::GetHandle() const noexcept {
|
||||
return m_Handle;
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
void Socket::SetStatus(Socket::Status status) {
|
||||
m_Status = status;
|
||||
m_Status = status;
|
||||
}
|
||||
|
||||
Socket::Status Socket::GetStatus() const noexcept {
|
||||
return m_Status;
|
||||
return m_Status;
|
||||
}
|
||||
|
||||
bool Socket::Connect(const std::string& ip, uint16_t port) {
|
||||
IPAddress addr(ip);
|
||||
return Connect(addr, port);
|
||||
IPAddress addr(ip);
|
||||
return Connect(addr, port);
|
||||
}
|
||||
|
||||
std::size_t Socket::Send(const std::string& data) {
|
||||
return this->Send(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
|
||||
return this->Send(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
|
||||
}
|
||||
|
||||
std::size_t Socket::Send(DataBuffer& buffer) {
|
||||
std::string data = buffer.ToString();
|
||||
return this->Send(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
|
||||
std::string data = buffer.ToString();
|
||||
return this->Send(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
|
||||
}
|
||||
|
||||
void Socket::Disconnect() {
|
||||
if (m_Handle < 0)
|
||||
closesocket(m_Handle);
|
||||
m_Status = Disconnected;
|
||||
if (m_Handle < 0)
|
||||
closesocket(m_Handle);
|
||||
m_Status = Disconnected;
|
||||
}
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -14,58 +14,58 @@ namespace network {
|
||||
TCPListener::TCPListener() {}
|
||||
|
||||
TCPListener::~TCPListener() {
|
||||
Destroy();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool TCPListener::Listen(uint16_t port, int maxConnections) {
|
||||
if ((m_Handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
return false;
|
||||
if ((m_Handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
return false;
|
||||
|
||||
struct sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
struct sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (::bind(m_Handle, reinterpret_cast<sockaddr*>(&address), sizeof(address)) < 0)
|
||||
return false;
|
||||
if (::bind(m_Handle, reinterpret_cast<sockaddr*>(&address), sizeof(address)) < 0)
|
||||
return false;
|
||||
|
||||
if (::listen(m_Handle, maxConnections) < 0)
|
||||
return false;
|
||||
if (::listen(m_Handle, maxConnections) < 0)
|
||||
return false;
|
||||
|
||||
m_Port = port;
|
||||
m_MaxConnections = maxConnections;
|
||||
m_Port = port;
|
||||
m_MaxConnections = maxConnections;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCPListener::Accept(TCPSocket& newSocket) {
|
||||
int addrlen = sizeof(newSocket.m_RemoteAddr);
|
||||
if ((newSocket.m_Handle = ::accept(m_Handle, reinterpret_cast<sockaddr*>(&newSocket.m_RemoteAddr),
|
||||
reinterpret_cast<socklen_t*>(&addrlen))) < 0)
|
||||
return false;
|
||||
newSocket.SetStatus(Socket::Status::Connected);
|
||||
newSocket.SetBlocking(false);
|
||||
return true;
|
||||
int addrlen = sizeof(newSocket.m_RemoteAddr);
|
||||
if ((newSocket.m_Handle = ::accept(m_Handle, reinterpret_cast<sockaddr*>(&newSocket.m_RemoteAddr),
|
||||
reinterpret_cast<socklen_t*>(&addrlen))) < 0)
|
||||
return false;
|
||||
newSocket.SetStatus(Socket::Status::Connected);
|
||||
newSocket.SetBlocking(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCPListener::Destroy() {
|
||||
if (m_Handle < 0)
|
||||
::closesocket(m_Handle);
|
||||
if (m_Handle < 0)
|
||||
::closesocket(m_Handle);
|
||||
}
|
||||
|
||||
bool TCPListener::Close() {
|
||||
if (::shutdown(m_Handle, SD_BOTH) == 0)
|
||||
return true;
|
||||
return false;
|
||||
if (::shutdown(m_Handle, SD_BOTH) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TCPListener::SetBlocking(bool blocking) {
|
||||
unsigned long mode = blocking ? 0 : 1;
|
||||
unsigned long mode = blocking ? 0 : 1;
|
||||
|
||||
if (::ioctlsocket(m_Handle, FIONBIO, &mode) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (::ioctlsocket(m_Handle, FIONBIO, &mode) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace td
|
||||
@@ -14,132 +14,132 @@ namespace td {
|
||||
namespace network {
|
||||
|
||||
TCPSocket::TCPSocket() : Socket(Socket::TCP), m_Port(0) {
|
||||
m_Handle = static_cast<SocketHandle>(INVALID_SOCKET);
|
||||
m_Handle = static_cast<SocketHandle>(INVALID_SOCKET);
|
||||
}
|
||||
|
||||
bool TCPSocket::Connect(const IPAddress& address, unsigned short port) {
|
||||
if (this->GetStatus() == Connected)
|
||||
return true;
|
||||
if (this->GetStatus() == Connected)
|
||||
return true;
|
||||
|
||||
struct addrinfo hints {};
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
struct addrinfo hints {};
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
|
||||
struct addrinfo* result = nullptr;
|
||||
struct addrinfo* result = nullptr;
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
if (::getaddrinfo(address.ToString().c_str(), std::to_string(static_cast<int>(port)).c_str(), &hints, &result) != 0) {
|
||||
std::cerr << "Failed to get address info !\n";
|
||||
return false;
|
||||
}
|
||||
if (::getaddrinfo(address.ToString().c_str(), std::to_string(static_cast<int>(port)).c_str(), &hints, &result) != 0) {
|
||||
std::cerr << "Failed to get address info !\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_Handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
std::cerr << "Failed to create socket !\n";
|
||||
return false;
|
||||
}
|
||||
if ((m_Handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
std::cerr << "Failed to create socket !\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct addrinfo* ptr = nullptr;
|
||||
for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
|
||||
struct sockaddr* sockaddr = ptr->ai_addr;
|
||||
if (::connect(m_Handle, sockaddr, sizeof(sockaddr_in)) != 0) {
|
||||
std::cerr << "Failed to connect with this address !\n";
|
||||
continue;
|
||||
}
|
||||
m_RemoteAddr = *sockaddr;
|
||||
break;
|
||||
}
|
||||
struct addrinfo* ptr = nullptr;
|
||||
for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
|
||||
struct sockaddr* sockaddr = ptr->ai_addr;
|
||||
if (::connect(m_Handle, sockaddr, sizeof(sockaddr_in)) != 0) {
|
||||
std::cerr << "Failed to connect with this address !\n";
|
||||
continue;
|
||||
}
|
||||
m_RemoteAddr = *sockaddr;
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
freeaddrinfo(result);
|
||||
|
||||
if (!ptr) {
|
||||
std::cerr << "Could not find a suitable interface for connecting !\n";
|
||||
return false;
|
||||
}
|
||||
if (!ptr) {
|
||||
std::cerr << "Could not find a suitable interface for connecting !\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
this->SetStatus(Connected);
|
||||
m_RemoteIP = address;
|
||||
m_Port = port;
|
||||
return true;
|
||||
this->SetStatus(Connected);
|
||||
m_RemoteIP = address;
|
||||
m_Port = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t TCPSocket::Send(const unsigned char* data, size_t size) {
|
||||
if (this->GetStatus() != Connected)
|
||||
return 0;
|
||||
if (this->GetStatus() != Connected)
|
||||
return 0;
|
||||
|
||||
size_t sent = 0;
|
||||
size_t sent = 0;
|
||||
|
||||
while (sent < size) {
|
||||
int cur = ::send(m_Handle, reinterpret_cast<const char*>(data + sent), size - sent, 0);
|
||||
if (cur <= 0) {
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
sent += static_cast<std::size_t>(cur);
|
||||
}
|
||||
while (sent < size) {
|
||||
int cur = ::send(m_Handle, reinterpret_cast<const char*>(data + sent), size - sent, 0);
|
||||
if (cur <= 0) {
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
sent += static_cast<std::size_t>(cur);
|
||||
}
|
||||
|
||||
return sent;
|
||||
return sent;
|
||||
}
|
||||
|
||||
std::size_t TCPSocket::Receive(DataBuffer& buffer, std::size_t amount) {
|
||||
buffer.Resize(amount);
|
||||
buffer.SetReadOffset(0);
|
||||
buffer.Resize(amount);
|
||||
buffer.SetReadOffset(0);
|
||||
|
||||
int recvAmount = ::recv(m_Handle, reinterpret_cast<char*>(buffer.data()), amount, 0);
|
||||
if (recvAmount <= 0) {
|
||||
int recvAmount = ::recv(m_Handle, reinterpret_cast<char*>(buffer.data()), amount, 0);
|
||||
if (recvAmount <= 0) {
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
int err = WSAGetLastError();
|
||||
int err = WSAGetLastError();
|
||||
#else
|
||||
int err = errno;
|
||||
int err = errno;
|
||||
#endif
|
||||
if (err == WOULDBLOCK) {
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
if (err == WOULDBLOCK) {
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Disconnect();
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
buffer.Resize(static_cast<std::size_t>(recvAmount));
|
||||
return static_cast<std::size_t>(recvAmount);
|
||||
Disconnect();
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
buffer.Resize(static_cast<std::size_t>(recvAmount));
|
||||
return static_cast<std::size_t>(recvAmount);
|
||||
}
|
||||
|
||||
DataBuffer TCPSocket::Receive(std::size_t amount) {
|
||||
std::unique_ptr<char[]> buf(new char[amount]);
|
||||
std::unique_ptr<char[]> buf(new char[amount]);
|
||||
|
||||
int received = ::recv(m_Handle, buf.get(), amount, 0);
|
||||
int received = ::recv(m_Handle, buf.get(), amount, 0);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received <= 0) {
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
int err = WSAGetLastError();
|
||||
int err = WSAGetLastError();
|
||||
#else
|
||||
int err = errno;
|
||||
int err = errno;
|
||||
#endif
|
||||
if (err == WOULDBLOCK)
|
||||
return DataBuffer();
|
||||
if (err == WOULDBLOCK)
|
||||
return DataBuffer();
|
||||
|
||||
Disconnect();
|
||||
return DataBuffer();
|
||||
}
|
||||
Disconnect();
|
||||
return DataBuffer();
|
||||
}
|
||||
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
}
|
||||
|
||||
TCPSocket::TCPSocket(TCPSocket&& other) : Socket(TCP) {
|
||||
m_Handle = other.m_Handle;
|
||||
m_Port = other.m_Port;
|
||||
m_RemoteAddr = other.m_RemoteAddr;
|
||||
m_RemoteIP = other.m_RemoteIP;
|
||||
SetStatus(other.GetStatus());
|
||||
SetBlocking(other.IsBlocking());
|
||||
other.m_Handle = static_cast<SocketHandle>(INVALID_SOCKET);
|
||||
m_Handle = other.m_Handle;
|
||||
m_Port = other.m_Port;
|
||||
m_RemoteAddr = other.m_RemoteAddr;
|
||||
m_RemoteIP = other.m_RemoteIP;
|
||||
SetStatus(other.GetStatus());
|
||||
SetBlocking(other.IsBlocking());
|
||||
other.m_Handle = static_cast<SocketHandle>(INVALID_SOCKET);
|
||||
}
|
||||
|
||||
void SendPacket(const DataBuffer& data, network::TCPSocket& socket) {
|
||||
DataBuffer compressed = utils::Compress(data);
|
||||
socket.Send(reinterpret_cast<const std::uint8_t*>(compressed.ToString().data()), compressed.GetSize());
|
||||
DataBuffer compressed = utils::Compress(data);
|
||||
socket.Send(reinterpret_cast<const std::uint8_t*>(compressed.ToString().data()), compressed.GetSize());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,92 +12,91 @@ namespace td {
|
||||
namespace network {
|
||||
|
||||
UDPSocket::UDPSocket()
|
||||
: Socket(Socket::UDP), m_Port(0)
|
||||
{
|
||||
m_Handle = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
: Socket(Socket::UDP), m_Port(0) {
|
||||
m_Handle = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
bool UDPSocket::Connect(const IPAddress& address, unsigned short port) {
|
||||
if (this->GetStatus() == Connected)
|
||||
return true;
|
||||
if (this->GetStatus() == Connected)
|
||||
return true;
|
||||
|
||||
m_RemoteAddr.sin_port = htons(port);
|
||||
m_RemoteAddr.sin_family = AF_INET;
|
||||
m_RemoteAddr.sin_addr.s_addr = inet_addr(address.ToString().c_str());
|
||||
m_RemoteAddr.sin_port = htons(port);
|
||||
m_RemoteAddr.sin_family = AF_INET;
|
||||
m_RemoteAddr.sin_addr.s_addr = inet_addr(address.ToString().c_str());
|
||||
|
||||
this->SetStatus(Connected);
|
||||
m_RemoteIP = IPAddress(address);
|
||||
m_Port = port;
|
||||
return true;
|
||||
this->SetStatus(Connected);
|
||||
m_RemoteIP = IPAddress(address);
|
||||
m_Port = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t UDPSocket::Send(const unsigned char* data, std::size_t size) {
|
||||
std::size_t sent = 0;
|
||||
std::size_t sent = 0;
|
||||
|
||||
if (this->GetStatus() != Connected)
|
||||
return 0;
|
||||
if (this->GetStatus() != Connected)
|
||||
return 0;
|
||||
|
||||
while (sent < size) {
|
||||
int cur = ::sendto(m_Handle, reinterpret_cast<const char*>(data + sent), size - sent, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), sizeof(sockaddr_in));
|
||||
if (cur <= 0) {
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
sent += static_cast<std::size_t>(cur);
|
||||
}
|
||||
while (sent < size) {
|
||||
int cur = ::sendto(m_Handle, reinterpret_cast<const char*>(data + sent), size - sent, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), sizeof(sockaddr_in));
|
||||
if (cur <= 0) {
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
sent += static_cast<std::size_t>(cur);
|
||||
}
|
||||
|
||||
return sent;
|
||||
return sent;
|
||||
}
|
||||
|
||||
DataBuffer UDPSocket::Receive(std::size_t amount) {
|
||||
std::unique_ptr<char[]> buf(new char[amount]);
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
std::unique_ptr<char[]> buf(new char[amount]);
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
|
||||
int received = ::recvfrom(m_Handle, buf.get(), amount, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), &slen);
|
||||
int received = ::recvfrom(m_Handle, buf.get(), amount, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), &slen);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received <= 0) {
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
int err = WSAGetLastError();
|
||||
int err = WSAGetLastError();
|
||||
#else
|
||||
int err = errno;
|
||||
int err = errno;
|
||||
#endif
|
||||
if (err == WOULDBLOCK)
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
if (err == WOULDBLOCK)
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
|
||||
Disconnect();
|
||||
return DataBuffer();
|
||||
}
|
||||
Disconnect();
|
||||
return DataBuffer();
|
||||
}
|
||||
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
return DataBuffer(std::string(buf.get(), static_cast<std::size_t>(received)));
|
||||
}
|
||||
|
||||
std::size_t UDPSocket::Receive(DataBuffer& buffer, std::size_t amount) {
|
||||
buffer.Resize(amount);
|
||||
buffer.SetReadOffset(0);
|
||||
buffer.Resize(amount);
|
||||
buffer.SetReadOffset(0);
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
|
||||
int recvAmount = ::recvfrom(m_Handle, reinterpret_cast<char*>(buffer.data()), amount, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), &slen);
|
||||
if (recvAmount <= 0) {
|
||||
int recvAmount = ::recvfrom(m_Handle, reinterpret_cast<char*>(buffer.data()), amount, 0,
|
||||
reinterpret_cast<sockaddr*>(&m_RemoteAddr), &slen);
|
||||
if (recvAmount <= 0) {
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
int err = WSAGetLastError();
|
||||
int err = WSAGetLastError();
|
||||
#else
|
||||
int err = errno;
|
||||
int err = errno;
|
||||
#endif
|
||||
if (err == WOULDBLOCK) {
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
if (err == WOULDBLOCK) {
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Disconnect();
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
buffer.Resize(static_cast<std::size_t>(recvAmount));
|
||||
return static_cast<std::size_t>(recvAmount);
|
||||
Disconnect();
|
||||
buffer.Clear();
|
||||
return 0;
|
||||
}
|
||||
buffer.Resize(static_cast<std::size_t>(recvAmount));
|
||||
return static_cast<std::size_t>(recvAmount);
|
||||
}
|
||||
|
||||
} // ns network
|
||||
|
||||
@@ -4,33 +4,33 @@ namespace td {
|
||||
namespace protocol {
|
||||
|
||||
void PacketDispatcher::RegisterHandler(PacketType type, PacketHandler* handler) {
|
||||
auto found = std::find(m_Handlers[type].begin(), m_Handlers[type].end(), handler);
|
||||
if (found == m_Handlers[type].end())
|
||||
m_Handlers[type].push_back(handler);
|
||||
auto found = std::find(m_Handlers[type].begin(), m_Handlers[type].end(), handler);
|
||||
if (found == m_Handlers[type].end())
|
||||
m_Handlers[type].push_back(handler);
|
||||
}
|
||||
|
||||
void PacketDispatcher::UnregisterHandler(PacketType type, PacketHandler* handler) {
|
||||
auto found = std::find(m_Handlers[type].begin(), m_Handlers[type].end(), handler);
|
||||
if (found != m_Handlers[type].end())
|
||||
m_Handlers[type].erase(found);
|
||||
auto found = std::find(m_Handlers[type].begin(), m_Handlers[type].end(), handler);
|
||||
if (found != m_Handlers[type].end())
|
||||
m_Handlers[type].erase(found);
|
||||
}
|
||||
|
||||
void PacketDispatcher::UnregisterHandler(PacketHandler* handler) {
|
||||
for (auto& pair : m_Handlers) {
|
||||
if (pair.second.empty()) continue;
|
||||
for (auto& pair : m_Handlers) {
|
||||
if (pair.second.empty()) continue;
|
||||
|
||||
PacketType type = pair.first;
|
||||
PacketType type = pair.first;
|
||||
|
||||
m_Handlers[type].erase(std::remove(m_Handlers[type].begin(), m_Handlers[type].end(), handler), m_Handlers[type].end());
|
||||
}
|
||||
m_Handlers[type].erase(std::remove(m_Handlers[type].begin(), m_Handlers[type].end(), handler), m_Handlers[type].end());
|
||||
}
|
||||
}
|
||||
|
||||
void PacketDispatcher::Dispatch(const PacketPtr& packet) {
|
||||
if (!packet) return;
|
||||
if (!packet) return;
|
||||
|
||||
PacketType type = packet->GetType();
|
||||
for (PacketHandler* handler : m_Handlers[type])
|
||||
packet->Dispatch(handler);
|
||||
PacketType type = packet->GetType();
|
||||
for (PacketHandler* handler : m_Handlers[type])
|
||||
packet->Dispatch(handler);
|
||||
}
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -9,38 +9,38 @@ namespace PacketFactory {
|
||||
using PacketCreator = std::function<PacketPtr()>;
|
||||
|
||||
static std::map<PacketType, PacketCreator> packets = {
|
||||
{PacketType::PlayerLogin, []() -> PacketPtr {return std::make_unique<PlayerLoginPacket>();} },
|
||||
{PacketType::WorldBeginData, []() -> PacketPtr {return std::make_unique<WorldBeginDataPacket>();} },
|
||||
{PacketType::WorldData, []() -> PacketPtr {return std::make_unique<WorldDataPacket>();} },
|
||||
{PacketType::KeepAlive, []() -> PacketPtr {return std::make_unique<KeepAlivePacket>();} },
|
||||
{PacketType::UpdateMoney, []() -> PacketPtr {return std::make_unique<UpdateMoneyPacket>();} },
|
||||
{PacketType::UpdateEXP, []() -> PacketPtr {return std::make_unique<UpdateExpPacket>();} },
|
||||
{PacketType::UpdateLobbyTime, []() -> PacketPtr {return std::make_unique<UpdateLobbyTimePacket>(); } },
|
||||
{PacketType::UpdateGameState, []() -> PacketPtr {return std::make_unique<UpdateGameStatePacket>(); } },
|
||||
{PacketType::PlayerList, []() -> PacketPtr {return std::make_unique<PlayerListPacket>(); } },
|
||||
{PacketType::PlayerJoin, []() -> PacketPtr {return std::make_unique<PlayerJoinPacket>(); } },
|
||||
{PacketType::PlayerLeave, []() -> PacketPtr {return std::make_unique<PlayerLeavePacket>(); } },
|
||||
{PacketType::ConnectionInfo, []() -> PacketPtr {return std::make_unique<ConnexionInfoPacket>(); } },
|
||||
{PacketType::SelectTeam, []() -> PacketPtr {return std::make_unique<SelectTeamPacket>(); } },
|
||||
{PacketType::UpdatePlayerTeam, []() -> PacketPtr {return std::make_unique<UpdatePlayerTeamPacket>(); } },
|
||||
{PacketType::Disconnect, []() -> PacketPtr {return std::make_unique<DisconnectPacket>(); } },
|
||||
{PacketType::ServerTps, []() -> PacketPtr {return std::make_unique<ServerTpsPacket>(); } },
|
||||
{PacketType::SpawnMob, []() -> PacketPtr {return std::make_unique<SpawnMobPacket>(); } },
|
||||
{PacketType::PlaceTower, []() -> PacketPtr {return std::make_unique<PlaceTowerPacket>(); } },
|
||||
{PacketType::WorldAddTower, []() -> PacketPtr {return std::make_unique<WorldAddTowerPacket>(); } },
|
||||
{PacketType::RemoveTower, []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
|
||||
{PacketType::SendMobs, []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
|
||||
{PacketType::UpgradeTower, []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
|
||||
{PacketType::UpdateCastleLife, []() -> PacketPtr {return std::make_unique<UpdateCastleLifePacket>(); } },
|
||||
{PacketType::UpdateMobStates, []() -> PacketPtr {return std::make_unique<UpdateMobStatesPacket>(); } },
|
||||
{PacketType::PlayerBuyItem, []() -> PacketPtr {return std::make_unique<PlayerBuyItemPacket>(); } },
|
||||
{PacketType::PlayerBuyMobUpgrade, []() -> PacketPtr {return std::make_unique<PlayerBuyMobUpgradePacket>(); } },
|
||||
{PacketType::PlayerLogin, []() -> PacketPtr {return std::make_unique<PlayerLoginPacket>();} },
|
||||
{PacketType::WorldBeginData, []() -> PacketPtr {return std::make_unique<WorldBeginDataPacket>();} },
|
||||
{PacketType::WorldData, []() -> PacketPtr {return std::make_unique<WorldDataPacket>();} },
|
||||
{PacketType::KeepAlive, []() -> PacketPtr {return std::make_unique<KeepAlivePacket>();} },
|
||||
{PacketType::UpdateMoney, []() -> PacketPtr {return std::make_unique<UpdateMoneyPacket>();} },
|
||||
{PacketType::UpdateEXP, []() -> PacketPtr {return std::make_unique<UpdateExpPacket>();} },
|
||||
{PacketType::UpdateLobbyTime, []() -> PacketPtr {return std::make_unique<UpdateLobbyTimePacket>(); } },
|
||||
{PacketType::UpdateGameState, []() -> PacketPtr {return std::make_unique<UpdateGameStatePacket>(); } },
|
||||
{PacketType::PlayerList, []() -> PacketPtr {return std::make_unique<PlayerListPacket>(); } },
|
||||
{PacketType::PlayerJoin, []() -> PacketPtr {return std::make_unique<PlayerJoinPacket>(); } },
|
||||
{PacketType::PlayerLeave, []() -> PacketPtr {return std::make_unique<PlayerLeavePacket>(); } },
|
||||
{PacketType::ConnectionInfo, []() -> PacketPtr {return std::make_unique<ConnexionInfoPacket>(); } },
|
||||
{PacketType::SelectTeam, []() -> PacketPtr {return std::make_unique<SelectTeamPacket>(); } },
|
||||
{PacketType::UpdatePlayerTeam, []() -> PacketPtr {return std::make_unique<UpdatePlayerTeamPacket>(); } },
|
||||
{PacketType::Disconnect, []() -> PacketPtr {return std::make_unique<DisconnectPacket>(); } },
|
||||
{PacketType::ServerTps, []() -> PacketPtr {return std::make_unique<ServerTpsPacket>(); } },
|
||||
{PacketType::SpawnMob, []() -> PacketPtr {return std::make_unique<SpawnMobPacket>(); } },
|
||||
{PacketType::PlaceTower, []() -> PacketPtr {return std::make_unique<PlaceTowerPacket>(); } },
|
||||
{PacketType::WorldAddTower, []() -> PacketPtr {return std::make_unique<WorldAddTowerPacket>(); } },
|
||||
{PacketType::RemoveTower, []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
|
||||
{PacketType::SendMobs, []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
|
||||
{PacketType::UpgradeTower, []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
|
||||
{PacketType::UpdateCastleLife, []() -> PacketPtr {return std::make_unique<UpdateCastleLifePacket>(); } },
|
||||
{PacketType::UpdateMobStates, []() -> PacketPtr {return std::make_unique<UpdateMobStatesPacket>(); } },
|
||||
{PacketType::PlayerBuyItem, []() -> PacketPtr {return std::make_unique<PlayerBuyItemPacket>(); } },
|
||||
{PacketType::PlayerBuyMobUpgrade, []() -> PacketPtr {return std::make_unique<PlayerBuyMobUpgradePacket>(); } },
|
||||
};
|
||||
|
||||
PacketPtr CreatePacket(PacketType type, DataBuffer& buffer) {
|
||||
PacketPtr packet = packets[type]();
|
||||
packet->Deserialize(buffer);
|
||||
return packet;
|
||||
PacketPtr packet = packets[type]();
|
||||
packet->Deserialize(buffer);
|
||||
return packet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,559 +13,559 @@ const int BITS_IN_BYTE = 8;
|
||||
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
|
||||
|
||||
static unsigned int countBits(unsigned int number) {
|
||||
// log function in base 2
|
||||
// take only integer part
|
||||
return static_cast<unsigned int>(std::log2(number) + 1);
|
||||
// log function in base 2
|
||||
// take only integer part
|
||||
return static_cast<unsigned int>(std::log2(number) + 1);
|
||||
}
|
||||
|
||||
void Packet::WritePacketID(DataBuffer& data, bool packetID) const {
|
||||
if (packetID)
|
||||
data << GetID();
|
||||
if (packetID)
|
||||
data << GetID();
|
||||
}
|
||||
|
||||
static DataBuffer& operator<<(DataBuffer& buffer, game::TilePtr tile) {
|
||||
buffer << tile->GetType();
|
||||
buffer << tile->GetType();
|
||||
|
||||
switch (tile->GetType()) {
|
||||
switch (tile->GetType()) {
|
||||
|
||||
case game::TileType::Tower: {
|
||||
const game::TowerTile* towerTile = dynamic_cast<const game::TowerTile*>(tile.get());
|
||||
buffer << towerTile->color_palette_ref << towerTile->team_owner;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Tower: {
|
||||
const game::TowerTile* towerTile = dynamic_cast<const game::TowerTile*>(tile.get());
|
||||
buffer << towerTile->color_palette_ref << towerTile->team_owner;
|
||||
break;
|
||||
}
|
||||
|
||||
case game::TileType::Walk: {
|
||||
const game::WalkableTile* walkTile = dynamic_cast<const game::WalkableTile*>(tile.get());
|
||||
buffer << walkTile->direction;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Walk: {
|
||||
const game::WalkableTile* walkTile = dynamic_cast<const game::WalkableTile*>(tile.get());
|
||||
buffer << walkTile->direction;
|
||||
break;
|
||||
}
|
||||
|
||||
case game::TileType::Decoration: {
|
||||
const game::DecorationTile* decoTile = dynamic_cast<const game::DecorationTile*>(tile.get());
|
||||
buffer << decoTile->color_palette_ref;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Decoration: {
|
||||
const game::DecorationTile* decoTile = dynamic_cast<const game::DecorationTile*>(tile.get());
|
||||
buffer << decoTile->color_palette_ref;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static DataBuffer& operator>>(DataBuffer& buffer, game::TilePtr& tile) {
|
||||
game::TileType tileType;
|
||||
buffer >> tileType;
|
||||
switch (tileType) {
|
||||
case game::TileType::Tower: {
|
||||
auto tilePtr = std::make_shared<game::TowerTile>();
|
||||
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Walk: {
|
||||
auto tilePtr = std::make_shared<game::WalkableTile>();
|
||||
buffer >> tilePtr->direction;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Decoration: {
|
||||
auto tilePtr = std::make_shared<game::DecorationTile>();
|
||||
buffer >> tilePtr->color_palette_ref;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return buffer;
|
||||
game::TileType tileType;
|
||||
buffer >> tileType;
|
||||
switch (tileType) {
|
||||
case game::TileType::Tower: {
|
||||
auto tilePtr = std::make_shared<game::TowerTile>();
|
||||
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Walk: {
|
||||
auto tilePtr = std::make_shared<game::WalkableTile>();
|
||||
buffer >> tilePtr->direction;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
case game::TileType::Decoration: {
|
||||
auto tilePtr = std::make_shared<game::DecorationTile>();
|
||||
buffer >> tilePtr->color_palette_ref;
|
||||
tile = tilePtr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
DataBuffer PlayerLoginPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerName;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerName;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerLoginPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_PlayerName;
|
||||
data >> m_PlayerName;
|
||||
}
|
||||
|
||||
DataBuffer WorldBeginDataPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
const game::TowerTileColorPalette& towerTilePalette = m_Header.m_World->GetTowerTileColorPalette();
|
||||
const std::vector<Color>& decoTilePalette = m_Header.m_World->GetDecorationPalette();
|
||||
DataBuffer data;
|
||||
const game::TowerTileColorPalette& towerTilePalette = m_Header.m_World->GetTowerTileColorPalette();
|
||||
const std::vector<Color>& decoTilePalette = m_Header.m_World->GetDecorationPalette();
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
WritePacketID(data, packetID);
|
||||
|
||||
data << towerTilePalette << m_Header.m_World->GetWalkableTileColor()
|
||||
<< static_cast<std::uint16_t>(decoTilePalette.size());
|
||||
data << towerTilePalette << m_Header.m_World->GetWalkableTileColor()
|
||||
<< static_cast<std::uint16_t>(decoTilePalette.size());
|
||||
|
||||
// deco color palette
|
||||
std::size_t bufferSize = data.GetSize();
|
||||
data.Resize(bufferSize + decoTilePalette.size() * sizeof(Color));
|
||||
// deco color palette
|
||||
std::size_t bufferSize = data.GetSize();
|
||||
data.Resize(bufferSize + decoTilePalette.size() * sizeof(Color));
|
||||
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(Color));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(Color));
|
||||
|
||||
data << m_Header.m_World->GetBackgroundColor();
|
||||
data << m_Header.m_World->GetBackgroundColor();
|
||||
|
||||
const game::Spawn& redSpawn = m_Header.m_World->GetRedTeam().GetSpawn(), blueSpawn = m_Header.m_World->GetBlueTeam().GetSpawn();
|
||||
const game::TeamCastle& redCastle = m_Header.m_World->GetRedTeam().GetCastle(), blueCastle = m_Header.m_World->GetBlueTeam().GetCastle();
|
||||
const game::Spawn& redSpawn = m_Header.m_World->GetRedTeam().GetSpawn(), blueSpawn = m_Header.m_World->GetBlueTeam().GetSpawn();
|
||||
const game::TeamCastle& redCastle = m_Header.m_World->GetRedTeam().GetCastle(), blueCastle = m_Header.m_World->GetBlueTeam().GetCastle();
|
||||
|
||||
data << redSpawn << static_cast<utils::shape::Rectangle>(redCastle);
|
||||
data << blueSpawn << static_cast<utils::shape::Rectangle>(blueCastle);
|
||||
data << redSpawn << static_cast<utils::shape::Rectangle>(redCastle);
|
||||
data << blueSpawn << static_cast<utils::shape::Rectangle>(blueCastle);
|
||||
|
||||
// tile palette
|
||||
data << static_cast<std::uint64_t>(m_Header.m_World->GetTilePalette().size());
|
||||
// tile palette
|
||||
data << static_cast<std::uint64_t>(m_Header.m_World->GetTilePalette().size());
|
||||
|
||||
for (game::TilePtr tile : m_Header.m_World->GetTilePalette()) {
|
||||
data << tile;
|
||||
}
|
||||
for (game::TilePtr tile : m_Header.m_World->GetTilePalette()) {
|
||||
data << tile;
|
||||
}
|
||||
|
||||
data << m_Header.m_World->GetSpawnColors();
|
||||
data << m_Header.m_World->GetSpawnColors();
|
||||
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void WorldBeginDataPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_Header.m_TowerPlacePalette >> m_Header.m_WalkablePalette;
|
||||
data >> m_Header.m_TowerPlacePalette >> m_Header.m_WalkablePalette;
|
||||
|
||||
std::uint16_t decoPaletteSize;
|
||||
data >> decoPaletteSize;
|
||||
std::uint16_t decoPaletteSize;
|
||||
data >> decoPaletteSize;
|
||||
|
||||
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(Color);
|
||||
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(Color);
|
||||
|
||||
m_Header.m_DecorationPalette.resize(decoPaletteSize);
|
||||
m_Header.m_DecorationPalette.resize(decoPaletteSize);
|
||||
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(m_Header.m_DecorationPalette.data()), data.data() + data.GetReadOffset(), decoPalletteSizeByte);
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(m_Header.m_DecorationPalette.data()), data.data() + data.GetReadOffset(), decoPalletteSizeByte);
|
||||
|
||||
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
|
||||
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
|
||||
|
||||
data >> m_Header.m_Background;
|
||||
data >> m_Header.m_Background;
|
||||
|
||||
utils::shape::Rectangle redCastle, blueCastle;
|
||||
utils::shape::Rectangle redCastle, blueCastle;
|
||||
|
||||
data >> m_Header.m_RedSpawn >> redCastle;
|
||||
data >> m_Header.m_BlueSpawn >> blueCastle;
|
||||
data >> m_Header.m_RedSpawn >> redCastle;
|
||||
data >> m_Header.m_BlueSpawn >> blueCastle;
|
||||
|
||||
m_Header.m_RedCastle.SetShape(redCastle);
|
||||
m_Header.m_BlueCastle.SetShape(blueCastle);
|
||||
m_Header.m_RedCastle.SetShape(redCastle);
|
||||
m_Header.m_BlueCastle.SetShape(blueCastle);
|
||||
|
||||
std::uint64_t tilePaletteSize;
|
||||
data >> tilePaletteSize;
|
||||
std::uint64_t tilePaletteSize;
|
||||
data >> tilePaletteSize;
|
||||
|
||||
m_Header.m_TilePalette.reserve(tilePaletteSize);
|
||||
m_Header.m_TilePalette.reserve(tilePaletteSize);
|
||||
|
||||
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
|
||||
game::TilePtr tile;
|
||||
data >> tile;
|
||||
m_Header.m_TilePalette.push_back(tile);
|
||||
}
|
||||
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
|
||||
game::TilePtr tile;
|
||||
data >> tile;
|
||||
m_Header.m_TilePalette.push_back(tile);
|
||||
}
|
||||
|
||||
data >> m_Header.m_SpawnColorPalette;
|
||||
data >> m_Header.m_SpawnColorPalette;
|
||||
}
|
||||
|
||||
typedef std::vector<uint64_t> ChunkPackedData;
|
||||
|
||||
DataBuffer WorldDataPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
WritePacketID(data, packetID);
|
||||
|
||||
data << m_World->GetChunks().size();
|
||||
for (const auto& pair : m_World->GetChunks()) {
|
||||
game::ChunkCoord coords = pair.first;
|
||||
game::ChunkPtr chunk = pair.second;
|
||||
data << m_World->GetChunks().size();
|
||||
for (const auto& pair : m_World->GetChunks()) {
|
||||
game::ChunkCoord coords = pair.first;
|
||||
game::ChunkPtr chunk = pair.second;
|
||||
|
||||
data << coords.x << coords.y << static_cast<std::uint64_t>(chunk->palette.size());
|
||||
data << coords.x << coords.y << static_cast<std::uint64_t>(chunk->palette.size());
|
||||
|
||||
std::size_t bufferSize = data.GetSize();
|
||||
data.Resize(data.GetSize() + chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, chunk->palette.data(), chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||
std::size_t bufferSize = data.GetSize();
|
||||
data.Resize(data.GetSize() + chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, chunk->palette.data(), chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||
|
||||
std::uint8_t bitsPerTile = countBits(chunk->palette.size());
|
||||
std::uint8_t bitsPerTile = countBits(chunk->palette.size());
|
||||
|
||||
game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
|
||||
game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
|
||||
|
||||
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
|
||||
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
|
||||
|
||||
for (unsigned int tileNumber = 0; tileNumber < game::Chunk::ChunkSize; tileNumber++) {
|
||||
std::size_t startLong = static_cast<std::size_t>((tileNumber * bitsPerTile) / BITS_IN_LONG);
|
||||
std::size_t startOffset = static_cast<std::size_t>((tileNumber * bitsPerTile) % BITS_IN_LONG);
|
||||
std::size_t endLong = static_cast<std::size_t>(((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG);
|
||||
for (unsigned int tileNumber = 0; tileNumber < game::Chunk::ChunkSize; tileNumber++) {
|
||||
std::size_t startLong = static_cast<std::size_t>((tileNumber * bitsPerTile) / BITS_IN_LONG);
|
||||
std::size_t startOffset = static_cast<std::size_t>((tileNumber * bitsPerTile) % BITS_IN_LONG);
|
||||
std::size_t endLong = static_cast<std::size_t>(((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG);
|
||||
|
||||
std::uint64_t value = static_cast<std::uint64_t>(chunk->tiles[tileNumber]);
|
||||
std::uint64_t value = static_cast<std::uint64_t>(chunk->tiles[tileNumber]);
|
||||
|
||||
value &= individualValueMask;
|
||||
value &= individualValueMask;
|
||||
|
||||
chunkData[startLong] |= (value << startOffset);
|
||||
chunkData[startLong] |= (value << startOffset);
|
||||
|
||||
if (startLong != endLong) {
|
||||
chunkData[endLong] = (value >> (BITS_IN_LONG - startOffset));
|
||||
}
|
||||
}
|
||||
if (startLong != endLong) {
|
||||
chunkData[endLong] = (value >> (BITS_IN_LONG - startOffset));
|
||||
}
|
||||
}
|
||||
|
||||
bufferSize = data.GetSize();
|
||||
data.Resize(data.GetSize() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, chunkData.data(), chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
}
|
||||
return data;
|
||||
bufferSize = data.GetSize();
|
||||
data.Resize(data.GetSize() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data.data()) + bufferSize, chunkData.data(), chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void WorldDataPacket::Deserialize(DataBuffer& data) {
|
||||
std::uint64_t chunkCount;
|
||||
data >> chunkCount;
|
||||
std::uint64_t chunkCount;
|
||||
data >> chunkCount;
|
||||
|
||||
for (std::uint64_t chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) {
|
||||
game::ChunkPtr chunk = std::make_shared<game::Chunk>();
|
||||
for (std::uint64_t chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) {
|
||||
game::ChunkPtr chunk = std::make_shared<game::Chunk>();
|
||||
|
||||
decltype(game::ChunkCoord::x) chunkX, chunkY;
|
||||
data >> chunkX >> chunkY;
|
||||
decltype(game::ChunkCoord::x) chunkX, chunkY;
|
||||
data >> chunkX >> chunkY;
|
||||
|
||||
std::uint64_t chunkPaletteSize;
|
||||
data >> chunkPaletteSize;
|
||||
std::uint64_t chunkPaletteSize;
|
||||
data >> chunkPaletteSize;
|
||||
|
||||
game::ChunkPalette chunkPalette(chunkPaletteSize);
|
||||
game::ChunkPalette chunkPalette(chunkPaletteSize);
|
||||
|
||||
memcpy(reinterpret_cast<void*>(chunkPalette.data()), data.data() + data.GetReadOffset(), chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
|
||||
data.SetReadOffset(data.GetReadOffset() + chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
|
||||
memcpy(reinterpret_cast<void*>(chunkPalette.data()), data.data() + data.GetReadOffset(), chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
|
||||
data.SetReadOffset(data.GetReadOffset() + chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
|
||||
|
||||
chunk->palette = chunkPalette;
|
||||
chunk->palette = chunkPalette;
|
||||
|
||||
std::uint8_t bitsPerTile = countBits(chunkPaletteSize);
|
||||
std::uint8_t bitsPerTile = countBits(chunkPaletteSize);
|
||||
|
||||
// A bitmask that contains bitsPerTile set bits
|
||||
game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
|
||||
// A bitmask that contains bitsPerTile set bits
|
||||
game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
|
||||
|
||||
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
|
||||
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
|
||||
|
||||
memcpy(reinterpret_cast<void*>(chunkData.data()), data.data() + data.GetReadOffset(), chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
data.SetReadOffset(data.GetReadOffset() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
memcpy(reinterpret_cast<void*>(chunkData.data()), data.data() + data.GetReadOffset(), chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
data.SetReadOffset(data.GetReadOffset() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||
|
||||
for (unsigned int tileNumber = 0; tileNumber < game::Chunk::ChunkSize; tileNumber++) {
|
||||
std::size_t startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
|
||||
std::size_t startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
|
||||
std::size_t endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
|
||||
for (unsigned int tileNumber = 0; tileNumber < game::Chunk::ChunkSize; tileNumber++) {
|
||||
std::size_t startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
|
||||
std::size_t startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
|
||||
std::size_t endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
|
||||
|
||||
game::Chunk::ChunkData::value_type value;
|
||||
if (startLong == endLong) {
|
||||
value = (chunkData[startLong] >> startOffset);
|
||||
} else {
|
||||
int endOffset = BITS_IN_LONG - startOffset;
|
||||
value = (chunkData[startLong] >> startOffset | chunkData[endLong] << endOffset);
|
||||
}
|
||||
value &= individualValueMask;
|
||||
game::Chunk::ChunkData::value_type value;
|
||||
if (startLong == endLong) {
|
||||
value = (chunkData[startLong] >> startOffset);
|
||||
} else {
|
||||
int endOffset = BITS_IN_LONG - startOffset;
|
||||
value = (chunkData[startLong] >> startOffset | chunkData[endLong] << endOffset);
|
||||
}
|
||||
value &= individualValueMask;
|
||||
|
||||
chunk->tiles[tileNumber] = value;
|
||||
}
|
||||
chunk->tiles[tileNumber] = value;
|
||||
}
|
||||
|
||||
|
||||
m_WorldData.m_Chunks.insert({ {chunkX, chunkY}, chunk });
|
||||
}
|
||||
m_WorldData.m_Chunks.insert({ {chunkX, chunkY}, chunk });
|
||||
}
|
||||
}
|
||||
|
||||
DataBuffer KeepAlivePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_AliveID;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_AliveID;
|
||||
return data;
|
||||
}
|
||||
|
||||
void KeepAlivePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_AliveID;
|
||||
data >> m_AliveID;
|
||||
}
|
||||
|
||||
DataBuffer UpdateMoneyPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_NewAmount;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_NewAmount;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateMoneyPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_NewAmount;
|
||||
data >> m_NewAmount;
|
||||
}
|
||||
|
||||
DataBuffer UpdateExpPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_NewAmount;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_NewAmount;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateExpPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_NewAmount;
|
||||
data >> m_NewAmount;
|
||||
}
|
||||
|
||||
DataBuffer UpdateLobbyTimePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_RemainingTime;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_RemainingTime;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateLobbyTimePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_RemainingTime;
|
||||
data >> m_RemainingTime;
|
||||
}
|
||||
|
||||
DataBuffer UpdateGameStatePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_GameState;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_GameState;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateGameStatePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_GameState;
|
||||
data >> m_GameState;
|
||||
}
|
||||
|
||||
DataBuffer PlayerListPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint8_t>(m_Players.size());
|
||||
for (auto [playerID, playerInfo] : m_Players) {
|
||||
data << playerID << playerInfo.name << playerInfo.team;
|
||||
}
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint8_t>(m_Players.size());
|
||||
for (auto [playerID, playerInfo] : m_Players) {
|
||||
data << playerID << playerInfo.name << playerInfo.team;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerListPacket::Deserialize(DataBuffer& data) {
|
||||
std::uint8_t playerCount;
|
||||
data >> playerCount;
|
||||
std::uint8_t playerCount;
|
||||
data >> playerCount;
|
||||
|
||||
for (int i = 0; i < playerCount; i++) {
|
||||
std::uint8_t playerID;
|
||||
PlayerInfo playerInfo;
|
||||
data >> playerID >> playerInfo.name >> playerInfo.team;
|
||||
m_Players.insert({ playerID, playerInfo });
|
||||
}
|
||||
for (int i = 0; i < playerCount; i++) {
|
||||
std::uint8_t playerID;
|
||||
PlayerInfo playerInfo;
|
||||
data >> playerID >> playerInfo.name >> playerInfo.team;
|
||||
m_Players.insert({ playerID, playerInfo });
|
||||
}
|
||||
}
|
||||
|
||||
DataBuffer PlayerJoinPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID << m_PlayerName;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID << m_PlayerName;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerJoinPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_PlayerID >> m_PlayerName;
|
||||
data >> m_PlayerID >> m_PlayerName;
|
||||
}
|
||||
|
||||
DataBuffer PlayerLeavePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerLeavePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_PlayerID;
|
||||
data >> m_PlayerID;
|
||||
}
|
||||
|
||||
DataBuffer ConnexionInfoPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_ConnectionID;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_ConnectionID;
|
||||
return data;
|
||||
}
|
||||
|
||||
void ConnexionInfoPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_ConnectionID;
|
||||
data >> m_ConnectionID;
|
||||
}
|
||||
|
||||
DataBuffer SelectTeamPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_SelectedTeam;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_SelectedTeam;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SelectTeamPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_SelectedTeam;
|
||||
data >> m_SelectedTeam;
|
||||
}
|
||||
|
||||
DataBuffer UpdatePlayerTeamPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID << m_SelectedTeam;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_PlayerID << m_SelectedTeam;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdatePlayerTeamPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_PlayerID >> m_SelectedTeam;
|
||||
data >> m_PlayerID >> m_SelectedTeam;
|
||||
}
|
||||
|
||||
DataBuffer DisconnectPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_Reason;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_Reason;
|
||||
return data;
|
||||
}
|
||||
|
||||
void DisconnectPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_Reason;
|
||||
data >> m_Reason;
|
||||
}
|
||||
|
||||
DataBuffer ServerTpsPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TPS << m_PacketSendTime;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TPS << m_PacketSendTime;
|
||||
return data;
|
||||
}
|
||||
|
||||
void ServerTpsPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TPS >> m_PacketSendTime;
|
||||
data >> m_TPS >> m_PacketSendTime;
|
||||
}
|
||||
|
||||
DataBuffer SpawnMobPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_MobID << m_MobType << m_MobLevel << m_MobDirection
|
||||
<< m_Sender << m_MobX << m_MobY;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_MobID << m_MobType << m_MobLevel << m_MobDirection
|
||||
<< m_Sender << m_MobX << m_MobY;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SpawnMobPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_MobID >> m_MobType >> m_MobLevel >> m_MobDirection
|
||||
>> m_Sender >> m_MobX >> m_MobY;
|
||||
data >> m_MobID >> m_MobType >> m_MobLevel >> m_MobDirection
|
||||
>> m_Sender >> m_MobX >> m_MobY;
|
||||
}
|
||||
|
||||
DataBuffer PlaceTowerPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerX << m_TowerY << m_TowerType;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerX << m_TowerY << m_TowerType;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlaceTowerPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TowerX >> m_TowerY >> m_TowerType;
|
||||
data >> m_TowerX >> m_TowerY >> m_TowerType;
|
||||
}
|
||||
|
||||
DataBuffer WorldAddTowerPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID << m_TowerX << m_TowerY << m_TowerType << m_Builder;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID << m_TowerX << m_TowerY << m_TowerType << m_Builder;
|
||||
return data;
|
||||
}
|
||||
|
||||
void WorldAddTowerPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TowerID >> m_TowerX >> m_TowerY >> m_TowerType >> m_Builder;
|
||||
data >> m_TowerID >> m_TowerX >> m_TowerY >> m_TowerType >> m_Builder;
|
||||
}
|
||||
|
||||
DataBuffer RemoveTowerPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID;
|
||||
return data;
|
||||
}
|
||||
|
||||
void RemoveTowerPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TowerID;
|
||||
data >> m_TowerID;
|
||||
}
|
||||
|
||||
DataBuffer SendMobsPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint8_t>(m_MobSends.size());
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint8_t>(m_MobSends.size());
|
||||
|
||||
data.WriteSome(reinterpret_cast<const std::uint8_t*>(m_MobSends.data()), m_MobSends.size() * sizeof(m_MobSends));
|
||||
data.WriteSome(reinterpret_cast<const std::uint8_t*>(m_MobSends.data()), m_MobSends.size() * sizeof(m_MobSends));
|
||||
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SendMobsPacket::Deserialize(DataBuffer& data) {
|
||||
std::uint8_t mobSendCount;
|
||||
data >> mobSendCount;
|
||||
std::uint8_t mobSendCount;
|
||||
data >> mobSendCount;
|
||||
|
||||
m_MobSends.resize(mobSendCount);
|
||||
data.ReadSome(reinterpret_cast<std::uint8_t*>(m_MobSends.data()), mobSendCount * sizeof(MobSend));
|
||||
m_MobSends.resize(mobSendCount);
|
||||
data.ReadSome(reinterpret_cast<std::uint8_t*>(m_MobSends.data()), mobSendCount * sizeof(MobSend));
|
||||
}
|
||||
|
||||
DataBuffer UpgradeTowerPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID << m_TowerLevel;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_TowerID << m_TowerLevel;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpgradeTowerPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TowerID >> m_TowerLevel;
|
||||
data >> m_TowerID >> m_TowerLevel;
|
||||
}
|
||||
|
||||
DataBuffer UpdateCastleLifePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_CastleLife << m_Team;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_CastleLife << m_Team;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateCastleLifePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_CastleLife >> m_Team;
|
||||
data >> m_CastleLife >> m_Team;
|
||||
}
|
||||
|
||||
DataBuffer UpdateMobStatesPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint64_t>(m_MobStates.size());
|
||||
WritePacketID(data, packetID);
|
||||
data << static_cast<std::uint64_t>(m_MobStates.size());
|
||||
|
||||
data.WriteSome(reinterpret_cast<const std::uint8_t*>(m_MobStates.data()), m_MobStates.size() * sizeof(MobState));
|
||||
return data;
|
||||
data.WriteSome(reinterpret_cast<const std::uint8_t*>(m_MobStates.data()), m_MobStates.size() * sizeof(MobState));
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateMobStatesPacket::Deserialize(DataBuffer& data) {
|
||||
std::uint64_t mobCount;
|
||||
data >> mobCount;
|
||||
m_MobStates.resize(mobCount);
|
||||
|
||||
data.ReadSome(reinterpret_cast<std::uint8_t*>(m_MobStates.data()), mobCount * sizeof(MobState));
|
||||
std::uint64_t mobCount;
|
||||
data >> mobCount;
|
||||
m_MobStates.resize(mobCount);
|
||||
|
||||
data.ReadSome(reinterpret_cast<std::uint8_t*>(m_MobStates.data()), mobCount * sizeof(MobState));
|
||||
}
|
||||
|
||||
DataBuffer PlayerBuyItemPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_ItemType << m_Count;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_ItemType << m_Count;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerBuyItemPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_ItemType >> m_Count;
|
||||
data >> m_ItemType >> m_Count;
|
||||
}
|
||||
|
||||
DataBuffer PlayerBuyMobUpgradePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_MobType << m_MobLevel;
|
||||
return data;
|
||||
WritePacketID(data, packetID);
|
||||
data << m_MobType << m_MobLevel;
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerBuyMobUpgradePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_MobType >> m_MobLevel;
|
||||
data >> m_MobType >> m_MobLevel;
|
||||
}
|
||||
|
||||
REGISTER_DISPATCH_CLASS(PlayerLoginPacket)
|
||||
|
||||
@@ -23,27 +23,27 @@ Renderer::~Renderer() {
|
||||
}
|
||||
|
||||
void Renderer::UpdateIsometricView() {
|
||||
float isometricEased = utils::EaseInOutExpo(m_IsometricShade);
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetIsometricView(isometricEased);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetIsometricView(isometricEased);
|
||||
float isometricEased = utils::EaseInOutExpo(m_IsometricShade);
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetIsometricView(isometricEased);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetIsometricView(isometricEased);
|
||||
}
|
||||
|
||||
void Renderer::InitShaders() {
|
||||
m_WorldShader = std::make_unique<shader::WorldShader>();
|
||||
m_WorldShader->LoadShader();
|
||||
m_EntityShader = std::make_unique<shader::EntityShader>();
|
||||
m_EntityShader->LoadShader();
|
||||
SetIsometricView(true);
|
||||
UpdateIsometricView();
|
||||
m_WorldShader = std::make_unique<shader::WorldShader>();
|
||||
m_WorldShader->LoadShader();
|
||||
m_EntityShader = std::make_unique<shader::EntityShader>();
|
||||
m_EntityShader->LoadShader();
|
||||
SetIsometricView(true);
|
||||
UpdateIsometricView();
|
||||
}
|
||||
|
||||
// TODO : change loader check
|
||||
|
||||
bool Renderer::Init() {
|
||||
#if __has_include(<glbinding/glbinding.h>)
|
||||
glbinding::initialize();
|
||||
glbinding::initialize();
|
||||
#elif __has_include(<GL/glew.h>)
|
||||
glewInit();
|
||||
#elif __has_include(<glad/glad.h>)
|
||||
@@ -53,96 +53,96 @@ bool Renderer::Init() {
|
||||
#elif __has_include(<glbinding/Binding.h>)
|
||||
glbinding::Binding::initialize();
|
||||
#endif
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
InitShaders();
|
||||
return true;
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
InitShaders();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::RenderVAO(const GL::VertexArray& vao) {
|
||||
m_WorldShader->Start();
|
||||
vao.Bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vao.GetVertexCount()));
|
||||
vao.Unbind();
|
||||
m_WorldShader->Start();
|
||||
vao.Bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vao.GetVertexCount()));
|
||||
vao.Unbind();
|
||||
}
|
||||
|
||||
void Renderer::RenderModel(const Model& model) {
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetModelPos(model.positon);
|
||||
model.vao->Bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(model.vao->GetVertexCount()));
|
||||
model.vao->Unbind();
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetModelPos(model.positon);
|
||||
model.vao->Bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(model.vao->GetVertexCount()));
|
||||
model.vao->Unbind();
|
||||
}
|
||||
|
||||
void Renderer::UpdateIsometricFade() {
|
||||
static std::uint64_t lastTime = utils::GetTime();
|
||||
if (m_IsometricShade != static_cast<float>(m_IsometricView)) {
|
||||
float step = static_cast<float>(utils::GetTime() - lastTime) / 1000.0f * m_AnimationSpeed;
|
||||
if (m_IsometricShade < m_IsometricView) {
|
||||
m_IsometricShade += step;
|
||||
} else {
|
||||
m_IsometricShade -= step;
|
||||
}
|
||||
m_IsometricShade = std::min(m_IsometricShade, 1.0f);
|
||||
m_IsometricShade = std::max(m_IsometricShade, 0.0f);
|
||||
UpdateIsometricView();
|
||||
}
|
||||
lastTime = utils::GetTime();
|
||||
static std::uint64_t lastTime = utils::GetTime();
|
||||
if (m_IsometricShade != static_cast<float>(m_IsometricView)) {
|
||||
float step = static_cast<float>(utils::GetTime() - lastTime) / 1000.0f * m_AnimationSpeed;
|
||||
if (m_IsometricShade < m_IsometricView) {
|
||||
m_IsometricShade += step;
|
||||
} else {
|
||||
m_IsometricShade -= step;
|
||||
}
|
||||
m_IsometricShade = std::min(m_IsometricShade, 1.0f);
|
||||
m_IsometricShade = std::max(m_IsometricShade, 0.0f);
|
||||
UpdateIsometricView();
|
||||
}
|
||||
lastTime = utils::GetTime();
|
||||
}
|
||||
|
||||
void Renderer::Prepare() {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(m_BackgroundColor.r, m_BackgroundColor.g, m_BackgroundColor.b, 0);
|
||||
UpdateIsometricFade();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(m_BackgroundColor.r, m_BackgroundColor.g, m_BackgroundColor.b, 0);
|
||||
UpdateIsometricFade();
|
||||
}
|
||||
|
||||
void Renderer::Resize(int width, int height) {
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetAspectRatio(static_cast<float>(width) / height);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetAspectRatio(static_cast<float>(width) / height);
|
||||
glViewport(0, 0, width, height);
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetAspectRatio(static_cast<float>(width) / height);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetAspectRatio(static_cast<float>(width) / height);
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void Renderer::SetZoom(float zoom) {
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetZoom(zoom);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetZoom(zoom);
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetZoom(zoom);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetZoom(zoom);
|
||||
}
|
||||
|
||||
void Renderer::SetCamMovement(const Vec2f& mov) {
|
||||
m_CamPos.x += mov.x * (1 - m_IsometricView) + (0.5 * mov.x - mov.y) * m_IsometricView;
|
||||
m_CamPos.y += -mov.y * (1 - m_IsometricView) + (-0.5 * mov.x - mov.y) * m_IsometricView;
|
||||
SetCamPos(m_CamPos);
|
||||
m_CamPos.x += mov.x * (1 - m_IsometricView) + (0.5 * mov.x - mov.y) * m_IsometricView;
|
||||
m_CamPos.y += -mov.y * (1 - m_IsometricView) + (-0.5 * mov.x - mov.y) * m_IsometricView;
|
||||
SetCamPos(m_CamPos);
|
||||
}
|
||||
|
||||
void Renderer::SetCamPos(const Vec2f& newPos) {
|
||||
m_CamPos = newPos;
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetCamPos(newPos);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetCamPos(newPos);
|
||||
m_CamPos = newPos;
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetCamPos(newPos);
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetCamPos(newPos);
|
||||
}
|
||||
|
||||
void Renderer::SetIsometricView(bool isometric) {
|
||||
m_IsometricView = isometric;
|
||||
m_IsometricView = isometric;
|
||||
}
|
||||
|
||||
Vec2f Renderer::GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight) {
|
||||
float isometricEased = utils::EaseInOutExpo(m_IsometricShade);
|
||||
float isometricEased = utils::EaseInOutExpo(m_IsometricShade);
|
||||
|
||||
float relativeX = (cursorPos.x / windowWidth * 2) - 1;
|
||||
float relativeY = (cursorPos.y / windowHeight * 2) - 1;
|
||||
float relativeX = (cursorPos.x / windowWidth * 2) - 1;
|
||||
float relativeY = (cursorPos.y / windowHeight * 2) - 1;
|
||||
|
||||
float deltaX = relativeX * aspectRatio / zoom;
|
||||
float deltaY = relativeY / zoom;
|
||||
float deltaX = relativeX * aspectRatio / zoom;
|
||||
float deltaY = relativeY / zoom;
|
||||
|
||||
float worldX = m_CamPos.x + deltaX * (1 - isometricEased) + (0.5 * deltaX + deltaY) * isometricEased;
|
||||
float worldY = m_CamPos.y + deltaY * (1 - isometricEased) + (-0.5 * deltaX + deltaY) * isometricEased;
|
||||
float worldX = m_CamPos.x + deltaX * (1 - isometricEased) + (0.5 * deltaX + deltaY) * isometricEased;
|
||||
float worldY = m_CamPos.y + deltaY * (1 - isometricEased) + (-0.5 * deltaX + deltaY) * isometricEased;
|
||||
|
||||
return { worldX, worldY };
|
||||
return { worldX, worldY };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,49 +5,49 @@ namespace td {
|
||||
namespace render {
|
||||
|
||||
void VertexCache::AddData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors) {
|
||||
m_Indexes.insert({ index, {positions, colors} });
|
||||
m_VertexCount += colors.size(); // one color per vertex
|
||||
m_Indexes.insert({ index, {positions, colors} });
|
||||
m_VertexCount += colors.size(); // one color per vertex
|
||||
}
|
||||
|
||||
void VertexCache::RemoveData(std::uint64_t index) {
|
||||
auto it = m_Indexes.find(index);
|
||||
if (it != m_Indexes.end()) {
|
||||
m_Indexes.erase(it);
|
||||
m_VertexCount -= it->second.color.size(); // one color per vertex
|
||||
}
|
||||
auto it = m_Indexes.find(index);
|
||||
if (it != m_Indexes.end()) {
|
||||
m_Indexes.erase(it);
|
||||
m_VertexCount -= it->second.color.size(); // one color per vertex
|
||||
}
|
||||
}
|
||||
|
||||
void VertexCache::Clear() {
|
||||
m_Indexes.clear();
|
||||
m_VertexCount = 0;
|
||||
m_Indexes.clear();
|
||||
m_VertexCount = 0;
|
||||
}
|
||||
|
||||
void VertexCache::UpdateVertexArray() {
|
||||
m_VertexArray = std::make_unique<GL::VertexArray>(m_VertexCount); // one color per vertex
|
||||
m_VertexArray = std::make_unique<GL::VertexArray>(m_VertexCount); // one color per vertex
|
||||
|
||||
Vector positions;
|
||||
positions.reserve(m_VertexCount * 2);
|
||||
Vector positions;
|
||||
positions.reserve(m_VertexCount * 2);
|
||||
|
||||
Vector colors;
|
||||
colors.reserve(m_VertexCount);
|
||||
Vector colors;
|
||||
colors.reserve(m_VertexCount);
|
||||
|
||||
for (auto it = m_Indexes.begin(); it != m_Indexes.end(); it++) {
|
||||
const DataIndex& data = it->second;
|
||||
for (auto it = m_Indexes.begin(); it != m_Indexes.end(); it++) {
|
||||
const DataIndex& data = it->second;
|
||||
|
||||
positions.insert(positions.end(), data.position.begin(), data.position.end());
|
||||
colors.insert(colors.end(), data.color.begin(), data.color.end());
|
||||
}
|
||||
positions.insert(positions.end(), data.position.begin(), data.position.end());
|
||||
colors.insert(colors.end(), data.color.begin(), data.color.end());
|
||||
}
|
||||
|
||||
GL::VertexBuffer positionsBuffer(positions, 2);
|
||||
positionsBuffer.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer positionsBuffer(positions, 2);
|
||||
positionsBuffer.AddVertexAttribPointer(0, 2, 0);
|
||||
|
||||
GL::VertexBuffer colorsBuffer(colors, 1);
|
||||
colorsBuffer.AddVertexAttribPointer(1, 1, 0);
|
||||
GL::VertexBuffer colorsBuffer(colors, 1);
|
||||
colorsBuffer.AddVertexAttribPointer(1, 1, 0);
|
||||
|
||||
m_VertexArray->Bind();
|
||||
m_VertexArray->BindVertexBuffer(positionsBuffer);
|
||||
m_VertexArray->BindVertexBuffer(colorsBuffer);
|
||||
m_VertexArray->Unbind();
|
||||
m_VertexArray->Bind();
|
||||
m_VertexArray->BindVertexBuffer(positionsBuffer);
|
||||
m_VertexArray->BindVertexBuffer(colorsBuffer);
|
||||
m_VertexArray->Unbind();
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -12,118 +12,118 @@ namespace td {
|
||||
namespace render {
|
||||
|
||||
ImVec4 WorldRenderer::GetImGuiTeamColor(game::TeamColor color) {
|
||||
switch (color) {
|
||||
case td::game::TeamColor::None:
|
||||
break;
|
||||
case td::game::TeamColor::Red:
|
||||
return ImVec4(1, 0, 0, 1);
|
||||
case td::game::TeamColor::Blue:
|
||||
return ImVec4(0, 0, 1, 1);
|
||||
}
|
||||
return ImVec4(1, 1, 1, 1);
|
||||
switch (color) {
|
||||
case td::game::TeamColor::None:
|
||||
break;
|
||||
case td::game::TeamColor::Red:
|
||||
return ImVec4(1, 0, 0, 1);
|
||||
case td::game::TeamColor::Blue:
|
||||
return ImVec4(0, 0, 1, 1);
|
||||
}
|
||||
return ImVec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void WorldRenderer::LoadModels() {
|
||||
utils::LOGD("World Created !");
|
||||
m_WorldVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadWorldModel(m_World)));
|
||||
m_MobVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadMobModel()));
|
||||
m_SelectTileVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadTileSelectModel()));
|
||||
utils::LOGD(utils::format("Vertex Count : %u", m_WorldVao->GetVertexCount()));
|
||||
utils::LOGD("World Created !");
|
||||
m_WorldVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadWorldModel(m_World)));
|
||||
m_MobVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadMobModel()));
|
||||
m_SelectTileVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadTileSelectModel()));
|
||||
utils::LOGD(utils::format("Vertex Count : %u", m_WorldVao->GetVertexCount()));
|
||||
}
|
||||
|
||||
WorldRenderer::WorldRenderer(game::World* world, client::ClientGame* client) : m_Client(client), m_Renderer(m_Client->GetRenderer()), m_World(world), m_Zoom(0.1) {
|
||||
m_Renderer->SetZoom(m_Zoom);
|
||||
m_Renderer->SetCamMovement({});
|
||||
m_TowerPlacePopup = std::make_unique<gui::TowerPlacePopup>(m_Client->GetClient());
|
||||
m_MobTooltip = std::make_unique<gui::MobTooltip>(m_Client->GetClient());
|
||||
m_CastleTooltip = std::make_unique<gui::CastleTooltip>(m_Client->GetClient());
|
||||
m_Client->GetWorldClient().GetWorldNotifier().BindListener(this);
|
||||
m_Renderer->SetZoom(m_Zoom);
|
||||
m_Renderer->SetCamMovement({});
|
||||
m_TowerPlacePopup = std::make_unique<gui::TowerPlacePopup>(m_Client->GetClient());
|
||||
m_MobTooltip = std::make_unique<gui::MobTooltip>(m_Client->GetClient());
|
||||
m_CastleTooltip = std::make_unique<gui::CastleTooltip>(m_Client->GetClient());
|
||||
m_Client->GetWorldClient().GetWorldNotifier().BindListener(this);
|
||||
}
|
||||
|
||||
void WorldRenderer::UpdateCursorPos() {
|
||||
m_CursorPos = GetCursorWorldPos();
|
||||
m_CursorPos = GetCursorWorldPos();
|
||||
}
|
||||
|
||||
void WorldRenderer::Update() {
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.MouseDown[0] && !ImGui::IsAnyItemActive()) {
|
||||
ImVec2 mouseDelta = ImGui::GetIO().MouseDelta;
|
||||
const float relativeX = mouseDelta.x / (float)Display::GetWindowWidth() * 2;
|
||||
const float relativeY = mouseDelta.y / (float)Display::GetWindowHeight() * 2;
|
||||
MoveCam(relativeX, relativeY, Display::GetAspectRatio());
|
||||
}
|
||||
if (io.MouseWheel != 0) {
|
||||
ChangeZoom(io.MouseWheel);
|
||||
}
|
||||
UpdateCursorPos();
|
||||
if (ImGui::IsMouseClicked(0)) {
|
||||
if (!m_PopupOpened) {
|
||||
m_HoldCursorPos = { io.MousePos.x, io.MousePos.y };
|
||||
} else {
|
||||
m_PopupOpened = false;
|
||||
}
|
||||
}
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.MouseDown[0] && !ImGui::IsAnyItemActive()) {
|
||||
ImVec2 mouseDelta = ImGui::GetIO().MouseDelta;
|
||||
const float relativeX = mouseDelta.x / (float)Display::GetWindowWidth() * 2;
|
||||
const float relativeY = mouseDelta.y / (float)Display::GetWindowHeight() * 2;
|
||||
MoveCam(relativeX, relativeY, Display::GetAspectRatio());
|
||||
}
|
||||
if (io.MouseWheel != 0) {
|
||||
ChangeZoom(io.MouseWheel);
|
||||
}
|
||||
UpdateCursorPos();
|
||||
if (ImGui::IsMouseClicked(0)) {
|
||||
if (!m_PopupOpened) {
|
||||
m_HoldCursorPos = { io.MousePos.x, io.MousePos.y };
|
||||
} else {
|
||||
m_PopupOpened = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseDoubleClicked(1)) RemoveTower();
|
||||
if (ImGui::IsMouseDoubleClicked(1)) RemoveTower();
|
||||
}
|
||||
|
||||
void WorldRenderer::RemoveTower() {
|
||||
Vec2f cursorPos = GetCursorWorldPos();
|
||||
Vec2f cursorPos = GetCursorWorldPos();
|
||||
|
||||
game::TowerPtr clickedTower = m_World->GetTower(cursorPos);
|
||||
game::TowerPtr clickedTower = m_World->GetTower(cursorPos);
|
||||
|
||||
if (clickedTower != nullptr) {
|
||||
m_Client->GetClient()->RemoveTower(clickedTower->GetID());
|
||||
}
|
||||
if (clickedTower != nullptr) {
|
||||
m_Client->GetClient()->RemoveTower(clickedTower->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderWorld() const {
|
||||
m_Renderer->RenderVAO(*m_WorldVao);
|
||||
m_Renderer->RenderVAO(*m_WorldVao);
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderMobs() const {
|
||||
for (game::MobPtr mob : m_World->GetMobList()) {
|
||||
Renderer::Model model;
|
||||
model.vao = m_MobVao.get();
|
||||
model.positon = { mob->GetCenterX(), mob->GetCenterY() };
|
||||
m_Renderer->RenderModel(model);
|
||||
}
|
||||
for (game::MobPtr mob : m_World->GetMobList()) {
|
||||
Renderer::Model model;
|
||||
model.vao = m_MobVao.get();
|
||||
model.positon = { mob->GetCenterX(), mob->GetCenterY() };
|
||||
m_Renderer->RenderModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderTowers() const {
|
||||
if (!m_TowersCache.IsEmpty())
|
||||
m_Renderer->RenderVAO(m_TowersCache.GetVertexArray());
|
||||
if (!m_TowersCache.IsEmpty())
|
||||
m_Renderer->RenderVAO(m_TowersCache.GetVertexArray());
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderTileSelect() const {
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
|
||||
if (m_MobTooltip->IsShown() || m_CastleTooltip->IsShown()) return;
|
||||
if (m_MobTooltip->IsShown() || m_CastleTooltip->IsShown()) return;
|
||||
|
||||
Renderer::Model tileSelectModel;
|
||||
tileSelectModel.vao = m_SelectTileVao.get();
|
||||
tileSelectModel.positon = { std::floor(m_CursorPos.x), std::floor(m_CursorPos.y) };
|
||||
Renderer::Model tileSelectModel;
|
||||
tileSelectModel.vao = m_SelectTileVao.get();
|
||||
tileSelectModel.positon = { std::floor(m_CursorPos.x), std::floor(m_CursorPos.y) };
|
||||
|
||||
m_Renderer->RenderModel(tileSelectModel);
|
||||
m_Renderer->RenderModel(tileSelectModel);
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderPopups() {
|
||||
m_TowerPlacePopup->Render();
|
||||
RenderTowerUpgradePopup();
|
||||
m_TowerPlacePopup->Render();
|
||||
RenderTowerUpgradePopup();
|
||||
}
|
||||
|
||||
void WorldRenderer::Render() {
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
RenderWorld();
|
||||
RenderMobs();
|
||||
RenderTowers();
|
||||
RenderTileSelect();
|
||||
RenderTooltips();
|
||||
RenderPopups();
|
||||
DetectClick();
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
RenderWorld();
|
||||
RenderMobs();
|
||||
RenderTowers();
|
||||
RenderTileSelect();
|
||||
RenderTooltips();
|
||||
RenderPopups();
|
||||
DetectClick();
|
||||
}
|
||||
|
||||
WorldRenderer::~WorldRenderer() {
|
||||
@@ -131,174 +131,174 @@ WorldRenderer::~WorldRenderer() {
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderTooltips() const {
|
||||
RenderMobTooltip();
|
||||
RenderCastleTooltip();
|
||||
RenderMobTooltip();
|
||||
RenderCastleTooltip();
|
||||
}
|
||||
|
||||
void WorldRenderer::MoveCam(float relativeX, float relativeY, float aspectRatio) {
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
float movementX = -relativeX / m_Zoom * aspectRatio;
|
||||
float movementY = relativeY / m_Zoom;
|
||||
m_Renderer->SetCamMovement({ movementX, movementY });
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
float movementX = -relativeX / m_Zoom * aspectRatio;
|
||||
float movementY = relativeY / m_Zoom;
|
||||
m_Renderer->SetCamMovement({ movementX, movementY });
|
||||
}
|
||||
|
||||
void WorldRenderer::ChangeZoom(float zoomStep) {
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
static float sensibility = 1.5f;
|
||||
if (zoomStep < 0) {
|
||||
m_Zoom /= -zoomStep * sensibility;
|
||||
} else {
|
||||
m_Zoom *= zoomStep * sensibility;
|
||||
}
|
||||
m_Renderer->SetZoom(m_Zoom);
|
||||
m_Renderer->SetCamMovement({});
|
||||
if (m_WorldVao == nullptr)
|
||||
return;
|
||||
static float sensibility = 1.5f;
|
||||
if (zoomStep < 0) {
|
||||
m_Zoom /= -zoomStep * sensibility;
|
||||
} else {
|
||||
m_Zoom *= zoomStep * sensibility;
|
||||
}
|
||||
m_Renderer->SetZoom(m_Zoom);
|
||||
m_Renderer->SetCamMovement({});
|
||||
}
|
||||
|
||||
void WorldRenderer::Click() {
|
||||
const game::TowerPtr tower = m_Client->GetWorld().GetTower(GetClickWorldPos());
|
||||
m_TowerPlacePopup->SetClickPos(GetClickWorldPos());
|
||||
if (tower != nullptr) { // there is a tower here
|
||||
ImGui::OpenPopup("TowerUpgrade");
|
||||
} else if (m_Client->GetWorld().CanPlaceLittleTower(GetClickWorldPos(), m_Client->GetPlayer()->GetID())) {
|
||||
ImGui::OpenPopup("TowerPlace");
|
||||
}
|
||||
const game::TowerPtr tower = m_Client->GetWorld().GetTower(GetClickWorldPos());
|
||||
m_TowerPlacePopup->SetClickPos(GetClickWorldPos());
|
||||
if (tower != nullptr) { // there is a tower here
|
||||
ImGui::OpenPopup("TowerUpgrade");
|
||||
} else if (m_Client->GetWorld().CanPlaceLittleTower(GetClickWorldPos(), m_Client->GetPlayer()->GetID())) {
|
||||
ImGui::OpenPopup("TowerPlace");
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::SetCamPos(float camX, float camY) {
|
||||
m_CamPos = { camX, camY };
|
||||
m_Renderer->SetCamPos(m_CamPos);
|
||||
m_CamPos = { camX, camY };
|
||||
m_Renderer->SetCamPos(m_CamPos);
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderTowerUpgradePopup() {
|
||||
if (ImGui::BeginPopup("TowerUpgrade")) {
|
||||
m_PopupOpened = true;
|
||||
game::TowerPtr tower = m_Client->GetWorld().GetTower(GetClickWorldPos());
|
||||
if (tower == nullptr) {
|
||||
ImGui::EndPopup();
|
||||
return;
|
||||
}
|
||||
ImGui::Text("Tower : %s", game::TowerFactory::GetTowerName(tower->GetType()).c_str());
|
||||
if (ImGui::BeginPopup("TowerUpgrade")) {
|
||||
m_PopupOpened = true;
|
||||
game::TowerPtr tower = m_Client->GetWorld().GetTower(GetClickWorldPos());
|
||||
if (tower == nullptr) {
|
||||
ImGui::EndPopup();
|
||||
return;
|
||||
}
|
||||
ImGui::Text("Tower : %s", game::TowerFactory::GetTowerName(tower->GetType()).c_str());
|
||||
|
||||
for (int y = 0; y < 3; y++) { // path: 0 -> top 1 -> middle 2 -> bottom
|
||||
for (int x = 0; x < 4; x++) { // level: 1, 2, 3, 4
|
||||
for (int y = 0; y < 3; y++) { // path: 0 -> top 1 -> middle 2 -> bottom
|
||||
for (int x = 0; x < 4; x++) { // level: 1, 2, 3, 4
|
||||
|
||||
if (x > 0)
|
||||
ImGui::SameLine();
|
||||
if (x > 0)
|
||||
ImGui::SameLine();
|
||||
|
||||
std::uint8_t currentLevel = x + 1;
|
||||
game::TowerPath currentPath = game::TowerPath(y);
|
||||
std::uint8_t currentLevel = x + 1;
|
||||
game::TowerPath currentPath = game::TowerPath(y);
|
||||
|
||||
const game::TowerStats* towerStats = game::GetTowerStats(tower->GetType(), { currentLevel, currentPath });
|
||||
game::TowerPath towerPath = tower->GetLevel().GetPath();
|
||||
const game::TowerStats* towerStats = game::GetTowerStats(tower->GetType(), { currentLevel, currentPath });
|
||||
game::TowerPath towerPath = tower->GetLevel().GetPath();
|
||||
|
||||
bool disabled = towerStats == nullptr;
|
||||
bool disabled = towerStats == nullptr;
|
||||
|
||||
int towerLevel = tower->GetLevel().GetLevel();
|
||||
int towerLevel = tower->GetLevel().GetLevel();
|
||||
|
||||
bool alreadyUpgraded = currentLevel <= towerLevel;
|
||||
bool canUpgrade = (towerLevel + 1) == currentLevel;
|
||||
bool alreadyUpgraded = currentLevel <= towerLevel;
|
||||
bool canUpgrade = (towerLevel + 1) == currentLevel;
|
||||
|
||||
if (canUpgrade && towerPath != game::TowerPath::Base) {
|
||||
if (currentPath != towerPath) {
|
||||
canUpgrade = false;
|
||||
}
|
||||
}
|
||||
if (canUpgrade && towerPath != game::TowerPath::Base) {
|
||||
if (currentPath != towerPath) {
|
||||
canUpgrade = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PushID(x * 4 + y);
|
||||
if (disabled) {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
ImGui::Button("", ImVec2(100, 100));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndDisabled();
|
||||
} else if (alreadyUpgraded) {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("Already", ImVec2(100, 100));
|
||||
ImGui::EndDisabled();
|
||||
} else if (canUpgrade) {
|
||||
if (ImGui::Button("Upgrade", ImVec2(100, 100))) {
|
||||
m_Client->GetClient()->UpgradeTower(tower->GetID(), { currentLevel, currentPath });
|
||||
}
|
||||
} else {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("Locked", ImVec2(100, 100));
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
ImGui::PushID(x * 4 + y);
|
||||
if (disabled) {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
ImGui::Button("", ImVec2(100, 100));
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndDisabled();
|
||||
} else if (alreadyUpgraded) {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("Already", ImVec2(100, 100));
|
||||
ImGui::EndDisabled();
|
||||
} else if (canUpgrade) {
|
||||
if (ImGui::Button("Upgrade", ImVec2(100, 100))) {
|
||||
m_Client->GetClient()->UpgradeTower(tower->GetID(), { currentLevel, currentPath });
|
||||
}
|
||||
} else {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("Locked", ImVec2(100, 100));
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::DetectClick() {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (ImGui::IsMouseReleased(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemFocused()) {
|
||||
Vec2f cursorPos = { io.MousePos.x, io.MousePos.y };
|
||||
if (cursorPos == m_HoldCursorPos) {
|
||||
m_LastClicked = m_HoldCursorPos;
|
||||
Click();
|
||||
}
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (ImGui::IsMouseReleased(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemFocused()) {
|
||||
Vec2f cursorPos = { io.MousePos.x, io.MousePos.y };
|
||||
if (cursorPos == m_HoldCursorPos) {
|
||||
m_LastClicked = m_HoldCursorPos;
|
||||
Click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderMobTooltip() const {
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
|
||||
DetectMobHovering();
|
||||
m_MobTooltip->Render();
|
||||
DetectMobHovering();
|
||||
m_MobTooltip->Render();
|
||||
}
|
||||
|
||||
void WorldRenderer::RenderCastleTooltip() const {
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
if (ImGui::IsAnyItemHovered()) return;
|
||||
|
||||
DetectCastleHovering();
|
||||
m_CastleTooltip->Render();
|
||||
DetectCastleHovering();
|
||||
m_CastleTooltip->Render();
|
||||
}
|
||||
|
||||
void WorldRenderer::DetectMobHovering() const {
|
||||
Vec2f cursorWorldPos = GetCursorWorldPos();
|
||||
for (game::MobPtr mob : m_World->GetMobList()) {
|
||||
if (mob->CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
|
||||
m_MobTooltip->SetMob(mob.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_MobTooltip->SetMob(nullptr);
|
||||
Vec2f cursorWorldPos = GetCursorWorldPos();
|
||||
for (game::MobPtr mob : m_World->GetMobList()) {
|
||||
if (mob->CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
|
||||
m_MobTooltip->SetMob(mob.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_MobTooltip->SetMob(nullptr);
|
||||
}
|
||||
|
||||
void WorldRenderer::DetectCastleHovering() const {
|
||||
Vec2f cursorWorldPos = GetCursorWorldPos();
|
||||
for (const game::Team& team : m_World->GetTeams()) {
|
||||
if (team.GetCastle().CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
|
||||
m_CastleTooltip->SetCastle(&team.GetCastle());
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_CastleTooltip->SetCastle(nullptr);
|
||||
Vec2f cursorWorldPos = GetCursorWorldPos();
|
||||
for (const game::Team& team : m_World->GetTeams()) {
|
||||
if (team.GetCastle().CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
|
||||
m_CastleTooltip->SetCastle(&team.GetCastle());
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_CastleTooltip->SetCastle(nullptr);
|
||||
}
|
||||
|
||||
void WorldRenderer::OnTowerAdd(game::TowerPtr tower) {
|
||||
WorldLoader::RenderData RenderData = WorldLoader::LoadTowerModel(tower);
|
||||
m_TowersCache.AddData(tower->GetID(), RenderData.positions, RenderData.colors);
|
||||
m_TowersCache.UpdateVertexArray();
|
||||
WorldLoader::RenderData RenderData = WorldLoader::LoadTowerModel(tower);
|
||||
m_TowersCache.AddData(tower->GetID(), RenderData.positions, RenderData.colors);
|
||||
m_TowersCache.UpdateVertexArray();
|
||||
}
|
||||
|
||||
void WorldRenderer::OnTowerRemove(game::TowerPtr tower) {
|
||||
m_TowersCache.RemoveData(tower->GetID());
|
||||
m_TowersCache.UpdateVertexArray();
|
||||
m_TowersCache.RemoveData(tower->GetID());
|
||||
m_TowersCache.UpdateVertexArray();
|
||||
}
|
||||
|
||||
Vec2f WorldRenderer::GetCursorWorldPos() const {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
return m_Renderer->GetCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight());
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
return m_Renderer->GetCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight());
|
||||
}
|
||||
|
||||
Vec2f WorldRenderer::GetClickWorldPos() const {
|
||||
return m_Renderer->GetCursorWorldPos(m_LastClicked, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight());
|
||||
return m_Renderer->GetCursorWorldPos(m_LastClicked, Display::GetAspectRatio(), m_Zoom, Display::GetWindowWidth(), Display::GetWindowHeight());
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -13,14 +13,14 @@ CastleTooltip::CastleTooltip(client::Client* client) : GuiWidget(client) {
|
||||
}
|
||||
|
||||
void CastleTooltip::Render() {
|
||||
if (m_Castle == nullptr) return;
|
||||
if (m_Castle == nullptr) return;
|
||||
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(m_Castle->GetTeam()->GetColor()));
|
||||
ImGui::Text("Castle : ");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Text("\tCastle HP : %i/%i", static_cast<int>(m_Castle->GetLife()), game::TeamCastle::CastleMaxLife);
|
||||
ImGui::EndTooltip();
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(m_Castle->GetTeam()->GetColor()));
|
||||
ImGui::Text("Castle : ");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Text("\tCastle HP : %i/%i", static_cast<int>(m_Castle->GetLife()), game::TeamCastle::CastleMaxLife);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -13,25 +13,25 @@ FrameMenu::FrameMenu(client::Client* client) : GuiWidget(client), m_VSync(true),
|
||||
}
|
||||
|
||||
void FrameMenu::Render() {
|
||||
ImGui::Begin("FPS Counter");
|
||||
ImGui::Text("FPS : %i", (int)ImGui::GetIO().Framerate);
|
||||
if (ImGui::Checkbox("V-Sync", &m_VSync)) {
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
}
|
||||
if (ImGui::Checkbox("Vue Isometrique ?", &m_IsometricView)) {
|
||||
GetClient()->GetRenderer()->SetIsometricView(m_IsometricView);
|
||||
}
|
||||
ImGui::Begin("FPS Counter");
|
||||
ImGui::Text("FPS : %i", (int)ImGui::GetIO().Framerate);
|
||||
if (ImGui::Checkbox("V-Sync", &m_VSync)) {
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
}
|
||||
if (ImGui::Checkbox("Vue Isometrique ?", &m_IsometricView)) {
|
||||
GetClient()->GetRenderer()->SetIsometricView(m_IsometricView);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
ImGui::Checkbox("Demo Window", &m_ShowDemoWindow);
|
||||
ImGui::Checkbox("Demo Window", &m_ShowDemoWindow);
|
||||
#endif
|
||||
|
||||
ImGui::End();
|
||||
ImGui::End();
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
if (m_ShowDemoWindow)
|
||||
ImGui::ShowDemoWindow(&m_ShowDemoWindow);
|
||||
if (m_ShowDemoWindow)
|
||||
ImGui::ShowDemoWindow(&m_ShowDemoWindow);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -14,83 +14,83 @@ GameMenu::GameMenu(client::Client* client) : GuiWidget(client), m_SummonMenu(std
|
||||
}
|
||||
|
||||
void GameMenu::Render() {
|
||||
if (!m_Client->IsConnected()) return;
|
||||
if (!m_Client->IsConnected()) return;
|
||||
|
||||
if (GetClient()->GetGame().GetGameState() == td::game::GameState::Lobby) {
|
||||
ImGui::Begin("Lobby");
|
||||
if (GetClient()->GetGame().GetGameState() == td::game::GameState::Lobby) {
|
||||
ImGui::Begin("Lobby");
|
||||
|
||||
ShowTPS();
|
||||
ShowPlayers();
|
||||
ShowLobbyProgress();
|
||||
ShowTeamSelection();
|
||||
ShowTPS();
|
||||
ShowPlayers();
|
||||
ShowLobbyProgress();
|
||||
ShowTeamSelection();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
if (GetClient()->GetGame().GetGameState() == td::game::GameState::Game) {
|
||||
ImGui::Begin("Game");
|
||||
ImGui::End();
|
||||
}
|
||||
if (GetClient()->GetGame().GetGameState() == td::game::GameState::Game) {
|
||||
ImGui::Begin("Game");
|
||||
|
||||
ShowTPS();
|
||||
ShowStats();
|
||||
ShowPlayers();
|
||||
ShowTPS();
|
||||
ShowStats();
|
||||
ShowPlayers();
|
||||
|
||||
ImGui::End();
|
||||
ImGui::End();
|
||||
|
||||
m_SummonMenu->Render();
|
||||
}
|
||||
m_SummonMenu->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void GameMenu::ShowPlayers() {
|
||||
if (ImGui::TreeNode(std::string("Players (" + std::to_string(GetClient()->GetGame().GetPlayers().size()) + ")##player_list").c_str())) {
|
||||
for (auto pair : GetClient()->GetGame().GetPlayers()) {
|
||||
const td::game::Player& player = pair.second;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(player.GetTeamColor()));
|
||||
ImGui::Text("%s", player.GetName().c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode(std::string("Players (" + std::to_string(GetClient()->GetGame().GetPlayers().size()) + ")##player_list").c_str())) {
|
||||
for (auto pair : GetClient()->GetGame().GetPlayers()) {
|
||||
const td::game::Player& player = pair.second;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(player.GetTeamColor()));
|
||||
ImGui::Text("%s", player.GetName().c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
void GameMenu::ShowTeamSelection() {
|
||||
if (GetClient()->GetGame().GetPlayer() == nullptr)
|
||||
return;
|
||||
td::game::TeamColor playerTeam = GetClient()->GetGame().GetPlayer()->GetTeamColor();
|
||||
if (GetClient()->GetGame().GetPlayer() == nullptr)
|
||||
return;
|
||||
td::game::TeamColor playerTeam = GetClient()->GetGame().GetPlayer()->GetTeamColor();
|
||||
|
||||
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Red ? "Leave" : "Join") + std::string(" Red Team")).c_str())) {
|
||||
if (playerTeam == td::game::TeamColor::Red)
|
||||
GetClient()->SelectTeam(td::game::TeamColor::None);
|
||||
else
|
||||
GetClient()->SelectTeam(td::game::TeamColor::Red);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Blue ? "Leave" : "Join") + std::string(" Blue Team")).c_str())) {
|
||||
if (playerTeam == td::game::TeamColor::Blue)
|
||||
GetClient()->SelectTeam(td::game::TeamColor::None);
|
||||
else
|
||||
GetClient()->SelectTeam(td::game::TeamColor::Blue);
|
||||
}
|
||||
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Red ? "Leave" : "Join") + std::string(" Red Team")).c_str())) {
|
||||
if (playerTeam == td::game::TeamColor::Red)
|
||||
GetClient()->SelectTeam(td::game::TeamColor::None);
|
||||
else
|
||||
GetClient()->SelectTeam(td::game::TeamColor::Red);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Blue ? "Leave" : "Join") + std::string(" Blue Team")).c_str())) {
|
||||
if (playerTeam == td::game::TeamColor::Blue)
|
||||
GetClient()->SelectTeam(td::game::TeamColor::None);
|
||||
else
|
||||
GetClient()->SelectTeam(td::game::TeamColor::Blue);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMenu::ShowLobbyProgress() {
|
||||
const int timePassed = server::Lobby::LobbyWaitingTime - GetClient()->GetGame().GetLobbyTime();
|
||||
const float progress = (float)timePassed / (float)(server::Lobby::LobbyWaitingTime);
|
||||
if (progress > 0 && progress < 1) {
|
||||
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), std::string(std::to_string(GetClient()->GetGame().GetLobbyTime() / 1000) + "s").c_str());
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::Text("Time Remaining");
|
||||
} else {
|
||||
ImGui::Text("Waiting for players ...\n");
|
||||
}
|
||||
const int timePassed = server::Lobby::LobbyWaitingTime - GetClient()->GetGame().GetLobbyTime();
|
||||
const float progress = (float)timePassed / (float)(server::Lobby::LobbyWaitingTime);
|
||||
if (progress > 0 && progress < 1) {
|
||||
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), std::string(std::to_string(GetClient()->GetGame().GetLobbyTime() / 1000) + "s").c_str());
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||
ImGui::Text("Time Remaining");
|
||||
} else {
|
||||
ImGui::Text("Waiting for players ...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void GameMenu::ShowTPS() {
|
||||
ImGui::Text("Server TPS : %.1f", GetClient()->GetConnexion().GetServerTPS());
|
||||
ImGui::Text("Server Ping : %i", GetClient()->GetConnexion().GetServerPing());
|
||||
ImGui::Text("Server TPS : %.1f", GetClient()->GetConnexion().GetServerTPS());
|
||||
ImGui::Text("Server Ping : %i", GetClient()->GetConnexion().GetServerPing());
|
||||
}
|
||||
|
||||
void GameMenu::ShowStats() {
|
||||
ImGui::Text("Gold : %i", GetClient()->GetGame().GetPlayer()->GetGold());
|
||||
ImGui::Text("EXP: %i", GetClient()->GetGame().GetPlayer()->GetExp());
|
||||
ImGui::Text("Gold : %i", GetClient()->GetGame().GetPlayer()->GetGold());
|
||||
ImGui::Text("EXP: %i", GetClient()->GetGame().GetPlayer()->GetExp());
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -8,83 +8,83 @@ namespace td {
|
||||
namespace gui {
|
||||
|
||||
MainMenu::MainMenu(client::Client* client) : GuiWidget(client), m_ConnectPort(25565) {
|
||||
m_ConnectAddress = "localhost";
|
||||
m_ConnectAddress.reserve(256);
|
||||
m_ConnectAddress = "localhost";
|
||||
m_ConnectAddress.reserve(256);
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
if (m_Server != nullptr)
|
||||
m_Server->Stop();
|
||||
if (m_Server != nullptr)
|
||||
m_Server->Stop();
|
||||
}
|
||||
|
||||
void MainMenu::Render() {
|
||||
if (m_Server != nullptr && !m_Server->IsRunning()) {
|
||||
m_Server.reset(0); // destroying server if it stoped
|
||||
}
|
||||
if (m_Server != nullptr && !m_Server->IsRunning()) {
|
||||
m_Server.reset(0); // destroying server if it stoped
|
||||
}
|
||||
|
||||
if (m_Client->IsConnected()) return;
|
||||
if (m_Client->IsConnected()) return;
|
||||
|
||||
ImGui::Begin("Main Menu");
|
||||
if (ImGui::Button("Rejoindre une partie##join")) {
|
||||
ImGui::OpenPopup("Rejoindre une partie##join_popup");
|
||||
}
|
||||
if (ImGui::Button("Créer une partie")) {
|
||||
ImGui::OpenPopup("Créer une partie##create_popup");
|
||||
}
|
||||
if (ImGui::Button("Options")) {
|
||||
// TODO: add settings
|
||||
}
|
||||
ImGui::Begin("Main Menu");
|
||||
if (ImGui::Button("Rejoindre une partie##join")) {
|
||||
ImGui::OpenPopup("Rejoindre une partie##join_popup");
|
||||
}
|
||||
if (ImGui::Button("Créer une partie")) {
|
||||
ImGui::OpenPopup("Créer une partie##create_popup");
|
||||
}
|
||||
if (ImGui::Button("Options")) {
|
||||
// TODO: add settings
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Rejoindre une partie##join_popup")) {
|
||||
ImGui::InputText("Server Adress", &m_ConnectAddress.front(), m_ConnectAddress.capacity());
|
||||
ImGui::InputInt("Port", &m_ConnectPort, -1);
|
||||
if (ImGui::Button("Rejoindre")) {
|
||||
GetClient()->Connect(td::network::Dns::Resolve(m_ConnectAddress), m_ConnectPort);
|
||||
m_TriedToConnect = true;
|
||||
}
|
||||
if (m_TriedToConnect) {
|
||||
ImGui::Text("Impossible de se connecter");
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
m_TriedToConnect = false;
|
||||
}
|
||||
if (ImGui::BeginPopup("Rejoindre une partie##join_popup")) {
|
||||
ImGui::InputText("Server Adress", &m_ConnectAddress.front(), m_ConnectAddress.capacity());
|
||||
ImGui::InputInt("Port", &m_ConnectPort, -1);
|
||||
if (ImGui::Button("Rejoindre")) {
|
||||
GetClient()->Connect(td::network::Dns::Resolve(m_ConnectAddress), m_ConnectPort);
|
||||
m_TriedToConnect = true;
|
||||
}
|
||||
if (m_TriedToConnect) {
|
||||
ImGui::Text("Impossible de se connecter");
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
m_TriedToConnect = false;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Créer une partie##create_popup")) {
|
||||
ImGui::InputInt("Server Port", &m_ServerPort, -1);
|
||||
ImGui::Text("%s", std::string("Fichier de monde sélectionné : " + (m_WorldFilePath.empty() ? std::string("Aucun") : m_WorldFilePath)).c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Ouvrir un fichier")) {
|
||||
ImGui::OpenPopup("WorldFileDialog");
|
||||
}
|
||||
if (m_FileDialog.showFileDialog("WorldFileDialog", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(600, 300), ".tdmap")) {
|
||||
m_WorldFilePath = m_FileDialog.selected_path;
|
||||
}
|
||||
if (ImGui::Button("Créer")) {
|
||||
if (!StartServer()) {
|
||||
m_TriedToCreate = true;
|
||||
} else {
|
||||
GetClient()->Connect(td::network::Dns::Resolve("localhost"), m_ServerPort);
|
||||
}
|
||||
}
|
||||
if (m_TriedToCreate)
|
||||
ImGui::Text("Failed to launch server");
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
m_TriedToConnect = false;
|
||||
}
|
||||
if (ImGui::BeginPopup("Créer une partie##create_popup")) {
|
||||
ImGui::InputInt("Server Port", &m_ServerPort, -1);
|
||||
ImGui::Text("%s", std::string("Fichier de monde sélectionné : " + (m_WorldFilePath.empty() ? std::string("Aucun") : m_WorldFilePath)).c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Ouvrir un fichier")) {
|
||||
ImGui::OpenPopup("WorldFileDialog");
|
||||
}
|
||||
if (m_FileDialog.showFileDialog("WorldFileDialog", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(600, 300), ".tdmap")) {
|
||||
m_WorldFilePath = m_FileDialog.selected_path;
|
||||
}
|
||||
if (ImGui::Button("Créer")) {
|
||||
if (!StartServer()) {
|
||||
m_TriedToCreate = true;
|
||||
} else {
|
||||
GetClient()->Connect(td::network::Dns::Resolve("localhost"), m_ServerPort);
|
||||
}
|
||||
}
|
||||
if (m_TriedToCreate)
|
||||
ImGui::Text("Failed to launch server");
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
m_TriedToConnect = false;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool MainMenu::StartServer() {
|
||||
if (m_WorldFilePath.empty())
|
||||
return false;
|
||||
m_Server = std::make_unique<td::server::Server>(m_WorldFilePath);
|
||||
if (!m_Server->Start(m_ServerPort)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (m_WorldFilePath.empty())
|
||||
return false;
|
||||
m_Server = std::make_unique<td::server::Server>(m_WorldFilePath);
|
||||
if (!m_Server->Start(m_ServerPort)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -15,29 +15,29 @@ MobTooltip::MobTooltip(client::Client* client) : GuiWidget(client) {
|
||||
}
|
||||
|
||||
void MobTooltip::Render() {
|
||||
if (m_Mob == nullptr) return;
|
||||
if (m_Mob == nullptr) return;
|
||||
|
||||
// TODO: add sender null check
|
||||
// TODO: add sender null check
|
||||
|
||||
const game::Player* sender = GetClient()->GetGame().GetPlayerById(m_Mob->GetSender());
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Sender :");
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(sender->GetTeamColor()));
|
||||
ImGui::Text("%s", sender->GetName().c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Text("Mob HP : %.1f/%i", m_Mob->GetHealth(), m_Mob->GetStats()->GetMaxLife());
|
||||
ImGui::Text("Mob Type : %s", game::MobFactory::GetMobName(m_Mob->GetType()).c_str());
|
||||
ImGui::Text("Mob Level : %i", m_Mob->GetLevel());
|
||||
ImGui::NewLine();
|
||||
ImGui::Text("Mob Stats :");
|
||||
ImGui::Text("\tMax health : %i", m_Mob->GetStats()->GetMaxLife());
|
||||
ImGui::Text("\tSpeed : %.1f", m_Mob->GetStats()->GetMovementSpeed());
|
||||
ImGui::Text("\tDamage : %.1f", m_Mob->GetStats()->GetDamage());
|
||||
ImGui::Text("\tMoney cost : %i", m_Mob->GetStats()->GetMoneyCost());
|
||||
ImGui::Text("\tEXP cost : %i", m_Mob->GetStats()->GetExpCost());
|
||||
ImGui::Text("\tEXP reward : %i", m_Mob->GetStats()->GetExpReward());
|
||||
ImGui::EndTooltip();
|
||||
const game::Player* sender = GetClient()->GetGame().GetPlayerById(m_Mob->GetSender());
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Sender :");
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::GetImGuiTeamColor(sender->GetTeamColor()));
|
||||
ImGui::Text("%s", sender->GetName().c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Text("Mob HP : %.1f/%i", m_Mob->GetHealth(), m_Mob->GetStats()->GetMaxLife());
|
||||
ImGui::Text("Mob Type : %s", game::MobFactory::GetMobName(m_Mob->GetType()).c_str());
|
||||
ImGui::Text("Mob Level : %i", m_Mob->GetLevel());
|
||||
ImGui::NewLine();
|
||||
ImGui::Text("Mob Stats :");
|
||||
ImGui::Text("\tMax health : %i", m_Mob->GetStats()->GetMaxLife());
|
||||
ImGui::Text("\tSpeed : %.1f", m_Mob->GetStats()->GetMovementSpeed());
|
||||
ImGui::Text("\tDamage : %.1f", m_Mob->GetStats()->GetDamage());
|
||||
ImGui::Text("\tMoney cost : %i", m_Mob->GetStats()->GetMoneyCost());
|
||||
ImGui::Text("\tEXP cost : %i", m_Mob->GetStats()->GetExpCost());
|
||||
ImGui::Text("\tEXP reward : %i", m_Mob->GetStats()->GetExpReward());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -6,76 +6,76 @@ namespace td {
|
||||
namespace gui {
|
||||
|
||||
SummonMenu::SummonMenu(client::Client* client) : GuiWidget(client), m_MenuOpened(true) {
|
||||
m_Values.fill(0);
|
||||
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<protocol::MobSend> 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();
|
||||
}
|
||||
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<protocol::MobSend> 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--;
|
||||
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
|
||||
|
||||
@@ -22,64 +22,64 @@ namespace td {
|
||||
namespace render {
|
||||
|
||||
void TowerGui::InitWidgets() {
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::MainMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::GameMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::FrameMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::UpdateMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::MainMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::GameMenu>(m_Client.get()));
|
||||
m_GuiManager.AddWidget(std::make_unique<td::gui::FrameMenu>(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),
|
||||
m_GlContext(glContext), m_Renderer(renderer), m_Client(std::make_unique<client::Client>(m_Renderer)) {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplSDL2_InitForOpenGL(m_Window, m_GlContext);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
ImFontConfig c;
|
||||
c.SizePixels = 25;
|
||||
ImGui::GetIO().Fonts->AddFontDefault(&c);
|
||||
InitWidgets();
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplSDL2_InitForOpenGL(m_Window, m_GlContext);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
ImFontConfig c;
|
||||
c.SizePixels = 25;
|
||||
ImGui::GetIO().Fonts->AddFontDefault(&c);
|
||||
InitWidgets();
|
||||
}
|
||||
|
||||
void TowerGui::BeginFrame() {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void TowerGui::EndFrame() {
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
void TowerGui::Tick() {
|
||||
static std::uint64_t lastTime = td::utils::GetTime();
|
||||
std::uint64_t time = td::utils::GetTime();
|
||||
static std::uint64_t lastTime = td::utils::GetTime();
|
||||
std::uint64_t time = td::utils::GetTime();
|
||||
|
||||
std::uint64_t delta = time - lastTime;
|
||||
std::uint64_t delta = time - lastTime;
|
||||
|
||||
m_Client->Tick(delta);
|
||||
m_Client->Tick(delta);
|
||||
|
||||
lastTime = td::utils::GetTime();
|
||||
lastTime = td::utils::GetTime();
|
||||
}
|
||||
|
||||
void TowerGui::Render() {
|
||||
Tick();
|
||||
BeginFrame();
|
||||
Tick();
|
||||
BeginFrame();
|
||||
|
||||
m_Client->Render();
|
||||
m_Client->Render();
|
||||
|
||||
m_GuiManager.RenderWidgets();
|
||||
m_GuiManager.RenderWidgets();
|
||||
|
||||
EndFrame();
|
||||
EndFrame();
|
||||
}
|
||||
|
||||
TowerGui::~TowerGui() {
|
||||
m_Client->CloseConnection();
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
m_Client->CloseConnection();
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -14,51 +14,51 @@ TowerPlacePopup::TowerPlacePopup(client::Client* client) : GuiWidget(client) {
|
||||
}
|
||||
|
||||
void TowerPlacePopup::Render() {
|
||||
if (ImGui::BeginPopup("TowerPlace")) {
|
||||
ImGui::BeginChild("TowerPlacePopupChild", ImVec2(800, m_TowerPopupTileHeight + 20), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
for (int i = 0; i < (int)game::TowerType::TowerCount; i++) {
|
||||
if (i > 0) ImGui::SameLine();
|
||||
if (ImGui::BeginPopup("TowerPlace")) {
|
||||
ImGui::BeginChild("TowerPlacePopupChild", ImVec2(800, m_TowerPopupTileHeight + 20), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
for (int i = 0; i < (int)game::TowerType::TowerCount; i++) {
|
||||
if (i > 0) ImGui::SameLine();
|
||||
|
||||
game::TowerType towerType = game::TowerType(i);
|
||||
const game::TowerInfo& towerInfo = game::GetTowerInfo(towerType);
|
||||
game::TowerType towerType = game::TowerType(i);
|
||||
const game::TowerInfo& towerInfo = game::GetTowerInfo(towerType);
|
||||
|
||||
if (!towerInfo.IsBigTower() || (towerInfo.IsBigTower() &&
|
||||
GetClient()->GetGame().GetWorld().CanPlaceBigTower(m_ClickWorldPos, GetClient()->GetGame().GetPlayer()->GetID()))) {
|
||||
if (!towerInfo.IsBigTower() || (towerInfo.IsBigTower() &&
|
||||
GetClient()->GetGame().GetWorld().CanPlaceBigTower(m_ClickWorldPos, GetClient()->GetGame().GetPlayer()->GetID()))) {
|
||||
|
||||
ImGui::BeginChild(std::to_string(i).c_str(), ImVec2(m_TowerPopupTileWidth, m_TowerPopupTileHeight), true);
|
||||
ImGui::BeginChild(std::to_string(i).c_str(), ImVec2(m_TowerPopupTileWidth, m_TowerPopupTileHeight), true);
|
||||
|
||||
ImGui::Text(towerInfo.GetName().c_str());
|
||||
ImGui::Text(towerInfo.GetName().c_str());
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(m_TowerPopupTileWidth - 10 - ImGui::CalcTextSize("(?)").x);
|
||||
ImGui::TextDisabled("(?)");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(m_TowerPopupTileWidth - 10 - ImGui::CalcTextSize("(?)").x);
|
||||
ImGui::TextDisabled("(?)");
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(towerInfo.GetDescription().c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(towerInfo.GetDescription().c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
std::string buyText = std::to_string(100) + " golds";
|
||||
std::string buyText = std::to_string(100) + " golds";
|
||||
|
||||
ImGui::SetCursorPosY(m_TowerPopupTileHeight - m_PlaceTowerButtonHeight - 10);
|
||||
ImGui::SetCursorPosX(m_TowerPopupTileWidth / 2.0f - m_PlaceTowerButtonWidth / 2.0f);
|
||||
ImGui::SetCursorPosY(m_TowerPopupTileHeight - m_PlaceTowerButtonHeight - 10);
|
||||
ImGui::SetCursorPosX(m_TowerPopupTileWidth / 2.0f - m_PlaceTowerButtonWidth / 2.0f);
|
||||
|
||||
if (ImGui::Button(buyText.c_str(), ImVec2(m_PlaceTowerButtonWidth, m_PlaceTowerButtonHeight))) {
|
||||
GetClient()->PlaceTower(towerType, m_ClickWorldPos);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button(buyText.c_str(), ImVec2(m_PlaceTowerButtonWidth, m_PlaceTowerButtonHeight))) {
|
||||
GetClient()->PlaceTower(towerType, m_ClickWorldPos);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void TowerPlacePopup::SetClickPos(const Vec2f& worldPos) {
|
||||
m_ClickWorldPos = worldPos;
|
||||
m_ClickWorldPos = worldPos;
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -10,90 +10,90 @@ namespace td {
|
||||
namespace gui {
|
||||
|
||||
UpdateMenu::UpdateMenu(client::Client* client) : GuiWidget(client), m_Opened(true), m_Updater(std::make_unique<utils::Updater>()) {
|
||||
CheckUpdates();
|
||||
CheckUpdates();
|
||||
}
|
||||
|
||||
UpdateMenu::~UpdateMenu() {}
|
||||
|
||||
void UpdateMenu::Render() {
|
||||
RenderErrorPopup();
|
||||
if (m_Opened) {
|
||||
ImGui::Begin("Updater", &m_Opened);
|
||||
if (IsUpdateChecked()) {
|
||||
RenderErrorPopup();
|
||||
if (m_Opened) {
|
||||
ImGui::Begin("Updater", &m_Opened);
|
||||
if (IsUpdateChecked()) {
|
||||
|
||||
bool updateAvailable = m_UpdateAvailable.get();
|
||||
if (updateAvailable) {
|
||||
bool updateAvailable = m_UpdateAvailable.get();
|
||||
if (updateAvailable) {
|
||||
|
||||
if (m_Updater->IsFileWrited()) {
|
||||
ImGui::Text("The update is now installed");
|
||||
ImGui::Text("The game needs to be restarted");
|
||||
} else if (m_Updater->IsDownloadComplete()) {
|
||||
ImGui::Text("Download done!");
|
||||
if (ImGui::Button("Install")) {
|
||||
if (!m_Updater->WriteFile()) {
|
||||
m_Error = "Failed to write file !\n";
|
||||
ImGui::OpenPopup("UpdateError");
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Updater->CancelDownload();
|
||||
m_Updater->ClearCache();
|
||||
}
|
||||
} else {
|
||||
if (m_Updater->GetDownloadProgress() > 0) {
|
||||
ImGui::Text("Downloading ...");
|
||||
ImGui::ProgressBar(m_Updater->GetDownloadProgress());
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Updater->CancelDownload();
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("An update is available!");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
|
||||
ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());
|
||||
if (m_Updater->IsFileWrited()) {
|
||||
ImGui::Text("The update is now installed");
|
||||
ImGui::Text("The game needs to be restarted");
|
||||
} else if (m_Updater->IsDownloadComplete()) {
|
||||
ImGui::Text("Download done!");
|
||||
if (ImGui::Button("Install")) {
|
||||
if (!m_Updater->WriteFile()) {
|
||||
m_Error = "Failed to write file !\n";
|
||||
ImGui::OpenPopup("UpdateError");
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Updater->CancelDownload();
|
||||
m_Updater->ClearCache();
|
||||
}
|
||||
} else {
|
||||
if (m_Updater->GetDownloadProgress() > 0) {
|
||||
ImGui::Text("Downloading ...");
|
||||
ImGui::ProgressBar(m_Updater->GetDownloadProgress());
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Updater->CancelDownload();
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("An update is available!");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
|
||||
ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());
|
||||
|
||||
bool canDownloadFile = m_Updater->CanUpdate();
|
||||
bool canDownloadFile = m_Updater->CanUpdate();
|
||||
|
||||
if (!canDownloadFile) ImGui::BeginDisabled();
|
||||
if (!canDownloadFile) ImGui::BeginDisabled();
|
||||
|
||||
if (ImGui::Button("Download")) {
|
||||
m_Updater->DownloadUpdate();
|
||||
}
|
||||
if (ImGui::Button("Download")) {
|
||||
m_Updater->DownloadUpdate();
|
||||
}
|
||||
|
||||
if (!canDownloadFile) ImGui::EndDisabled();
|
||||
if (!canDownloadFile) ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Opened = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("No update available!");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
|
||||
ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Checking updates ...");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
m_Opened = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("No update available!");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
|
||||
ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Checking updates ...");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateMenu::RenderErrorPopup() {
|
||||
if (ImGui::BeginPopup("UpdateError")) {
|
||||
ImGui::Text("Error : %s", m_Error.c_str());
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (ImGui::BeginPopup("UpdateError")) {
|
||||
ImGui::Text("Error : %s", m_Error.c_str());
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool UpdateMenu::IsUpdateChecked() {
|
||||
return m_UpdateAvailable.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
|
||||
return m_UpdateAvailable.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
|
||||
}
|
||||
|
||||
void UpdateMenu::CheckUpdates() {
|
||||
m_UpdateAvailable = std::async(std::launch::async, [&]() { return m_Updater->CheckUpdate();});
|
||||
m_UpdateAvailable = std::async(std::launch::async, [&]() { return m_Updater->CheckUpdate();});
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -11,233 +11,233 @@ namespace render {
|
||||
namespace WorldLoader {
|
||||
|
||||
GL::VertexArray LoadMobModel() {
|
||||
std::vector<float> positions = {
|
||||
-0.5, -0.5,
|
||||
0.5, -0.5,
|
||||
-0.5, 0.5,
|
||||
std::vector<float> positions = {
|
||||
-0.5, -0.5,
|
||||
0.5, -0.5,
|
||||
-0.5, 0.5,
|
||||
|
||||
0.5, -0.5,
|
||||
-0.5, 0.5,
|
||||
0.5, 0.5
|
||||
};
|
||||
0.5, -0.5,
|
||||
-0.5, 0.5,
|
||||
0.5, 0.5
|
||||
};
|
||||
|
||||
float yellowFloat;
|
||||
int yellow = 255 << 24 | 255 << 16 | 255;
|
||||
memcpy(&yellowFloat, &yellow, sizeof(int));
|
||||
float yellowFloat;
|
||||
int yellow = 255 << 24 | 255 << 16 | 255;
|
||||
memcpy(&yellowFloat, &yellow, sizeof(int));
|
||||
|
||||
std::vector<float> colors = {
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
std::vector<float> colors = {
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
yellowFloat
|
||||
};
|
||||
yellowFloat,
|
||||
yellowFloat,
|
||||
yellowFloat
|
||||
};
|
||||
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
|
||||
GL::VertexArray mobVao(colors.size()); // each pos = 1 color
|
||||
mobVao.Bind();
|
||||
mobVao.BindVertexBuffer(positionVBO);
|
||||
mobVao.BindVertexBuffer(colorVBO);
|
||||
mobVao.Unbind();
|
||||
return mobVao;
|
||||
GL::VertexArray mobVao(colors.size()); // each pos = 1 color
|
||||
mobVao.Bind();
|
||||
mobVao.BindVertexBuffer(positionVBO);
|
||||
mobVao.BindVertexBuffer(colorVBO);
|
||||
mobVao.Unbind();
|
||||
return mobVao;
|
||||
}
|
||||
|
||||
GL::VertexArray LoadWorldModel(const td::game::World* world) {
|
||||
std::vector<float> positions;
|
||||
std::vector<float> colors;
|
||||
std::vector<float> positions;
|
||||
std::vector<float> colors;
|
||||
|
||||
for (const auto& chunkInfo : world->GetChunks()) {
|
||||
const td::game::ChunkCoord& coords = chunkInfo.first;
|
||||
td::game::ChunkPtr chunk = chunkInfo.second;
|
||||
for (const auto& chunkInfo : world->GetChunks()) {
|
||||
const td::game::ChunkCoord& coords = chunkInfo.first;
|
||||
td::game::ChunkPtr chunk = chunkInfo.second;
|
||||
|
||||
std::int32_t chunkX = coords.x * td::game::Chunk::ChunkWidth;
|
||||
std::int32_t chunkY = coords.y * td::game::Chunk::ChunkHeight;
|
||||
std::int32_t chunkX = coords.x * td::game::Chunk::ChunkWidth;
|
||||
std::int32_t chunkY = coords.y * td::game::Chunk::ChunkHeight;
|
||||
|
||||
for (int tileY = 0; tileY < td::game::Chunk::ChunkHeight; tileY++) {
|
||||
for (int tileX = 0; tileX < td::game::Chunk::ChunkWidth; tileX++) {
|
||||
int tileNumber = tileY * td::game::Chunk::ChunkWidth + tileX;
|
||||
td::game::TileIndex tileIndex = chunk->GetTileIndex(tileNumber);
|
||||
td::game::TilePtr tile = world->GetTilePtr(tileIndex);
|
||||
for (int tileY = 0; tileY < td::game::Chunk::ChunkHeight; tileY++) {
|
||||
for (int tileX = 0; tileX < td::game::Chunk::ChunkWidth; tileX++) {
|
||||
int tileNumber = tileY * td::game::Chunk::ChunkWidth + tileX;
|
||||
td::game::TileIndex tileIndex = chunk->GetTileIndex(tileNumber);
|
||||
td::game::TilePtr tile = world->GetTilePtr(tileIndex);
|
||||
|
||||
if (tile == nullptr)
|
||||
continue;
|
||||
if (tile == nullptr)
|
||||
continue;
|
||||
|
||||
positions.insert(positions.end(), {
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY + 1),
|
||||
positions.insert(positions.end(), {
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY + 1),
|
||||
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY + 1),
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY + 1),
|
||||
});
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY),
|
||||
static_cast<float>(chunkX + tileX), static_cast<float>(chunkY + tileY + 1),
|
||||
static_cast<float>(chunkX + tileX + 1), static_cast<float>(chunkY + tileY + 1),
|
||||
});
|
||||
|
||||
const td::Color* tileColor = world->GetTileColor(tile);
|
||||
const td::Color* tileColor = world->GetTileColor(tile);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= tileColor->r << 24;
|
||||
color |= tileColor->g << 16;
|
||||
color |= tileColor->b << 8;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= tileColor->r << 24;
|
||||
color |= tileColor->g << 16;
|
||||
color |= tileColor->b << 8;
|
||||
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int spawnColor = 0; spawnColor < 2; spawnColor++) {
|
||||
const game::Spawn& spawn = world->GetTeam(game::TeamColor(spawnColor)).GetSpawn();
|
||||
float fromX = spawn.GetTopLeft().GetX(), toX = spawn.GetBottomRight().GetX();
|
||||
float fromY = spawn.GetTopLeft().GetY(), toY = spawn.GetBottomRight().GetY();
|
||||
for (int spawnColor = 0; spawnColor < 2; spawnColor++) {
|
||||
const game::Spawn& spawn = world->GetTeam(game::TeamColor(spawnColor)).GetSpawn();
|
||||
float fromX = spawn.GetTopLeft().GetX(), toX = spawn.GetBottomRight().GetX();
|
||||
float fromY = spawn.GetTopLeft().GetY(), toY = spawn.GetBottomRight().GetY();
|
||||
|
||||
positions.insert(positions.end(), {
|
||||
fromX, fromY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
positions.insert(positions.end(), {
|
||||
fromX, fromY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
|
||||
toX, toY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
});
|
||||
toX, toY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
});
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).r << 24;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).g << 16;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).b << 8;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).r << 24;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).g << 16;
|
||||
color |= world->GetSpawnColor(game::TeamColor(spawnColor)).b << 8;
|
||||
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
for (int castleColor = 0; castleColor < 2; castleColor++) {
|
||||
const game::TeamCastle& castle = world->GetTeam(game::TeamColor(castleColor)).GetCastle();
|
||||
float fromX = castle.GetTopLeft().GetX(), toX = castle.GetBottomRight().GetX();
|
||||
float fromY = castle.GetTopLeft().GetY(), toY = castle.GetBottomRight().GetY();
|
||||
for (int castleColor = 0; castleColor < 2; castleColor++) {
|
||||
const game::TeamCastle& castle = world->GetTeam(game::TeamColor(castleColor)).GetCastle();
|
||||
float fromX = castle.GetTopLeft().GetX(), toX = castle.GetBottomRight().GetX();
|
||||
float fromY = castle.GetTopLeft().GetY(), toY = castle.GetBottomRight().GetY();
|
||||
|
||||
positions.insert(positions.end(), {
|
||||
fromX, fromY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
positions.insert(positions.end(), {
|
||||
fromX, fromY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
|
||||
toX, toY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
});
|
||||
toX, toY,
|
||||
fromX, toY,
|
||||
toX, fromY,
|
||||
});
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).r << 24;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).g << 16;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).b << 8;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int color = 255;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).r << 24;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).g << 16;
|
||||
color |= world->GetSpawnColor(game::TeamColor(castleColor)).b << 8;
|
||||
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
int newColorIndex = colors.size();
|
||||
colors.push_back(0);
|
||||
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
memcpy(colors.data() + newColorIndex, &color, 1 * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
|
||||
GL::VertexArray worldVao(positions.size() / 2); // each pos = 2 vertecies
|
||||
worldVao.Bind();
|
||||
worldVao.BindVertexBuffer(positionVBO);
|
||||
worldVao.BindVertexBuffer(colorVBO);
|
||||
worldVao.Unbind();
|
||||
return worldVao;
|
||||
GL::VertexArray worldVao(positions.size() / 2); // each pos = 2 vertecies
|
||||
worldVao.Bind();
|
||||
worldVao.BindVertexBuffer(positionVBO);
|
||||
worldVao.BindVertexBuffer(colorVBO);
|
||||
worldVao.Unbind();
|
||||
return worldVao;
|
||||
}
|
||||
|
||||
GL::VertexArray LoadTileSelectModel() {
|
||||
std::vector<float> positions = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
std::vector<float> positions = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
|
||||
1, 0,
|
||||
0, 1,
|
||||
1, 1
|
||||
};
|
||||
1, 0,
|
||||
0, 1,
|
||||
1, 1
|
||||
};
|
||||
|
||||
int color = 255 << 24 | 255 << 16 | 255 << 8 | 150;
|
||||
float colorFloat;
|
||||
int color = 255 << 24 | 255 << 16 | 255 << 8 | 150;
|
||||
float colorFloat;
|
||||
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(&colorFloat), &color, sizeof(float));
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(&colorFloat), &color, sizeof(float));
|
||||
|
||||
std::vector<float> colors(6, colorFloat);
|
||||
std::vector<float> colors(6, colorFloat);
|
||||
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
GL::VertexBuffer positionVBO(positions, 2);
|
||||
positionVBO.AddVertexAttribPointer(0, 2, 0);
|
||||
GL::VertexBuffer colorVBO(colors, 1);
|
||||
colorVBO.AddVertexAttribPointer(1, 1, 0);
|
||||
|
||||
GL::VertexArray tileSelectVao(positions.size() / 2); // each pos = 2 vertecies
|
||||
tileSelectVao.Bind();
|
||||
tileSelectVao.BindVertexBuffer(positionVBO);
|
||||
tileSelectVao.BindVertexBuffer(colorVBO);
|
||||
tileSelectVao.Unbind();
|
||||
GL::VertexArray tileSelectVao(positions.size() / 2); // each pos = 2 vertecies
|
||||
tileSelectVao.Bind();
|
||||
tileSelectVao.BindVertexBuffer(positionVBO);
|
||||
tileSelectVao.BindVertexBuffer(colorVBO);
|
||||
tileSelectVao.Unbind();
|
||||
|
||||
return tileSelectVao;
|
||||
return tileSelectVao;
|
||||
}
|
||||
|
||||
RenderData LoadTowerModel(game::TowerPtr tower) {
|
||||
RenderData renderData;
|
||||
RenderData renderData;
|
||||
|
||||
float towerX, towerDX;
|
||||
float towerY, towerDY;
|
||||
float towerX, towerDX;
|
||||
float towerY, towerDY;
|
||||
|
||||
if (tower->GetSize() == game::TowerSize::Little) {
|
||||
towerX = tower->GetCenterX() - 1.5f;
|
||||
towerDX = tower->GetCenterX() + 1.5f;
|
||||
if (tower->GetSize() == game::TowerSize::Little) {
|
||||
towerX = tower->GetCenterX() - 1.5f;
|
||||
towerDX = tower->GetCenterX() + 1.5f;
|
||||
|
||||
towerY = tower->GetCenterY() - 1.5f;
|
||||
towerDY = tower->GetCenterY() + 1.5f;
|
||||
} else {
|
||||
towerX = tower->GetCenterX() - 2.5f;
|
||||
towerDX = tower->GetCenterX() + 2.5f;
|
||||
towerY = tower->GetCenterY() - 1.5f;
|
||||
towerDY = tower->GetCenterY() + 1.5f;
|
||||
} else {
|
||||
towerX = tower->GetCenterX() - 2.5f;
|
||||
towerDX = tower->GetCenterX() + 2.5f;
|
||||
|
||||
towerY = tower->GetCenterY() - 2.5f;
|
||||
towerDY = tower->GetCenterY() + 2.5f;
|
||||
}
|
||||
std::vector<float> positions = {
|
||||
towerX, towerY,
|
||||
towerDX, towerY,
|
||||
towerX, towerDY,
|
||||
towerY = tower->GetCenterY() - 2.5f;
|
||||
towerDY = tower->GetCenterY() + 2.5f;
|
||||
}
|
||||
std::vector<float> positions = {
|
||||
towerX, towerY,
|
||||
towerDX, towerY,
|
||||
towerX, towerDY,
|
||||
|
||||
towerDX, towerY,
|
||||
towerX, towerDY,
|
||||
towerDX, towerDY
|
||||
};
|
||||
towerDX, towerY,
|
||||
towerX, towerDY,
|
||||
towerDX, towerDY
|
||||
};
|
||||
|
||||
renderData.positions = positions;
|
||||
renderData.positions = positions;
|
||||
|
||||
std::uint8_t towerType = static_cast<std::uint8_t>(tower->GetType());
|
||||
std::uint8_t r = 10 * towerType + 40, g = 5 * towerType + 30, b = 10 * towerType + 20;
|
||||
std::uint8_t towerType = static_cast<std::uint8_t>(tower->GetType());
|
||||
std::uint8_t r = 10 * towerType + 40, g = 5 * towerType + 30, b = 10 * towerType + 20;
|
||||
|
||||
float colorFloat;
|
||||
int color = r << 24 | g << 16 | b << 8 | 255;
|
||||
memcpy(&colorFloat, &color, sizeof(int));
|
||||
float colorFloat;
|
||||
int color = r << 24 | g << 16 | b << 8 | 255;
|
||||
memcpy(&colorFloat, &color, sizeof(int));
|
||||
|
||||
std::vector<float> colors(6, colorFloat);
|
||||
renderData.colors = colors;
|
||||
std::vector<float> colors(6, colorFloat);
|
||||
renderData.colors = colors;
|
||||
|
||||
return renderData;
|
||||
return renderData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -96,31 +96,31 @@ void main(void){
|
||||
EntityShader::EntityShader() : ShaderProgram() {}
|
||||
|
||||
void EntityShader::LoadShader() {
|
||||
ShaderProgram::LoadProgram(vertexSource, fragmentSource);
|
||||
ShaderProgram::LoadProgram(vertexSource, fragmentSource);
|
||||
}
|
||||
|
||||
void EntityShader::GetAllUniformLocation() {
|
||||
m_LocationAspectRatio = static_cast<unsigned int>(GetUniformLocation("aspectRatio"));
|
||||
m_LocationZoom = static_cast<unsigned int>(GetUniformLocation("zoom"));
|
||||
m_LocationCam = static_cast<unsigned int>(GetUniformLocation("camPos"));
|
||||
m_LocationTranslation = static_cast<unsigned int>(GetUniformLocation("translation"));
|
||||
m_LocationViewtype = static_cast<unsigned int>(GetUniformLocation("isometricView"));
|
||||
m_LocationAspectRatio = static_cast<unsigned int>(GetUniformLocation("aspectRatio"));
|
||||
m_LocationZoom = static_cast<unsigned int>(GetUniformLocation("zoom"));
|
||||
m_LocationCam = static_cast<unsigned int>(GetUniformLocation("camPos"));
|
||||
m_LocationTranslation = static_cast<unsigned int>(GetUniformLocation("translation"));
|
||||
m_LocationViewtype = static_cast<unsigned int>(GetUniformLocation("isometricView"));
|
||||
}
|
||||
|
||||
void EntityShader::SetCamPos(const Vec2f& camPos) {
|
||||
LoadVector(m_LocationCam, camPos);
|
||||
LoadVector(m_LocationCam, camPos);
|
||||
}
|
||||
void EntityShader::SetZoom(float zoom) {
|
||||
LoadFloat(m_LocationZoom, zoom);
|
||||
LoadFloat(m_LocationZoom, zoom);
|
||||
}
|
||||
void EntityShader::SetAspectRatio(float aspectRatio) {
|
||||
LoadFloat(m_LocationAspectRatio, aspectRatio);
|
||||
LoadFloat(m_LocationAspectRatio, aspectRatio);
|
||||
}
|
||||
void EntityShader::SetModelPos(const Vec2f& modelPos) {
|
||||
LoadVector(m_LocationTranslation, modelPos);
|
||||
LoadVector(m_LocationTranslation, modelPos);
|
||||
}
|
||||
void EntityShader::SetIsometricView(float isometric) {
|
||||
LoadFloat(m_LocationViewtype, isometric);
|
||||
LoadFloat(m_LocationViewtype, isometric);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,117 +22,117 @@ namespace td {
|
||||
namespace shader {
|
||||
|
||||
ShaderProgram::ShaderProgram() :
|
||||
m_ProgramID(0), m_VertexShaderID(0), m_FragmentShaderID(0) {
|
||||
m_ProgramID(0), m_VertexShaderID(0), m_FragmentShaderID(0) {
|
||||
}
|
||||
|
||||
ShaderProgram::~ShaderProgram() {
|
||||
CleanUp();
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void ShaderProgram::Start() const {
|
||||
glUseProgram(m_ProgramID);
|
||||
glUseProgram(m_ProgramID);
|
||||
}
|
||||
|
||||
void ShaderProgram::Stop() const {
|
||||
glUseProgram(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
int ShaderProgram::GetUniformLocation(const std::string& uniformName) const {
|
||||
const int location = glGetUniformLocation(m_ProgramID, uniformName.c_str());
|
||||
if (location == -1) {
|
||||
utils::LOGD(utils::format("Warning ! Uniform variable %s not found !", uniformName.c_str()));
|
||||
}
|
||||
return location;
|
||||
const int location = glGetUniformLocation(m_ProgramID, uniformName.c_str());
|
||||
if (location == -1) {
|
||||
utils::LOGD(utils::format("Warning ! Uniform variable %s not found !", uniformName.c_str()));
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadFloat(unsigned int location, float value) const {
|
||||
glUniform1f(static_cast<GLint>(location), value);
|
||||
glUniform1f(static_cast<GLint>(location), value);
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadInt(unsigned int location, int value) const {
|
||||
glUniform1i(static_cast<GLint>(location), value);
|
||||
glUniform1i(static_cast<GLint>(location), value);
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadVector(unsigned int location,
|
||||
const Vec2f& vector) const {
|
||||
glUniform2f(static_cast<GLint>(location), vector.x, vector.y);
|
||||
const Vec2f& vector) const {
|
||||
glUniform2f(static_cast<GLint>(location), vector.x, vector.y);
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadVector(unsigned int location,
|
||||
const Vec3f& vector) const {
|
||||
glUniform3f(static_cast<GLint>(location), vector.x, vector.y, vector.z);
|
||||
const Vec3f& vector) const {
|
||||
glUniform3f(static_cast<GLint>(location), vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadBoolean(unsigned int location, bool value) const {
|
||||
glUniform1i(static_cast<GLint>(location), value);
|
||||
glUniform1i(static_cast<GLint>(location), value);
|
||||
}
|
||||
|
||||
void ShaderProgram::CleanUp() const {
|
||||
Stop();
|
||||
glDetachShader(m_ProgramID, m_VertexShaderID);
|
||||
glDetachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glDeleteShader(m_VertexShaderID);
|
||||
glDeleteShader(m_FragmentShaderID);
|
||||
glDeleteProgram(m_ProgramID);
|
||||
Stop();
|
||||
glDetachShader(m_ProgramID, m_VertexShaderID);
|
||||
glDetachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glDeleteShader(m_VertexShaderID);
|
||||
glDeleteShader(m_FragmentShaderID);
|
||||
glDeleteProgram(m_ProgramID);
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadProgramFile(const std::string& vertexFile,
|
||||
const std::string& fragmentFile) {
|
||||
m_VertexShaderID = static_cast<unsigned int>(LoadShaderFromFile(vertexFile, GL_VERTEX_SHADER));
|
||||
m_FragmentShaderID = static_cast<unsigned int>(LoadShaderFromFile(fragmentFile, GL_FRAGMENT_SHADER));
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, m_VertexShaderID);
|
||||
glAttachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glLinkProgram(m_ProgramID);
|
||||
glValidateProgram(m_ProgramID);
|
||||
GetAllUniformLocation();
|
||||
const std::string& fragmentFile) {
|
||||
m_VertexShaderID = static_cast<unsigned int>(LoadShaderFromFile(vertexFile, GL_VERTEX_SHADER));
|
||||
m_FragmentShaderID = static_cast<unsigned int>(LoadShaderFromFile(fragmentFile, GL_FRAGMENT_SHADER));
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, m_VertexShaderID);
|
||||
glAttachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glLinkProgram(m_ProgramID);
|
||||
glValidateProgram(m_ProgramID);
|
||||
GetAllUniformLocation();
|
||||
}
|
||||
|
||||
void ShaderProgram::LoadProgram(const std::string& vertexSource,
|
||||
const std::string& fragmentSource) {
|
||||
m_VertexShaderID = static_cast<unsigned int>(LoadShader(vertexSource, GL_VERTEX_SHADER));
|
||||
m_FragmentShaderID = static_cast<unsigned int>(LoadShader(fragmentSource, GL_FRAGMENT_SHADER));
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, m_VertexShaderID);
|
||||
glAttachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glLinkProgram(m_ProgramID);
|
||||
glValidateProgram(m_ProgramID);
|
||||
GetAllUniformLocation();
|
||||
const std::string& fragmentSource) {
|
||||
m_VertexShaderID = static_cast<unsigned int>(LoadShader(vertexSource, GL_VERTEX_SHADER));
|
||||
m_FragmentShaderID = static_cast<unsigned int>(LoadShader(fragmentSource, GL_FRAGMENT_SHADER));
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, m_VertexShaderID);
|
||||
glAttachShader(m_ProgramID, m_FragmentShaderID);
|
||||
glLinkProgram(m_ProgramID);
|
||||
glValidateProgram(m_ProgramID);
|
||||
GetAllUniformLocation();
|
||||
}
|
||||
|
||||
unsigned int ShaderProgram::LoadShader(const std::string& source, GLenum type) {
|
||||
unsigned int shaderID = glCreateShader(type);
|
||||
unsigned int shaderID = glCreateShader(type);
|
||||
|
||||
const char* c_str = source.c_str();
|
||||
int* null = 0;
|
||||
glShaderSource(shaderID, 1, &c_str, null); // @suppress("Function cannot be resolved")
|
||||
glCompileShader(shaderID);
|
||||
GLint compilesuccessful;
|
||||
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compilesuccessful);
|
||||
if (compilesuccessful == false) {
|
||||
GLsizei size;
|
||||
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &size);
|
||||
std::vector<char> shaderError(static_cast<std::size_t>(size));
|
||||
glGetShaderInfoLog(shaderID, size, &size, shaderError.data());
|
||||
const char* c_str = source.c_str();
|
||||
int* null = 0;
|
||||
glShaderSource(shaderID, 1, &c_str, null); // @suppress("Function cannot be resolved")
|
||||
glCompileShader(shaderID);
|
||||
GLint compilesuccessful;
|
||||
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compilesuccessful);
|
||||
if (compilesuccessful == false) {
|
||||
GLsizei size;
|
||||
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &size);
|
||||
std::vector<char> shaderError(static_cast<std::size_t>(size));
|
||||
glGetShaderInfoLog(shaderID, size, &size, shaderError.data());
|
||||
|
||||
utils::LOGE("Could not compile shader !");
|
||||
utils::LOGE("Could not compile shader !");
|
||||
|
||||
utils::LOGE(shaderError.data());
|
||||
}
|
||||
return shaderID;
|
||||
utils::LOGE(shaderError.data());
|
||||
}
|
||||
return shaderID;
|
||||
}
|
||||
|
||||
unsigned int ShaderProgram::LoadShaderFromFile(const std::string& file, GLenum type) {
|
||||
std::stringstream stream;
|
||||
std::ifstream fileStream(file);
|
||||
std::stringstream stream;
|
||||
std::ifstream fileStream(file);
|
||||
|
||||
if (fileStream) {
|
||||
stream << fileStream.rdbuf();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (fileStream) {
|
||||
stream << fileStream.rdbuf();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LoadShader(stream.str(), type);
|
||||
return LoadShader(stream.str(), type);
|
||||
}
|
||||
|
||||
} // namespace shader
|
||||
|
||||
@@ -90,27 +90,27 @@ void main(void){
|
||||
WorldShader::WorldShader() : ShaderProgram() {}
|
||||
|
||||
void WorldShader::LoadShader() {
|
||||
ShaderProgram::LoadProgram(vertexSource, fragmentSource);
|
||||
ShaderProgram::LoadProgram(vertexSource, fragmentSource);
|
||||
}
|
||||
|
||||
void WorldShader::GetAllUniformLocation() {
|
||||
m_LocationAspectRatio = static_cast<unsigned int>(GetUniformLocation("aspectRatio"));
|
||||
m_LocationZoom = static_cast<unsigned int>(GetUniformLocation("zoom"));
|
||||
m_LocationCam = static_cast<unsigned int>(GetUniformLocation("camPos"));
|
||||
m_LocationViewtype = static_cast<unsigned int>(GetUniformLocation("isometricView"));
|
||||
m_LocationAspectRatio = static_cast<unsigned int>(GetUniformLocation("aspectRatio"));
|
||||
m_LocationZoom = static_cast<unsigned int>(GetUniformLocation("zoom"));
|
||||
m_LocationCam = static_cast<unsigned int>(GetUniformLocation("camPos"));
|
||||
m_LocationViewtype = static_cast<unsigned int>(GetUniformLocation("isometricView"));
|
||||
}
|
||||
|
||||
void WorldShader::SetCamPos(const Vec2f& camPos) {
|
||||
LoadVector(m_LocationCam, camPos);
|
||||
LoadVector(m_LocationCam, camPos);
|
||||
}
|
||||
void WorldShader::SetZoom(float zoom) {
|
||||
LoadFloat(m_LocationZoom, zoom);
|
||||
LoadFloat(m_LocationZoom, zoom);
|
||||
}
|
||||
void WorldShader::SetAspectRatio(float aspectRatio) {
|
||||
LoadFloat(m_LocationAspectRatio, aspectRatio);
|
||||
LoadFloat(m_LocationAspectRatio, aspectRatio);
|
||||
}
|
||||
void WorldShader::SetIsometricView(float isometric) {
|
||||
LoadFloat(m_LocationViewtype, isometric);
|
||||
LoadFloat(m_LocationViewtype, isometric);
|
||||
}
|
||||
|
||||
} // namespace shader
|
||||
|
||||
@@ -16,118 +16,118 @@ namespace td {
|
||||
namespace utils {
|
||||
|
||||
bool Updater::CheckUpdate() {
|
||||
httplib::Client client("thesims.freeboxos.fr", 30000);
|
||||
httplib::Client client("thesims.freeboxos.fr", 30000);
|
||||
|
||||
if (auto res = client.Get("/Tower%20Defense/version")) {
|
||||
if (auto res = client.Get("/Tower%20Defense/version")) {
|
||||
|
||||
std::string currentVersion = GetCurrentVersion();
|
||||
m_LastVersion = res.value().body;
|
||||
std::string currentVersion = GetCurrentVersion();
|
||||
m_LastVersion = res.value().body;
|
||||
|
||||
// we only look at the first line
|
||||
m_LastVersion = m_LastVersion.substr(0, m_LastVersion.find('\n'));
|
||||
// we only look at the first line
|
||||
m_LastVersion = m_LastVersion.substr(0, m_LastVersion.find('\n'));
|
||||
|
||||
utils::LOG(utils::format("Current version : [%s]", GetCurrentVersion().c_str()));
|
||||
utils::LOG(utils::format("Last version : [%s]", m_LastVersion.c_str()));
|
||||
utils::LOG(utils::format("Current version : [%s]", GetCurrentVersion().c_str()));
|
||||
utils::LOG(utils::format("Last version : [%s]", m_LastVersion.c_str()));
|
||||
|
||||
if (currentVersion != m_LastVersion) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
utils::LOGE(utils::format("Error code : %u", res.error()));
|
||||
return false;
|
||||
}
|
||||
if (currentVersion != m_LastVersion) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
utils::LOGE(utils::format("Error code : %u", res.error()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Updater::CanUpdate() {
|
||||
return !GetDownloadFileURL().empty();
|
||||
return !GetDownloadFileURL().empty();
|
||||
}
|
||||
|
||||
std::string Updater::GetDownloadFileURL() {
|
||||
Os systemOs = GetSystemOs();
|
||||
Architecture systemArch = GetSystemArchitecture();
|
||||
Os systemOs = GetSystemOs();
|
||||
Architecture systemArch = GetSystemArchitecture();
|
||||
|
||||
switch (systemOs) {
|
||||
switch (systemOs) {
|
||||
|
||||
case Os::Windows: {
|
||||
case Os::Windows: {
|
||||
|
||||
switch (systemArch) {
|
||||
case Architecture::x86_64:
|
||||
return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86_64).exe";
|
||||
case Architecture::x86:
|
||||
return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86).exe";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
switch (systemArch) {
|
||||
case Architecture::x86_64:
|
||||
return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86_64).exe";
|
||||
case Architecture::x86:
|
||||
return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86).exe";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
default: // not supported on Android and Linux (package managers are better)
|
||||
return "";
|
||||
}
|
||||
default: // not supported on Android and Linux (package managers are better)
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string Updater::GetLocalFilePath() {
|
||||
#ifdef _WIN32
|
||||
char filePathBuffer[1024];
|
||||
GetModuleFileName(nullptr, filePathBuffer, sizeof(filePathBuffer));
|
||||
char filePathBuffer[1024];
|
||||
GetModuleFileName(nullptr, filePathBuffer, sizeof(filePathBuffer));
|
||||
|
||||
std::string filePath = filePathBuffer;
|
||||
return filePath;
|
||||
std::string filePath = filePathBuffer;
|
||||
return filePath;
|
||||
#endif
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
void Updater::DownloadUpdate() {
|
||||
if (m_DownloadComplete) return;
|
||||
if (m_DownloadComplete) return;
|
||||
|
||||
m_CancelDownload = false;
|
||||
m_CancelDownload = false;
|
||||
|
||||
std::string newFileUrl = GetDownloadFileURL();
|
||||
std::string newFileUrl = GetDownloadFileURL();
|
||||
|
||||
httplib::Client client("thesims.freeboxos.fr", 30000);
|
||||
httplib::Client client("thesims.freeboxos.fr", 30000);
|
||||
|
||||
httplib::ContentReceiver reciever = [&](const char* data, size_t data_length) {
|
||||
std::string fileData(data, data_length);
|
||||
m_FileBuffer << fileData;
|
||||
return true;
|
||||
};
|
||||
httplib::ContentReceiver reciever = [&](const char* data, size_t data_length) {
|
||||
std::string fileData(data, data_length);
|
||||
m_FileBuffer << fileData;
|
||||
return true;
|
||||
};
|
||||
|
||||
httplib::Progress progress = [&](uint64_t len, uint64_t total) {
|
||||
m_Progress = (float)len * 100.0f / total;
|
||||
return !m_CancelDownload;
|
||||
};
|
||||
httplib::Progress progress = [&](uint64_t len, uint64_t total) {
|
||||
m_Progress = (float)len * 100.0f / total;
|
||||
return !m_CancelDownload;
|
||||
};
|
||||
|
||||
auto res = client.Get(newFileUrl.c_str(), reciever, progress);
|
||||
auto res = client.Get(newFileUrl.c_str(), reciever, progress);
|
||||
|
||||
if (!m_CancelDownload) {
|
||||
m_DownloadComplete = true;
|
||||
}
|
||||
if (!m_CancelDownload) {
|
||||
m_DownloadComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Updater::RemoveOldFile() {
|
||||
std::remove(std::string(GetLocalFilePath() + "_old").c_str());
|
||||
std::remove(std::string(GetLocalFilePath() + "_old").c_str());
|
||||
}
|
||||
|
||||
bool Updater::WriteFile() {
|
||||
if (m_FileWrited || !m_DownloadComplete) return false;
|
||||
if (m_FileWrited || !m_DownloadComplete) return false;
|
||||
|
||||
if (!m_FileBuffer.WriteFile(GetLocalFilePath() + "_recent"))
|
||||
return false;
|
||||
if (!m_FileBuffer.WriteFile(GetLocalFilePath() + "_recent"))
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
std::rename(GetLocalFilePath().c_str(), std::string(GetLocalFilePath() + "_old").c_str());
|
||||
std::rename(std::string(GetLocalFilePath() + "_recent").c_str(), GetLocalFilePath().c_str());
|
||||
std::rename(GetLocalFilePath().c_str(), std::string(GetLocalFilePath() + "_old").c_str());
|
||||
std::rename(std::string(GetLocalFilePath() + "_recent").c_str(), GetLocalFilePath().c_str());
|
||||
#endif
|
||||
|
||||
m_FileWrited = true;
|
||||
m_DownloadComplete = false;
|
||||
m_FileWrited = true;
|
||||
m_DownloadComplete = false;
|
||||
|
||||
ClearCache();
|
||||
ClearCache();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -38,134 +38,134 @@ static float aspectRatio;
|
||||
static bool shouldClose = false;
|
||||
|
||||
void WindowResizeEvent(int width, int height) {
|
||||
aspectRatio = (float)width / height;
|
||||
renderer->Resize(width, height);
|
||||
lastWidth = width;
|
||||
lastHeight = height;
|
||||
aspectRatio = (float)width / height;
|
||||
renderer->Resize(width, height);
|
||||
lastWidth = width;
|
||||
lastHeight = height;
|
||||
}
|
||||
|
||||
bool Create() {
|
||||
window = SDL_CreateWindow(WindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WindowWidth, WindowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
// Prepare and create context
|
||||
window = SDL_CreateWindow(WindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WindowWidth, WindowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
// Prepare and create context
|
||||
#ifdef __ANDROID__
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#endif
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
|
||||
if (!glContext) {
|
||||
std::cerr << "Could not create context! SDL error: " << SDL_GetError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!glContext) {
|
||||
std::cerr << "Could not create context! SDL error: " << SDL_GetError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int major, minor, mask;
|
||||
int r, g, b, a, depth;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
|
||||
int major, minor, mask;
|
||||
int r, g, b, a, depth;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
|
||||
|
||||
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
|
||||
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
|
||||
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
|
||||
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a);
|
||||
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
|
||||
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
|
||||
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
|
||||
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a);
|
||||
|
||||
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
|
||||
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
|
||||
|
||||
const char* mask_desc;
|
||||
const char* mask_desc;
|
||||
|
||||
if (mask & SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||
mask_desc = "core";
|
||||
} else if (mask & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) {
|
||||
mask_desc = "compatibility";
|
||||
} else if (mask & SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
mask_desc = "es";
|
||||
} else {
|
||||
mask_desc = "?";
|
||||
}
|
||||
if (mask & SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||
mask_desc = "core";
|
||||
} else if (mask & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) {
|
||||
mask_desc = "compatibility";
|
||||
} else if (mask & SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
mask_desc = "es";
|
||||
} else {
|
||||
mask_desc = "?";
|
||||
}
|
||||
|
||||
td::utils::LOG(td::utils::format("GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
|
||||
td::utils::LOG(td::utils::format("GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
|
||||
|
||||
SDL_GL_MakeCurrent(window, glContext);
|
||||
SDL_GL_MakeCurrent(window, glContext);
|
||||
|
||||
if (!renderer->Init()) {
|
||||
exit(1);
|
||||
}
|
||||
towerGui = std::make_unique<td::render::TowerGui>(window, glContext, renderer.get());
|
||||
WindowResizeEvent(WindowWidth, WindowHeight);
|
||||
return true;
|
||||
if (!renderer->Init()) {
|
||||
exit(1);
|
||||
}
|
||||
towerGui = std::make_unique<td::render::TowerGui>(window, glContext, renderer.get());
|
||||
WindowResizeEvent(WindowWidth, WindowHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Render() {
|
||||
renderer->Prepare();
|
||||
towerGui->Render();
|
||||
renderer->Prepare();
|
||||
towerGui->Render();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
SDL_GL_SwapWindow(window);
|
||||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
renderer.reset(0);
|
||||
towerGui.reset(0);
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
window = NULL;
|
||||
renderer.reset(0);
|
||||
towerGui.reset(0);
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
void PollEvents() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_WINDOWEVENT) {
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE: {
|
||||
shouldClose = true;
|
||||
}
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_WINDOWEVENT) {
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE: {
|
||||
shouldClose = true;
|
||||
}
|
||||
|
||||
case SDL_WINDOWEVENT_RESIZED: {
|
||||
int windowWidth, windowHeight;
|
||||
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||
WindowResizeEvent(windowWidth, windowHeight);
|
||||
}
|
||||
case SDL_WINDOWEVENT_RESIZED: {
|
||||
int windowWidth, windowHeight;
|
||||
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||
WindowResizeEvent(windowWidth, windowHeight);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCloseRequested() {
|
||||
return shouldClose;
|
||||
return shouldClose;
|
||||
}
|
||||
|
||||
bool IsMouseDown(int button) {
|
||||
return ImGui::GetIO().MouseDown[button];
|
||||
return ImGui::GetIO().MouseDown[button];
|
||||
}
|
||||
|
||||
float GetAspectRatio() {
|
||||
return aspectRatio;
|
||||
return aspectRatio;
|
||||
}
|
||||
|
||||
int GetWindowWidth() {
|
||||
return lastWidth;
|
||||
return lastWidth;
|
||||
}
|
||||
int GetWindowHeight() {
|
||||
return lastHeight;
|
||||
return lastHeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user