game_client.cpp 10.5 KB
Newer Older
louiz’'s avatar
louiz’ committed
1
2
#include <logging/logging.hpp>
#include <game/game_client.hpp>
3
#include <utils/time.hpp>
louiz’'s avatar
louiz’ committed
4
#include <world/world_callbacks.hpp>
5
#include <world/task.hpp>
louiz’'s avatar
louiz’ committed
6

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

10
11
namespace ph = std::placeholders;

louiz’'s avatar
louiz’ committed
12
GameClient::GameClient(const std::shared_ptr<Screen>& screen):
louiz’'s avatar
louiz’ committed
13
  Game(),
louiz’'s avatar
louiz’ committed
14
15
16
17
  ClientBase(),
  current_selection(),
  screen(screen),
  camera(this, this->screen.get()),
louiz’'s avatar
louiz’ committed
18
19
  hud(this, this->screen.get()),
  debug_hud(this, this->screen.get())
louiz’'s avatar
louiz’ committed
20
{
louiz’'s avatar
louiz’ committed
21
  this->turn_handler.set_next_turn_callback(std::bind(&GameClient::on_next_turn,
22
                                               this, ph::_1));
louiz’'s avatar
louiz’ committed
23
24
25

  this->connect("127.0.0.1", 7879);

26
27
28
  this->install_callback(
      "OCCUPANT_LEFT",
      std::bind(&GameClient::occupant_left_callback, this, ph::_1));
29
  this->install_callback("SEED",
30
                         std::bind(&GameClient::handle_seed_message, this, ph::_1));
louiz’'s avatar
louiz’ committed
31
  this->install_callback("NEW_ENTITY",
32
33
34
35
36
                         std::bind(&Game::new_entity_callback, this, ph::_1));
  this->install_callback("START", std::bind(&GameClient::handle_start_message, this, ph::_1));
  this->install_callback("T", std::bind(&GameClient::turn_callback, this, ph::_1));
  this->install_callback("MOVE", std::bind(&Game::move_callback, this, ph::_1));
  this->install_callback("CAST", std::bind(&Game::cast_callback, this, ph::_1));
louiz’'s avatar
louiz’ committed
37
38
39

  this->screen->add_element(&this->camera, 0);
  this->screen->add_element(&this->hud, 1);
louiz’'s avatar
louiz’ committed
40
  this->screen->add_element(&this->get_debug_hud(), 2);
louiz’'s avatar
louiz’ committed
41
42
43
44

  /**
   * Install world callbacks
   */
45
46
  this->world.callbacks->entity_created =
      std::bind(&GameClient::on_entity_created, this, ph::_1);
47
48
  this->world.callbacks->task_changed =
      std::bind(&GameClient::on_entity_task_changed, this, ph::_1, ph::_2);
49
50
51
52
  this->world.callbacks->entity_deleted =
      std::bind(&GameClient::on_entity_deleted, this, ph::_1);
  this->world.callbacks->ability_casted =
      std::bind(&GameClient::on_ability_casted, this, ph::_1, ph::_2, ph::_3, ph::_4);
53
54
55
  this->world.callbacks->impact =
      std::bind(&GameClient::on_impact, this, ph::_1, ph::_2);

louiz’'s avatar
louiz’ committed
56
57
58
59
60
61
62
63
}

GameClient::~GameClient()
{
}

