Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions include/game/GameLogic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

#include <cmath>
#include <memory>
#include <unordered_map>

#include <glm/glm.hpp>
#include <nlohmann/json.hpp>

// #include "config/ConfigManager.hpp"
// #include "logging/Logger.hpp"
// #include "network/ConnectionManager.hpp"
// #include "database/DbManager.hpp"
#include "network/PredictionSystem.hpp"

#include "game/LogicCore.hpp"
#include "game/PlayerManager.hpp"
#include "game/InventorySystem.hpp"
#include "game/LootTableManager.hpp"
//#include "game/MobSystem.hpp"
#include "game/SkillSystem.hpp"
#include "game/QuestManager.hpp"
#include "game/EntityManager.hpp"
Expand Down Expand Up @@ -90,6 +87,7 @@ class GameLogic : public LogicCore
void HandleCollisionCheck(uint64_t sessionId, const nlohmann::json& data);
void HandleEntitySpawnRequest(uint64_t sessionId, const nlohmann::json& data);
void HandleFamiliarCommand(uint64_t sessionId, const nlohmann::json& data);
void HandlePlayerState(uint64_t sessionId, const std::vector<uint8_t>& data);

// Message handling
void HandleMessage(uint64_t sessionId, const nlohmann::json& message);
Expand All @@ -99,16 +97,24 @@ class GameLogic : public LogicCore
void OnPlayerDisconnected(uint64_t sessionId);

