restructure project

This commit is contained in:
2023-08-13 11:59:13 +02:00
parent b4836847f5
commit 50c17e8ed1
210 changed files with 471 additions and 422 deletions

148
include/td/Defines.h Normal file
View File

@@ -0,0 +1,148 @@
#pragma once
#include <cstdint>
namespace td {
static constexpr float PI = 3.141592653f;
template<typename T>
struct Vec2 {
union {
T x;
T r;
};
union {
T y;
T g;
};
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;
}
template<typename T>
struct Vec3 {
union {
T x;
T r;
};
union {
T y;
T g;
};
union {
T z;
T b;
};
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;
}
template<typename T>
struct Vec4 {
union {
T x;
T r;
};
union {
T y;
T g;
};
union {
T z;
T b;
};
union {
T w;
T a;
};
constexpr Vec4(Vec3<T> vec, T W = 1) : x(vec.x), y(vec.y), z(vec.z), w(W) {}
constexpr Vec4(T X = 0, T Y = 0, T Z = 0, T W = 0) : x(X), y(Y), z(Z), w(W) {}
};
template<typename T>
inline bool operator==(const Vec4<T>& vec4, const Vec4<T>& other) {
return vec4.x == other.x && vec4.y == other.y && vec4.z == other.z && vec4.w = other.w;
}
using Vec2i = Vec2<int>;
using Vec2u = Vec2<unsigned int>;
using Vec2f = Vec2<float>;
using Vec2d = Vec2<double>;
using Vec3i = Vec3<int>;
using Vec3u = Vec3<unsigned int>;
using Vec3f = Vec3<float>;
using Vec3d = Vec3<double>;
using Vec4i = Vec4<int>;
using Vec4u = Vec4<unsigned int>;
using Vec4f = Vec4<float>;
using Vec4d = Vec4<double>;
using Color = Vec3<unsigned char>;
template<typename T>
struct Mat4 {
static const std::size_t MATRIX_SIZE = 4;
T x0, x1, x2, x3;
T y0, y1, y2, y3;
T z0, z1, z2, z3;
T w0, w1, w2, w3;
T operator[] (std::size_t offset) const {
return reinterpret_cast<const T*>(this)[offset];
}
T& operator[] (std::size_t offset) {
return reinterpret_cast<T*>(this)[offset];
}
T* data() {
return reinterpret_cast<T*>(this);
}
const T* data() const{
return reinterpret_cast<const T*>(this);
}
T at(std::size_t row, std::size_t column) const {
return operator[](row * MATRIX_SIZE + column);
}
T& at(std::size_t row, std::size_t column) {
return operator[](row * MATRIX_SIZE + column);
}
};
typedef Mat4<float> Mat4f;
typedef Mat4<int> Mat4i;
typedef Mat4<double> Mat4d;
template<typename T>
inline bool operator==(const Mat4<T>& mat, const Mat4<T>& other) {
return mat.x0 == other.x0 && mat.y0 == other.y0 && mat.z0 == other.z0 && mat.w0 == other.w0 &&
mat.x1 == other.x1 && mat.y1 == other.y1 && mat.z1 == other.z1 && mat.w1 == other.w1 &&
mat.x2 == other.x2 && mat.y2 == other.y2 && mat.z2 == other.z2 && mat.w2 == other.w2 &&
mat.x3 == other.x3 && mat.y3 == other.y3 && mat.z3 == other.z3 && mat.w3 == other.w3;
}
} // namespace td

View File

@@ -0,0 +1,71 @@
#pragma once
#include "td/game/Team.h"
#include "td/game/World.h"
#include "td/game/Player.h"
namespace td {
namespace game {
enum class GameState : std::uint8_t {
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 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;
public:
Game(World* world);
virtual ~Game();
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& 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)]; }
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 PlayerList& GetPlayers() const { return m_Players; }
PlayerList& GetPlayers() { return m_Players; }
const Player* GetPlayerById(PlayerID id) const;
Player* GetPlayerById(PlayerID id);
const TeamList& GetTeams() const { return m_Teams; }
};
} // namespace game
} // namespace td

View File

@@ -0,0 +1,25 @@
/*
* GameManager.h
*
* Created on: 4 nov. 2020
* Author: simon
*/
#ifndef GAME_GAMEMANAGER_H_
#define GAME_GAMEMANAGER_H_
namespace GameManager {
void Render();
void Init();
void Destroy();
void Tick();
void StartServer();
}
#endif /* GAME_GAMEMANAGER_H_ */

262
include/td/game/Mobs.h Normal file
View File

@@ -0,0 +1,262 @@
#pragma once
#include "td/Defines.h"
#include "Towers.h"
#include "Types.h"
#include "Team.h"
#include "td/misc/ObjectNotifier.h"
#include <vector>
#include <memory>
namespace td {
namespace game {
struct WalkableTile;
enum class EffectType : std::uint8_t {
Slowness = 0,
Stun,
Fire,
Poison,
Heal,
};
enum class MobType : std::uint8_t {
Zombie = 0,
Spider,
Skeleton,
Pigman,
Creeper,
Silverfish,
Blaze,
Witch,
Slime,
Giant,
MOB_COUNT
};
typedef std::uint32_t MobID;
typedef std::uint8_t MobLevel;
typedef std::vector<TowerType> TowerImmunities;
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;
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) {
}
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
};
const MobStats* GetMobStats(MobType type, std::uint8_t level);
const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level);
const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level);
class Mob : public utils::shape::Rectangle {
protected:
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
float m_HitCooldown;
utils::Timer m_EffectFireTimer;
utils::Timer m_EffectPoisonTimer;
utils::Timer m_EffectHealTimer;
TeamCastle* m_CastleTarget;
utils::CooldownTimer m_AttackTimer;
public:
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level),
m_HitCooldown(0), m_EffectFireTimer(1000), m_EffectPoisonTimer(1000),
m_EffectHealTimer(1000), m_CastleTarget(nullptr), m_AttackTimer(1000) {
}
virtual MobType GetType() const = 0;
virtual void Tick(std::uint64_t delta, World* world);
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; }
void Damage(float dmg, const Tower* damager) {
m_Health = std::max(0.0f, m_Health - dmg);
m_LastDamage = damager;
m_HitCooldown = 0.1;
}
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(EffectType type);
void AddEffect(EffectType type, float durationSec, Tower* tower);
bool HasEffect(EffectType type);
bool HasTakenDamage() { return m_HitCooldown > 0; }
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; }
protected:
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);
};
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
virtual MobType GetType() const { return MobType::Giant; }
};
namespace MobFactory {
MobPtr CreateMob(MobID id, MobType type, std::uint8_t level, PlayerID sender);
std::string GetMobName(MobType type);
}
class MobListener {
public:
virtual void OnMobSpawn(Mob* mob) {}
virtual void OnMobDie(Mob* mob) {}
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) {}
};
typedef utils::ObjectNotifier<MobListener> MobNotifier;
} // namespace game
} // namespace td

51
include/td/game/Player.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <string>
#include "td/game/Team.h"
#include "td/game/PlayerUpgrades.h"
namespace td {
namespace game {
class Player {
private:
TeamColor m_TeamColor;
PlayerUpgrades m_Upgrades;
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) {}
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; }
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; }
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; }
PlayerID GetID() const { return m_ID; }
};
} // namespace game
} // namespace td

View File

@@ -0,0 +1,34 @@
#pragma once
#include "Mobs.h"
namespace td {
namespace game {
class PlayerUpgrades {
private:
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;
public:
static const int MAX_MOB_LEVEL = 5;
static const int MAX_CLICKER_LEVEL = 3;
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; }
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);
}
void UpgradeClicker() { m_ClickerLevel = std::min(m_ClickerLevel + 1, MAX_CLICKER_LEVEL); }
void SetGoldPerSecond(std::uint8_t goldPerSecond) { m_GoldPerSecond = goldPerSecond; }
};
} // namespace game
} // namespace td

92
include/td/game/Team.h Normal file
View File

@@ -0,0 +1,92 @@
#pragma once
#include "Types.h"
#include "td/misc/Shapes.h"
#include <vector>
#include <memory>
#include <cmath>
namespace td {
namespace game {
class Player;
enum class TeamColor : std::int8_t {
None = -1,
Red,
Blue
};
class Spawn : public utils::shape::Rectangle {
private:
Direction m_Direction;
public:
Spawn() {
SetWidth(5);
SetHeight(5);
}
Direction GetDirection() const { return m_Direction; }
void SetDirection(Direction direction) { m_Direction = direction; }
};
class Team;
class TeamCastle : public utils::shape::Rectangle {
private:
const Team* m_Team;
float m_Life;
public:
static constexpr int CastleMaxLife = 1000;
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
SetWidth(5);
SetHeight(5);
}
TeamCastle() : TeamCastle(nullptr) {}
float GetLife() const { return m_Life; }
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 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;
public:
Team(TeamColor color);
void AddPlayer(Player* newPlayer);
void RemovePlayer(const Player* player);
TeamColor GetColor() const;
const Spawn& GetSpawn() const { return m_Spawn; }
Spawn& GetSpawn() { return m_Spawn; }
const TeamCastle& GetCastle() const { return m_TeamCastle; }
TeamCastle& GetCastle() { return m_TeamCastle; }
std::uint8_t GetPlayerCount() const;
};
typedef std::array<Team, 2> TeamList;
} // namespace game
} // namespace td

266
include/td/game/Towers.h Normal file
View File

@@ -0,0 +1,266 @@
#pragma once
#include <string>
#include <memory>
#include "td/misc/Time.h"
#include "td/misc/Shapes.h"
#include "td/game/Types.h"
namespace td {
namespace game {
class World;
class Mob;
typedef std::shared_ptr<Mob> MobPtr;
enum class TowerType : std::uint8_t {
Archer = 0,
Ice,
Sorcerer,
Zeus,
Mage,
Artillery,
Quake,
Poison,
Leach,
Turret,
Necromancer,
TowerCount
};
enum class TowerSize : std::uint8_t {
Little = 3, // 3x3
Big = 5, // 5x5
};
enum class TowerPath : std::uint8_t {
Top = 0,
Base, // Base Path
Bottom
};
class TowerStats {
private:
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) {
}
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;
public:
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; }
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;
}
};
const TowerStats* GetTowerStats(TowerType type, TowerLevel level);
typedef std::uint16_t TowerID;
class Tower : public utils::shape::Circle {
private:
TowerID m_ID;
TowerType m_Type;
TowerLevel m_Level{};
PlayerID m_Builder;
protected:
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());
}
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());
}
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);
};
typedef std::shared_ptr<Tower> TowerPtr;
namespace TowerFactory {
TowerPtr CreateTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, PlayerID builder);
std::string GetTowerName(TowerType type);
} // namespace TowerFactory
class TowerInfo {
private:
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) {
}
const std::string& GetName() const { return m_Name; }
const std::string& GetDescription() const { return m_Description; }
bool IsBigTower() const { return m_IsBigTower; }
};
const TowerInfo& GetTowerInfo(TowerType type);
// ---------- Little Towers ----------
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) {}
virtual TowerSize GetSize() const { return TowerSize::Little; }
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) {}
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);
};
class IceTower : public LittleTower {
public:
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);
};
class MageTower : public LittleTower {
public:
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);
};
class PoisonTower : public LittleTower {
public:
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);
};
class QuakeTower : public LittleTower {
public:
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);
};
class ArtilleryTower : public LittleTower {
public:
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);
};
class SorcererTower : public LittleTower {
public:
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);
};
class ZeusTower : public LittleTower {
public:
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);
};
// ---------- 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) {}
virtual TowerSize GetSize() const { return TowerSize::Big; }
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) {}
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) {}
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) {}
virtual TowerType GetType() const { return TowerType::Leach; }
virtual void Tick(std::uint64_t delta, World* world);
};
} // namespace game
} // namespace td