void GameClient::run()
{
64
  auto last_update = utils::now();
louiz’'s avatar
louiz’ committed
65

66
67
68
  // Dirty workaround, fixme. Should be 0.
  long ticks = -5;
  std::chrono::steady_clock::duration dt{0};
louiz’'s avatar
louiz’ committed
69
70
71
72
73
74
75
76
77

  // window->setMouseCursorVisible(false);
  while (this->screen->window().isOpen())
    {
      // Check for user events
      sf::Event event;
      while (this->screen->window().pollEvent(event))
        {
          if (event.type == sf::Event::Closed)
78
            this->screen->window().close();
louiz’'s avatar
louiz’ committed
79
80
81
          this->screen->handle_event(event);
        }

louiz’'s avatar
louiz’ committed
82
      // recv/send from the network
83
      this->poll();
louiz’'s avatar
louiz’ committed
84

85
86
87
      this->screen->window().clear(sf::Color(70, 80, 38));
      this->screen->draw();
      this->screen->window().display();
louiz’'s avatar
louiz’ committed
88

louiz’'s avatar
louiz’ committed
89
      // Get the elapsed time
90
      auto now = utils::now();
91
      auto elapsed = now - last_update;
92
      // Call update with the elapsed time
93
      this->screen->update(std::chrono::duration_cast<utils::Duration>(elapsed));
94
95
96
97
98
99
100
101
102
103
104
105

      // Update dt with the elapsed time. We add that to the remaining value
      // that was not “consumed” by a whole tick in the previous loop
      // iteration
      dt += elapsed;

      // Save the date of the last update
      last_update = now;

      // Tick everything, based on the elapsed time
      // this “consumes” dt. For example if the returned value is 3, dt is
      // reduced by 3 * tick_duration.
106
107
      ticks += utils::get_number_of_ticks(dt);
      for (; ticks > 0; --ticks)
louiz’'s avatar
louiz’ committed
108
        {
109
110
          if (!this->tick())
            break ;
louiz’'s avatar
louiz’ committed
111
112
113
114
115
116
117
          this->graphical_tick();
        }
    }
}

void GameClient::install_callbacks()
{
118
119
  this->install_callback(
      "NEW_OCCUPANT", std::bind(&GameClient::new_occupant_callback, this, ph::_1));
louiz’'s avatar
louiz’ committed
120
121
122
123
124
125
126
127
128
}

void GameClient::add_new_occupant(std::unique_ptr<Occupant>&& occupant)
{
  this->occupants_handler.add(std::move(occupant));
}

DebugHud& GameClient::get_debug_hud()
{
louiz’'s avatar
louiz’ committed
129
  return this->debug_hud;
louiz’'s avatar
louiz’ committed
130
131
}

louiz’'s avatar
louiz’ committed
132
133
134
135
136
Hud& GameClient::get_hud()
{
  return this->hud;
}

louiz’'s avatar
louiz’ committed
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
World& GameClient::get_world()
{
  return this->world;
}

Camera& GameClient::get_camera()
{
  return this->camera;
}

Screen& GameClient::get_screen()
{
  return *this->screen;
}

louiz’'s avatar
louiz’ committed
152
void GameClient::on_next_turn(TurnNb turn)
louiz’'s avatar
louiz’ committed
153
154
155
{
}

louiz’'s avatar
louiz’ committed
156
void GameClient::new_occupant_callback(Message* message)
louiz’'s avatar
louiz’ committed
157
158
159
{
  log_debug("new_occupant_callback");

louiz’'s avatar
louiz’ committed
160
  auto srl = message->parse_body_to_protobuf_object<ser::game::Occupant>();
louiz’'s avatar
louiz’ committed
161

louiz’'s avatar
louiz’ committed
162
  auto occupant = std::make_unique<Occupant>(srl);
louiz’'s avatar
louiz’ committed
163

louiz’'s avatar
louiz’ committed
164
  log_debug("Occupant: " << occupant->name << " " << occupant->id);
165
166
167
168
169
  if (this->occupants_handler.size() == 0)
    { // This occupant is actually us
      auto team = srl.team();
      this->set_self_team(team);
    }
louiz’'s avatar
louiz’ committed
170
  this->add_new_occupant(std::move(occupant));
louiz’'s avatar
louiz’ committed
171
172
}

louiz’'s avatar
louiz’ committed
173
void GameClient::occupant_left_callback(Message* message)
louiz’'s avatar
louiz’ committed
174
{
louiz’'s avatar
louiz’ committed
175
  auto srl = message->parse_body_to_protobuf_object<ser::game::Occupant>();
louiz’'s avatar
louiz’ committed
176

louiz’'s avatar
louiz’ committed
177
178
179
  Occupant occupant(srl);
  log_debug("Occupant to remove: " << occupant.id);
  this->occupants_handler.remove(occupant);
louiz’'s avatar
louiz’ committed
180
181
}

