1er commit

This commit is contained in:
2021-08-21 10:14:47 +02:00
commit a99ecf7c2d
99 changed files with 66605 additions and 0 deletions

51
include/game/BaseGame.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include "game/Team.h"
#include "game/World.h"
#include "game/Player.h"
namespace td {
namespace game {
enum class GameState : std::uint8_t{
Lobby,
Game,
EndGame
};
typedef std::map<std::uint8_t, Player> PlayerList;
class Game{
protected:
World* m_World;
std::array<Team, 2> 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[(std::uint8_t)TeamColor::Red]; }
const Team& getRedTeam() const{ return m_Teams[(std::uint8_t)TeamColor::Red]; }
Team& getBlueTeam(){ return m_Teams[(std::uint8_t)TeamColor::Blue]; }
const Team& getBlueTeam() const{ return m_Teams[(std::uint8_t)TeamColor::Blue]; }
Team& getTeam(TeamColor team){ return m_Teams[(std::uint8_t)team]; }
const Team& getTeam(TeamColor team) const{ return m_Teams[(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; }
};
} // namespace game
} // namespace td

36
include/game/Connexion.h Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#include "network/TCPSocket.h"
#include "protocol/PacketHandler.h"
#include "protocol/PacketDispatcher.h"
#include "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(protocol::Packet* packet);
REMOVE_COPY(Connexion);
};
} // namespace server
} // 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_ */

139
include/game/Mobs.h Normal file
View File

@@ -0,0 +1,139 @@
#pragma once
#include "Towers.h"
#include <cstdint>
#include <vector>
#include <memory>
namespace td {
namespace game {
enum class Direction : std::uint8_t{
PositiveX = 1 << 0,
NegativeX = 1 << 1,
PositiveY = 1 << 2,
NegativeY = 1 << 3,
};
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
};
typedef std::uint8_t PlayerID;
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;
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, std::uint16_t moneyCost,
std::uint16_t expCost, std::uint16_t maxLife,
std::uint16_t expReward): m_Damage(damage), m_Speed(speed),
m_MoneyCost(moneyCost), m_ExpCost(expCost), m_MaxLife(maxLife),
m_ExpReward(expReward){
}
float getDamage() const{ return m_Damage; }
float getMovementSpeed() const{ return m_Speed; }
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; }
};
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{
protected:
float m_Health;
private:
MobID m_ID;
PlayerID m_Sender;
MobLevel m_Level;
Direction m_Direction;
float m_X = 0, m_Y = 0;
public:
Mob(MobID id, MobLevel level, PlayerID sender): m_Sender(sender), m_Level(level){
}
virtual MobType getType() const = 0;
virtual void tick(std::uint64_t delta){}
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); }
float getHealth() const{ return m_Health; }
bool isAlive() const{ return m_Health > 0; }
void damage(float dmg){ m_Health -= dmg; }
void heal(float heal){ m_Health = std::min((float)getStats()->getMaxLife(), m_Health + heal); }
float getX() const{ return m_X; }
float setX(float x){ m_X = x; }
float getY() const{ return m_Y; }
float setY(float y){ m_Y = y; }
Direction getDirection() const{ return m_Direction; }
void setDirection(Direction dir){ m_Direction = dir; }
protected:
void initHealth(){m_Health = (float)getStats()->getMaxLife();}
};
typedef std::shared_ptr<Mob> MobPtr;
class Zombie : public Mob{
public:
Zombie(MobID id, std::uint8_t level, PlayerID sender): Mob(id, level, sender){initHealth();}
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){initHealth();}
virtual MobType getType() const{ return MobType::Spider; }
};
namespace MobFactory{
MobPtr createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender);
}
} // namespace game
} // namespace td