21
include/td/game/Types.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include <cstdint>
// include Log for every files
#include "td/misc/Log.h"
namespace td {
namespace game {
enum class Direction : std::uint8_t {
PositiveX = 1 << 0,
NegativeX = 1 << 1,
PositiveY = 1 << 2,
NegativeY = 1 << 3,
};
typedef std::uint8_t PlayerID;
} // namespace game
} // namespace td

245
include/td/game/World.h Normal file
View File

@@ -0,0 +1,245 @@
#pragma once
#include <memory>
#include <vector>
#include <map>
#include <unordered_map>
#include <array>
#include "Mobs.h"
#include "Team.h"
namespace td {
namespace game {
struct ChunkCoord {
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;
}
};
}
}
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);
}
};
}
namespace td {
namespace protocol {
class WorldBeginDataPacket;
class WorldDataPacket;
}
namespace game {
class Game;
enum class TileType : std::uint8_t {
None = 0,
Tower,
Walk,
Decoration,
/*Heal,
Lava,
Bedrock,
Freeze,
Ice,*/
};
static constexpr Color BLACK{ 0, 0, 0 };
static constexpr Color WHITE{ 255, 255, 255 };
static constexpr Color RED{ 255, 0, 0 };
static constexpr Color GREEN{ 0, 255, 0 };
static constexpr Color BLUE{ 0, 0, 255 };
struct Tile {
virtual TileType GetType() const = 0;
};
struct TowerTile : Tile {
std::uint8_t color_palette_ref;
TeamColor team_owner;
virtual TileType GetType() const { return TileType::Tower; }
};
struct WalkableTile : Tile {
Direction direction;
virtual TileType GetType() const { return TileType::Walk; }
};
struct DecorationTile : Tile {
std::uint16_t color_palette_ref;
virtual TileType GetType() const { return TileType::Decoration; }
};
typedef std::shared_ptr<Tile> TilePtr;
typedef std::vector<std::uint16_t> ChunkPalette;
typedef std::shared_ptr<WalkableTile> WalkableTilePtr;
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;
// 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);
}
};
typedef std::shared_ptr<Chunk> ChunkPtr;
typedef std::array<Color, 2> TowerTileColorPalette;
typedef std::vector<TilePtr> TilePalette;
typedef std::vector<MobPtr> MobList;
typedef std::array<Color, 2> SpawnColorPalette;
typedef std::vector<TowerPtr> TowerList;
class WorldListener {
public:
WorldListener() {}
virtual void OnTowerAdd(TowerPtr tower) {}
virtual void OnTowerRemove(TowerPtr tower) {}
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) {}
};
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;
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
SpawnColorPalette m_SpawnColorPalette;
TilePalette m_TilePalette;
MobList m_Mobs;
TowerList m_Towers;
Game* m_Game;
WorldNotifier m_WorldNotifier;
MobNotifier m_MobNotifier;
public:
World(Game* game);
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;
void Tick(std::uint64_t delta);
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);
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 TilePalette& GetTilePalette() const { return m_TilePalette; }
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;
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 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 Color* GetTileColor(TilePtr tile) const;
Team& GetRedTeam();
const Team& GetRedTeam() const;
Team& GetBlueTeam();
const Team& GetBlueTeam() const;
Team& GetTeam(TeamColor team);
const Team& GetTeam(TeamColor team) const;
const TeamList& GetTeams() const;
const TowerList& GetTowers() const { return m_Towers; }
TowerPtr GetTowerById(TowerID tower);
const Player* GetPlayerById(PlayerID id) const;
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
// 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;
// MobListener
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();
};
} // namespace game
} // namespace td

4465
include/td/misc/Backward.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
#pragma once
#include <cstdint>
#include "DataBuffer.h"
namespace td {
namespace utils {
std::uint64_t Inflate(const std::string& source, std::string& dest);
std::uint64_t Deflate(const std::string& source, std::string& dest);
DataBuffer Compress(const DataBuffer& buffer);
DataBuffer Decompress(DataBuffer& buffer);
DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength);
} // namespace utils
} // namespace td

View File

@@ -0,0 +1,177 @@
#pragma once
#include <vector>
#include <algorithm>
#include <cstring>
#include <cassert>
#include <string>
namespace td {
class DataBuffer {
private:
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;
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);
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;
}
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<<(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;
}
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;
}
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 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(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 Resize(std::size_t size) {
m_Buffer.resize(size);
}
void Reserve(std::size_t amount) {
m_Buffer.reserve(amount);
}
void erase(iterator it) {
m_Buffer.erase(it);
}
void Clear() {
m_Buffer.clear();
m_ReadOffset = 0;
}
bool IsFinished() const {
return m_ReadOffset >= m_Buffer.size();
}
std::uint8_t* data() {
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::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;
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);
};
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
} // ns td

