begin serversimulation

This commit is contained in:
2025-08-03 18:20:21 +02:00
parent c0a560a16e
commit 731c742346
6 changed files with 58 additions and 25 deletions

View File

@@ -21,10 +21,8 @@ struct UpgradeTower {
sp::BitField<std::uint8_t, 4> m_Upgrade; sp::BitField<std::uint8_t, 4> m_Upgrade;
}; };
using EntityTypeInt = std::uint8_t;
struct SpawnTroop { struct SpawnTroop {
sp::BitField<EntityTypeInt, 5> m_Type; sp::BitField<EntityType, 5> m_Type;
sp::BitField<std::uint8_t, 3> m_Level; sp::BitField<std::uint8_t, 3> m_Level;
EntityCoords m_Position; EntityCoords m_Position;
PlayerID m_Sender; PlayerID m_Sender;

View File

@@ -95,6 +95,16 @@ struct WorldData {
game::ChunkList m_Chunks; game::ChunkList m_Chunks;
}; };
struct SpawnTroop {
sp::BitField<EntityType, 5> m_Type;
sp::BitField<std::uint8_t, 3> m_Level;
};
struct PlaceTower {
TowerType m_Type;
TowerCoords m_Position;
};
} // namespace pdata } // namespace pdata
} // namespace protocol } // namespace protocol
} // namespace td } // namespace td

View File