40
include/game/Player.h Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#include <cstdint>
#include <string>
#include "game/Team.h"
namespace td{
namespace game{
class Player{
private:
game::TeamColor m_TeamColor = game::TeamColor::None;
std::uint32_t m_Gold = 0;
std::int32_t m_EXP;
std::string m_Name;
std::uint8_t m_ID;
std::uint8_t m_GoldPerSecond = 5;
public:
Player(std::uint8_t id = 0) : m_ID(id){}
const std::string& getName() const{return m_Name;}
void setName(const std::string& name){m_Name = name;}
game::TeamColor getTeamColor() const{return m_TeamColor;}
void setTeamColor(game::TeamColor teamColor){m_TeamColor = teamColor;}
std::uint8_t getGoldPerSecond() const{ return m_GoldPerSecond;}
void setGoldPerSecond(std::uint8_t goldPerSecond){m_GoldPerSecond = goldPerSecond;}
std::uint32_t getGold() const{ return m_Gold;}
void setGold(std::uint32_t gold){m_Gold = gold;}
std::uint8_t getID() const{return m_ID;}
};
} // namespace game
} // namespace td

34
include/game/Team.h Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <vector>
#include <memory>
#include <algorithm>
namespace td {
namespace game {
class Player;
enum class TeamColor : std::int8_t{
None = -1,
Red,
Blue
};
class Team{
private:
std::vector<Player*> m_Players;
TeamColor m_Color;
public:
Team(TeamColor color);
void addPlayer(Player* newPlayer);
void removePlayer(const Player* player);
TeamColor getColor() const;
std::uint8_t getPlayerCount() const;
};
} // namespace game
} // namespace td

212
include/game/Towers.h Normal file
View File

@@ -0,0 +1,212 @@
#pragma once
#include <cstdint>
#include "misc/Time.h"
namespace td {
namespace game {
enum class TowerType : std::uint8_t{
Archer = 0,
Ice,
Sorcerer,
Zeus,
Mage,
Artillery,
Quake,
Poison,
Leach,
Turret,
Necromancer
};
enum class TowerSize : bool{
Little = 0, // 3x3
Big, // 5x5
};
enum class TowerPath : std::uint8_t{
Top = 1, // 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 : 1;
public:
TowerLevel(): m_Level(1), m_Path(TowerPath::Top){}
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() * (std::uint8_t)level.getPath() <
other.getLevel() * (std::uint8_t)other.getPath();
}
};
const TowerStats* getTowerStats(TowerType type, TowerLevel level);
class Tower{
private:
std::uint16_t m_X, m_Y;
TowerLevel m_Level{};
protected:
utils::Timer m_Timer;
public: // converting seconds to millis
Tower(std::uint16_t x, std::uint16_t y): m_X(x), m_Y(y), m_Timer(getStats()->getDamageRate() * 1000){}
virtual TowerType getType() const = 0;
virtual TowerSize getSize() const = 0;
virtual void tick(std::uint64_t delta) = 0;
void upgrade(std::uint8_t level, TowerPath path){
m_Level.setLevel(level);
m_Level.setPath(path);
}
std::uint16_t getX() const{ return m_X; }
std::uint16_t getY() const{ return m_Y; }
const TowerLevel& getLevel() const{ return m_Level; }
const TowerStats* getStats() const{ return getTowerStats(getType(), m_Level); }
};
// ---------- Little Towers ----------
class LittleTower : public Tower{
public:
LittleTower(std::uint16_t x, std::uint16_t y): Tower(x, y){}
virtual TowerSize getSize() const{ return TowerSize::Little; }
virtual TowerType getType() const = 0;
virtual void tick(std::uint64_t delta) = 0;
};
class ArcherTower : public LittleTower{
public:
ArcherTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Archer; }
virtual void tick(std::uint64_t delta);
};
class IceTower : public LittleTower{
public:
IceTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Ice; }
virtual void tick(std::uint64_t delta);
};
class MageTower : public LittleTower{
public:
MageTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Mage; }
virtual void tick(std::uint64_t delta);
};
class PoisonTower : public LittleTower{
public:
PoisonTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Poison; }
virtual void tick(std::uint64_t delta);
};
class QuakeTower : public LittleTower{
public:
QuakeTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Quake; }
virtual void tick(std::uint64_t delta);
};
class ArtilleryTower : public LittleTower{
public:
ArtilleryTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Artillery; }
virtual void tick(std::uint64_t delta);
};
class SorcererTower : public LittleTower{
public:
SorcererTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Sorcerer; }
virtual void tick(std::uint64_t delta);
};
class ZeusTower : public LittleTower{
public:
ZeusTower(std::uint16_t x, std::uint16_t y): LittleTower(x, y){}
virtual TowerType getType() const{ return TowerType::Zeus; }
virtual void tick(std::uint64_t delta);
};
// ---------- Big Towers ----------
class BigTower : public Tower{
public:
BigTower(std::uint16_t x, std::uint16_t y): Tower(x, y){}
virtual TowerSize getSize() const{ return TowerSize::Big; }
virtual TowerType getType() const = 0;
virtual void tick(std::uint64_t delta) = 0;
};
class TurretTower : public BigTower{
public:
TurretTower(std::uint16_t x, std::uint16_t y): BigTower(x, y){}
virtual TowerType getType() const{ return TowerType::Turret; }
virtual void tick(std::uint64_t delta);
};
class NecromancerTower : public BigTower{
public:
NecromancerTower(std::uint16_t x, std::uint16_t y): BigTower(x, y){}
virtual TowerType getType() const{ return TowerType::Necromancer; }
virtual void tick(std::uint64_t delta);
};
class LeachTower : public BigTower{
public:
LeachTower(std::uint16_t x, std::uint16_t y): BigTower(x, y){}
virtual TowerType getType() const{ return TowerType::Leach; }
virtual void tick(std::uint64_t delta);
};
} // namespace game
} // namespace td

