Commit ebbbc5b0 authored by Hubert Denkmair's avatar Hubert Denkmair

stand vom letzten wochenende

parent 797510c4
......@@ -8,3 +8,6 @@
path = lib/uWebSockets
url = git@git.bingo-ev.de:GPN18Programmierspiel/uWebSockets.git
branch = cmake
[submodule "lib/nlohmann"]
path = lib/nlohmann
url = https://github.com/nlohmann/json.git
Subproject commit 46ec2fddf8774af2f9368bf563dd6e32fa91d77e
......@@ -7,7 +7,8 @@ include_directories(${EIGEN3_INCLUDE_DIR})
include_directories(
${PROJECT_NAME}
../lib/uWebSockets/src
../lib/msgpack-c/include/
../lib/msgpack-c/include
../lib/nlohmann/single_include
)
add_executable(
......@@ -15,7 +16,9 @@ add_executable(
main.cpp
RelayServer.h RelayServer.cpp
TcpProtocol.h TcpProtocol.cpp
SpatialMap.h MsgPackProtocol.h
SpatialMap.h
MsgPackProtocol.h MsgPackProtocol.cpp
JsonProtocol.h JsonProtocol.cpp
WebsocketConnection.h WebsocketConnection.cpp
)
......
#include "JsonProtocol.h"
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::Message &msg)
{
switch (msg.messageType)
{
case MESSAGE_TYPE_GAME_INFO:
to_json(j, *static_cast<const GameInfoMessage*>(&msg));
break;
case MESSAGE_TYPE_WORLD_UPDATE:
to_json(j, *static_cast<const WorldUpdateMessage*>(&msg));
break;
case MESSAGE_TYPE_TICK:
to_json(j, *static_cast<const TickMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_SPAWN:
to_json(j, *static_cast<const BotSpawnMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_KILL:
to_json(j, *static_cast<const BotKillMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_MOVE:
to_json(j, *static_cast<const BotMoveMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_SPAWN:
to_json(j, *static_cast<const FoodSpawnMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_CONSUME:
to_json(j, *static_cast<const FoodConsumeMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_DECAY:
to_json(j, *static_cast<const FoodDecayMessage*>(&msg));
break;
case MESSAGE_TYPE_PLAYER_INFO:
to_json(j, *static_cast<const PlayerInfoMessage*>(&msg));
break;
}
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::GameInfoMessage &msg)
{
j = json {
{"t", "GameInfo"},
{"world_size_x", msg.world_size_x},
{"world_size_y", msg.world_size_y},
{"food_decay_per_frame", msg.food_decay_per_frame}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::WorldUpdateMessage &msg)
{
json bots = json::object();
for (auto& bot: msg.bots)
{
bots[std::to_string(bot.guid)] = bot;
}
json food = json::object();
for (auto& item: msg.food)
{
food[std::to_string(item.guid)] = item;
}
j = json {
{"t", "WorldUpdate"},
{"bots", bots},
{"food", food}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::BotItem &item)
{
j = json {
{"id", item.guid},
{"name", item.name},
{"segment_radius", item.segment_radius},
{"color", item.color},
{"snake_segments", item.segments},
{"heading", 0}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::SnakeSegmentItem &item)
{
j = json{
{"pos_x", item.pos().x()},
{"pos_y", item.pos().y()}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::FoodItem &item)
{
j = json {
{"id", item.guid},
{"pos_x", item.pos().x()},
{"pos_y", item.pos().y()},
{"value", item.value}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::TickMessage &msg)
{
j = json {
{"t", "Tick"},
{"frame_id", msg.frame_id}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::BotSpawnMessage &msg)
{
j = json {
{"t", "BotSpawn"},
{"bot", msg.bot}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::BotKillMessage &msg)
{
j = json {
{"t", "BotKill"},
{"killer_id", msg.killer_id},
{"victim_id", msg.victim_id}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::BotMoveMessage &msg)
{
j = json {
{"t", "BotMove"},
{"items", msg.items}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::BotMoveItem &item)
{
j = json {
{"bot_id", item.bot_id},
{"segment_data", item.new_segments},
{"length", item.current_length},
{"segment_radius", item.current_segment_radius}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::FoodSpawnMessage &msg)
{
j = json {
{"t", "FoodSpawn"},
{"items", msg.new_food}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::FoodConsumeMessage &msg)
{
j = json {
{"t", "FoodConsume"},
{"items", msg.items}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::FoodConsumeItem &item)
{
j = json {
{"food_id", item.food_id},
{"bot_id", item.bot_id}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::FoodDecayMessage &msg)
{
j = json {
{"t", "FoodDecay"},
{"items", msg.food_ids}
};
}
void MsgPackProtocol::to_json(nlohmann::json &j, const MsgPackProtocol::PlayerInfoMessage &msg)
{
j = json {
{"t", "PlayerInfo"},
{"player_id", msg.player_id}
};
}
#pragma once
#include "MsgPackProtocol.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace MsgPackProtocol
{
void to_json(json& j, const Message& msg);
void to_json(json& j, const GameInfoMessage& msg);
void to_json(json& j, const WorldUpdateMessage& msg);
void to_json(json& j, const BotItem& item);
void to_json(json& j, const SnakeSegmentItem& item);
void to_json(json& j, const FoodItem& item);
void to_json(json& j, const TickMessage& msg);
void to_json(json& j, const BotSpawnMessage& msg);
void to_json(json& j, const BotKillMessage& msg);
void to_json(json& j, const BotMoveMessage& msg);
void to_json(json& j, const BotMoveItem& item);
void to_json(json& j, const FoodSpawnMessage& msg);
void to_json(json& j, const FoodConsumeMessage& msg);
void to_json(json& j, const FoodConsumeItem& item);
void to_json(json& j, const FoodDecayMessage& msg);
void to_json(json& j, const PlayerInfoMessage& msg);
}
#include "MsgPackProtocol.h"
void MsgPackProtocol::pack(msgpack::sbuffer &buf, const Message &msg)
{
switch (msg.messageType)
{
case MESSAGE_TYPE_GAME_INFO:
msgpack::pack(buf, *static_cast<const GameInfoMessage*>(&msg));
break;
case MESSAGE_TYPE_WORLD_UPDATE:
msgpack::pack(buf, *static_cast<const WorldUpdateMessage*>(&msg));
break;
case MESSAGE_TYPE_TICK:
msgpack::pack(buf, *static_cast<const TickMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_SPAWN:
msgpack::pack(buf, *static_cast<const BotSpawnMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_KILL:
msgpack::pack(buf, *static_cast<const BotKillMessage*>(&msg));
break;
case MESSAGE_TYPE_BOT_MOVE:
msgpack::pack(buf, *static_cast<const BotMoveMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_SPAWN:
msgpack::pack(buf, *static_cast<const FoodSpawnMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_CONSUME:
msgpack::pack(buf, *static_cast<const FoodConsumeMessage*>(&msg));
break;
case MESSAGE_TYPE_FOOD_DECAY:
msgpack::pack(buf, *static_cast<const FoodDecayMessage*>(&msg));
break;
case MESSAGE_TYPE_PLAYER_INFO:
msgpack::pack(buf, *static_cast<const PlayerInfoMessage*>(&msg));
break;
}
}
......@@ -2,12 +2,11 @@
#include <vector>
#include <msgpack.hpp>
#include "types.h"
namespace MsgPackProtocol
{
enum
typedef enum
{
MESSAGE_TYPE_GAME_INFO = 0x00,
MESSAGE_TYPE_WORLD_UPDATE = 0x01,
......@@ -23,7 +22,7 @@ namespace MsgPackProtocol
MESSAGE_TYPE_FOOD_DECAY = 0x32,
MESSAGE_TYPE_PLAYER_INFO = 0xF0,
};
} MessageType;
static constexpr const uint8_t PROTOCOL_VERSION = 1;
......@@ -54,8 +53,9 @@ namespace MsgPackProtocol
struct Message
{
MessageType messageType;
Message(MessageType type) : messageType(type) {}
virtual ~Message() = default;
virtual void pack(msgpack::sbuffer& buf) const = 0;
};
struct GameInfoMessage : public Message
......@@ -63,32 +63,32 @@ namespace MsgPackProtocol
double world_size_x = 0;
double world_size_y = 0;
double food_decay_per_frame = 0;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
GameInfoMessage(): Message(MESSAGE_TYPE_GAME_INFO) {}
};
struct PlayerInfoMessage : public Message
{
guid_t player_id; // id der von dieser Verbindung gesteuerten Schlange
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
PlayerInfoMessage(): Message(MESSAGE_TYPE_PLAYER_INFO) {}
};
struct TickMessage : public Message
{
guid_t frame_id; // frame counter since start of server
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
TickMessage(): Message(MESSAGE_TYPE_TICK) {}
};
struct WorldUpdateMessage : public Message
{
std::vector<BotItem> bots;
std::vector<FoodItem> food;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
WorldUpdateMessage(): Message(MESSAGE_TYPE_WORLD_UPDATE) {}
};
struct BotSpawnMessage : public Message
{
BotItem bot;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
BotSpawnMessage(): Message(MESSAGE_TYPE_BOT_SPAWN) {}
};
struct BotMoveItem
......@@ -102,20 +102,20 @@ namespace MsgPackProtocol
struct BotMoveMessage : public Message
{
std::vector<BotMoveItem> items;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
BotMoveMessage(): Message(MESSAGE_TYPE_BOT_MOVE) {}
};
struct BotKillMessage : public Message
{
guid_t killer_id;
guid_t victim_id; // victim is deleted in this frame
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
BotKillMessage(): Message(MESSAGE_TYPE_BOT_KILL) {}
};
struct FoodSpawnMessage : public Message
{
std::vector<FoodItem> new_food;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
FoodSpawnMessage(): Message(MESSAGE_TYPE_FOOD_SPAWN) {}
};
struct FoodConsumeItem
......@@ -127,15 +127,16 @@ namespace MsgPackProtocol
struct FoodConsumeMessage : public Message
{
std::vector<FoodConsumeItem> items;
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
FoodConsumeMessage(): Message(MESSAGE_TYPE_FOOD_CONSUME) {}
};
struct FoodDecayMessage : public Message
{
std::vector<guid_t> food_ids; // food is deleted in this frame
void pack(msgpack::sbuffer& buf) const override { msgpack::pack(buf, *this); }
FoodDecayMessage(): Message(MESSAGE_TYPE_FOOD_DECAY) {}
};
void pack(msgpack::sbuffer& buf, const Message& msg);
}
namespace msgpack {
......
......@@ -19,7 +19,7 @@ void TcpProtocol::SetFrameCompleteCallback(TcpProtocol::FrameCompleteCallback ca
}
bool TcpProtocol::Read(int socket)
{
{
ssize_t bytesRead = read(socket, &_buf[_bufTail], _buf.size()-_bufTail);
if (bytesRead<=0) { return false; }
......@@ -82,8 +82,12 @@ void TcpProtocol::OnMessageReceived(const char* data, size_t count)
break;
case MsgPackProtocol::MESSAGE_TYPE_BOT_MOVE:
OnBotMoveReceived(obj.get().as<MsgPackProtocol::BotMoveMessage>());
{
auto msg = std::make_unique<MsgPackProtocol::BotMoveMessage>();
obj.get().convert(*msg);
OnBotMoveReceived(std::move(msg));
break;
}
case MsgPackProtocol::MESSAGE_TYPE_FOOD_SPAWN:
OnFoodSpawnReceived(obj.get().as<MsgPackProtocol::FoodSpawnMessage>());
......@@ -101,15 +105,16 @@ void TcpProtocol::OnMessageReceived(const char* data, size_t count)
void TcpProtocol::OnGameInfoReceived(const MsgPackProtocol::GameInfoMessage& msg)
{
_segments = std::make_unique<SnakeSegmentMap>(msg.world_size_x, msg.world_size_y, 1000);
_foodMap = std::make_unique<FoodMap>(msg.world_size_x, msg.world_size_y, 1000);
//_segments = std::make_unique<SnakeSegmentMap>(msg.world_size_x, msg.world_size_y, 1000);
//_foodMap = std::make_unique<FoodMap>(msg.world_size_x, msg.world_size_y, 1000);
_gameInfo = msg;
}
void TcpProtocol::OnWorldUpdateReceived(const MsgPackProtocol::WorldUpdateMessage &msg)
{
_bots = msg.bots;
_food = msg.food;
_worldUpdate = msg;
_bots = _worldUpdate.bots;
_food = _worldUpdate.food;
}
void TcpProtocol::OnTickReceived(const MsgPackProtocol::TickMessage &msg)
......@@ -151,6 +156,7 @@ void TcpProtocol::OnBotSpawnReceived(const MsgPackProtocol::BotSpawnMessage &msg
{
_pendingMessages.push_back(std::make_unique<MsgPackProtocol::BotSpawnMessage>(msg));
_bots.push_back(msg.bot);
_bots.back().segments.reserve(100);
}
void TcpProtocol::OnBotKillReceived(const MsgPackProtocol::BotKillMessage& msg)
......@@ -159,10 +165,9 @@ void TcpProtocol::OnBotKillReceived(const MsgPackProtocol::BotKillMessage& msg)
_bots.erase(std::remove_if(_bots.begin(), _bots.end(), [msg](const BotItem& bot) { return bot.guid == msg.victim_id; }));
}
void TcpProtocol::OnBotMoveReceived(const MsgPackProtocol::BotMoveMessage &msg)
void TcpProtocol::OnBotMoveReceived(std::unique_ptr<MsgPackProtocol::BotMoveMessage> msg)
{
_pendingMessages.push_back(std::make_unique<MsgPackProtocol::BotMoveMessage>(msg));
for (auto& item: msg.items)
for (auto& item: msg->items)
{
auto it = std::find_if(_bots.begin(), _bots.end(), [item](const BotItem& bot) { return bot.guid == item.bot_id; });
if (it == _bots.end()) { return; }
......@@ -172,5 +177,6 @@ void TcpProtocol::OnBotMoveReceived(const MsgPackProtocol::BotMoveMessage &msg)
bot.segments.resize(item.current_length);
bot.segment_radius = item.current_segment_radius;
}
_pendingMessages.push_back(std::move(msg));
}
......@@ -44,11 +44,10 @@ class TcpProtocol
MsgPackProtocol::WorldUpdateMessage _worldUpdate;
std::vector<FoodItem>& _food;
std::vector<BotItem>& _bots;
std::unique_ptr<FoodMap> _foodMap;
std::vector<std::unique_ptr<MsgPackProtocol::Message>> _pendingMessages;
std::unique_ptr<SnakeSegmentMap> _segments;
//std::unique_ptr<FoodMap> _foodMap;
//std::unique_ptr<SnakeSegmentMap> _segments;
void OnMessageReceived(const char *data, size_t count);
......@@ -62,5 +61,5 @@ class TcpProtocol
void OnBotSpawnReceived(const MsgPackProtocol::BotSpawnMessage& msg);
void OnBotKillReceived(const MsgPackProtocol::BotKillMessage &msg);
void OnBotMoveReceived(const MsgPackProtocol::BotMoveMessage &msg);
void OnBotMoveReceived(std::unique_ptr<MsgPackProtocol::BotMoveMessage> msg);
};
#include "WebsocketConnection.h"
#include "TcpProtocol.h"
#include "MsgPackProtocol.h"
#include "JsonProtocol.h"
WebsocketConnection::WebsocketConnection(uWS::WebSocket<uWS::SERVER> *websocket)
: _websocket(websocket)
......@@ -19,20 +20,17 @@ void WebsocketConnection::FrameComplete(uint64_t frame_id, const TcpProtocol &pr
msgpack::sbuffer buf;
for (auto& msg: proto.GetPendingMessages())
{
buf.clear();
msg->pack(buf);
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
sendString(json(*msg).dump());
}
}
void WebsocketConnection::sendInitialData(const TcpProtocol &proto)
{
msgpack::sbuffer buf;
buf.clear();
proto.GetGameInfo().pack(buf);
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
sendString(json(proto.GetGameInfo()).dump());
sendString(json(proto.GetWorldUpdate()).dump());
}
buf.clear();
proto.GetWorldUpdate().pack(buf);
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
void WebsocketConnection::sendString(std::string data)
{
_websocket->send(data.data(), data.length(), uWS::OpCode::TEXT);
}
......@@ -9,6 +9,7 @@ class WebsocketConnection
public:
WebsocketConnection(uWS::WebSocket<uWS::SERVER> *websocket);
void FrameComplete(uint64_t frame_id, const TcpProtocol& proto);
void sendString(std::string data);
private:
uWS::WebSocket<uWS::SERVER> *_websocket;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment