game_server.cpp 8.29 KB
Newer Older
louiz’'s avatar
louiz’ committed
1
#include <game/game_server.hpp>
louiz’'s avatar
louiz’ committed
2
#include <game/turn.hpp>
louiz’'s avatar
louiz’ committed
3
4
#include <algorithm>

louiz’'s avatar
louiz’ committed
5
6
7
8
9
10
#include "game.pb.h"
#include "orders.pb.h"
#include "requests.pb.h"

GameServer::GameServer(short port):
  Game(),
louiz’'s avatar
louiz’ committed
11
  Server<RemoteGameClient>(port),
louiz’'s avatar
louiz’ committed
12
  replay()
louiz’'s avatar
louiz’ committed
13
{
louiz’'s avatar
louiz’ committed
14
15
16
  this->turn_handler.set_next_turn_callback(std::bind(&GameServer::on_next_turn, this,
                                                      std::placeholders::_1));
  this->start_game();
louiz’'s avatar
louiz’ committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30
}

GameServer::~GameServer()
{
}

void GameServer::on_new_client(RemoteGameClient* new_client)
{
  // Give a pointer to ourself (the server) to this new client, so that it
  // can communicate with us later
  new_client->set_game_server(this);

  // First send the new player to all connected clients.
  // (including the just-new-connected one)
louiz’'s avatar
louiz’ committed
31
32
  Message* message = new Message();
  message->set_name("NEW_OCCUPANT");
louiz’'s avatar
louiz’ committed
33

louiz’'s avatar
louiz’ committed
34
  auto new_occupant = std::make_unique<Occupant>(new_client->get_id(), "coucou");
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  // Get the first team not already taken by an other occupant
  uint16_t team;
  for (team = 1;; team++)
    {
      bool res = std::none_of(this->occupants_handler.begin(),
                              this->occupants_handler.end(),
                              [team](const auto& occupant)
                              {
                                return occupant->get_team() == team;
                              });
      if (res)
        break;
    }
  new_occupant->set_team(team);

louiz’'s avatar
louiz’ committed
51
52
  message->set_body(new_occupant->serialize());
  this->send_to_all_clients(message);
louiz’'s avatar
louiz’ committed
53

louiz’'s avatar
louiz’ committed
54
55
  this->occupants_handler.add(std::move(new_occupant));
  log_debug("There are now " << this->occupants_handler.size() << " occupants");
louiz’'s avatar
louiz’ committed
56
57
58

  // Then send the list of already-connected clients to the new
  // one.
louiz’'s avatar
louiz’ committed
59
  for (const auto& occupant: this->occupants_handler)
louiz’'s avatar
louiz’ committed
60
    {
louiz’'s avatar
louiz’ committed
61
      if (occupant->id != new_client->get_id())
louiz’'s avatar
louiz’ committed
62
63
     { // Do not send the information about itself, it
       // already just received that.
louiz’'s avatar
louiz’ committed
64
65
66
67
       message = new Message();
       message->set_name("NEW_OCCUPANT");
       message->set_body(occupant->serialize());
       new_client->send(message);
louiz’'s avatar
louiz’ committed
68
69
70
71
72
73
     }
    }
  // Send the replay to the new client.
  this->send_replay(new_client);
  // Send an action to indicate at what turn the replay ends
  // and where the game currently is.
louiz’'s avatar
louiz’ committed
74
75
76
  this->send_start_message(new_client);
  // Send the futur actions to the new client
  this->send_future_actions(new_client);
louiz’'s avatar
louiz’ committed
77
78
79
80
}

void GameServer::send_replay(RemoteGameClient* new_client)
{
louiz’'s avatar
louiz’ committed
81
82
  for (const auto& order: this->replay.get_orders())
    new_client->send(new Message(order));
louiz’'s avatar
louiz’ committed
83
84
}

louiz’'s avatar
louiz’ committed
85
void GameServer::send_future_actions(RemoteGameClient* new_client)
louiz’'s avatar
louiz’ committed
86
{
louiz’'s avatar
louiz’ committed
87
88
89
90
91
  // Turn* turn;
  // Action* action;
  // Message* message;
  // ActionEvent* event;
  // std::size_t occupants_handler = this->occupants_handler.size();
louiz’'s avatar
louiz’ committed
92

louiz’'s avatar
louiz’ committed
93
94
95
96
97
98
99
100
101
102
103
  // for (const auto& turn: this->turn_handler.get_turns())
  //   {
  //     for (const auto& action: turn.get_actions())
  //       {
  //         event = action->get_event();
  //         message = new Message;
  //         message->set_name(event->name);
  //         message->set_body(event->to_string().c_str());
  //         new_client->send(message);
  //       }
  //   }
louiz’'s avatar
louiz’ committed
104
105
}