190
include/game/World.h Normal file
View File

@@ -0,0 +1,190 @@
#pragma once
#include <memory>
#include <vector>
#include <map>
#include <unordered_map>
#include "Mobs.h"
#include "Team.h"
namespace td{
namespace game{
typedef std::pair<std::int16_t, std::int16_t> ChunkCoord;
}
}
namespace std{
template <>
struct hash<td::game::ChunkCoord>{
std::size_t operator()(const td::game::ChunkCoord& key) const{
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((std::hash<std::int16_t>()(key.first) ^ (std::hash<std::int16_t>()(key.second) << 1)) >> 1);
}
};
}
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,*/
};
struct Color{
std::uint8_t r, g, b;
};
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; }
};
struct Spawn{
Direction direction;
std::int32_t x, y;
};
struct TeamCastle{
std::int32_t x, y;
std::uint16_t life = 1000;
};
typedef std::shared_ptr<Tile> TilePtr;
typedef std::vector<std::uint16_t> ChunkPalette;
typedef std::shared_ptr<WalkableTile> WalkableTilePtr;
typedef std::array<std::uint16_t, 32 * 32> ChunkData;
typedef std::uint32_t TileIndex;
//32 x 32 area
struct Chunk{
enum{ ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
// 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;
class World{
protected:
TowerTileColorPalette m_TowerPlacePalette;
Color m_WalkablePalette;
std::vector<Color> m_DecorationPalette;
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
SpawnColorPalette m_SpawnColorPalette;
Spawn m_Spawns[2];
TeamCastle m_Castles[2];
TilePalette m_TilePalette;
MobList m_Mobs;
Game* m_Game;
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);
TilePtr getTile(std::int32_t x, std::int32_t y);
const TowerTileColorPalette& getTowerTileColorPalette() const{ return m_TowerPlacePalette; }
const Color& getWalkableTileColor() const{ return m_WalkablePalette; }
const std::vector<Color>& getDecorationPalette() const{ return m_DecorationPalette; }
const TilePalette& getTilePalette() const{ return m_TilePalette; }
TilePtr getTilePtr(TileIndex index) const{
if(index == 0)
return nullptr;
return m_TilePalette.at(index - 1);
}
const std::unordered_map<ChunkCoord, ChunkPtr>& getChunks() const{ return m_Chunks; }
const Spawn& getRedSpawn() const{ return m_Spawns[(std::size_t) TeamColor::Red]; }
const Spawn& getBlueSpawn() const{ return m_Spawns[(std::size_t) TeamColor::Blue]; }
const Spawn& getSpawn(TeamColor color) const{ return m_Spawns[(std::size_t) color]; }
const Color& getSpawnColor(TeamColor color) const{ return m_SpawnColorPalette[(std::size_t) color]; }
const SpawnColorPalette& getSpawnColors() const{ return m_SpawnColorPalette; }
const TeamCastle& getRedCastle() const{ return m_Castles[(std::size_t) TeamColor::Red]; }
const TeamCastle& getBlueCastle() const{ return m_Castles[(std::size_t) TeamColor::Blue]; }
const MobList& getMobList() const{ return m_Mobs; }
MobList& getMobList(){ return m_Mobs; }
const Color& getTileColor(TilePtr tile) const;
private:
void moveMobs(std::uint64_t delta);
};
} // namespace game
} // namespace td

View File

@@ -0,0 +1,34 @@
#pragma once
#include "ClientConnexion.h"
#include "ClientGame.h"
#include "game/Team.h"
#include "game/Player.h"
namespace td {
namespace client {
class Client{
private:
ClientConnexion m_Connexion;
ClientGame m_Game{m_Connexion.GetDispatcher()};
bool m_Connected;
public:
Client(){}
const ClientGame& getGame() const{ return m_Game; }
const ClientConnexion& getConnexion() const{ return m_Connexion; }
void tick(std::uint64_t delta);
void connect(const std::string& address, std::uint16_t port);
void closeConnection();
bool isConnected() const{ return m_Connexion.getSocketStatus() == network::Socket::Connected; }
void selectTeam(game::TeamColor team);
};
} // namespace client
} // namespace td

View File

@@ -0,0 +1,37 @@
#pragma once
#include "protocol/PacketHandler.h"
#include "network/TCPSocket.h"
#include "game/Connexion.h"
namespace td {
namespace client {
class ClientConnexion : public protocol::Connexion{
private:
std::uint8_t m_ConnectionID;
std::string m_DisconnectReason;
float m_ServerTPS;
int m_Ping = 0;
public:
ClientConnexion();
virtual bool updateSocket();
virtual void HandlePacket(protocol::KeepAlivePacket* packet);
virtual void HandlePacket(protocol::ConnexionInfoPacket* packet);
virtual void HandlePacket(protocol::DisconnectPacket* packet);
virtual void HandlePacket(protocol::ServerTpsPacket* packet);
const std::string& getDisconnectReason() const{ return m_DisconnectReason; }
float getServerTPS() const{ return m_ServerTPS; }
int getServerPing() const {return m_Ping;}
REMOVE_COPY(ClientConnexion);
private:
void registerHandlers();
void login();
};
} // namespace client
} // namespace td

View File

@@ -0,0 +1,36 @@
#pragma once
#include "game/BaseGame.h"
#include "protocol/PacketHandler.h"
#include "WorldClient.h"
namespace td {
namespace client {
class ClientGame : public protocol::PacketHandler, public game::Game{
private:
std::uint8_t m_ConnexionID;
std::uint32_t m_LobbyTime = 0;
game::Player* m_Player = nullptr;
client::WorldClient m_WorldClient{this};
public:
ClientGame(protocol::PacketDispatcher* dispatcher);
virtual ~ClientGame();
virtual void tick(std::uint64_t delta);
std::uint32_t getLobbyTime() const{return m_LobbyTime;}
const game::Player* getPlayer() const{return m_Player;}
virtual void HandlePacket(protocol::ConnexionInfoPacket* packet);
virtual void HandlePacket(protocol::PlayerJoinPacket* packet);
virtual void HandlePacket(protocol::PlayerLeavePacket* packet);
virtual void HandlePacket(protocol::PlayerListPacket* packet);
virtual void HandlePacket(protocol::UpdatePlayerTeamPacket* packet);
virtual void HandlePacket(protocol::UpdateGameStatePacket* packet);
virtual void HandlePacket(protocol::UpdateLobbyTimePacket* packet);
virtual void HandlePacket(protocol::UpdateMoneyPacket* packet);
};
} // namespace client
} // namespace td

View File

@@ -0,0 +1,23 @@
#pragma once
#include "game/World.h"
#include "protocol/PacketHandler.h"
namespace td {
namespace client {
class ClientGame;
class WorldClient : public game::World, public protocol::PacketHandler{
private:
ClientGame* m_Game;
public:
WorldClient(ClientGame* game);
virtual void HandlePacket(protocol::WorldBeginDataPacket* packet);
virtual void HandlePacket(protocol::WorldDataPacket* packet);
virtual void HandlePacket(protocol::SpawnMobPacket* packet);
};
} // namespace client
} // namespace td

View File