69
include/td/misc/Easing.h Normal file
View File

@@ -0,0 +1,69 @@
#pragma once
namespace td {
namespace utils {
constexpr float PI = 3.14159274101257324219;
/* Sine functions */
float EaseInSine(float x);
float EaseOutSine(float x);
float EaseInOutSine(float x);
/* Cubic functions */
float EaseInCubic(float x);
float EaseOutCubic(float x);
float EaseInOutCubic(float x);
/* Quint functions */
float EaseInQuint(float x);
float EaseOutQuint(float x);
float EaseInOutQuint(float x);
/* Circ functions */
float EaseInCirc(float x);
float EaseOutCirc(float x);
float EaseInOutCirc(float x);
/* Elastic functions */
float EaseInElastic(float x);
float EaseOutElastic(float x);
float EaseInOutElastic(float x);
/* Quad functions */
float EaseInQuad(float x);
float EaseOutQuad(float x);
float EaseInOutQuad(float x);
/* Quart functions */
float EaseInQuart(float x);
float EaseOutQuart(float x);
float EaseInOutQuart(float x);
/* Expo functions */
float EaseInExpo(float x);
float EaseOutExpo(float x);
float EaseInOutExpo(float x);
/* Back functions */
float EaseInBack(float x);
float EaseOutBack(float x);
float EaseInOutBack(float x);
/* Bounce functions */
float EaseInBounce(float x);
float EaseOutBounce(float x);
float EaseInOutBounce(float x);
} // namespace utils
} // namespace td

23
include/td/misc/Format.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <memory>
#include <stdexcept>
namespace td {
namespace utils {
template <typename... 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) {
throw std::runtime_error("Error during formatting.");
}
std::unique_ptr<char[]> buf(new char[size]);
snprintf(buf.get(), static_cast<std::size_t>(size), format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
} // namespace utils
} // namespace td

13
include/td/misc/Log.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <string>
namespace td {
namespace utils {
void LOG(const std::string& msg);
void LOGD(const std::string& msg);
void LOGE(const std::string& err);
} // namespace utils
} // namespace td

177
include/td/misc/Maths.h Normal file
View File

@@ -0,0 +1,177 @@
#pragma once
#include "td/Defines.h"
#include <cmath>
namespace td {
//////////////////////////////////////////////////////////////////
// Operators //
//////////////////////////////////////////////////////////////////
template<typename T>
Vec2<T> operator+(const Vec2<T>& vect, const Vec2<T>& other) {
return {vect.x + other.x, vect.y + other.y};
}
template<typename T>
Vec2<T> operator- (const Vec2<T>& vect) {
return { -vect.x, -vect.y };
}
template<typename T>
Vec2<T> operator- (const Vec2<T>& vect, const Vec2<T>& other) {
return vect + (-other);
}
template<typename T>
Vec3<T> operator- (const Vec3<T>& vect) {
return { -vect.x, -vect.y, -vect.z };
}
template<typename T>
Vec3<T> operator+ (const Vec3<T>& vect, const Vec3<T>& other) {
return { vect.x + other.x, vect.y + other.y, vect.z + other.y };
}
template<typename T>
Vec3<T> operator- (const Vec3<T>& vect, const Vec3<T>& other) {
return vect + (-other);
}
template<typename T>
Vec4<T> operator- (const Vec4<T>& vect) {
return { -vect.x, -vect.y, -vect.z, -vect.w };
}
template<typename T>
Vec4<T> operator+ (const Vec4<T>& vect, const Vec4<T>& other) {
return { vect.x + other.x, vect.y + other.y, vect.z + other.y, vect.w + other.w };
}
template<typename T>
Vec4<T> operator- (const Vec4<T>& vect, const Vec4<T>& other) {
return vect + (-other);
}
//////////////////////////////////////////////////////////////////
// Vectors //
//////////////////////////////////////////////////////////////////
namespace maths {
template<typename T>
T Length(const Vec3<T>& vect) {
return std::sqrt(vect.x * vect.x + vect.y * vect.y + vect.z * vect.z);
}
template<typename T>
Vec3<T> Normalize(const Vec3<T>& vect) {
T length = Length(vect);
return { vect.x / length, vect.y / length, vect.z / length };
}
template<typename T>
Vec4<T> Normalize(const Vec4<T>& vect) {
T length = std::sqrt(vect.x * vect.x + vect.y * vect.y + vect.z * vect.z + vect.w * vect.w);
return { vect.x / length, vect.y / length, vect.z / length, vect.w / length };
}
template<typename T>
T Dot(const Vec3<T>& vect, const Vec3<T>& other) {
return vect.x * other.x + vect.y * other.y + vect.z * other.z;
}
template<typename T>
Vec3<T> Cross(const Vec3<T>& vect, const Vec3<T>& other) {
return {
vect.y * other.z - vect.z * other.y,
vect.z * other.x - vect.x * other.z,
vect.x * other.y - vect.y * other.x,
};
}
template<typename T>
T Dot(const Vec4<T>& vect, const Vec4<T>& other) {
return vect.x * other.x + vect.y * other.y + vect.z * other.z + vect.w * other.w;
}
template<typename T>
T Distance(const Vec3<T>& vect, const Vec3<T>& other) {
return Length(vect - other);
}
//////////////////////////////////////////////////////////////////
// Matricies //
//////////////////////////////////////////////////////////////////
template<typename T>
Vec4<T> Dot(const Mat4<T>& mat, const Vec4<T>& vect) {
return {
mat.x0 * vect.x + mat.x1 * vect.y + mat.x2 * vect.z + mat.x3 * vect.w,
mat.y0 * vect.x + mat.y1 * vect.y + mat.y2 * vect.z + mat.y3 * vect.w,
mat.z0 * vect.x + mat.z1 * vect.y + mat.z2 * vect.z + mat.z3 * vect.w,
mat.w0 * vect.x + mat.w1 * vect.y + mat.w2 * vect.z + mat.w3 * vect.w
};
}
template<typename T>
Mat4<T> Dot(const Mat4<T>& mat, const Mat4<T>& other) {
Mat4<T> result {};
for (std::size_t i = 0; i < Mat4<T>::MATRIX_SIZE; i++) {
for (std::size_t j = 0; j < Mat4<T>::MATRIX_SIZE; j++) {
for (std::size_t k = 0; k < Mat4<T>::MATRIX_SIZE; k++) {
result.at(i, j) += mat.at(i, k) * other.at(k, j);
}
}
}
return result;
}
template<typename T>
Mat4<T> Identity() {
Mat4<T> result{};
result.x0 = static_cast<T>(1);
result.y1 = static_cast<T>(1);
result.z2 = static_cast<T>(1);
result.w3 = static_cast<T>(1);
return result;
}
template<typename T>
Mat4<T> Transpose(const Mat4<T>& mat) {
Mat4<T> result;
result.x1 = mat.y0;
result.x2 = mat.z0;
result.x3 = mat.w0;
result.y0 = mat.x1;
result.y2 = mat.z1;
result.y3 = mat.w1;
result.z0 = mat.x2;
result.z1 = mat.y2;
result.z3 = mat.w2;
result.w0 = mat.x3;
result.w1 = mat.y3;
result.w2 = mat.z3;
result.x0 = mat.x0;
result.y1 = mat.y1;
result.z2 = mat.z2;
result.w3 = mat.w3;
return result;
}
Mat4f Perspective(float fovY, float aspectRatio, float zNear, float zFar);
Mat4f Look(const Vec3f& eye, const Vec3f& center, const Vec3f& up);
Mat4f Inverse(const Mat4f& mat);
} // namespace maths
} // namespace td

