1er commit
This commit is contained in:
21
src/game/BaseGame.cpp
Normal file
21
src/game/BaseGame.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "game/BaseGame.h"
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
Game::Game(World* world) : m_World(world){
|
||||
|
||||
}
|
||||
|
||||
Game::~Game(){
|
||||
|
||||
}
|
||||
|
||||
void Game::tick(std::uint64_t delta){
|
||||
if(m_GameState == GameState::Game){
|
||||
m_World->tick(delta);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
76
src/game/Connexion.cpp
Normal file
76
src/game/Connexion.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "game/Connexion.h"
|
||||
#include "protocol/PacketDispatcher.h"
|
||||
#include "protocol/PacketFactory.h"
|
||||
#include "game/server/Server.h"
|
||||
#include "misc/Compression.h"
|
||||
|
||||
#include "misc/Time.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
namespace td {
|
||||
namespace protocol {
|
||||
|
||||
Connexion::Connexion() : protocol::PacketHandler(nullptr){
|
||||
|
||||
}
|
||||
|
||||
Connexion::Connexion(Connexion&& move) : m_Socket(std::move(move.m_Socket)), protocol::PacketHandler(&m_Dispatcher){
|
||||
|
||||
}
|
||||
|
||||
Connexion::Connexion(protocol::PacketDispatcher* dispatcher) : protocol::PacketHandler(dispatcher){
|
||||
|
||||
}
|
||||
|
||||
Connexion::Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket) : protocol::PacketHandler(dispatcher), m_Socket(std::move(socket)){
|
||||
|
||||
}
|
||||
|
||||
bool Connexion::updateSocket(){
|
||||
if(m_Socket.GetStatus() != network::Socket::Connected)
|
||||
return false;
|
||||
|
||||
DataBuffer buffer;
|
||||
m_Socket.Receive(buffer, sizeof(std::size_t));
|
||||
if (buffer.GetSize() > 0){
|
||||
std::size_t packetLenght;
|
||||
buffer >> packetLenght;
|
||||
|
||||
m_Socket.Receive(buffer, packetLenght);
|
||||
|
||||
DataBuffer decompressed = utils::Decompress(buffer, packetLenght);
|
||||
|
||||
protocol::PacketType packetType;
|
||||
decompressed >> packetType;
|
||||
|
||||
protocol::Packet* packet = protocol::PacketFactory::createPacket(packetType, decompressed);
|
||||
GetDispatcher()->Dispatch(packet);
|
||||
delete packet;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Connexion::connect(const std::string& address, std::uint16_t port){
|
||||
if(!m_Socket.Connect(address, port)){
|
||||
return false;
|
||||
}
|
||||
m_Socket.SetBlocking(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Connexion::sendPacket(protocol::Packet* packet){
|
||||
network::SendPacket(packet->Serialize(), m_Socket);
|
||||
}
|
||||
|
||||
void Connexion::closeConnection(){
|
||||
m_Socket.Disconnect();
|
||||
}
|
||||
|
||||
Connexion::~Connexion(){
|
||||
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace td
|
||||
220
src/game/Mobs.cpp
Normal file
220
src/game/Mobs.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
#include "game/Mobs.h"
|
||||
#include <map>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
typedef std::pair<MobType, std::uint8_t> MobKey;
|
||||
|
||||
const std::map<MobKey, MobStats> MobConstants = {
|
||||
// damage speed money_cost exp_cost exp_reward max_health
|
||||
{{MobType::Zombie, 1},{MobStats{1, 1.6, 15, 0, 7, 40}}},
|
||||
{{MobType::Zombie, 2},{MobStats{1, 1.6, 18, 88, 9, 56}}},
|
||||
{{MobType::Zombie, 3},{MobStats{1, 1.6, 22, 153, 10, 78}}},
|
||||
{{MobType::Zombie, 4},{MobStats{1.5, 1.6, 26, 268, 13, 110}}},
|
||||
{{MobType::Zombie, 5},{MobStats{2, 1.6, 31, 469, 15, 154}}},
|
||||
|
||||
{{MobType::Spider, 1},{MobStats{1, 1.6, 25, 100, 15, 80}}},
|
||||
{{MobType::Spider, 2},{MobStats{1, 2, 30, 175, 16, 112}}},
|
||||
{{MobType::Spider, 3},{MobStats{1.5, 2, 36, 306, 18, 157}}},
|
||||
{{MobType::Spider, 4},{MobStats{2.5, 2, 43, 536, 19, 222}}},
|
||||
{{MobType::Spider, 5},{MobStats{1.5, 2.5, 52, 938, 22, 307}}},
|
||||
|
||||
{{MobType::Skeleton, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Skeleton, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Skeleton, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Skeleton, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Skeleton, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Pigman, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Pigman, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Pigman, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Pigman, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Pigman, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Creeper, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Creeper, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Creeper, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Creeper, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Creeper, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Silverfish, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Silverfish, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Silverfish, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Silverfish, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Silverfish, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Blaze, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Blaze, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Blaze, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Blaze, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Blaze, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Witch, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Witch, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Witch, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Witch, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Witch, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Slime, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Slime, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Slime, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Slime, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Slime, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
|
||||
{{MobType::Giant, 1},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Giant, 2},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Giant, 3},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Giant, 4},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
{{MobType::Giant, 5},{MobStats{0, 0, 0, 0, 0, 0}}},
|
||||
};
|
||||
|
||||
const MobStats* getMobStats(MobType type, std::uint8_t level){
|
||||
return &MobConstants.at(MobKey{type, level});
|
||||
}
|
||||
|
||||
const std::map<MobKey, TowerImmunities> MobsTowerImmunities = {
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
{{MobType::Spider, 5},{TowerType::Archer, TowerType::Artillery, TowerType::Leach, TowerType::Necromancer, TowerType::Poison, TowerType::Quake, TowerType::Sorcerer, TowerType::Turret, TowerType::Zeus}},
|
||||
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{}},
|
||||
{{MobType::Skeleton, 4},{}},
|
||||
{{MobType::Skeleton, 5},{}},
|
||||
|
||||
{{MobType::Pigman, 1},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 2},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 3},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 4},{TowerType::Zeus}},
|
||||
{{MobType::Pigman, 5},{TowerType::Zeus}},
|
||||
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{}},
|
||||
{{MobType::Silverfish, 5},{}},
|
||||
|
||||
{{MobType::Blaze, 1},{}},
|
||||
{{MobType::Blaze, 2},{}},
|
||||
{{MobType::Blaze, 3},{}},
|
||||
{{MobType::Blaze, 4},{}},
|
||||
{{MobType::Blaze, 5},{}},
|
||||
|
||||
{{MobType::Witch, 1},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 2},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 3},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 4},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
{{MobType::Witch, 5},{TowerType::Zeus, TowerType::Mage, TowerType::Poison}},
|
||||
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{}},
|
||||
{{MobType::Slime, 5},{}},
|
||||
|
||||
{{MobType::Giant, 1},{}},
|
||||
{{MobType::Giant, 2},{}},
|
||||
{{MobType::Giant, 3},{}},
|
||||
{{MobType::Giant, 4},{}},
|
||||
{{MobType::Giant, 5},{}},
|
||||
};
|
||||
|
||||
const TowerImmunities& getMobTowerImmunities(MobType type, std::uint8_t level){
|
||||
return MobsTowerImmunities.at({type, level});
|
||||
}
|
||||
|
||||
const std::map<MobKey, EffectImmunities> MobsEffectImmunities = {
|
||||
{{MobType::Zombie, 1},{}},
|
||||
{{MobType::Zombie, 2},{}},
|
||||
{{MobType::Zombie, 3},{}},
|
||||
{{MobType::Zombie, 4},{}},
|
||||
{{MobType::Zombie, 5},{}},
|
||||
|
||||
{{MobType::Spider, 1},{}},
|
||||
{{MobType::Spider, 2},{}},
|
||||
{{MobType::Spider, 3},{}},
|
||||
{{MobType::Spider, 4},{}},
|
||||
{{MobType::Spider, 5},{}},
|
||||
|
||||
{{MobType::Skeleton, 1},{}},
|
||||
{{MobType::Skeleton, 2},{}},
|
||||
{{MobType::Skeleton, 3},{EffectType::Fire}},
|
||||
{{MobType::Skeleton, 4},{EffectType::Fire}},
|
||||
{{MobType::Skeleton, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Pigman, 1},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 2},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 3},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 4},{EffectType::Fire}},
|
||||
{{MobType::Pigman, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Creeper, 1},{}},
|
||||
{{MobType::Creeper, 2},{}},
|
||||
{{MobType::Creeper, 3},{}},
|
||||
{{MobType::Creeper, 4},{}},
|
||||
{{MobType::Creeper, 5},{}},
|
||||
|
||||
{{MobType::Silverfish, 1},{}},
|
||||
{{MobType::Silverfish, 2},{}},
|
||||
{{MobType::Silverfish, 3},{}},
|
||||
{{MobType::Silverfish, 4},{EffectType::Fire}},
|
||||
{{MobType::Silverfish, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Blaze, 1},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 2},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 3},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 4},{EffectType::Fire}},
|
||||
{{MobType::Blaze, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Witch, 1},{}},
|
||||
{{MobType::Witch, 2},{}},
|
||||
{{MobType::Witch, 3},{}},
|
||||
{{MobType::Witch, 4},{}},
|
||||
{{MobType::Witch, 5},{}},
|
||||
|
||||
{{MobType::Slime, 1},{}},
|
||||
{{MobType::Slime, 2},{}},
|
||||
{{MobType::Slime, 3},{}},
|
||||
{{MobType::Slime, 4},{EffectType::Fire}},
|
||||
{{MobType::Slime, 5},{EffectType::Fire}},
|
||||
|
||||
{{MobType::Giant, 1},{EffectType::Stun}},
|
||||
{{MobType::Giant, 2},{EffectType::Stun}},
|
||||
{{MobType::Giant, 3},{EffectType::Stun}},
|
||||
{{MobType::Giant, 4},{EffectType::Stun}},
|
||||
{{MobType::Giant, 5},{EffectType::Stun}},
|
||||
};
|
||||
|
||||
const EffectImmunities& getMobEffectImmunities(MobType type, std::uint8_t level){
|
||||
return MobsEffectImmunities.at({type, level});
|
||||
}
|
||||
|
||||
MobPtr MobFactory::createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender){
|
||||
using MobCreator = std::function<std::shared_ptr<Mob>(MobID, std::uint8_t, PlayerID)>;
|
||||
|
||||
static std::map<MobType, MobCreator> mobFactory = {
|
||||
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
||||
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
||||
};
|
||||
|
||||
return mobFactory[type](id, level, sender);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
27
src/game/Team.cpp
Normal file
27
src/game/Team.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "game/Player.h"
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
Team::Team(TeamColor color): m_Color(color){}
|
||||
|
||||
void Team::addPlayer(Player* newPlayer){
|
||||
m_Players.push_back(newPlayer);
|
||||
newPlayer->setTeamColor(m_Color);
|
||||
}
|
||||
|
||||
void Team::removePlayer(const Player* player){
|
||||
m_Players.erase(std::find(m_Players.begin(), m_Players.end(), player));
|
||||
}
|
||||
|
||||
TeamColor Team::getColor() const{
|
||||
return m_Color;
|
||||
}
|
||||
|
||||
std::uint8_t Team::getPlayerCount() const{
|
||||
return m_Players.size();
|
||||
}
|
||||
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
161
src/game/Towers.cpp
Normal file
161
src/game/Towers.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "game/Towers.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
const std::map<std::pair<TowerType, TowerLevel>, TowerStats> TowerConstants = {
|
||||
// // rate damage range
|
||||
{{TowerType::Archer, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Archer, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Archer, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Archer, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Archer, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Archer, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Ice, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Ice, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Ice, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Ice, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Sorcerer, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Sorcerer, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Sorcerer, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Sorcerer, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Zeus, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Zeus, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Zeus, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Mage, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Mage, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Mage, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Mage, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Artillery, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Artillery, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Artillery, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Artillery, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Artillery, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Quake, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Quake, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Quake, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Quake, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Poison, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Poison, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Poison, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Poison, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Poison, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Poison, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Leach, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Leach, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Turret, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Turret, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Turret, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
{{TowerType::Necromancer, {1, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Necromancer, {2, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Necromancer, {3, TowerPath::Top}}, {0, 0, 0}},
|
||||
{{TowerType::Necromancer, {4, TowerPath::Top}}, {0, 0, 0}},
|
||||
|
||||
{{TowerType::Necromancer, {3, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
{{TowerType::Necromancer, {4, TowerPath::Bottom}}, {0, 0, 0}},
|
||||
};
|
||||
|
||||
const TowerStats* getTowerStats(TowerType type, TowerLevel level){
|
||||
return &TowerConstants.at({type, level});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ArcherTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void IceTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void MageTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void PoisonTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void QuakeTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void ZeusTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void ArtilleryTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void SorcererTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LeachTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void TurretTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
void NecromancerTower::tick(std::uint64_t delta){
|
||||
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
386
src/game/World.cpp
Normal file
386
src/game/World.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
#include "game/World.h"
|
||||
#include "protocol/PacketDispatcher.h"
|
||||
#include "protocol/Protocol.h"
|
||||
#include "game/BaseGame.h"
|
||||
#include "misc/Random.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "misc/Compression.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define WRITE_MAP 0
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
World::World(Game* game) : m_Game(game){
|
||||
#if WRITE_MAP
|
||||
loadMapFromFile("");
|
||||
#endif
|
||||
}
|
||||
|
||||
TilePtr World::getTile(std::int32_t x, std::int32_t y){
|
||||
std::int16_t chunkX = x / Chunk::ChunkWidth;
|
||||
std::int16_t chunkY = y / Chunk::ChunkHeight;
|
||||
|
||||
std::uint16_t subChunkX = x % Chunk::ChunkWidth;
|
||||
std::uint16_t subChunkY = y % Chunk::ChunkHeight;
|
||||
|
||||
auto chunkIt = m_Chunks.find({chunkX, chunkY});
|
||||
if(chunkIt == m_Chunks.end())
|
||||
return nullptr;
|
||||
|
||||
ChunkPtr chunk = chunkIt->second;
|
||||
|
||||
return getTilePtr(chunk->getTileIndex(subChunkY * Chunk::ChunkWidth + subChunkX));
|
||||
}
|
||||
|
||||
bool World::loadMap(const protocol::WorldBeginDataPacket* worldHeader){
|
||||
m_TowerPlacePalette = worldHeader->getTowerTilePalette();
|
||||
m_WalkablePalette = worldHeader->getWalkableTileColor();
|
||||
m_DecorationPalette = worldHeader->getDecorationPalette();
|
||||
|
||||
m_Spawns[(std::size_t) TeamColor::Red] = worldHeader->getRedSpawn();
|
||||
m_Spawns[(std::size_t) TeamColor::Blue] = worldHeader->getBlueSpawn();
|
||||
|
||||
m_SpawnColorPalette = worldHeader->getSpawnPalette();
|
||||
|
||||
m_Castles[(std::size_t) TeamColor::Red] = worldHeader->getRedCastle();
|
||||
m_Castles[(std::size_t) TeamColor::Blue] = worldHeader->getBlueCastle();
|
||||
|
||||
m_TilePalette = worldHeader->getTilePalette();
|
||||
}
|
||||
|
||||
bool World::loadMap(const protocol::WorldDataPacket* worldData){
|
||||
m_Chunks = worldData->getChunks();
|
||||
}
|
||||
|
||||
bool World::loadMapFromFile(const std::string& fileName){
|
||||
#if !WRITE_MAP
|
||||
DataBuffer buffer;
|
||||
if(!buffer.ReadFile(fileName)){
|
||||
std::cerr << "Failed to load map from file " << fileName << " !\n";
|
||||
}
|
||||
|
||||
std::cout << "File size : " << buffer.GetSize() << std::endl;
|
||||
|
||||
DataBuffer mapHeaderPacketBuffer = utils::Decompress(buffer);
|
||||
DataBuffer mapDataPacketBuffer = utils::Decompress(buffer);
|
||||
|
||||
protocol::PacketType packetType;
|
||||
|
||||
mapHeaderPacketBuffer >> packetType;
|
||||
|
||||
protocol::WorldBeginDataPacket headerPacket;
|
||||
headerPacket.Deserialize(mapHeaderPacketBuffer);
|
||||
|
||||
mapDataPacketBuffer >> packetType;
|
||||
|
||||
protocol::WorldDataPacket dataPacket;
|
||||
dataPacket.Deserialize(mapDataPacketBuffer);
|
||||
|
||||
loadMap(&headerPacket);
|
||||
loadMap(&dataPacket);
|
||||
|
||||
#else
|
||||
m_WalkablePalette = {102, 102, 153};
|
||||
|
||||
m_TowerPlacePalette[0] = {204, 51, 0};
|
||||
m_TowerPlacePalette[1] = {255, 153, 0};
|
||||
|
||||
WalkableTile walkableTileDown; // 1
|
||||
walkableTileDown.direction = Direction::PositiveY;
|
||||
m_TilePalette.push_back(std::make_shared<WalkableTile>(walkableTileDown));
|
||||
|
||||
WalkableTile walkableTileUp; // 2
|
||||
walkableTileUp.direction = Direction::NegativeY;
|
||||
m_TilePalette.push_back(std::make_shared<WalkableTile>(walkableTileUp));
|
||||
|
||||
WalkableTile walkableTileLeft; // 3
|
||||
walkableTileLeft.direction = Direction::NegativeX;
|
||||
m_TilePalette.push_back(std::make_shared<WalkableTile>(walkableTileLeft));
|
||||
|
||||
WalkableTile walkableTileRight; // 4
|
||||
walkableTileRight.direction = Direction::PositiveX;
|
||||
m_TilePalette.push_back(std::make_shared<WalkableTile>(walkableTileRight));
|
||||
|
||||
TowerTile redTile0; // 5
|
||||
redTile0.color_palette_ref = 0;
|
||||
redTile0.team_owner = TeamColor::Red;
|
||||
m_TilePalette.push_back(std::make_shared<TowerTile>(redTile0));
|
||||
|
||||
TowerTile redTile1; // 6
|
||||
redTile1.color_palette_ref = 1;
|
||||
redTile1.team_owner = TeamColor::Red;
|
||||
m_TilePalette.push_back(std::make_shared<TowerTile>(redTile1));
|
||||
|
||||
TowerTile blueTile0; // 7
|
||||
blueTile0.color_palette_ref = 0;
|
||||
blueTile0.team_owner = TeamColor::Blue;
|
||||
m_TilePalette.push_back(std::make_shared<TowerTile>(blueTile0));
|
||||
|
||||
TowerTile blueTile1; // 8
|
||||
blueTile1.color_palette_ref = 1;
|
||||
blueTile1.team_owner = TeamColor::Blue;
|
||||
m_TilePalette.push_back(std::make_shared<TowerTile>(blueTile1));
|
||||
|
||||
m_Castles[(uint) TeamColor::Red].x = 58;
|
||||
m_Castles[(uint) TeamColor::Red].y = 43;
|
||||
|
||||
m_Spawns[(uint) TeamColor::Red].direction = Direction::PositiveY;
|
||||
m_Spawns[(uint) TeamColor::Red].x = 13;
|
||||
m_Spawns[(uint) TeamColor::Red].y = 13;
|
||||
|
||||
m_SpawnColorPalette[(uint) TeamColor::Red] = {255, 0, 0};
|
||||
|
||||
//Chunks
|
||||
|
||||
Chunk chunk0;
|
||||
for (int i = 0; i <= 6; i++){
|
||||
chunk0.palette.push_back(i);
|
||||
}
|
||||
chunk0.tiles = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,
|
||||
0,0,0,0,0,0,6,5,6,5,6,0,0,0,0,0,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
0,0,0,0,0,0,5,6,5,6,5,0,0,0,0,0,5,5,5,2,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
0,0,0,0,0,0,6,5,6,5,6,0,0,0,0,0,5,5,5,2,2,4,4,4,4,4,4,4,4,4,4,1,
|
||||
0,0,0,0,0,0,5,6,5,6,5,0,0,0,0,0,0,0,0,2,2,2,4,4,4,4,4,4,4,4,1,1,
|
||||
0,0,0,0,0,0,6,5,6,5,6,0,0,0,0,0,0,0,0,2,2,2,2,4,4,4,4,4,4,1,1,1,
|
||||
0,0,0,0,0,6,6,6,5,5,5,0,0,0,0,0,6,6,6,2,2,2,2,2,5,5,5,5,5,1,1,1,
|
||||
0,0,0,0,0,6,6,6,5,5,5,1,1,1,1,1,6,6,6,2,2,2,2,2,5,6,6,6,5,1,1,1,
|
||||
0,0,0,0,0,6,6,6,5,5,5,1,1,1,1,1,6,6,6,2,2,2,2,2,5,6,5,6,5,1,1,1,
|
||||
0,0,0,0,0,5,5,5,6,6,6,1,1,1,1,1,5,5,5,2,2,2,2,2,5,6,6,6,5,1,1,1,
|
||||
0,0,0,0,0,5,5,5,6,6,6,1,1,1,1,1,5,5,5,2,2,2,2,2,5,5,5,5,5,1,1,1,
|
||||
0,0,0,0,0,5,5,5,6,6,6,1,1,1,1,1,5,5,5,2,2,2,2,2,6,6,6,6,6,1,1,1,
|
||||
0,0,0,0,0,6,6,6,5,5,5,1,1,1,1,4,4,4,4,2,2,2,2,2,6,5,5,5,6,1,1,4,
|
||||
0,0,0,0,0,6,6,6,5,5,5,1,1,1,4,4,4,4,4,4,2,2,2,2,6,5,6,5,6,1,4,4,
|
||||
0,0,0,0,0,6,6,6,5,5,5,1,1,4,4,4,4,4,4,4,4,2,2,2,6,5,5,5,6,4,4,4,
|
||||
0,0,0,0,0,5,5,5,6,6,6,1,4,4,4,4,4,4,4,4,4,4,2,2,6,6,6,6,6,0,0,0,
|
||||
0,0,0,0,0,5,5,5,6,6,6,4,4,4,4,4,4,4,4,4,4,4,4,2,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,5,5,5,6,6,6,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,
|
||||
0,0,0,0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,
|
||||
0,0,0,0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,
|
||||
0,0,0,0,0,6,6,6,5,5,5,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
0,0,0,0,0,0,0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
0,0,0,0,0,0,0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
};
|
||||
|
||||
|
||||
Chunk chunk1;
|
||||
for (int i = 0; i <= 6; i++){
|
||||
chunk1.palette.push_back(i);
|
||||
}
|
||||
|
||||
chunk1.tiles = {
|
||||
0,0,0,0,0,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
0,0,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,6,6,6,5,5,5,
|
||||
0,0,6,6,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,6,6,6,
|
||||
6,6,5,5,5,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,6,6,6,
|
||||
6,6,5,5,5,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,6,6,6,
|
||||
6,6,5,5,5,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,5,5,5,
|
||||
5,5,6,6,6,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,5,5,5,
|
||||
5,5,6,6,6,2,2,2,2,2,0,0,5,5,5,6,6,6,5,5,5,6,6,6,1,1,1,1,1,5,5,5,
|
||||
5,5,6,6,6,2,2,2,2,2,0,0,5,5,5,6,6,6,5,5,5,6,6,6,1,1,1,1,1,6,6,6,
|
||||
4,1,5,5,5,2,2,2,2,2,0,0,5,5,5,6,6,6,5,5,5,6,6,6,1,1,1,1,1,6,6,6,
|
||||
1,1,5,5,5,2,2,2,2,2,3,3,3,3,3,3,3,3,3,5,5,5,5,5,1,1,1,1,1,6,6,6,
|
||||
1,1,5,5,5,2,2,2,2,3,3,3,3,3,3,3,3,3,2,5,6,6,6,5,1,1,1,1,1,5,5,5,
|
||||
1,1,6,6,6,2,2,2,3,3,3,3,3,3,3,3,3,2,2,5,6,5,6,5,1,1,1,1,1,5,5,5,
|
||||
1,1,6,6,6,2,2,3,3,3,3,3,3,3,3,3,2,2,2,5,6,6,6,5,1,1,1,1,1,5,5,5,
|
||||
1,1,6,6,6,2,3,3,3,3,3,3,3,3,3,2,2,2,2,5,5,5,5,5,1,1,1,1,1,6,6,6,
|
||||
1,1,5,5,5,6,6,6,5,5,5,6,6,6,2,2,2,2,2,6,6,6,6,6,1,1,1,1,1,6,6,6,
|
||||
1,1,5,5,5,6,6,6,5,5,5,6,6,6,2,2,2,2,2,6,5,5,5,6,1,1,1,1,1,6,6,6,
|
||||
1,1,5,5,5,6,6,6,5,5,5,6,6,6,2,2,2,2,2,6,5,6,5,6,1,1,1,1,1,5,5,5,
|
||||
1,4,4,4,4,4,4,4,4,4,1,5,5,5,2,2,2,2,2,6,5,5,5,6,1,1,1,1,1,5,5,5,
|
||||
4,4,4,4,4,4,4,4,4,1,1,5,5,5,2,2,2,2,2,6,6,6,6,6,1,1,1,1,1,5,5,5,
|
||||
4,4,4,4,4,4,4,4,1,1,1,5,5,5,2,2,2,2,2,5,5,5,5,5,1,1,1,1,1,6,6,6,
|
||||
4,4,4,4,4,4,4,1,1,1,1,6,6,6,2,2,2,2,2,5,6,6,6,5,1,1,1,1,1,6,6,6,
|
||||
4,4,4,4,4,4,1,1,1,1,1,6,6,6,2,2,2,2,2,5,6,5,6,5,1,1,1,1,1,6,6,6,
|
||||
6,6,6,5,5,5,1,1,1,1,1,6,6,6,2,2,2,2,2,5,6,6,6,5,1,1,1,1,1,5,5,5,
|
||||
6,6,6,5,5,5,1,1,1,1,1,5,5,5,2,2,2,2,2,5,5,5,5,5,1,1,1,1,1,5,5,5,
|
||||
6,6,6,5,5,5,1,1,1,1,1,5,5,5,2,2,2,2,2,6,6,6,6,6,1,1,1,1,1,5,5,5,
|
||||
0,6,6,6,6,6,1,1,1,1,1,5,5,5,2,2,2,2,2,6,5,5,5,6,1,1,1,1,1,6,6,6,
|
||||
0,6,5,5,5,6,1,1,1,1,1,6,6,6,2,2,2,2,2,6,5,6,5,6,1,1,1,1,1,6,6,6,
|
||||
0,6,5,6,5,6,1,1,1,1,1,6,6,6,2,2,2,2,2,6,5,5,5,6,1,1,1,1,1,6,6,6,
|
||||
0,6,5,5,5,6,1,1,1,1,1,6,6,6,2,2,2,2,2,6,6,6,6,6,1,1,1,1,1,5,5,5,
|
||||
0,6,6,6,6,6,1,1,1,1,1,5,5,5,2,2,2,2,2,5,5,5,5,5,1,1,1,1,1,5,5,5,
|
||||
};
|
||||
|
||||
|
||||
Chunk chunk2;
|
||||
for (int i = 0; i <= 6; i++){
|
||||
chunk2.palette.push_back(i);
|
||||
}
|
||||
|
||||
chunk2.tiles = {
|
||||
0,5,5,5,5,5,1,1,1,1,1,5,5,5,2,2,2,2,2,5,6,6,6,5,1,1,1,1,1,5,5,5,
|
||||
0,5,6,6,6,5,1,1,1,1,1,5,5,5,2,2,2,2,2,5,6,5,6,5,1,1,1,1,1,6,6,6,
|
||||
0,5,6,5,6,5,1,1,1,1,1,0,0,0,2,2,2,2,2,5,6,6,6,5,1,1,1,1,1,6,6,6,
|
||||
0,5,6,6,6,5,1,1,1,1,1,0,0,0,2,2,2,2,2,5,5,5,5,5,1,1,1,1,1,6,6,6,
|
||||
0,5,5,5,5,5,1,1,1,1,4,4,4,4,2,2,2,2,2,6,6,6,6,6,1,1,1,1,1,5,5,5,
|
||||
0,6,6,6,6,6,1,1,1,4,4,4,4,4,4,2,2,2,2,6,5,5,5,6,1,1,1,1,1,5,5,5,
|
||||
0,6,5,5,5,6,1,1,4,4,4,4,4,4,4,4,2,2,2,6,5,6,5,6,1,1,1,1,1,5,5,5,
|
||||
0,6,5,6,5,6,1,4,4,4,4,4,4,4,4,4,4,2,2,6,5,5,5,6,1,1,1,1,1,6,6,6,
|
||||
0,6,5,5,5,6,4,4,4,4,4,4,4,4,4,4,4,4,2,6,6,6,6,6,1,1,1,1,1,6,6,6,
|
||||
0,6,6,6,6,6,5,5,5,5,5,6,6,6,6,6,5,5,5,5,5,0,0,0,0,0,0,0,0,6,6,6,
|
||||
0,0,0,0,0,0,5,6,6,6,5,6,5,5,5,6,5,6,6,6,5,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,5,6,5,6,5,6,5,6,5,6,5,6,5,6,5,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,5,6,6,6,5,6,5,5,5,6,5,6,6,6,5,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,5,5,5,5,5,6,6,6,6,6,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
|
||||
m_Chunks.insert({{0, 0}, std::make_shared<Chunk>(chunk0)});
|
||||
m_Chunks.insert({{1, 0}, std::make_shared<Chunk>(chunk1)});
|
||||
m_Chunks.insert({{1, 1}, std::make_shared<Chunk>(chunk2)});
|
||||
|
||||
|
||||
// blue map = same but with offset of 64
|
||||
|
||||
|
||||
m_Castles[(uint) TeamColor::Blue].x = 58 + 64;
|
||||
m_Castles[(uint) TeamColor::Blue].y = 43;
|
||||
|
||||
m_Spawns[(uint) TeamColor::Blue].direction = Direction::PositiveY;
|
||||
m_Spawns[(uint) TeamColor::Blue].x = 13 + 64;
|
||||
m_Spawns[(uint) TeamColor::Blue].y = 13;
|
||||
|
||||
m_SpawnColorPalette[(uint) TeamColor::Blue] = {0, 0, 255};
|
||||
|
||||
Chunk chunk01;
|
||||
chunk01.palette = {0, 1, 2, 3, 4, 7, 8};
|
||||
|
||||
chunk01.tiles = chunk0.tiles; // the tiles indicies are the same, only the palette has changed
|
||||
|
||||
|
||||
Chunk chunk11;
|
||||
chunk11.palette = {0, 1, 2, 3, 4, 7, 8};
|
||||
|
||||
chunk11.tiles = chunk1.tiles; // the tiles indicies are the same, only the palette has changed
|
||||
|
||||
|
||||
Chunk chunk21;
|
||||
chunk21.palette = {0, 1, 2, 3, 4, 7, 8};
|
||||
|
||||
chunk21.tiles = chunk2.tiles; // the tiles indicies are the same, only the palette has changed
|
||||
|
||||
m_Chunks.insert({{2, 0}, std::make_shared<Chunk>(chunk01)});
|
||||
m_Chunks.insert({{3, 0}, std::make_shared<Chunk>(chunk11)});
|
||||
m_Chunks.insert({{3, 1}, std::make_shared<Chunk>(chunk21)});
|
||||
|
||||
saveMap("tdmap.tdmap");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool World::saveMap(const std::string& fileName) const{
|
||||
protocol::WorldBeginDataPacket headerPacket(this);
|
||||
protocol::WorldDataPacket dataPacket(this);
|
||||
|
||||
DataBuffer mapHeaderCompressed = utils::Compress(headerPacket.Serialize());
|
||||
DataBuffer mapDataCompressed = utils::Compress(dataPacket.Serialize());
|
||||
|
||||
std::cout << "Header Packet Size : " << mapHeaderCompressed.GetSize() << std::endl;
|
||||
std::cout << "World Data Packet Size : " << mapDataCompressed.GetSize() << std::endl;
|
||||
|
||||
DataBuffer buffer = mapHeaderCompressed << mapDataCompressed;
|
||||
std::cout << "Total Size : " << buffer.GetSize() << std::endl;
|
||||
buffer.WriteFile(fileName);
|
||||
std::cout << "----- Map Saved ! -----\n";
|
||||
}
|
||||
|
||||
void World::tick(std::uint64_t delta){
|
||||
moveMobs(delta);
|
||||
}
|
||||
|
||||
void World::spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir){
|
||||
MobPtr mob = MobFactory::createMob(id, type, level, sender);
|
||||
mob->setX(x);
|
||||
mob->setY(y);
|
||||
mob->setDirection(dir);
|
||||
m_Mobs.push_back(mob);
|
||||
}
|
||||
|
||||
void World::moveMobs(std::uint64_t delta){
|
||||
for(MobPtr mob : m_Mobs){
|
||||
TilePtr tile = getTile(mob->getX(), mob->getY());
|
||||
|
||||
Direction tileDir;
|
||||
|
||||
if(tile != nullptr && tile->getType() == TileType::Walk){
|
||||
WalkableTile* walkTile = dynamic_cast<WalkableTile*>(tile.get());
|
||||
mob->setDirection(walkTile->direction);
|
||||
}
|
||||
|
||||
float mobWalkSpeed = mob->getStats()->getMovementSpeed();
|
||||
|
||||
float walkAmount = mobWalkSpeed * ((float) delta / 1000.0f);
|
||||
|
||||
switch(mob->getDirection()){
|
||||
case Direction::NegativeX:{
|
||||
mob->setX(mob->getX() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveX:{
|
||||
mob->setX(mob->getX() + walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::NegativeY:{
|
||||
mob->setY(mob->getY() - walkAmount);
|
||||
break;
|
||||
}
|
||||
case Direction::PositiveY:{
|
||||
mob->setY(mob->getY() + walkAmount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Color& World::getTileColor(TilePtr tile) const{
|
||||
switch(tile->getType()){
|
||||
case TileType::Tower:{
|
||||
TowerTile* towerTile = (TowerTile*) tile.get();
|
||||
return m_TowerPlacePalette[towerTile->color_palette_ref];
|
||||
}
|
||||
case TileType::Walk:{
|
||||
return m_WalkablePalette;
|
||||
}
|
||||
case TileType::Decoration:{
|
||||
DecorationTile* towerTile = (DecorationTile*) tile.get();
|
||||
return m_DecorationPalette[towerTile->color_palette_ref];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return m_DecorationPalette[0];
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
47
src/game/client/Client.cpp
Normal file
47
src/game/client/Client.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "game/client/Client.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace td {
|
||||
namespace client {
|
||||
|
||||
void Client::connect(const std::string& address, std::uint16_t port){
|
||||
if(!m_Connexion.connect(address, port)){
|
||||
std::cout << "Failed to connect !\n";
|
||||
return;
|
||||
}
|
||||
m_Connected = true;
|
||||
}
|
||||
|
||||
void Client::selectTeam(game::TeamColor team){
|
||||
if(!m_Connected)
|
||||
return;
|
||||
|
||||
protocol::SelectTeamPacket packet(team);
|
||||
m_Connexion.sendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::closeConnection(){
|
||||
if(!m_Connected)
|
||||
return;
|
||||
|
||||
m_Connected = false;
|
||||
|
||||
protocol::DisconnectPacket packet;
|
||||
m_Connexion.sendPacket(&packet);
|
||||
}
|
||||
|
||||
void Client::tick(std::uint64_t delta){
|
||||
if(!m_Connected)
|
||||
return;
|
||||
m_Connected = m_Connexion.updateSocket();
|
||||
if(!m_Connected){
|
||||
std::cout << "Disconnected ! (Reason : " << m_Connexion.getDisconnectReason() << ")\n";
|
||||
}else{
|
||||
m_Game.tick(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace client
|
||||
} // namespace td
|
||||
49
src/game/client/ClientConnexion.cpp
Normal file
49
src/game/client/ClientConnexion.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "game/client/ClientConnexion.h"
|
||||
#include "render/WorldRenderer.h"
|
||||
|
||||
namespace td {
|
||||
namespace client {
|
||||
|
||||
ClientConnexion::ClientConnexion(): Connexion(&m_Dispatcher){
|
||||
registerHandlers();
|
||||
}
|
||||
|
||||
void ClientConnexion::registerHandlers(){
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ServerTps, this);
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(protocol::KeepAlivePacket* packet){
|
||||
protocol::KeepAlivePacket keepAlivePacket(packet->getAliveID());
|
||||
sendPacket(&keepAlivePacket);
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(protocol::ConnexionInfoPacket* packet){
|
||||
m_ConnectionID = packet->getConnectionID();
|
||||
login();
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(protocol::ServerTpsPacket* packet){
|
||||
m_ServerTPS = packet->getTPS();
|
||||
m_Ping = utils::getTime() - packet->getPacketSendTime();
|
||||
}
|
||||
|
||||
void ClientConnexion::login(){
|
||||
td::protocol::PlayerLoginPacket loginPacket("Persson" + std::to_string(m_ConnectionID));
|
||||
sendPacket(&loginPacket);
|
||||
}
|
||||
|
||||
bool ClientConnexion::updateSocket(){
|
||||
return Connexion::updateSocket();
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(protocol::DisconnectPacket* packet){
|
||||
m_DisconnectReason = packet->getReason();
|
||||
closeConnection();
|
||||
render::WorldRenderer::destroy();
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace td
|
||||
94
src/game/client/ClientGame.cpp
Normal file
94
src/game/client/ClientGame.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "game/client/ClientGame.h"
|
||||
#include "protocol/PacketDispatcher.h"
|
||||
//#include "game/Team.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace td {
|
||||
namespace client {
|
||||
|
||||
ClientGame::ClientGame(protocol::PacketDispatcher* dispatcher): protocol::PacketHandler(dispatcher), game::Game(&m_WorldClient){
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::ConnectionInfo, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerJoin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerList, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLeave, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdatePlayerTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateLobbyTime, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateGameState, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMoney, this);
|
||||
}
|
||||
|
||||
ClientGame::~ClientGame(){
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
}
|
||||
|
||||
void ClientGame::tick(std::uint64_t delta){
|
||||
game::Game::tick(delta);
|
||||
if (m_GameState == game::GameState::Lobby && m_Players.size() >= 2){
|
||||
m_LobbyTime -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::PlayerJoinPacket* packet){
|
||||
game::Player player(packet->getPlayerID());
|
||||
player.setName(packet->getPlayerName());
|
||||
|
||||
m_Players.insert({player.getID(), player});
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::PlayerLeavePacket* packet){
|
||||
game::Player* player = &m_Players[packet->getPlayerID()];
|
||||
if (player->getTeamColor() != game::TeamColor::None){
|
||||
m_Teams[(std::size_t)player->getTeamColor()].removePlayer(player);
|
||||
}
|
||||
m_Players.erase(player->getID());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::PlayerListPacket* packet){
|
||||
for (auto pair : packet->getPlayers()){
|
||||
std::uint8_t playerID = pair.first;
|
||||
protocol::PlayerInfo playerInfo = pair.second;
|
||||
game::Player player(playerID);
|
||||
player.setName(playerInfo.name);
|
||||
player.setTeamColor(playerInfo.team);
|
||||
m_Players.insert({playerID, player});
|
||||
if (player.getTeamColor() != game::TeamColor::None){
|
||||
m_Teams[(std::size_t)player.getTeamColor()].addPlayer(&m_Players[playerID]);
|
||||
}
|
||||
}
|
||||
m_Player = &m_Players[m_ConnexionID];
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::UpdatePlayerTeamPacket* packet){
|
||||
game::Player* player = &m_Players[packet->getPlayerID()];
|
||||
if (player->getTeamColor() == game::TeamColor::None){ //join a team
|
||||
getTeam(packet->getSelectedTeam()).addPlayer(player);
|
||||
}
|
||||
else if (packet->getSelectedTeam() == game::TeamColor::None){ // leave a team
|
||||
getTeam(player->getTeamColor()).removePlayer(player);
|
||||
player->setTeamColor(game::TeamColor::None);
|
||||
}
|
||||
else{ // change team
|
||||
getTeam(player->getTeamColor()).removePlayer(player);
|
||||
getTeam(packet->getSelectedTeam()).addPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::UpdateGameStatePacket* packet){
|
||||
setGameState(packet->getGameState());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::ConnexionInfoPacket* packet){
|
||||
m_ConnexionID = packet->getConnectionID();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::UpdateLobbyTimePacket* packet){
|
||||
m_LobbyTime = packet->getRemainingTime();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(protocol::UpdateMoneyPacket* packet){
|
||||
m_Player->setGold(packet->getGold());
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace td
|
||||
30
src/game/client/WorldClient.cpp
Normal file
30
src/game/client/WorldClient.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "game/client/WorldClient.h"
|
||||
#include "protocol/PacketDispatcher.h"
|
||||
#include "game/client/ClientGame.h"
|
||||
#include "render/WorldRenderer.h"
|
||||
|
||||
namespace td{
|
||||
namespace client{
|
||||
|
||||
WorldClient::WorldClient(ClientGame* game) : m_Game(game), game::World(game), protocol::PacketHandler(game->GetDispatcher()){
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldBeginData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(protocol::WorldBeginDataPacket* packet){
|
||||
loadMap(packet);
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(protocol::WorldDataPacket* packet){
|
||||
loadMap(packet);
|
||||
render::WorldRenderer::init(this);
|
||||
}
|
||||
|
||||
void WorldClient::HandlePacket(protocol::SpawnMobPacket* packet){
|
||||
spawnMobAt(packet->getMobID(), packet->getMobType(), packet->getMobLevel(), packet->getSender(),
|
||||
packet->getMobX(), packet->getMobY(), packet->getMobDirection());
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace td
|
||||
76
src/game/server/Lobby.cpp
Normal file
76
src/game/server/Lobby.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "game/server/Lobby.h"
|
||||
#include "game/server/Server.h"
|
||||
|
||||
#include "misc/Time.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace td {
|
||||
namespace server {
|
||||
|
||||
/*static constexpr std::uint8_t timeNotifications[] = {
|
||||
2 * 60, // 2 min
|
||||
60 + 30, // 1 min 30 s
|
||||
60, // 1 min
|
||||
30, // 30 s
|
||||
15, // 15 s
|
||||
10, // 10 s
|
||||
5, // 5 s
|
||||
4, // 4 s
|
||||
3, // 3 s
|
||||
2, // 2 s
|
||||
1, // 1 s
|
||||
};*/
|
||||
|
||||
Lobby::Lobby(Server* server) : m_Server(server), m_Timer(1000, std::bind(&Lobby::sendTimeRemaining, this)){
|
||||
|
||||
}
|
||||
|
||||
void Lobby::tick(){
|
||||
if (m_GameStarted || m_StartTimerTime == 0)
|
||||
return;
|
||||
|
||||
if(utils::getTime() - m_StartTimerTime >= LOBBY_WAITING_TIME){
|
||||
protocol::UpdateGameStatePacket packet(game::GameState::Game);
|
||||
m_Server->broadcastPacket(&packet);
|
||||
m_GameStarted = true;
|
||||
m_Server->lauchGame();
|
||||
return;
|
||||
}
|
||||
|
||||
m_Timer.update();
|
||||
}
|
||||
|
||||
void Lobby::sendTimeRemaining(){
|
||||
protocol::UpdateLobbyTimePacket packet(LOBBY_WAITING_TIME - (utils::getTime() - m_StartTimerTime)); // converting second to millis
|
||||
m_Server->broadcastPacket(&packet);
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerJoin(std::uint8_t playerID){
|
||||
if(m_GameStarted)
|
||||
return;
|
||||
std::cout << "(Server) Player Joined Lobby !\n";
|
||||
m_Players.push_back(playerID);
|
||||
if (m_Players.size() == 2){ // start timer if a second player join the match
|
||||
m_StartTimerTime = utils::getTime();
|
||||
m_Timer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerLeave(std::uint8_t playerID){
|
||||
if(m_GameStarted)
|
||||
return;
|
||||
std::cout << "(Server) Player Leaved Lobby !\n";
|
||||
auto it = std::find(m_Players.begin(), m_Players.end(), playerID);
|
||||
if (it == m_Players.end())
|
||||
return;
|
||||
m_Players.erase(it);
|
||||
if (m_Players.size() == 1){
|
||||
protocol::UpdateLobbyTimePacket packet(0);
|
||||
m_Server->broadcastPacket(&packet);
|
||||
m_StartTimerTime = 0; // reset timer if there is only one player left
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace td
|
||||
105
src/game/server/Server.cpp
Normal file
105
src/game/server/Server.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "game/server/Server.h"
|
||||
#include <iostream>
|
||||
#include "protocol/PacketFactory.h"
|
||||
|
||||
namespace td {
|
||||
namespace server {
|
||||
|
||||
Server::Server(const std::string& worldFilePath){
|
||||
m_Game.getWorld()->loadMapFromFile(worldFilePath);
|
||||
}
|
||||
|
||||
void Server::lauchGame(){
|
||||
m_Game.startGame();
|
||||
}
|
||||
|
||||
bool Server::start(std::uint16_t port){
|
||||
if(!m_Listener.listen(port, 10)){
|
||||
std::cout << "Failed to bind port " << port << " !\n";
|
||||
return false;
|
||||
}
|
||||
if(!m_Listener.setBlocking(false)){
|
||||
std::cout << "Failed to block server socket !\n";
|
||||
return false;
|
||||
}
|
||||
std::cout << "Server started at port " << port << " !\n";
|
||||
m_TickCounter.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::stop(){
|
||||
protocol::DisconnectPacket packet("Server closed");
|
||||
broadcastPacket(&packet);
|
||||
|
||||
m_Listener.close();
|
||||
m_Listener.destroy();
|
||||
|
||||
m_Connections.clear();
|
||||
getPlayers().clear();
|
||||
}
|
||||
|
||||
void Server::tick(std::uint64_t delta){
|
||||
accept();
|
||||
updateSockets();
|
||||
m_Lobby.tick();
|
||||
m_Game.tick(delta);
|
||||
if(m_TickCounter.update()){
|
||||
protocol::ServerTpsPacket packet(m_TickCounter.getTPS(), utils::getTime());
|
||||
broadcastPacket(&packet);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::accept(){
|
||||
static std::uint8_t newPlayerID = 0;
|
||||
network::TCPSocket newSocket;
|
||||
if (m_Listener.accept(newSocket)){
|
||||
ServerConnexion con(newSocket, newPlayerID);
|
||||
m_Connections.insert(std::move(ConnexionMap::value_type{newPlayerID, std::move(con)}));
|
||||
OnPlayerJoin(newPlayerID);
|
||||
m_Connections[newPlayerID].setServer(this);
|
||||
newPlayerID++;
|
||||
}
|
||||
}
|
||||
|
||||
void Server::updateSockets(){
|
||||
std::int16_t closedConnexionID = -1;
|
||||
for (auto& connection : m_Connections){
|
||||
ServerConnexion& con = connection.second;
|
||||
if(con.getSocketStatus() != network::Socket::Status::Connected){
|
||||
closedConnexionID = connection.first;
|
||||
}else{
|
||||
con.updateSocket();
|
||||
}
|
||||
}
|
||||
if(closedConnexionID != -1){
|
||||
removeConnexion(closedConnexionID);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::broadcastPacket(protocol::Packet* packet){
|
||||
for (auto& connection : m_Connections){
|
||||
ServerConnexion& con = connection.second;
|
||||
con.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::removeConnexion(std::uint8_t connexionID){
|
||||
getPlayers().erase(getPlayers().find(connexionID));
|
||||
m_Connections.erase(connexionID);
|
||||
m_Lobby.OnPlayerLeave(connexionID);
|
||||
OnPlayerLeave(connexionID);
|
||||
}
|
||||
|
||||
void Server::OnPlayerJoin(std::uint8_t id){
|
||||
m_Lobby.OnPlayerJoin(id);
|
||||
|
||||
getPlayers().insert({id, game::Player{id}});
|
||||
}
|
||||
|
||||
void Server::OnPlayerLeave(std::uint8_t id){
|
||||
protocol::PlayerLeavePacket packet(id);
|
||||
broadcastPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace td
|
||||
153
src/game/server/ServerConnexion.cpp
Normal file
153
src/game/server/ServerConnexion.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "game/server/ServerConnexion.h"
|
||||
#include "protocol/PacketDispatcher.h"
|
||||
#include "protocol/PacketFactory.h"
|
||||
#include "game/server/Server.h"
|
||||
|
||||
#include "misc/Time.h"
|
||||
#include "misc/Random.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#define KEEP_ALIVE_TIMEOUT 10 * 1000 // 10s
|
||||
|
||||
namespace td{
|
||||
namespace server{
|
||||
|
||||
/*
|
||||
NEVER TRUST USER INPUT
|
||||
*/
|
||||
|
||||
|
||||
ServerConnexion::ServerConnexion(): m_Player(0){
|
||||
|
||||
}
|
||||
|
||||
ServerConnexion::ServerConnexion(network::TCPSocket& socket, std::uint8_t id) : Connexion::Connexion(&m_Dispatcher, socket), m_ID(id), m_Player(0){
|
||||
Connexion::updateSocket();
|
||||
}
|
||||
|
||||
ServerConnexion::ServerConnexion(ServerConnexion&& move) : Connexion::Connexion(std::move(move)), m_Server(move.m_Server),
|
||||
m_ID(move.m_ID), m_KeepAlive(move.m_KeepAlive), m_Player(move.m_Player){
|
||||
|
||||
move.m_Server = nullptr;
|
||||
registerHandlers();
|
||||
}
|
||||
|
||||
void ServerConnexion::registerHandlers(){
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
}
|
||||
|
||||
bool ServerConnexion::updateSocket(){
|
||||
checkKeepAlive();
|
||||
return Connexion::updateSocket();
|
||||
}
|
||||
|
||||
void ServerConnexion::checkKeepAlive(){
|
||||
std::uint64_t time = utils::getTime();
|
||||
if (time - m_KeepAlive.sendTime > KEEP_ALIVE_TIMEOUT){
|
||||
if (m_KeepAlive.recievedResponse){
|
||||
sendKeepAlive();
|
||||
}
|
||||
else{
|
||||
protocol::DisconnectPacket packet("Time out");
|
||||
sendPacket(&packet);
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::sendKeepAlive(){
|
||||
m_KeepAlive.keepAliveID = utils::getRandomNumber(UINT64_MAX);
|
||||
m_KeepAlive.recievedResponse = false;
|
||||
|
||||
protocol::KeepAlivePacket keepAlivePacket(m_KeepAlive.keepAliveID);
|
||||
sendPacket(&keepAlivePacket);
|
||||
|
||||
std::uint64_t time = utils::getTime();
|
||||
m_KeepAlive.sendTime = time;
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(protocol::PlayerLoginPacket* packet){
|
||||
if (m_Player->getName().empty() && !packet->getPlayerName().empty()){
|
||||
m_Player->setName(packet->getPlayerName());
|
||||
|
||||
protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->getName());
|
||||
m_Server->broadcastPacket(&joinPacket);
|
||||
|
||||
std::map<std::uint8_t, protocol::PlayerInfo> playerNames;
|
||||
for (const auto& pair : m_Server->getPlayers()){
|
||||
const game::Player& player = pair.second;
|
||||
if (!player.getName().empty()){
|
||||
protocol::PlayerInfo playerInfo;
|
||||
playerInfo.name = player.getName();
|
||||
playerInfo.team = player.getTeamColor();
|
||||
playerNames.insert({player.getID(), playerInfo});
|
||||
}
|
||||
}
|
||||
|
||||
protocol::PlayerListPacket listPacket(playerNames);
|
||||
sendPacket(&listPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(protocol::SelectTeamPacket* packet){
|
||||
if(m_Server->getGame().getGameState() != game::GameState::Lobby)
|
||||
return;
|
||||
if((std::int8_t) packet->getSelectedTeam() >= -1 || (std::int8_t) packet->getSelectedTeam() <= 1){
|
||||
//m_Player->setTeamColor(packet->getSelectedTeam());
|
||||
if(m_Player->getTeamColor() == game::TeamColor::None){ //join a team
|
||||
m_Server->getGame().getTeam(packet->getSelectedTeam()).addPlayer(m_Player);
|
||||
}else if(packet->getSelectedTeam() == game::TeamColor::None){ // leave a team
|
||||
m_Server->getGame().getTeam(m_Player->getTeamColor()).removePlayer(m_Player);
|
||||
m_Player->setTeamColor(game::TeamColor::None);
|
||||
}else{ // change team
|
||||
m_Server->getGame().getTeam(m_Player->getTeamColor()).removePlayer(m_Player);
|
||||
m_Server->getGame().getTeam(packet->getSelectedTeam()).addPlayer(m_Player);
|
||||
}
|
||||
protocol::UpdatePlayerTeamPacket updateTeamPacket(m_ID, packet->getSelectedTeam());
|
||||
m_Server->broadcastPacket(&updateTeamPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(protocol::KeepAlivePacket* packet){
|
||||
if(packet->getAliveID() == m_KeepAlive.keepAliveID)
|
||||
m_KeepAlive.recievedResponse = true;
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(protocol::DisconnectPacket* packet){
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void ServerConnexion::setServer(Server* server){
|
||||
m_Server = server;
|
||||
m_Player = &m_Server->getPlayers().at(m_ID);
|
||||
initConnection();
|
||||
sendKeepAlive();
|
||||
}
|
||||
|
||||
void ServerConnexion::initConnection(){
|
||||
protocol::UpdateGameStatePacket statePacket(m_Server->getGame().getGameState());
|
||||
sendPacket(&statePacket);
|
||||
|
||||
protocol::ConnexionInfoPacket conPacket(m_ID);
|
||||
sendPacket(&conPacket);
|
||||
|
||||
if (m_Server->getGame().getGameState() == game::GameState::Game){
|
||||
protocol::WorldBeginDataPacket headerDataPacket(m_Server->getGame().getWorld());
|
||||
protocol::WorldBeginDataPacket dataPacket(m_Server->getGame().getWorld());
|
||||
sendPacket(&headerDataPacket);
|
||||
sendPacket(&dataPacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ServerConnexion::~ServerConnexion(){
|
||||
if (GetDispatcher() != nullptr)
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace td
|
||||
57
src/game/server/ServerGame.cpp
Normal file
57
src/game/server/ServerGame.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "game/server/ServerGame.h"
|
||||
#include "game/server/Server.h"
|
||||
|
||||
namespace td {
|
||||
namespace server {
|
||||
|
||||
ServerGame::ServerGame(server::Server* server) : m_Server(server), m_ServerWorld(server, this), game::Game(&m_ServerWorld){
|
||||
|
||||
}
|
||||
|
||||
void ServerGame::tick(std::uint64_t delta){
|
||||
Game::tick(delta);
|
||||
m_GoldMineTimer.update();
|
||||
}
|
||||
|
||||
void ServerGame::startGame(){
|
||||
protocol::WorldBeginDataPacket headerMapData(m_World);
|
||||
m_Server->broadcastPacket(&headerMapData);
|
||||
|
||||
protocol::WorldDataPacket mapData(m_World);
|
||||
m_Server->broadcastPacket(&mapData);
|
||||
|
||||
m_GameState = game::GameState::Game;
|
||||
|
||||
balanceTeams();
|
||||
|
||||
m_ServerWorld.spawnMobs(game::MobType::Zombie, 1, 0, 12);
|
||||
}
|
||||
|
||||
void ServerGame::updateGoldMines(){
|
||||
for(auto& pair : m_Server->getPlayers()){
|
||||
game::Player* player = &pair.second;
|
||||
player->setGold(player->getGold() + player->getGoldPerSecond());
|
||||
protocol::UpdateMoneyPacket packet(player->getGold());
|
||||
m_Server->getConnexions()[player->getID()].sendPacket(&packet);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::balanceTeams(){
|
||||
for(auto playerInfo : m_Players){
|
||||
game::Player& player = playerInfo.second;
|
||||
if(player.getTeamColor() == game::TeamColor::None){
|
||||
game::Team& redTeam = getRedTeam();
|
||||
game::Team& blueTeam = getBlueTeam();
|
||||
if(blueTeam.getPlayerCount() > redTeam.getPlayerCount()){
|
||||
redTeam.addPlayer(&player);
|
||||
}else{
|
||||
blueTeam.addPlayer(&player);
|
||||
}
|
||||
protocol::UpdatePlayerTeamPacket packet(player.getID(), player.getTeamColor());
|
||||
m_Server->broadcastPacket(&packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
50
src/game/server/ServerWorld.cpp
Normal file
50
src/game/server/ServerWorld.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "game/server/ServerWorld.h"
|
||||
#include "game/server/Server.h"
|
||||
#include "misc/Random.h"
|
||||
|
||||
#define MOB_SPAWN_PRECISION 100.0f
|
||||
|
||||
namespace td {
|
||||
namespace server {
|
||||
|
||||
ServerWorld::ServerWorld(Server* server, ServerGame* game) : m_Server(server), game::World(game){
|
||||
|
||||
}
|
||||
|
||||
void ServerWorld::spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count){
|
||||
for (int i = 0; i < count; i++){
|
||||
game::TeamColor senderTeam = m_Game->getPlayers().at(sender).getTeamColor();
|
||||
game::Spawn* enemyMobSpawn;
|
||||
|
||||
if(senderTeam == game::TeamColor::Red){
|
||||
enemyMobSpawn = &m_Spawns[(std::size_t) game::TeamColor::Blue];
|
||||
}else{
|
||||
enemyMobSpawn = &m_Spawns[(std::size_t) game::TeamColor::Red];
|
||||
}
|
||||
|
||||
std::int32_t spawnCenterX = enemyMobSpawn->x;
|
||||
std::int32_t spawnCenterY = enemyMobSpawn->y;
|
||||
|
||||
std::int32_t minSpawnY = spawnCenterY - 2;
|
||||
std::int32_t maxSpawnY = spawnCenterY + 2;
|
||||
|
||||
std::int32_t minSpawnX = spawnCenterX - 2;
|
||||
std::int32_t maxSpawnX = spawnCenterX + 2;
|
||||
|
||||
std::uint64_t randomX = utils::getRandomNumber(std::abs(minSpawnX - maxSpawnX) * MOB_SPAWN_PRECISION);
|
||||
float mobX = (float) randomX / MOB_SPAWN_PRECISION + (float) minSpawnX;
|
||||
|
||||
std::uint64_t randomY = utils::getRandomNumber(std::abs(minSpawnY - maxSpawnY) * MOB_SPAWN_PRECISION);
|
||||
float mobY = (float) randomY / MOB_SPAWN_PRECISION + (float) minSpawnY;
|
||||
|
||||
spawnMobAt(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->direction);
|
||||
|
||||
protocol::SpawnMobPacket packet(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->direction);
|
||||
m_Server->broadcastPacket(&packet);
|
||||
|
||||
m_CurrentMobID++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace td
|
||||
Reference in New Issue
Block a user