// Broadcasting
void BroadcastBinaryToNearbyPlayers(const glm::vec3& position, uint16_t messageType,
void BroadcastToNearbyPlayers(const glm::vec3& position, uint16_t messageType,
const std::vector<uint8_t>& data, float radius = 50.0f);
void BroadcastToNearbyOnlinePlayers(const glm::vec3& position, uint16_t messageType,
const std::vector<uint8_t>& data, float radius = 50.0f);
void BroadcastToNearbyPlayers(const glm::vec3& position, const nlohmann::json& message, float radius = 50.0f);
void SyncNearbyEntitiesToPlayer(uint64_t sessionId, const glm::vec3& position);

// Helper broadcast methods
void BroadcastToAllPlayers(const nlohmann::json& message);
void BroadcastToAllPlayersBinary(uint16_t messageType, const std::vector<uint8_t>& data);
void BroadcastToPlayers(const std::vector<uint64_t>& sessionIds, const nlohmann::json& message);

// Broadcast entity spawn to nearby players
void BroadcastEntitySpawn(uint64_t entityId, EntityType type, const glm::vec3& position,
float yaw, const std::string& name);
void SendPositionCorrection(uint64_t sessionId, const glm::vec3& position, const glm::vec3& velocity);
void BroadcastPlayerState(uint64_t playerId, const ServerState& state);
void BroadcastEntityDespawn(uint64_t entityId, const glm::vec3& position);

private:
GameLogic();
~GameLogic();
Expand All @@ -125,6 +131,9 @@ class GameLogic : public LogicCore
// Connection manager for broadcasting
std::shared_ptr<ConnectionManager> connectionManager_;

std::unordered_map<uint64_t, PredictionSystem> playerPrediction_;
std::mutex predictionMutex_;

// Thread functions
void GameLoop();
void SpawnerLoop();
Expand Down
6 changes: 6 additions & 0 deletions include/game/Player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,16 @@ class Player : public GameEntity {
nlohmann::json JsonGetInventory() const;
nlohmann::json ToJson() const;

// =============== Movement state getters/setters ===============
bool IsOnGround() const { return onGround_; }
void SetOnGround(bool g) { onGround_ = g; }

private:
uint64_t id_;
std::string username_;

bool onGround_{true};

//struct Position {float x, y, z;} position_;
std::chrono::system_clock::time_point last_movement_;

Expand Down
2 changes: 2 additions & 0 deletions include/network/GameServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "network/WebSocketProtocol.hpp"
#include "network/WebSocketSession.hpp"

#include "game/GameLogic.hpp"

class GameServer {
public:
GameServer(const WorkerGroupConfig& groupConfig, const ConfigManager& globalConfig);
Expand Down
5 changes: 5 additions & 0 deletions include/network/GameSession.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ class GameSession : public IConnection, public std::enable_shared_from_this<Game
const glm::vec3& velocity, uint32_t last_input_id);
void SendPositionCorrection(const glm::vec3& position, const glm::vec3& velocity);

void SetPlayerStateHandler(std::function<void(const ClientInput&)> handler);

private:
// Core networking
asio::ip::tcp::socket socket_;
Expand Down Expand Up @@ -399,6 +401,8 @@ class GameSession : public IConnection, public std::enable_shared_from_this<Game
// Queue management
size_t max_write_queue_size_{1000};

std::function<void(const ClientInput&)> player_state_handler_;

// Private methods
void StartHeartbeat();
void CheckHeartbeat();
Expand Down Expand Up @@ -429,5 +433,6 @@ class GameSession : public IConnection, public std::enable_shared_from_this<Game
asio::ip::tcp::socket& GetSocket();
const asio::ip::tcp::socket& GetSocket() const;
void HandleNetworkError(std::error_code ec);
void SetupDefaultHandlers();
};

60 changes: 30 additions & 30 deletions include/network/PredictionSystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ struct ClientInput {
bool jumping{false};
bool crouching{false};
bool sprinting{false};

// Serialization
std::vector<uint8_t> Serialize() const;
static ClientInput Deserialize(const uint8_t* data, size_t length);

// Validity check
bool IsValid() const { return input_id > 0; }
};
Expand All @@ -30,85 +30,85 @@ struct ServerState {
glm::vec3 velocity;
glm::vec3 rotation;
bool on_ground{true};

// Serialization
std::vector<uint8_t> Serialize() const;
static ServerState Deserialize(const uint8_t* data, size_t length);

// Interpolation
static ServerState Interpolate(const ServerState& a, const ServerState& b, float t);
};

class PredictionSystem {
public:
PredictionSystem();

// Client-side methods
void StoreClientInput(const ClientInput& input);
ServerState PredictPosition(uint64_t current_time) const;

// Server-side methods
void StoreServerState(const ServerState& state);
std::vector<ClientInput> GetUnprocessedInputs(uint32_t last_processed) const;

// Reconciliation
struct ReconciliationResult {
bool needs_correction{false};
ServerState corrected_state;
std::vector<uint32_t> processed_inputs;
};

ReconciliationResult ReconcileWithServer(const ServerState& server_state);

// State management
ServerState GetLastConfirmedState() const { return last_confirmed_state_; }
ServerState GetLatestPredictedState() const { return latest_predicted_state_; }

// Input history
const std::deque<ClientInput>& GetInputHistory() const { return input_history_; }

// Clear history
void Clear();

// Statistics
struct PredictionStats {
uint32_t total_predictions{0};
uint32_t corrections_sent{0};
uint32_t corrections_received{0};
float average_correction_distance{0.0f};
uint64_t last_correction_time{0};

void Reset();
std::string ToString() const;
};

const PredictionStats& GetStats() const { return stats_; }


// Helper methods
ServerState SimulateMovement(const ServerState& start_state,
const std::vector<ClientInput>& inputs,
float delta_time) const;

ServerState ApplyInput(const ServerState& state, const ClientInput& input, float delta_time) const;

private:
mutable std::mutex mutex_;

// Input history (client-side)
std::deque<ClientInput> input_history_;
static constexpr size_t MAX_INPUT_HISTORY = 1000;

// Server state history
std::deque<ServerState> server_state_history_;
static constexpr size_t MAX_STATE_HISTORY = 100;

// Current states
ServerState last_confirmed_state_;
mutable ServerState latest_predicted_state_;

// Statistics
PredictionStats stats_;

// Helper methods
ServerState SimulateMovement(const ServerState& start_state,
const std::vector<ClientInput>& inputs,
float delta_time) const;

ServerState ApplyInput(const ServerState& state, const ClientInput& input, float delta_time) const;


// Physics constants
static constexpr float GRAVITY = -9.81f;
static constexpr float MAX_SPEED = 10.0f;
Expand All @@ -121,18 +121,18 @@ class PredictionSystem {
class InputBuffer {
public:
InputBuffer(size_t max_size = 1000);

void AddInput(const ClientInput& input);
std::vector<ClientInput> GetOrderedInputs() const;
ClientInput GetNextInput() const;
bool HasInputs() const { return !inputs_.empty(); }
void Clear();
size_t Size() const { return inputs_.size(); }

private:
mutable std::mutex mutex_;
std::vector<ClientInput> inputs_;
size_t max_size_;

void SortAndTrim();
};
10 changes: 9 additions & 1 deletion include/network/WebSocketSession.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "logging/Logger.hpp"

#include "network/IConnection.hpp"
#include "network/BinaryProtocol.hpp"
#include "network/WebSocketProtocol.hpp"

class WebSocketSession : public IConnection, public std::enable_shared_from_this<WebSocketSession> {
Expand Down Expand Up @@ -53,6 +54,10 @@ class WebSocketSession : public IConnection, public std::enable_shared_from_this

std::string GetRemoteAddress() const override;

using BinaryMessageHandler = std::function<void(uint16_t, const std::vector<uint8_t>&)>;
void SetBinaryMessageHandler(BinaryMessageHandler handler);
void SetDefaultBinaryMessageHandler(BinaryMessageHandler handler);

private:
WebSocketProtocol::WebSocketConnection::Pointer wsConn_;
uint64_t sessionId_;
Expand All @@ -77,7 +82,10 @@ class WebSocketSession : public IConnection, public std::enable_shared_from_this
mutable std::mutex propertiesMutex_;
std::map<std::string, std::string> properties_;

BinaryMessageHandler binary_handler_;
BinaryMessageHandler default_binary_handler_;

// Internal helpers
void OnMessage(const WebSocketProtocol::WebSocketMessage& msg);
void OnClose(uint16_t code, const std::string& reason);
};
};
Loading
Loading