TcpProtocol.cpp 4.58 KB
Newer Older
Hubert Denkmair's avatar
Hubert Denkmair committed
1
2
3
4
#include "TcpProtocol.h"
#include <stdint.h>
#include <unistd.h>
#include <array>
Hubert Denkmair's avatar
Hubert Denkmair committed
5
6
#include <msgpack.hpp>
#include <iostream>
Hubert Denkmair's avatar
Hubert Denkmair committed
7
8
9
10
11
12
13
14

void TcpProtocol::SetMessageReceivedCallback(TcpProtocol::MessageReceivedCallback callback)
{
	_messageReceivedCallback = callback;
}

bool TcpProtocol::Read(int socket)
{
15
	std::array<char, 8192> readbuf;
Hubert Denkmair's avatar
Hubert Denkmair committed
16
17
18
19
	ssize_t bytesRead = read(socket, readbuf.data(), readbuf.size());
	if (bytesRead<=0) { return false; }
	_buf.insert(_buf.end(), &readbuf[0], &readbuf[static_cast<size_t>(bytesRead)]);

Hubert Denkmair's avatar
Hubert Denkmair committed
20
	while (true)
Hubert Denkmair's avatar
Hubert Denkmair committed
21
	{
Hubert Denkmair's avatar
Hubert Denkmair committed
22
23
		if ((_awaitedSize==0) && (_buf.size() >= 4))
		{
24
			_awaitedSize = ntohl(*(reinterpret_cast<uint32_t*>(&_buf[0])));
Hubert Denkmair's avatar
Hubert Denkmair committed
25
26
27
28
29
30
31
32
33
34
35
36
37
			_buf.erase(_buf.begin(), _buf.begin()+4);
		}
		else if ((_awaitedSize>0) && (_buf.size() >= _awaitedSize))
		{
			std::vector<char> v(_buf.begin(), _buf.begin()+_awaitedSize);
			OnMessageReceived(v);
			_buf.erase(_buf.begin(), _buf.begin()+_awaitedSize);
			_awaitedSize = 0;
		}
		else
		{
			return true;
		}
Hubert Denkmair's avatar
Hubert Denkmair committed
38
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
39
40
41
42
43
44
45
}

void TcpProtocol::OnMessageReceived(std::vector<char> &data)
{
	_messageReceivedCallback(data);

	msgpack::object_handle obj;
46
	uint64_t version, message_type;
Hubert Denkmair's avatar
Hubert Denkmair committed
47

48
	msgpack::unpack(obj, data.data(), data.size());
Hubert Denkmair's avatar
Hubert Denkmair committed
49
	if (obj.get().type != msgpack::type::ARRAY) { return; }
50

Hubert Denkmair's avatar
Hubert Denkmair committed
51
52
	auto arr = obj.get().via.array;
	if (arr.size<2) { return; }
53
54
	arr.ptr[0] >> version;
	arr.ptr[1] >> message_type;
Hubert Denkmair's avatar
Hubert Denkmair committed
55

Hubert Denkmair's avatar
Hubert Denkmair committed
56
	switch (message_type)
Hubert Denkmair's avatar
Hubert Denkmair committed
57
	{
58
		case MsgPackProtocol::MESSAGE_TYPE_GAME_INFO:
59
			OnGameInfoReceived(obj.get().as<MsgPackProtocol::GameInfoMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
60
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
61

62
		case MsgPackProtocol::MESSAGE_TYPE_WORLD_UPDATE:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
63
			OnWorldUpdateReceived(obj.get().as<MsgPackProtocol::WorldUpdateMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
64
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
65

66
		case MsgPackProtocol::MESSAGE_TYPE_TICK:
67
			OnTickReceived(obj.get().as<MsgPackProtocol::TickMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
68
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
69

70
		case MsgPackProtocol::MESSAGE_TYPE_BOT_SPAWN:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
71
			OnBotSpawnReceived(obj.get().as<MsgPackProtocol::BotSpawnMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
72
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
73

74
		case MsgPackProtocol::MESSAGE_TYPE_BOT_KILL:
75
			OnBotKillReceived(obj.get().as<MsgPackProtocol::BotKillMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
76
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
77

78
		case MsgPackProtocol::MESSAGE_TYPE_BOT_MOVE:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
79
			OnBotMoveReceived(obj.get().as<MsgPackProtocol::BotMoveMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
80
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
81

82
		case MsgPackProtocol::MESSAGE_TYPE_FOOD_SPAWN:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
83
			OnFoodSpawnReceived(obj.get().as<MsgPackProtocol::FoodSpawnMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
84
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
85

86
		case MsgPackProtocol::MESSAGE_TYPE_FOOD_CONSUME:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
87
			OnFoodConsumedReceived(obj.get().as<MsgPackProtocol::FoodConsumeMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
88
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
89

90
		case MsgPackProtocol::MESSAGE_TYPE_FOOD_DECAY:
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
91
			OnFoodDecayedReceived(obj.get().as<MsgPackProtocol::FoodDecayMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
92
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
93
94
	}
}
Hubert Denkmair's avatar
Hubert Denkmair committed
95

96
void TcpProtocol::OnGameInfoReceived(const MsgPackProtocol::GameInfoMessage& msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
97
{
98
99
100
	_segments = std::make_unique<SnakeSegmentMap>(msg.world_size_x, msg.world_size_y, 1000);
	_food = std::make_unique<FoodMap>(msg.world_size_x, msg.world_size_y, 1000);
	_gameInfo = msg;
Hubert Denkmair's avatar
Hubert Denkmair committed
101
102
}

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
103
void TcpProtocol::OnWorldUpdateReceived(const MsgPackProtocol::WorldUpdateMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
104
{
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
105
106
107
108
109
	for (auto& bot: msg.bots)
	{
		_bots.push_back(bot);
	}

Hubert Denkmair's avatar
Hubert Denkmair committed
110
	if (_food == nullptr) { return; }
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
111
112
113
114
	for (auto& food: msg.food)
	{
		_food->addElement(food);
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
115
116
}

117
118
119
120
121
void TcpProtocol::OnTickReceived(const MsgPackProtocol::TickMessage &msg)
{
	(void)msg;
}

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
122
void TcpProtocol::OnFoodSpawnReceived(const MsgPackProtocol::FoodSpawnMessage& msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
123
{
Hubert Denkmair's avatar
Hubert Denkmair committed
124
	if (_food == nullptr) { return; }
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
125
126
127
128
	for (auto& item: msg.new_food)
	{
		_food->addElement(item);
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
129
130
}

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
131
void TcpProtocol::OnFoodConsumedReceived(const MsgPackProtocol::FoodConsumeMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
132
{
Hubert Denkmair's avatar
Hubert Denkmair committed
133
	if (_food == nullptr) { return; }
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
134
135
136
137
	for (auto& item: msg.items)
	{
		_food->erase_if([item](const FoodItem& food) { return food.guid == item.food_id; });
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
138
}
Hubert Denkmair's avatar
Hubert Denkmair committed
139

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
140
void TcpProtocol::OnFoodDecayedReceived(const MsgPackProtocol::FoodDecayMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
141
{
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
142
143
144
145
146
147
148
149
150
151
	if (_food == nullptr) { return; }
	for (auto& item: msg.food_ids)
	{
		_food->erase_if([item](const FoodItem& food) { return food.guid == item; });
	}
}

void TcpProtocol::OnBotSpawnReceived(const MsgPackProtocol::BotSpawnMessage &msg)
{
	_bots.push_back(msg.bot);
Hubert Denkmair's avatar
Hubert Denkmair committed
152
153
}

154
void TcpProtocol::OnBotKillReceived(const MsgPackProtocol::BotKillMessage& msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
155
{
156
	_bots.erase(std::remove_if(_bots.begin(), _bots.end(), [msg](const BotItem& bot) { return bot.guid == msg.victim_id; }));
Hubert Denkmair's avatar
Hubert Denkmair committed
157
158
}

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
159
void TcpProtocol::OnBotMoveReceived(const MsgPackProtocol::BotMoveMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
160
{
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
161
162
163
164
165
	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; }
		auto& bot = *it;
Hubert Denkmair's avatar
Hubert Denkmair committed
166

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
167
168
169
170
		bot.segments.insert(bot.segments.begin(), item.new_segments.begin(), item.new_segments.end());
		bot.segments.resize(item.current_length);
		bot.segment_radius = item.current_segment_radius;
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
171
172
}