182
183
184
185
186
187
188
void GameClient::handle_seed_message(Message* message)
{
  auto srl = message->parse_body_to_protobuf_object<ser::order::Seed>();
  log_debug("Seed value received: " << srl.value());
  this->world.seed(srl.value());
}

louiz’'s avatar
louiz’ committed
189
void GameClient::handle_start_message(Message* message)
louiz’'s avatar
louiz’ committed
190
{
louiz’'s avatar
louiz’ committed
191
192
193
194
195
  auto srl = message->parse_body_to_protobuf_object<ser::order::Start>();
  log_debug("The first turn to start is " << srl.turn());
  if (srl.turn() != 0)
    this->turn_handler.mark_as_ready_until(srl.turn());
  do
louiz’'s avatar
louiz’ committed
196
    {
louiz’'s avatar
louiz’ committed
197
198
      this->tick();
    } while (!this->turn_handler.is_paused());
louiz’'s avatar
louiz’ committed
199

louiz’'s avatar
louiz’ committed
200
  // this->world.start();
louiz’'s avatar
louiz’ committed
201
202
}

203
204
205
206
207
208
void GameClient::set_self_team(const uint16_t team)
{
  log_debug("Our team is number: " << team);
  this->team = team;
}

209
210
211
212
213
uint16_t GameClient::get_self_team() const
{
  return this->team;
}

louiz’'s avatar
louiz’ committed
214
void GameClient::turn_callback(Message*)
louiz’'s avatar
louiz’ committed
215
{
louiz’'s avatar
louiz’ committed
216
217
  log_debug("GameClient::turn_callback");
  this->turn_handler.mark_turn_as_ready();
louiz’'s avatar
louiz’ committed
218
219
}

louiz’'s avatar
louiz’ committed
220
void GameClient::path_callback(Message* message)
louiz’'s avatar
louiz’ committed
221
222
223
{
}

louiz’'s avatar
louiz’ committed
224
bool GameClient::action_move(const std::vector<EntityId>& ids, const Position& pos, const bool queue)
louiz’'s avatar
louiz’ committed
225
{
louiz’'s avatar
louiz’ committed
226
  ser::request::Move srl;
louiz’'s avatar
louiz’ committed
227
228
  if (queue)
    srl.set_queue(queue);
louiz’'s avatar
louiz’ committed
229
230
231
232
233
  srl.mutable_pos()->set_x(pos.x.raw());
  srl.mutable_pos()->set_y(pos.y.raw());
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  this->send_message("MOVE", srl);
234
  this->sounds_handler.play(SoundType::DefaultOk, true);
louiz’'s avatar
louiz’ committed
235
236
237
  return true;
}

238
239
240
241
242
243
244
245
246
247
248
249
250
251
bool GameClient::action_follow(const std::vector<EntityId>& ids,
                               const EntityId& target_id, const bool queue)
{
  ser::request::Move srl;
  if (queue)
    srl.set_queue(queue);
  srl.set_target(target_id);
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  this->send_message("MOVE", srl);
  this->sounds_handler.play(SoundType::DefaultOk, true);
  return true;
}

252
253
254
bool GameClient::action_cast(const std::vector<EntityId>& ids,
                             const Position& pos, const AbilityType& type,
                             const bool queue)
louiz’'s avatar
louiz’ committed
255
256
257
258
259
260
261
262
263
264
265
266
267
{
  ser::request::Cast srl;
  if (queue)
    srl.set_queue(queue);
  srl.mutable_pos()->set_x(pos.x.raw());
  srl.mutable_pos()->set_y(pos.y.raw());
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  srl.set_type(static_cast<uint32_t>(type));
  this->send_message("CAST", srl);
  return true;
}

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
bool GameClient::action_cast(const std::vector<EntityId>& ids,
                             const EntityId target_id, const AbilityType& type,
                             const bool queue)
{
  ser::request::Cast srl;
  if (queue)
    srl.set_queue(queue);
  srl.set_target(target_id);
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  srl.set_type(static_cast<uint32_t>(type));
  this->send_message("CAST", srl);
  return true;
}

