143 lines
3.6 KiB
C++
143 lines
3.6 KiB
C++
#pragma once
|
|
#include <boost/beast/core.hpp>
|
|
#include <boost/beast/websocket.hpp>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <mutex>
|
|
#include <queue>
|
|
#include <unordered_set>
|
|
#include <Eigen/Dense>
|
|
#include "../src/network/ClientState.h"
|
|
#define _USE_MATH_DEFINES
|
|
#include <math.h>
|
|
|
|
namespace beast = boost::beast;
|
|
namespace http = beast::http;
|
|
namespace websocket = beast::websocket;
|
|
namespace net = boost::asio;
|
|
using tcp = net::ip::tcp;
|
|
static constexpr float kWorldZOffset = 45000.0f;
|
|
static const Eigen::Vector3f kWorldOffset(0.0f, 0.0f, kWorldZOffset);
|
|
|
|
static constexpr float kShipRadius = 15.0f;
|
|
static constexpr float kSpawnShipMargin = 25.0f;
|
|
static constexpr float kSpawnBoxMargin = 15.0f;
|
|
static constexpr float kSpawnZJitter = 60.0f;
|
|
|
|
std::vector<std::string> split(const std::string& s, char delimiter);
|
|
|
|
struct DeathInfo {
|
|
int targetId = -1;
|
|
uint64_t serverTime = 0;
|
|
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
|
int killerId = -1;
|
|
};
|
|
|
|
|
|
struct ServerBox {
|
|
Eigen::Vector3f position;
|
|
Eigen::Matrix3f rotation;
|
|
float collisionRadius = 2.0f;
|
|
bool destroyed = false;
|
|
};
|
|
|
|
struct Projectile {
|
|
int shooterId = -1;
|
|
uint64_t spawnMs = 0;
|
|
Eigen::Vector3f pos;
|
|
Eigen::Vector3f vel;
|
|
float lifeMs = PROJECTILE_LIFE;
|
|
};
|
|
|
|
struct BoxDestroyedInfo {
|
|
int boxIndex = -1;
|
|
uint64_t serverTime = 0;
|
|
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
|
int destroyedBy = -1;
|
|
};
|
|
|
|
class Server;
|
|
|
|
class Session : public std::enable_shared_from_this<Session> {
|
|
Server& server_;
|
|
websocket::stream<beast::tcp_stream> ws_;
|
|
beast::flat_buffer buffer_;
|
|
int id_;
|
|
bool is_writing_ = false;
|
|
std::queue<std::shared_ptr<std::string>> writeQueue_;
|
|
std::mutex writeMutex_;
|
|
|
|
|
|
public:
|
|
ClientStateInterval timedClientStates;
|
|
bool joined_ = false;
|
|
std::chrono::system_clock::time_point lastReceivedTime_;
|
|
|
|
bool hasReservedSpawn_ = false;
|
|
Eigen::Vector3f reservedSpawn_ = Eigen::Vector3f(0.0f, 0.0f, kWorldZOffset);
|
|
|
|
std::string nickname = "Player";
|
|
int shipType = 0;
|
|
|
|
Session(Server& server, tcp::socket&& socket, int id);
|
|
int get_id() const;
|
|
bool hasSpawnReserved() const;
|
|
const Eigen::Vector3f& reservedSpawn() const;
|
|
bool fetchStateAtTime(std::chrono::system_clock::time_point targetTime, ClientState& outState) const;
|
|
void send_message(const std::string& msg);
|
|
void run();
|
|
bool IsMessageValid(const std::string& fullMessage);
|
|
bool is_timed_out(std::chrono::system_clock::time_point now) const;
|
|
void force_disconnect();
|
|
|
|
private:
|
|
void sendBoxesToClient();
|
|
public:
|
|
void init();
|
|
ClientState get_latest_state(std::chrono::system_clock::time_point now);
|
|
void doWrite();
|
|
private:
|
|
|
|
void do_read();
|
|
void process_message(const std::string& msg);
|
|
};
|
|
|
|
class Server
|
|
{
|
|
public:
|
|
tcp::acceptor& acceptor_;
|
|
net::io_context& ioc_;
|
|
net::steady_timer timer;
|
|
std::vector<BoxDestroyedInfo> g_boxDestructions;
|
|
std::mutex g_boxDestructions_mutex;
|
|
|
|
std::vector<ServerBox> g_serverBoxes;
|
|
std::mutex g_boxes_mutex;
|
|
|
|
std::vector<std::shared_ptr<Session>> g_sessions;
|
|
std::mutex g_sessions_mutex;
|
|
|
|
std::vector<Projectile> g_projectiles;
|
|
std::mutex g_projectiles_mutex;
|
|
|
|
std::unordered_set<int> g_dead_players;
|
|
std::mutex g_dead_mutex;
|
|
|
|
int next_id = 1000;
|
|
|
|
std::vector<ServerBox> generateServerBoxes(int count);
|
|
public:
|
|
Server(tcp::acceptor& acceptor, net::io_context& ioc);
|
|
|
|
void broadcastToAll(const std::string& message);
|
|
void broadcastToAllExceptId(const std::string& message, int id);
|
|
void createProjectile(int id, Eigen::Vector3f pos, Eigen::Quaternionf dir, float velocity);
|
|
void update_world();
|
|
Eigen::Vector3f PickSafeSpawnPos(int forPlayerId);
|
|
// Caller must hold g_boxes_mutex
|
|
Eigen::Vector3f PickSafeBoxPos(int skipIdx);
|
|
void init();
|
|
void accept();
|
|
};
|