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
}