@@ -9,7 +9,8 @@ namespace sim {
using GameHistory = std::vector<td::protocol::LockStep>; using GameHistory = std::vector<td::protocol::LockStep>;
using GameBuffer = std::vector<std::optional<td::protocol::LockStep>>; using GameBuffer = std::vector<std::optional<td::protocol::LockStep>>;
class RealTimeSimulation { // TODO: OnEnd signal
class ClientSimulation : public protocol::PacketHandler {
private: private:
std::uint64_t m_StepTime; std::uint64_t m_StepTime;
game::World& m_World; game::World& m_World;
@@ -28,21 +29,21 @@ class RealTimeSimulation {
* \brief Replay constructor * \brief Replay constructor
* \param a_StepTime in ms * \param a_StepTime in ms
*/ */
RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime); ClientSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime);
/** /**
* \brief Live update constructor (continuous game updates) * \brief Live update constructor (continuous game updates)
* \param a_StepTime in ms * \param a_StepTime in ms
*/ */
RealTimeSimulation(game::World& a_World, std::uint64_t a_StepTime); ClientSimulation(game::World& a_World, std::uint64_t a_StepTime);
/** /**
* \return the progress [0-1] between two steps * \return the progress [0-1] between two steps
*/ */
float Update(); float Update();
void HandlePacket(const protocol::packets::LockStepsPacket& a_LockSteps); void Handle(const protocol::packets::LockStepsPacket& a_LockSteps) override;
void HandlePacket(const protocol::packets::PredictCommandPacket& a_Predict); void Handle(const protocol::packets::PredictCommandPacket& a_Predict) override;
private: private:
void Step(); void Step();

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

@@ -1,14 +1,14 @@
#include <iostream> #include <iostream>
#include <td/protocol/packet/PacketSerialize.h>
#include <fstream> #include <fstream>
#include <td/game/World.h> #include <td/game/World.h>
#include <td/input/Display.h> #include <td/input/Display.h>
#include <td/protocol/packet/PacketSerialize.h>
#include <td/protocol/packet/Packets.h> #include <td/protocol/packet/Packets.h>
#include <td/render/renderer/EntityRenderer.h> #include <td/render/renderer/EntityRenderer.h>
#include <td/render/renderer/TowerRenderer.h> #include <td/render/renderer/TowerRenderer.h>
#include <td/render/renderer/WorldRenderer.h> #include <td/render/renderer/WorldRenderer.h>
#include <td/simulation/RealTimeSimulation.h> #include <td/simulation/ClientSimulation.h>
#include <sp/common/DataBuffer.h> #include <sp/common/DataBuffer.h>
#include <sp/extensions/Compress.h> #include <sp/extensions/Compress.h>
@@ -59,8 +59,8 @@ td::game::World GetWorld() {
WorldApply wa(w); WorldApply wa(w);
td::protocol::PacketDispatcher d; td::protocol::PacketDispatcher d;
d.RegisterHandler(td::protocol::PacketID::WorldData, &wa);
d.RegisterHandler(td::protocol::PacketID::WorldHeader, &wa); d.RegisterHandler(td::protocol::PacketID::WorldHeader, &wa);
d.RegisterHandler(td::protocol::PacketID::WorldData, &wa);
d.Dispatch(*header); d.Dispatch(*header);
d.Dispatch(*data); d.Dispatch(*data);
@@ -83,7 +83,7 @@ td::sim::GameHistory GetCustomHistory() {
td::sim::GameHistory gh(MAX_COUNT); td::sim::GameHistory gh(MAX_COUNT);
auto spawn = td::protocol::CommandPtr( auto spawn = td::protocol::CommandPtr(
std::make_shared<td::protocol::commands::SpawnTroopCommand>(0, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0)); std::make_shared<td::protocol::commands::SpawnTroopCommand>(td::EntityType::Zombie, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0));
gh[0].push_back(spawn); gh[0].push_back(spawn);
auto tower = td::protocol::CommandPtr( auto tower = td::protocol::CommandPtr(
@@ -114,17 +114,17 @@ int main(int argc, char** argv) {
cam.SetCamPos({77, 7, 13}); cam.SetCamPos({77, 7, 13});
cam.UpdatePerspective(display.GetAspectRatio()); cam.UpdatePerspective(display.GetAspectRatio());
td::sim::RealTimeSimulation simulation(w, 50); td::sim::ClientSimulation simulation(w, 50);
display.OnKeyDown.Connect([&simulation](SDL_Keycode key) { display.OnKeyDown.Connect([&simulation](SDL_Keycode key) {
static int counter = 0; static int counter = 0;
if (key == SDLK_A) { if (key == SDLK_A) {
auto spawn = td::protocol::CommandPtr( auto spawn = td::protocol::CommandPtr(
std::make_shared<td::protocol::commands::SpawnTroopCommand>(0, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0)); std::make_shared<td::protocol::commands::SpawnTroopCommand>(td::EntityType::Zombie, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0));
std::array<td::protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps{}; std::array<td::protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps{};
steps[0].push_back(spawn); steps[0].push_back(spawn);
td::protocol::packets::LockStepsPacket packet{counter * LOCKSTEP_BUFFER_SIZE * 3, steps}; td::protocol::packets::LockStepsPacket packet{counter * LOCKSTEP_BUFFER_SIZE * 3, steps};
simulation.HandlePacket(packet); simulation.Handle(packet);
counter++; counter++;
} }
}); });

View File

@@ -1,18 +1,18 @@
#include <td/simulation/RealTimeSimulation.h> #include <td/simulation/ClientSimulation.h>
#include <chrono> #include <chrono>
namespace td { namespace td {
namespace sim { namespace sim {
const protocol::LockStep RealTimeSimulation::EMPTY_LOCKSTEP; const protocol::LockStep ClientSimulation::EMPTY_LOCKSTEP;
std::uint64_t GetTime() { std::uint64_t GetTime() {
return static_cast<std::uint64_t>( return static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count()); std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
} }
RealTimeSimulation::RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime) : ClientSimulation::ClientSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime) :
m_StepTime(a_StepTime), m_StepTime(a_StepTime),
m_World(a_World), m_World(a_World),
m_CurrentTime(0), m_CurrentTime(0),
@@ -27,7 +27,7 @@ RealTimeSimulation::RealTimeSimulation(game::World& a_World, GameHistory&& a_His
Step(); Step();
} }
RealTimeSimulation::RealTimeSimulation(game::World& a_World, std::uint64_t a_StepTime) : ClientSimulation::ClientSimulation(game::World& a_World, std::uint64_t a_StepTime) :
m_StepTime(a_StepTime), m_StepTime(a_StepTime),
m_World(a_World), m_World(a_World),
m_History(std::numeric_limits<std::uint16_t>::max()), m_History(std::numeric_limits<std::uint16_t>::max()),
@@ -39,7 +39,7 @@ RealTimeSimulation::RealTimeSimulation(game::World& a_World, std::uint64_t a_Ste
Step(); Step();
} }
float RealTimeSimulation::Update() { float ClientSimulation::Update() {
// TODO: handle freezes (m_CurrentTime > 2 * m_StepTime) // TODO: handle freezes (m_CurrentTime > 2 * m_StepTime)
m_CurrentTime += GetTime() - m_LastTime; m_CurrentTime += GetTime() - m_LastTime;
m_LastTime = GetTime(); m_LastTime = GetTime();
@@ -50,7 +50,7 @@ float RealTimeSimulation::Update() {
return (float)m_CurrentTime / (float)m_StepTime; return (float)m_CurrentTime / (float)m_StepTime;
} }
void RealTimeSimulation::Step() { void ClientSimulation::Step() {
const auto& step = m_History[m_CurrentStep]; const auto& step = m_History[m_CurrentStep];
if (step.has_value()) { if (step.has_value()) {
m_LastSnapshot = m_World.Tick(step.value(), FpFloat(m_StepTime) / FpFloat(1000)); m_LastSnapshot = m_World.Tick(step.value(), FpFloat(m_StepTime) / FpFloat(1000));
@@ -61,7 +61,7 @@ void RealTimeSimulation::Step() {
m_CurrentStep++; m_CurrentStep++;
} }
void RealTimeSimulation::HandlePacket(const protocol::packets::LockStepsPacket& a_LockSteps) { void ClientSimulation::Handle(const protocol::packets::LockStepsPacket& a_LockSteps) {
const auto& steps = a_LockSteps->m_LockSteps; const auto& steps = a_LockSteps->m_LockSteps;
for (std::size_t i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) { for (std::size_t i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) {
m_History[a_LockSteps->m_FirstFrameNumber + i] = steps[i]; m_History[a_LockSteps->m_FirstFrameNumber + i] = steps[i];
@@ -69,15 +69,17 @@ void RealTimeSimulation::HandlePacket(const protocol::packets::LockStepsPacket&
FastReplay(); FastReplay();
} }
void RealTimeSimulation::HandlePacket(const protocol::packets::PredictCommandPacket& a_Predict) {} void ClientSimulation::Handle(const protocol::packets::PredictCommandPacket& a_Predict) {
}
void RealTimeSimulation::FastForward(std::size_t a_Count) { void ClientSimulation::FastForward(std::size_t a_Count) {
for (std::size_t i = 0; i < a_Count; i++) { for (std::size_t i = 0; i < a_Count; i++) {
Step(); Step();
} }
} }
void RealTimeSimulation::FastReplay() { void ClientSimulation::FastReplay() {
if (m_LastValidStep >= m_CurrentStep) if (m_LastValidStep >= m_CurrentStep)
return; return;