View File

@@ -0,0 +1,36 @@
#pragma once
#include <algorithm>
#include <functional>
#include <vector>
namespace td {
namespace utils {
template <typename Listener>
class ObjectNotifier {
protected:
std::vector<Listener*> m_Listeners;
public:
void BindListener(Listener* listener) {
m_Listeners.push_back(listener);
}
void UnbindListener(Listener* listener) {
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
if (iter == m_Listeners.end()) return;
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...)();
}
};
} // namespace utils
} // namespace td

View File

@@ -0,0 +1,54 @@
#pragma once
namespace td {
namespace utils {
enum class Os {
Windows = 0,
Linux,
Android,
Unknown,
};
enum class Architecture {
x86_64 = 0,
x86,
Arm64,
Armhf,
Unknown,
};
inline Os GetSystemOs() {
#if defined(_WIN32) || defined(_WIN64)
return Os::Windows;
#elif defined(__ANDROID__)
return Os::Android;
#elif defined(__unix__)
return Os::Linux;
#else
#pragma message ("Target OS unknown or unsupported !")
return Os::Unknown;
#endif
}
inline Architecture GetSystemArchitecture() {
#if defined(_WIN64)
return Architecture::x86_64;
#elif defined(_WIN32)
return Architecture::x86;
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__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;
#elif defined(__aarch64__)
return Architecture::Arm64;
#elif defined(__arm__) || defined(_M_ARM)
return Architecture::Armhf;
#else
#pragma message ("Target CPU architecture unknown or unsupported !")
return Architecture::Unknown;
#endif
}
} // namespace utils
} // namespace td

25
include/td/misc/Random.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <random>
namespace td {
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);
}
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);
}
} // namespace utils
} // namespace td

96
include/td/misc/Shapes.h Normal file
View File

@@ -0,0 +1,96 @@
#pragma once
#include <cstdint>
namespace td {
namespace utils {
namespace shape {
class Point {
private:
float m_X, m_Y;
public:
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; }
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;
};
class Circle;
class Rectangle {
private:
Point m_Center;
float m_Width, m_Height;
public:
Rectangle() {}
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; }
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 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; }
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;
};
class Circle {
private:
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) {}
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; }
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; }
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;
};
} // namespace shape
} // namespace utils
} // namespace td

76
include/td/misc/Time.h Normal file
View File

@@ -0,0 +1,76 @@
#pragma once
#include <cstdint>
#include <functional>
namespace td {
namespace utils {
std::uint64_t GetTime();
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_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) {}
void Update();
void Update(std::uint64_t delta);
void Reset();
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; }
};
// 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;
public:
Timer() : m_Interval(0) {}
Timer(std::uint64_t interval) : m_Interval(interval) {}
bool Update(std::uint64_t delta);
void Reset();
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;
public:
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
bool Update(std::uint64_t delta);
void ApplyCooldown();
void Reset();
void SetCooldown(std::uint64_t newCooldown) { m_CooldownTime = newCooldown; }
std::uint64_t GetCooldown() const { return m_CooldownTime; }
};
} // namespace utils
} // namespace td