louiz’'s avatar
louiz’ committed
106
void GameServer::send_start_message(RemoteGameClient* client)
louiz’'s avatar
louiz’ committed
107
{
louiz’'s avatar
louiz’ committed
108
109
110
111
112
113
  Message* message = new Message;
  ser::order::Start start_msg;
  start_msg.set_turn(this->turn_handler.get_current_turn());
  message->set_name("START");
  message->set_body(start_msg);
  client->send(message);
louiz’'s avatar
louiz’ committed
114
115
116
117
}

void GameServer::on_client_left(RemoteGameClient* client)
{
louiz’'s avatar
louiz’ committed
118
  const auto it = std::remove_if(this->occupants_handler.begin(), this->occupants_handler.end(),
louiz’'s avatar
louiz’ committed
119
120
                           [client](const auto& occupant)
                                 {
louiz’'s avatar
louiz’ committed
121
                                   return occupant->id == client->get_id();
louiz’'s avatar
louiz’ committed
122
                                 });
louiz’'s avatar
louiz’ committed
123
  std::for_each(it, this->occupants_handler.end(),
louiz’'s avatar
louiz’ committed
124
125
               [this](const auto& occupant)
               {
louiz’'s avatar
louiz’ committed
126
127
128
129
                 Message* message = new Message;
                 message->set_name("OCCUPANT_LEFT");
                 message->set_body(occupant->serialize());
                 this->send_to_all_clients(message);
louiz’'s avatar
louiz’ committed
130
               });
louiz’'s avatar
louiz’ committed
131
  this->occupants_handler.erase(it, this->occupants_handler.end());
louiz’'s avatar
louiz’ committed
132
133
134
135
}

void GameServer::tick()
{
louiz’'s avatar
louiz’ committed
136
137
138
  this->turn_handler.tick();
  if (this->turn_handler.is_paused())
    return;
louiz’'s avatar
louiz’ committed
139
140
141
  this->world.tick();
}

louiz’'s avatar
louiz’ committed
142
143
144
145
146
147
148
149
150
// void GameServer::pause_game()
// {
//   this->started = false;
// }

// void GameServer::unpause_game()
// {
//   this->started = true;
// }
louiz’'s avatar
louiz’ committed
151

louiz’'s avatar
louiz’ committed
152
void GameServer::start_game()
louiz’'s avatar
louiz’ committed
153
{
louiz’'s avatar
louiz’ committed
154
155
156
157
  this->send_new_entity_order(0, {300, 300}, 1);
  this->send_new_entity_order(0, {400, 800.12}, 1);
  this->send_new_entity_order(0, {500, 500}, 2);
  this->send_new_entity_order(0, {320, 610}, 2);
louiz’'s avatar
louiz’ committed
158
  this->turn_handler.mark_turn_as_ready();
louiz’'s avatar
louiz’ committed
159
160
}

louiz’'s avatar
louiz’ committed
161
void GameServer::on_next_turn(const TurnNb n)
louiz’'s avatar
louiz’ committed
162
{
louiz’'s avatar
louiz’ committed
163
164
165
  log_debug("GameServer::on_next_turn(" << n << ")");
  this->turn_handler.mark_turn_as_ready();
  this->send_message_to_all("T", {});
louiz’'s avatar
louiz’ committed
166
167
}

louiz’'s avatar
louiz’ committed
168
void GameServer::send_order_to_all(const char* name, const google::protobuf::Message& srl)
louiz’'s avatar
louiz’ committed
169
{
louiz’'s avatar
louiz’ committed
170
171
172
173
174
  Message* message = new Message;
  message->set_name(name);
  message->set_body(srl);
  this->replay.insert_order(*message);
  this->send_to_all_clients(message);
louiz’'s avatar
louiz’ committed
175
176
}

louiz’'s avatar
louiz’ committed
177
void GameServer::send_message_to_all(const char* name, const std::string& data)
louiz’'s avatar
louiz’ committed
178
{
louiz’'s avatar
louiz’ committed
179
180
181
182
  Message* message = new Message;
  message->set_name(name);
  message->set_body(data.data(), data.size());
  this->send_to_all_clients(message);
louiz’'s avatar
louiz’ committed
183
184
}

