TcpProtocol.cpp 4.69 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)
{
Hubert Denkmair's avatar
Hubert Denkmair committed
15
	std::array<char, 1024> 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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
		if ((_awaitedSize==0) && (_buf.size() >= 4))
		{
			_awaitedSize = static_cast<uint8_t>(_buf[0])<<24
						 | static_cast<uint8_t>(_buf[1])<<16
						 | static_cast<uint8_t>(_buf[2])<<8
						 | static_cast<uint8_t>(_buf[3])<<0;
			_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
41
	}
Hubert Denkmair's avatar
Hubert Denkmair committed
42
43
44
45
46
47
48
}

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

	msgpack::object_handle obj;
49
	uint64_t version, message_type;
Hubert Denkmair's avatar
Hubert Denkmair committed
50

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

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

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

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

69
		case MsgPackProtocol::MESSAGE_TYPE_TICK:
70
			OnTickReceived(obj.get().as<MsgPackProtocol::TickMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
71
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
72

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

77
		case MsgPackProtocol::MESSAGE_TYPE_BOT_KILL:
78
			OnBotKillReceived(obj.get().as<MsgPackProtocol::BotKillMessage>());
Hubert Denkmair's avatar
Hubert Denkmair committed
79
			break;
Hubert Denkmair's avatar
Hubert Denkmair committed
80

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

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

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

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

99
void TcpProtocol::OnGameInfoReceived(const MsgPackProtocol::GameInfoMessage& msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
100
{
101
102
103
	_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
104
105
}

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

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

120
121
122
123
124
void TcpProtocol::OnTickReceived(const MsgPackProtocol::TickMessage &msg)
{
	(void)msg;
}

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

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
134
void TcpProtocol::OnFoodConsumedReceived(const MsgPackProtocol::FoodConsumeMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
135
{
Hubert Denkmair's avatar
Hubert Denkmair committed
136
	if (_food == nullptr) { return; }
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
137
138
139
140
	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
141
}
Hubert Denkmair's avatar
Hubert Denkmair committed
142

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
143
void TcpProtocol::OnFoodDecayedReceived(const MsgPackProtocol::FoodDecayMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
144
{
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
145
146
147
148
149
150
151
152
153
154
	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
155
156
}

157
void TcpProtocol::OnBotKillReceived(const MsgPackProtocol::BotKillMessage& msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
158
{
159
	_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
160
161
}

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
162
void TcpProtocol::OnBotMoveReceived(const MsgPackProtocol::BotMoveMessage &msg)
Hubert Denkmair's avatar
Hubert Denkmair committed
163
{
Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
164
165
166
167
168
	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
169

Hubert Denkmair's avatar
cleanup    
Hubert Denkmair committed
170
171
172
173
		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
174
175
}