Merge branch 'experimental' into dev

This commit is contained in:
2025-08-04 10:22:42 +02:00
97 changed files with 3654 additions and 2069 deletions

View File

@@ -0,0 +1,63 @@
#pragma once
#include <td/game/World.h>
#include <optional>
namespace td {
namespace sim {
using GameHistory = std::vector<td::protocol::LockStep>;
using GameBuffer = std::vector<std::optional<td::protocol::LockStep>>;
// TODO: OnEnd signal
class ClientSimulation : public protocol::PacketHandler {
private:
std::uint64_t m_StepTime;
game::World& m_World;
GameBuffer m_History;
std::uint64_t m_CurrentTime;
std::uint64_t m_LastTime;
std::size_t m_CurrentStep;
std::shared_ptr<WorldSnapshot> m_LastSnapshot;
std::uint64_t m_LastValidStep;
static const protocol::LockStep EMPTY_LOCKSTEP;
public:
/**
* \brief Replay constructor
* \param a_StepTime in ms
*/
ClientSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime);
/**
* \brief Live update constructor (continuous game updates)
* \param a_StepTime in ms
*/
ClientSimulation(game::World& a_World, std::uint64_t a_StepTime);
/**
* \return the progress [0-1] between two steps
*/
float Update();
void Handle(const protocol::packets::LockStepsPacket& a_LockSteps) override;
void Handle(const protocol::packets::PredictCommandPacket& a_Predict) override;
private:
void Step();
/**
* \brief Ticks a_Count times
*/
void FastForward(std::size_t a_Count);
/**
* \brief Tries to recompute simulation if needed (for example in late command receival)
*/
void FastReplay();
};
} // namespace sim
} // namespace td

View File

@@ -0,0 +1,27 @@
#pragma once
#include <td/game/World.h>
#include <td/protocol/command/Commands.h>
namespace td {
namespace sim {
class CommandApply : public protocol::CommandHandler {
private:
const game::World& m_World;
WorldSnapshot& m_Snapshot;
public:
CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot);
virtual void Handle(const protocol::commands::EndCommand& a_End) override;
virtual void Handle(const protocol::commands::PlaceTowerCommand& a_PlaceTower) override;
virtual void Handle(const protocol::commands::PlayerJoinCommand& a_PlayerJoin) override;
virtual void Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) override;
virtual void Handle(const protocol::commands::TeamChangeCommand& a_TeamChange) override;
virtual void Handle(const protocol::commands::UpgradeTowerCommand& a_UpgradeTower) override;
virtual void Handle(const protocol::commands::UseItemCommand& a_UseItem) override;
};
} // namespace sim
} // namespace td

View File

@@ -0,0 +1,31 @@
#pragma once
#include <optional>
#include <td/protocol/command/Commands.h>
#include <td/protocol/packet/Packets.h>
namespace td {
namespace game {
class GameHistory {
private:
using HistorySizeType = StepsType;
std::vector<std::optional<protocol::LockStep>> m_History;
public:
GameHistory();
void SetLockStep(HistorySizeType a_Index, protocol::LockStep&& a_LockStep);
const protocol::LockStep& GetLockStep(HistorySizeType a_Index) const;
bool HasLockStep(HistorySizeType a_Index) const;
void FromPacket(td::protocol::pdata::LockSteps&& a_Steps);
td::protocol::packets::LockStepsPacket ToPacket(HistorySizeType a_StartIndex);
};
} // namespace game
} // namespace td

View File

@@ -0,0 +1,22 @@
#pragma once
#include <td/game/World.h>
namespace td {
namespace sim {
// TODO: OnEnd signal
class ServerSimulation {
private:
game::World& m_World;
std::uint64_t m_StepTime;
std::uint64_t m_CurrentTime;
public:
ServerSimulation(game::World& a_World, std::uint64_t a_StepTime);
void Update();
};
} // namespace sim
} // namespace td

View File

@@ -0,0 +1,18 @@
#pragma once
#include <td/game/WorldTypes.h>
#include <td/game/Mobs.h>
namespace td {
namespace sim {
struct WorldSnapshot {
game::MobList m_Mobs;
game::TowerList m_Towers;
game::TeamList m_Teams;
};
} // namespace sim
} // namespace td

View File

@@ -0,0 +1,41 @@
#pragma once
#include <td/protocol/command/Commands.h>
#include <td/simulation/WorldSnapshot.h>
namespace td {
namespace game {
class World;
}
namespace sim {
class IWorldSystem {
public:
virtual void Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta) = 0;
virtual ~IWorldSystem() = default;
};
class WorldTicker {
private:
std::vector<std::unique_ptr<IWorldSystem>> m_Systems;
public:
WorldTicker();
WorldSnapshot NextStep(
const game::World& a_World, WorldSnapshot& a_PreviousState, const protocol::LockStep& a_LockStep, FpFloat a_Delta);
private:
void ApplySteps(const game::World& a_World, WorldSnapshot& a_State, const protocol::LockStep& a_LockStep);
void Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta);
WorldSnapshot CreateNext(WorldSnapshot& a_PreviousState);
template <typename T>
void AddSystem() {
m_Systems.push_back(std::make_unique<T>());
}
};
} // namespace sim
} // namespace td

View File

@@ -0,0 +1,14 @@
#pragma once
#include <td/simulation/WorldTicker.h>
namespace td {
namespace sim {
class EntityMove : public IWorldSystem {
public:
virtual void Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta) override;
};
} // namespace sim
} // namespace td