View File

@@ -0,0 +1,36 @@
#pragma once
#include "td/network/TCPSocket.h"
#include "td/protocol/PacketHandler.h"
#include "td/protocol/PacketDispatcher.h"
#include "td/game/Player.h"
namespace td {
namespace protocol {
class Connexion : public protocol::PacketHandler {
protected:
protocol::PacketDispatcher m_Dispatcher;
private:
network::TCPSocket m_Socket;
public:
Connexion();
Connexion(Connexion&& move);
Connexion(protocol::PacketDispatcher* dispatcher);
Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket);
virtual ~Connexion();
virtual bool UpdateSocket();
void CloseConnection();
bool Connect(const std::string& address, std::uint16_t port);
network::Socket::Status GetSocketStatus() const { return m_Socket.GetStatus(); }
void SendPacket(const protocol::Packet* packet);
REMOVE_COPY(Connexion);
};
} // namespace server
} // namespace td

7968
include/td/network/HttpLib.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
#ifndef NETWORK_IPADDRESS_H_
#define NETWORK_IPADDRESS_H_
#include <string>
#include <iosfwd>
#include <vector>
namespace td {
namespace network {
/* IPv4 address */
class IPAddress {
private:
std::uint32_t m_Address;
bool m_Valid;
public:
/* Create an invalid address */
IPAddress() noexcept;
/* Initialize by string IP */
IPAddress(const std::string& 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;
/* 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);
/* 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;
static IPAddress LocalAddress();
bool operator==(const IPAddress& right);
bool operator!=(const IPAddress& right);
bool operator==(bool b);
};
typedef std::vector<IPAddress> IPAddresses;
std::ostream& operator<<(std::ostream& os, const IPAddress& addr);
std::wostream& operator<<(std::wostream& os, const IPAddress& addr);
} // ns network
} // ns td
#endif

View File

@@ -0,0 +1,31 @@
#ifndef NETWORK_NETWORK_H_
#define NETWORK_NETWORK_H_
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include "td/network/Socket.h"
#include "td/network/IPAddress.h"
#include "td/network/UDPSocket.h"
#include "td/network/TCPSocket.h"
namespace td {
namespace network {
class Dns {
public:
static IPAddresses Resolve(const std::string& host);
};
} // ns network
} // ns td
#endif

View File

@@ -0,0 +1,90 @@
#ifndef NETWORK_SOCKET_H_
#define NETWORK_SOCKET_H_
#include <string>
#include <vector>
#include <memory>
#include "td/misc/DataBuffer.h"
#ifdef _WIN32
#include <ws2tcpip.h>
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/ioctl.h>
#define closesocket close
#endif
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define REMOVE_COPY(className) \
className(const className &) = delete;\
className& operator=(const className &) = delete
namespace td {
namespace network {
class IPAddress;
typedef int SocketHandle;
class Socket {
public:
enum Status { Connected, Disconnected, Error };
enum Type { TCP, UDP };
private:
bool m_Blocking;
Type m_Type;
Status m_Status;
protected:
SocketHandle m_Handle;
Socket(Type type);
void SetStatus(Status status);
public:
virtual ~Socket();
Socket(Socket&& rhs) = default;
Socket& operator=(Socket&& rhs) = default;
bool SetBlocking(bool block);
bool IsBlocking() 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;
void Disconnect();
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 Receive(DataBuffer& buffer, std::size_t amount) = 0;
};
typedef std::shared_ptr<Socket> SocketPtr;
} // ns network
} // ns td
#endif

View File

@@ -0,0 +1,35 @@
#pragma once
#include "TCPSocket.h"
namespace td {
namespace network {
class TCPListener {
int m_Handle;
std::uint16_t m_Port;
int m_MaxConnections;
public:
TCPListener();
~TCPListener();
bool Listen(std::uint16_t port, int maxConnections);
bool Accept(TCPSocket& newSocket);
void Destroy();
bool Close();
bool SetBlocking(bool blocking);
std::uint16_t GetListeningPort() const {
return m_Port;
}
int GetMaximumConnections() const {
return m_MaxConnections;
}
REMOVE_COPY(TCPListener);
};
} // namespace network
} // namespace td

View File

@@ -0,0 +1,39 @@
#ifndef NETWORK_TCP_SOCKET_H_
#define NETWORK_TCP_SOCKET_H_
#include "td/network/IPAddress.h"
#include "td/network/Socket.h"
#include <cstdint>
namespace td {
namespace network {
class TCPListener;
class TCPSocket : public Socket {
private:
IPAddress m_RemoteIP;
uint16_t m_Port;
sockaddr m_RemoteAddr;
public:
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);
REMOVE_COPY(TCPSocket);
friend class TCPListener;
};
void SendPacket(const DataBuffer& data, network::TCPSocket& socket);
} // ns network
} // ns td
#endif

View File

@@ -0,0 +1,31 @@
#ifndef NETWORK_UDP_SOCKET_H_
#define NETWORK_UDP_SOCKET_H_
#include "td/network/IPAddress.h"
#include "td/network/Socket.h"
#include <cstdint>
namespace td {
namespace network {
class UDPSocket : public Socket {
private:
IPAddress m_RemoteIP;
uint16_t m_Port;
sockaddr_in m_RemoteAddr;
public:
UDPSocket();
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);
};
} // ns network
} // ns td
#endif

View File

@@ -0,0 +1,33 @@
#pragma once
#include "td/protocol/Protocol.h"
#include <map>
#include <vector>
namespace td {
namespace protocol {
class PacketHandler;
class PacketDispatcher {
private:
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
public:
PacketDispatcher() = default;
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 RegisterHandler(PacketType type, PacketHandler* handler);
void UnregisterHandler(PacketType type, PacketHandler* handler);
void UnregisterHandler(PacketHandler* handler);
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,13 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
namespace PacketFactory {
PacketPtr CreatePacket(PacketType type, DataBuffer& buffer);
}
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,49 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/protocol/PacketsForward.h"
namespace td {
namespace protocol {
class PacketDispatcher;
class PacketHandler {
private:
PacketDispatcher* m_Dispatcher;
public:
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
virtual ~PacketHandler() {}
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) {}
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,27 @@
#include "packets/ConnectionInfoPacket.h"
#include "packets/DisconnectPacket.h"
#include "packets/KeepAlivePacket.h"
#include "packets/PlaceTowerPacket.h"
#include "packets/PlayerBuyItemPacket.h"
#include "packets/PlayerBuyMobUpgradePacket.h"
#include "packets/PlayerJoinPacket.h"
#include "packets/PlayerLeavePacket.h"
#include "packets/PlayerListPacket.h"
#include "packets/PlayerLoginPacket.h"
#include "packets/RemoveTowerPacket.h"
#include "packets/SelectTeamPacket.h"
#include "packets/SendMobsPacket.h"
#include "packets/ServerTpsPacket.h"
#include "packets/SpawnMobPacket.h"
#include "packets/UpdateCastleLifePacket.h"
#include "packets/UpdateExpPacket.h"
#include "packets/UpdateGameStatePacket.h"
#include "packets/UpdateLobbyTimePacket.h"
#include "packets/UpdateMobStatesPacket.h"
#include "packets/UpdateMoneyPacket.h"
#include "packets/UpdatePlayerTeamPacket.h"
#include "packets/UpgradeTowerPacket.h"
#include "packets/WorldAddTowerPacket.h"
#include "packets/WorldAddTowerPacket.h"
#include "packets/WorldBeginDataPacket.h"
#include "packets/WorldDataPacket.h"

View File

@@ -0,0 +1,34 @@
#pragma once
namespace td {
namespace protocol {
class PlayerLoginPacket;
class WorldBeginDataPacket;
class WorldDataPacket;
class KeepAlivePacket;
class UpdateExpPacket;
class UpdateMoneyPacket;
class UpdateLobbyTimePacket;
class UpdateGameStatePacket;
class PlayerListPacket;
class PlayerJoinPacket;
class PlayerLeavePacket;
class ConnexionInfoPacket;
class SelectTeamPacket;
class UpdatePlayerTeamPacket;
class DisconnectPacket;
class ServerTpsPacket;
class SpawnMobPacket;
class PlaceTowerPacket;
class WorldAddTowerPacket;
class RemoveTowerPacket;
class SendMobsPacket;
class UpgradeTowerPacket;
class UpdateCastleLifePacket;
class UpdateMobStatesPacket;
class PlayerBuyItemPacket;
class PlayerBuyMobUpgradePacket;
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,66 @@
#pragma once
#include "td/misc/DataBuffer.h"
#include <memory>
namespace td {
namespace protocol {
class PacketHandler;
enum class PacketType : std::uint8_t {
// 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
KeepAlive,
Disconnect,
UpgradeTower,
RemoveTower,
PlayerBuyItem,
PlayerBuyMobUpgrade,
PACKET_COUNT
};
class Packet {
public:
Packet() {}
virtual ~Packet() {}
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;
virtual PacketType GetType() const = 0;
std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
};
typedef std::unique_ptr<Packet> PacketPtr;
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class ConnexionInfoPacket : public Packet {
private:
std::uint8_t m_ConnectionID;
public:
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;
std::uint8_t GetConnectionID() const { return m_ConnectionID; }
virtual PacketType GetType() const { return PacketType::ConnectionInfo; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class DisconnectPacket : public Packet {
private:
std::string m_Reason; // only when sent from server
public:
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;
const std::string& GetReason() const { return m_Reason; }
virtual PacketType GetType() const { return PacketType::Disconnect; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class KeepAlivePacket : public Packet {
private:
std::uint64_t m_AliveID;
public:
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;
std::uint64_t GetAliveID() const { return m_AliveID; }
virtual PacketType GetType() const { return PacketType::KeepAlive; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,32 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class PlaceTowerPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::PlaceTower; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,38 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
enum class ItemType : std::uint8_t {
// Upgrades
ClickerUpgrade,
GoldPerSecUpgrade,
// Items
};
/** Packet used by the client to buy items or upgrades
Packet used by the server to confirm transaction */
class PlayerBuyItemPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::PlayerBuyItem; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,31 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
/** Packet used by the client to buy mob upgrades
Packet used by the server to confirm transaction */
class PlayerBuyMobUpgradePacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::PlayerBuyMobUpgrade; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,28 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class PlayerJoinPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::PlayerJoin; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class PlayerLeavePacket : public Packet {
private:
std::uint8_t m_PlayerID;
public:
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;
std::uint8_t GetPlayerID() const { return m_PlayerID; }
virtual PacketType GetType() const { return PacketType::PlayerLeave; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,32 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
struct PlayerInfo {
std::string name;
game::TeamColor team;
};
class PlayerListPacket : public Packet {
private:
std::map<std::uint8_t, PlayerInfo> m_Players;
public:
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;
const std::map<std::uint8_t, PlayerInfo>& GetPlayers() const { return m_Players; }
virtual PacketType GetType() const { return PacketType::PlayerList; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class PlayerLoginPacket : public Packet {
private:
std::string m_PlayerName;
public:
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 PacketType GetType() const { return PacketType::PlayerLogin; }
const std::string& GetPlayerName() const { return m_PlayerName; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,27 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class RemoveTowerPacket : public Packet {
private:
game::TowerID m_TowerID;
public:
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;
game::TowerID GetTowerID() const { return m_TowerID; }
virtual PacketType GetType() const { return PacketType::RemoveTower; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,27 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class SelectTeamPacket : public Packet {
private:
game::TeamColor m_SelectedTeam;
public:
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;
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
virtual PacketType GetType() const { return PacketType::SelectTeam; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,33 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
struct MobSend { // represents a mob send
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;
public:
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;
const std::vector<MobSend>& GetMobSends() const { return m_MobSends; }
virtual PacketType GetType() const { return PacketType::SendMobs; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,30 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class ServerTpsPacket : public Packet {
private:
float m_TPS;
float m_MSPT;
std::uint64_t m_PacketSendTime; // used to calculate ping
public:
ServerTpsPacket() {}
ServerTpsPacket(float tps, float mspt, std::uint64_t sendTime) : m_TPS(tps), m_MSPT(mspt), m_PacketSendTime(sendTime) {}
virtual ~ServerTpsPacket() {}
virtual DataBuffer Serialize(bool packetID = true) const;
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
float GetTPS() const { return m_TPS; }
float GetMSPT() const { return m_MSPT; }
std::uint64_t GetPacketSendTime() const { return m_PacketSendTime; }
virtual PacketType GetType() const { return PacketType::ServerTps; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,41 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
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;
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() {}
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; }
virtual PacketType GetType() const { return PacketType::SpawnMob; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,29 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class UpdateCastleLifePacket : public Packet {
private:
std::uint16_t m_CastleLife;
game::TeamColor m_Team;
public:
UpdateCastleLifePacket() {}
UpdateCastleLifePacket(std::uint16_t life, game::TeamColor team) : m_CastleLife(life), m_Team(team) {}
virtual ~UpdateCastleLifePacket() {}
virtual DataBuffer Serialize(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; }
virtual PacketType GetType() const { return PacketType::UpdateCastleLife; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class UpdateExpPacket : public Packet {
private:
std::uint32_t m_NewAmount;
public:
UpdateExpPacket() {}
UpdateExpPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
virtual ~UpdateExpPacket() {}
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 PacketType GetType() const { return PacketType::UpdateEXP; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,27 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class UpdateGameStatePacket : public Packet {
private:
game::GameState m_GameState;
public:
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;
game::GameState GetGameState() const { return m_GameState; }
virtual PacketType GetType() const { return PacketType::UpdateGameState; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class UpdateLobbyTimePacket : public Packet {
private:
std::uint32_t m_RemainingTime;
public:
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;
std::uint32_t GetRemainingTime() const { return m_RemainingTime; }
virtual PacketType GetType() const { return PacketType::UpdateLobbyTime; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,47 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class MobState {
using Point = utils::shape::Point;
private:
game::MobID m_MobID;
Point m_MobPosition;
float m_MobLife;
game::Direction m_MobDirection;
public:
MobState() {}
MobState(game::MobID id, 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; }
};
class UpdateMobStatesPacket : public Packet {
private:
std::vector<MobState> m_MobStates;
public:
UpdateMobStatesPacket() {}
virtual ~UpdateMobStatesPacket() {}
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); }
const std::vector<MobState>& GetMobStates() const { return m_MobStates; }
virtual PacketType GetType() const { return PacketType::UpdateMobStates; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,26 @@
#pragma once
#include "td/protocol/Protocol.h"
namespace td {
namespace protocol {
class UpdateMoneyPacket : public Packet {
private:
std::uint32_t m_NewAmount;
public:
UpdateMoneyPacket() {}
UpdateMoneyPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
virtual ~UpdateMoneyPacket() {}
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 PacketType GetType() const { return PacketType::UpdateMoney; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,29 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class UpdatePlayerTeamPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::UpdatePlayerTeam; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,29 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class UpgradeTowerPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::UpgradeTower; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,36 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
class WorldAddTowerPacket : public Packet {
private:
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() {}
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; }
virtual PacketType GetType() const { return PacketType::WorldAddTower; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,60 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
struct WorldHeader {
game::TowerTileColorPalette m_TowerPlacePalette;
Color m_WalkablePalette;
std::vector<Color> m_DecorationPalette;
Color m_Background;
game::SpawnColorPalette m_SpawnColorPalette;
game::TilePalette m_TilePalette;
game::Spawn m_RedSpawn, m_BlueSpawn;
game::TeamCastle m_RedCastle, m_BlueCastle;
const game::World* m_World;
};
class WorldBeginDataPacket : public Packet {
private:
WorldHeader m_Header;
public:
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 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::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::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; }
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
};
} // namespace protocol
} // namespace td

View File

@@ -0,0 +1,36 @@
#pragma once
#include "td/protocol/Protocol.h"
#include "td/game/BaseGame.h"
namespace td {
namespace protocol {
struct WorldData {
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
};
class WorldDataPacket : public Packet {
private:
WorldData m_WorldData;
const game::World* m_World;
public:
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 PacketType GetType() const { return PacketType::WorldData; }
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; }
};
} // namespace protocol
} // namespace td