283
284
285
286
287
288
289
290
291
292
293
294
295
bool GameClient::action_cast(const std::vector<EntityId>& ids,
                             const AbilityType& type, const bool queue)
{
  ser::request::Cast srl;
  if (queue)
    srl.set_queue(queue);
  for (const EntityId id: ids)
    srl.add_entity_id(id);
  srl.set_type(static_cast<uint32_t>(type));
  this->send_message("CAST", srl);
  return true;
}

louiz’'s avatar
louiz’ committed
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
void GameClient::select_entity(const Entity* entity)
{
  this->current_selection.add_to_selection(entity);
}

void GameClient::unselect_entity(const Entity* entity)
{
  this->current_selection.remove_from_selection(entity);
}

void GameClient::clear_selection()
{
  this->current_selection.clear();
}

bool GameClient::is_entity_selected(const Entity* entity) const
{
  return this->current_selection.is_in_selection(entity);
}

louiz’'s avatar
louiz’ committed
316
317
318
319
320
Selection& GameClient::get_selection()
{
  return this->current_selection;
}

louiz’'s avatar
louiz’ committed
321
322
323
324
325
326
327
328
329
330
const Selection& GameClient::get_selection() const
{
  return this->current_selection;
}

void GameClient::add_selection_change_callback(const t_selection_changed_callback callback)
{
  this->current_selection.on_modified_callbacks.push_back(callback);
}

331
332
333
334
335
336
337
338
339
void GameClient::on_impact(const Entity* entity, const Entity* target)
{
  // Map of EntityType:SoundType?
  if (target)
    {
      this->sounds_handler.play(SoundType::ProjectileImpact, false, 20.f);
    }
}

340
void GameClient::on_entity_created(const Entity* entity)
louiz’'s avatar
louiz’ committed
341
{
louiz’'s avatar
louiz’ committed
342
  this->camera.on_new_entity(entity);
louiz’'s avatar
louiz’ committed
343
344
}

345
346
347
348
349
350
351
352
353
354
355
356
357
void GameClient::on_entity_task_changed(const Entity* entity, const Task* task)
{
  switch (task->get_type())
    {
      case TaskType::Concentrate:
        this->sounds_handler.play(SoundType::Concentrate, false, 100.f);
        break;
      case TaskType::Dash:
        this->sounds_handler.play(SoundType::Dash, false, 100.f);
        break;
    }
}

358
359
360
void GameClient::on_entity_deleted(const Entity* entity)
{
  this->camera.on_entity_deleted(entity);
louiz’'s avatar
louiz’ committed
361
  this->current_selection.remove_from_selection(entity);
louiz’'s avatar
louiz’ committed
362
363
  if (entity->get_type() == 2)
    this->sounds_handler.play(SoundType::EmpExplode, false, 100.f);
364
365
}

366
bool GameClient::tick()
louiz’'s avatar
louiz’ committed
367
368
369
{
  this->turn_handler.tick();
  if (this->turn_handler.is_paused())
370
    return false;
louiz’'s avatar
louiz’ committed
371
  this->world.tick();
372
  return true;
louiz’'s avatar
louiz’ committed
373
}
louiz’'s avatar
louiz’ committed
374
375
376
377
378
379
380
381
382
void GameClient::graphical_tick()
{
  this->camera.graphical_tick();
}

void GameClient::on_connection_closed()
{
  log_error("Connection closed by remote server");
}
louiz’'s avatar
louiz’ committed
383
384
385
386
387
388
389
390
391

void GameClient::on_ability_casted(const Entity* caster,
                                   const AbilityType& type,
                                   const Entity* target,
                                   const Position& position)
{
  log_debug("on_ability_casted: " << static_cast<std::size_t>(type));
  if (type == AbilityType::Blink)
    this->sounds_handler.play(SoundType::BlinkStart, false, 20.f);
louiz’'s avatar
louiz’ committed
392
393
  else if (type == AbilityType::Attack)
    this->sounds_handler.play(SoundType::ProjectileLaunch, false, 20.f);
louiz’'s avatar
louiz’ committed
394
395
  else if (type == AbilityType::Emp)
    this->sounds_handler.play(SoundType::EmpStart, false, 100.f);
louiz’'s avatar
louiz’ committed
396
}