louiz’'s avatar
louiz’ committed
185
void GameServer::send_turn()
louiz’'s avatar
louiz’ committed
186
{
louiz’'s avatar
louiz’ committed
187
188
189
  Message* message = new Message;
  message->set_name("T");
  this->send_to_all_clients(message);
louiz’'s avatar
louiz’ committed
190
191
192
193
194
195
}

void GameServer::init()
{
}

louiz’'s avatar
louiz’ committed
196
void GameServer::on_move_request(Message* message)
louiz’'s avatar
louiz’ committed
197
{
louiz’'s avatar
louiz’ committed
198
199
  auto srl = message->parse_body_to_protobuf_object<ser::request::Move>();
  if (!srl.IsInitialized())
louiz’'s avatar
louiz’ committed
200
    {
louiz’'s avatar
louiz’ committed
201
      log_error("Invalid data received for Move request : " << srl.InitializationErrorString());
louiz’'s avatar
louiz’ committed
202
203
      return ;
    }
louiz’'s avatar
louiz’ committed
204
205
206
207
  std::vector<EntityId> ids;
  for (const auto& id: srl.entity_id())
    ids.push_back(id);
  Position pos;
louiz’'s avatar
louiz’ committed
208
209
  pos.x.raw() = srl.pos().x();
  pos.y.raw() = srl.pos().y();
louiz’'s avatar
louiz’ committed
210
211
212
  this->send_move_order(ids, pos, srl.queue());
}

louiz’'s avatar
louiz’ committed
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
void GameServer::on_cast_request(Message* message)
{
  auto srl = message->parse_body_to_protobuf_object<ser::request::Cast>();
  if (!srl.IsInitialized())
    {
      log_error("Invalid data received for Cast request: " << srl.InitializationErrorString());
      return ;
    }
  std::vector<EntityId> ids;
  for (const auto& id: srl.entity_id())
    ids.push_back(id);
  if (srl.has_pos())
    {
      Position pos;
      pos.x.raw() = srl.pos().x();
      pos.y.raw() = srl.pos().y();
      this->send_cast_order(ids, pos, srl.type(), srl.queue());
    }
}

void GameServer::send_cast_order(const std::vector<EntityId>& ids, const Position& pos,
                                 const uint32_t type, const bool queue)
{
  ser::order::Cast srl;
  srl.set_turn(this->turn_handler.get_current_turn() + 2);
  if (queue)
    srl.set_queue(queue);
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  srl.set_type(type);
  srl.mutable_pos()->set_x(pos.x.raw());
  srl.mutable_pos()->set_y(pos.y.raw());
  this->send_order_to_all("CAST", srl);
  this->turn_handler.insert_action(std::bind(&World::do_cast, &this->world, ids, pos,
                                             static_cast<AbilityType>(type), queue),
                                   srl.turn());
}

louiz’'s avatar
louiz’ committed
251
252
void GameServer::send_new_entity_order(const EntityType type, const Position& pos,
                                       const uint16_t team)
louiz’'s avatar
louiz’ committed
253
{
louiz’'s avatar
louiz’ committed
254
  ser::order::NewEntity srl;
louiz’'s avatar
louiz’ committed
255
256
257
258
  srl.set_turn(this->turn_handler.get_current_turn() + 2);
  srl.set_type_id(type);
  srl.mutable_pos()->set_x(pos.x.raw());
  srl.mutable_pos()->set_y(pos.y.raw());
259
  srl.set_team(team);
louiz’'s avatar
louiz’ committed
260
261
  this->send_order_to_all("NEW_ENTITY", srl);
  this->turn_handler.insert_action(std::bind(&World::do_new_entity, &this->world, type, pos, team),
louiz’'s avatar
louiz’ committed
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
                                   srl.turn());
}

void GameServer::send_move_order(const std::vector<EntityId> ids, const Position& pos, const bool queue)
{
  ser::order::Move srl;
  srl.set_turn(this->turn_handler.get_current_turn() + 2);
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  srl.set_queue(queue);
  srl.mutable_pos()->set_x(pos.x.raw());
  srl.mutable_pos()->set_y(pos.y.raw());
  this->send_order_to_all("MOVE", srl);
  this->turn_handler.insert_action(std::bind(&World::do_move, &this->world, ids, pos, queue),
                                   srl.turn());
louiz’'s avatar
louiz’ committed
277
}