@@ -0,0 +1,31 @@
#pragma once
#include <vector>
#include "misc/Time.h"
namespace td {
namespace server {
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::Timer m_Timer;
public:
Lobby(Server* server);
void OnPlayerJoin(std::uint8_t playerID);
void OnPlayerLeave(std::uint8_t playerID);
void sendTimeRemaining();
void tick();
};
} // namespace server
} // namespace td

View File

@@ -0,0 +1,96 @@
#pragma once
#include <cstdint>
#include <map>
#include "network/TCPListener.h"
#include "protocol/Protocol.h"
#include "protocol/PacketDispatcher.h"
#include "protocol/PacketHandler.h"
#include "ServerGame.h"
#include "ServerConnexion.h"
#include "Lobby.h"
//#define LOBBY_WAITING_TIME 2 * 60 * 1000
#define LOBBY_WAITING_TIME 5 * 1000
#define SERVER_TPS 20
#define SERVER_TICK 1000 / SERVER_TPS
namespace td {
namespace server {
typedef std::map<std::uint8_t, ServerConnexion> ConnexionMap;
class TickCounter{
private:
float m_TPS;
std::uint64_t m_LastTPSTime;
std::uint8_t m_TickCount;
public:
TickCounter(){}
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 = (float)SERVER_TPS / (float)(timeElapsedSinceLast20Ticks / 1000.0f);
m_TickCount = 0;
m_LastTPSTime = td::utils::getTime();
return true;
}
return false;
}
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;
public:
Server(const std::string& worldFilePath);
virtual ~Server(){}
bool start(std::uint16_t port);
void tick(std::uint64_t delta);
void stop();
void lauchGame();
void removeConnexion(std::uint8_t connexionID);
void broadcastPacket(protocol::Packet* packet);
float getTPS() const{ return m_TickCounter.getTPS(); }
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 game::PlayerList& getPlayers() const{ return m_Game.getPlayers(); }
game::PlayerList& getPlayers(){ return m_Game.getPlayers(); }
private:
void accept();
void updateSockets();
void OnPlayerJoin(std::uint8_t id);
void OnPlayerLeave(std::uint8_t id);
};
} // namespace server
} // namespace td

View File

@@ -0,0 +1,56 @@
#pragma once
#include "network/TCPSocket.h"
#include "protocol/PacketHandler.h"
#include "protocol/PacketDispatcher.h"
#include "game/Player.h"
#include "game/Connexion.h"
namespace td{
namespace server{
class Server;
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;
public:
ServerConnexion();
ServerConnexion(network::TCPSocket& socket, std::uint8_t id);
ServerConnexion(ServerConnexion&& move);
virtual ~ServerConnexion();
void setServer(Server* server);
virtual void HandlePacket(protocol::PlayerLoginPacket* packet);
virtual void HandlePacket(protocol::KeepAlivePacket* packet);
virtual void HandlePacket(protocol::SelectTeamPacket* packet);
virtual void HandlePacket(protocol::DisconnectPacket* packet);
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();
REMOVE_COPY(ServerConnexion);
private:
void registerHandlers();
void checkKeepAlive();
void sendKeepAlive();
void initConnection();
};
} // namespace server
} // namespace td

View File

@@ -0,0 +1,29 @@
#pragma once
#include "game/BaseGame.h"
#include "misc/Time.h"
#include "ServerWorld.h"
namespace td {
namespace server {
class Server;
class ServerGame : public game::Game{
private:
Server* m_Server;
ServerWorld m_ServerWorld;
utils::Timer m_GoldMineTimer{1000, std::bind(&ServerGame::updateGoldMines, this)};
public:
ServerGame(Server* server);
~ServerGame(){}
virtual void tick(std::uint64_t delta);
void startGame();
private:
void balanceTeams();
void updateGoldMines();
};
} // namespace game
} // namespace td

View File

@@ -0,0 +1,21 @@
#pragma once
#include "game/World.h"
namespace td {
namespace server {
class Server;
class ServerGame;
class ServerWorld : public game::World{
private:
game::MobID m_CurrentMobID = 0;
Server* m_Server;
public:
ServerWorld(Server* server, ServerGame* game);
void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);
};
} // namespace server
} // namespace td