The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
info.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2016 by Tomasz Sniatowski <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "config.hpp"
18 #include "game_preferences.hpp"
19 #include "formula/string_utils.hpp"
20 #include "gettext.hpp"
21 #include "log.hpp"
22 #include "map/map.hpp"
23 #include "map/exception.hpp"
24 #include "wml_exception.hpp"
25 #include "wesnothd_connection.hpp"
26 #include <iterator>
27 
28 static lg::log_domain log_config("config");
29 #define ERR_CF LOG_STREAM(err, log_config)
30 static lg::log_domain log_engine("engine");
31 #define WRN_NG LOG_STREAM(warn, log_engine)
32 
33 static lg::log_domain log_lobby("lobby");
34 #define DBG_LB LOG_STREAM(debug, log_lobby)
35 #define LOG_LB LOG_STREAM(info, log_lobby)
36 #define WRN_LB LOG_STREAM(warn, log_lobby)
37 #define ERR_LB LOG_STREAM(err, log_lobby)
38 #define SCOPE_LB log_scope2(log_lobby, __func__)
39 
40 
42  : game_config_(game_config)
43  , gamelist_()
44  , gamelist_initialized_(false)
45  , rooms_()
46  , games_by_id_()
47  , games_()
48  , games_filtered_()
49  , users_()
50  , users_sorted_()
51  , whispers_()
52  , game_filter_()
53  , game_filter_invert_(false)
54  , games_visibility_()
55  , wesnothd_connection_(wesnothd_connection)
56 {
57 }
58 
60 {
61  delete_games();
62 }
63 
65 {
66  for(const auto & v : games_by_id_)
67  {
68  delete v.second;
69  }
70 }
71 
72 namespace
73 {
74 
75 std::string dump_games_map(const lobby_info::game_info_map& games)
76 {
77  std::stringstream ss;
78  for(const auto & v : games)
79  {
80  const game_info& game = *v.second;
81  ss << "G" << game.id << "(" << game.name << ") "
82  << game.display_status_string() << " ";
83  }
84  ss << "\n";
85  return ss.str();
86 }
87 
88 std::string dump_games_config(const config& gamelist)
89 {
90  std::stringstream ss;
91  for(const auto & c : gamelist.child_range("game"))
92  {
93  ss << "g" << c["id"] << "(" << c["name"] << ") "
95  }
96  ss << "\n";
97  return ss.str();
98 }
99 
100 } // end anonymous namespace
101 
103 {
104  SCOPE_LB;
105  gamelist_ = data;
106  gamelist_initialized_ = true;
107  delete_games();
108  games_by_id_.clear();
109  for(const auto & c : gamelist_.child("gamelist").child_range("game"))
110  {
111  game_info* game = new game_info(c, game_config_);
112  games_by_id_[game->id] = game;
113  }
114  DBG_LB << dump_games_map(games_by_id_);
115  DBG_LB << dump_games_config(gamelist_.child("gamelist"));
117 }
118 
119 
121 {
122  SCOPE_LB;
124  return false;
125  DBG_LB << "prediff " << dump_games_config(gamelist_.child("gamelist"));
126  try
127  {
128  gamelist_.apply_diff(data, true);
129  }
130  catch(config::error& e)
131  {
132  ERR_LB << "Error while applying the gamelist diff: '" << e.message
133  << "' Getting a new gamelist.\n";
134  wesnothd_connection_.send_data(config("refresh_lobby"));
135  return false;
136  }
137  DBG_LB << "postdiff " << dump_games_config(gamelist_.child("gamelist"));
138  DBG_LB << dump_games_map(games_by_id_);
139  config::child_itors range = gamelist_.child("gamelist").child_range("game");
140  for(config::child_iterator i = range.first; i != range.second; ++i) {
141  config& c = *i;
142  DBG_LB << "data process: " << c["id"] << " ("
143  << c[config::diff_track_attribute] << ")\n";
144  int game_id = c["id"];
145  if(game_id == 0) {
146  ERR_LB << "game with id 0 in gamelist config" << std::endl;
147  wesnothd_connection_.send_data(config("refresh_lobby"));
148  return false;
149  }
150  game_info_map::iterator current_i = games_by_id_.find(game_id);
151  const std::string& diff_result = c[config::diff_track_attribute];
152  if(diff_result == "new" || diff_result == "modified") {
153  if(current_i == games_by_id_.end()) {
154  games_by_id_.insert(std::make_pair(
155  game_id, new game_info(c, game_config_)));
156  } else {
157  // had a game with that id, so update it and mark it as such
158  *(current_i->second) = game_info(c, game_config_);
159  current_i->second->display_status = game_info::UPDATED;
160  }
161  } else if(diff_result == "deleted") {
162  if(current_i == games_by_id_.end()) {
163  WRN_LB << "Would have to delete a game that I don't have: "
164  << game_id << "\n";
165  } else {
166  if(current_i->second->display_status == game_info::NEW) {
167  // this means the game never made it through to the user
168  // interface
169  // so just deleting it is fine
170  games_by_id_.erase(current_i);
171  } else {
172  current_i->second->display_status = game_info::DELETED;
173  }
174  }
175  }
176  }
177  DBG_LB << dump_games_map(games_by_id_);
178  try
179  {
181  }
182  catch(config::error& e)
183  {
184  ERR_LB << "Error while applying the gamelist diff (2): '" << e.message
185  << "' Getting a new gamelist.\n";
186  wesnothd_connection_.send_data(config("refresh_lobby"));
187  return false;
188  }
189  DBG_LB << "postclean " << dump_games_config(gamelist_.child("gamelist"));
191  return true;
192 }
193 
195 {
196  SCOPE_LB;
197  users_.clear();
198  for(const auto & c : gamelist_.child_range("user"))
199  {
200  users_.push_back(user_info(c));
201  }
202  for(auto & ui : users_)
203  {
204  if(ui.game_id != 0) {
205  game_info* g = get_game_by_id(ui.game_id);
206  if(g == nullptr) {
207  WRN_NG << "User " << ui.name
208  << " has unknown game_id: " << ui.game_id << "\n";
209  } else {
210  switch(ui.relation) {
211  case user_info::FRIEND:
212  g->has_friends = true;
213  break;
214  case user_info::IGNORED:
215  g->has_ignored = true;
216  break;
217  default:
218  break;
219  }
220  }
221  }
222  }
223 }
224 
226 {
227  DBG_LB << "lobby_info::sync_games_display_status";
228  DBG_LB << "games_by_id_ size: " << games_by_id_.size();
230  while(i != games_by_id_.end()) {
231  if(i->second->display_status == game_info::DELETED) {
232  games_by_id_.erase(i++);
233  } else {
234  i->second->display_status = game_info::CLEAN;
235  ++i;
236  }
237  }
238  DBG_LB << " -> " << games_by_id_.size() << "\n";
240 }
241 
243 {
245  return i == games_by_id_.end() ? nullptr : i->second;
246 }
247 
249 {
250  std::map<int, game_info*>::const_iterator i = games_by_id_.find(id);
251  return i == games_by_id_.end() ? nullptr : i->second;
252 }
253 
255 {
256  for(auto & r : rooms_)
257  {
258  if(r.name() == name)
259  return &r;
260  }
261  return nullptr;
262 }
263 
265 {
266  for(const auto & r : rooms_)
267  {
268  if(r.name() == name)
269  return &r;
270  }
271  return nullptr;
272 }
273 
275 {
276  return get_room(name) != nullptr;
277 }
278 
280 {
281  return whispers_[name];
282 }
283 
285 {
286  if(!has_room(name)) {
287  rooms_.push_back(room_info(name));
288  }
289 }
290 
292 {
293  room_info* r = get_room(name);
294  DBG_LB << "lobby info: closing room " << name << " "
295  << static_cast<void*>(r) << "\n";
296  if(r) {
297  rooms_.erase(rooms_.begin() + (r - &rooms_[0]));
298  }
299 }
300 
301 const std::vector<game_info*>& lobby_info::games_filtered() const
302 {
303  return games_filtered_;
304 }
305 
307 {
308  game_filter_.append(f);
309 }
310 
312 {
314 }
315 
317 {
319 }
320 
322 {
323  games_filtered_.clear();
324  games_visibility_.clear();
325  games_.clear();
326  for(const auto & v : games_by_id_)
327  {
328  games_.push_back(v.second);
329  }
330 }
331 
333 {
334  games_filtered_.clear();
335  games_visibility_.clear();
336  for(auto g : games_)
337  {
338  game_info& gi = *g;
339  bool show = game_filter_.match(gi);
340  if(game_filter_invert_) {
341  show = !show;
342  }
343  games_visibility_.push_back(show);
344  if(show) {
345  games_filtered_.push_back(&gi);
346  }
347  }
348 }
349 
350 void lobby_info::update_user_statuses(int game_id, const room_info* room)
351 {
352  for(auto & user : users_)
353  {
354  user.update_state(game_id, room);
355  }
356 }
357 
358 
360 {
361  bool operator()(const user_info& u1, const user_info& u2)
362  {
363  return u1.name < u2.name;
364  }
365  bool operator()(const user_info* u1, const user_info* u2)
366  {
367  return operator()(*u1, *u2);
368  }
369 };
370 
372 {
373  bool operator()(const user_info& u1, const user_info& u2)
374  {
375  return static_cast<int>(u1.relation) < static_cast<int>(u2.relation);
376  }
377  bool operator()(const user_info* u1, const user_info* u2)
378  {
379  return operator()(*u1, *u2);
380  }
381 };
382 
384 {
385  bool operator()(const user_info& u1, const user_info& u2)
386  {
387  return static_cast<int>(u1.relation) < static_cast<int>(u2.relation)
388  || (u1.relation == u2.relation && u1.name < u2.name);
389  }
390  bool operator()(const user_info* u1, const user_info* u2)
391  {
392  return operator()(*u1, *u2);
393  }
394 };
395 
396 void lobby_info::sort_users(bool by_name, bool by_relation)
397 {
398  users_sorted_.clear();
399  for(auto & u : users_)
400  {
401  users_sorted_.push_back(&u);
402  }
403  if(by_name) {
404  if(by_relation) {
405  std::sort(users_sorted_.begin(),
406  users_sorted_.end(),
408  } else {
409  std::sort(users_sorted_.begin(),
410  users_sorted_.end(),
411  user_sorter_name());
412  }
413  } else if(by_relation) {
414  std::sort(users_sorted_.begin(),
415  users_sorted_.end(),
417  }
418 }
419 
420 const std::vector<user_info*>& lobby_info::users_sorted() const
421 {
422  return users_sorted_;
423 }
#define DBG_LB
Definition: info.cpp:34
void close_room(const std::string &name)
Definition: info.cpp:291
child_itors child_range(const std::string &key)
Definition: config.cpp:613
const char * display_status_string() const
Definition: data.cpp:369
bool game_filter_invert_
Definition: info.hpp:114
bool has_room(const std::string &name) const
Definition: info.cpp:274
void clear()
Definition: data.cpp:404
This class represents the information a client has about a room.
Definition: data.hpp:65
std::map< std::string, chat_log > whispers_
Definition: info.hpp:112
this class memorizes a chat session.
Definition: data.hpp:40
GLenum GLint * range
Definition: glew.h:3025
const GLfloat * c
Definition: glew.h:12741
lobby_info(const config &game_config, twesnothd_connection &)
Definition: info.cpp:41
game_info * get_game_by_id(int id)
Definition: info.cpp:242
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::vector< bool > games_visibility_
Definition: info.hpp:115
game_info_map games_by_id_
Definition: info.hpp:106
std::vector< game_info * > games_filtered_
Definition: info.hpp:109
~lobby_info()
Definition: info.cpp:59
void open_room(const std::string &name)
Definition: info.cpp:284
game_filter_and_stack game_filter_
Definition: info.hpp:113
bool operator()(const user_info *u1, const user_info *u2)
Definition: info.cpp:365
GLuint GLdouble u1
Definition: glew.h:2972
GLboolean GLboolean g
Definition: glew.h:7319
const std::vector< game_info * > & games_filtered() const
Definition: info.cpp:301
game_display_status display_status
Definition: data.hpp:184
void clear_diff_track(const config &diff)
Clear any tracking info from a previous apply_diff call with tracking.
Definition: config.cpp:1314
void process_userlist()
Definition: info.cpp:194
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
config gamelist_
Definition: info.hpp:102
Definitions for the interface to Wesnoth Markup Language (WML).
bool has_ignored
Definition: data.hpp:176
This class represents the information a client has about another player.
Definition: data.hpp:102
void set_game_filter_invert(bool value)
Definition: info.cpp:316
user_relation relation
Definition: data.hpp:127
void send_data(const configr_of &request)
std::map< int, game_info * > game_info_map
Definition: info.hpp:34
A class that represents a TCP/IP connection to the wesnothd server.
bool gamelist_initialized_
Definition: info.hpp:103
std::vector< game_info * > games_
Definition: info.hpp:108
const GLdouble * v
Definition: glew.h:1359
GLsizei const GLfloat * value
Definition: glew.h:1817
static lg::log_domain log_engine("engine")
bool operator()(const user_info &u1, const user_info &u2)
Definition: info.cpp:385
static lg::log_domain log_lobby("lobby")
bool match(const game_info &game) const
Definition: data.cpp:413
void update_user_statuses(int game_id, const room_info *room)
Definition: info.cpp:350
static lg::log_domain log_config("config")
const config & game_config_
Definition: info.hpp:101
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
Definition: config.cpp:1252
void apply_game_filter()
Definition: info.cpp:332
#define WRN_LB
Definition: info.cpp:36
void show(CVideo &video, const std::string &window_id, const t_string &message, const tpoint &mouse)
Shows a tip.
Definition: tip.cpp:133
void sync_games_display_status()
Definition: info.cpp:225
int id
Definition: data.hpp:144
void make_games_vector()
Definition: info.cpp:321
#define ERR_LB
Definition: info.cpp:37
chat_log & get_whisper_log(const std::string &name)
Definition: info.cpp:279
Game configuration data as global variables.
Definition: build_info.cpp:38
twesnothd_connection & wesnothd_connection_
Definition: info.hpp:116
bool operator()(const user_info &u1, const user_info &u2)
Definition: info.cpp:373
std::pair< child_iterator, child_iterator > child_itors
Definition: config.hpp:213
size_t i
Definition: function.cpp:1057
void append(game_filter_base *f)
Takes ownership.
Definition: data.cpp:399
#define SCOPE_LB
Definition: info.cpp:38
bool has_friends
Definition: data.hpp:175
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
bool operator()(const user_info *u1, const user_info *u2)
Definition: info.cpp:390
static int sort(lua_State *L)
Definition: ltablib.cpp:246
GLuint const GLchar * name
Definition: glew.h:1782
std::string name
Definition: data.hpp:125
bool operator()(const user_info &u1, const user_info &u2)
Definition: info.cpp:361
void clear_game_filter()
Definition: info.cpp:311
static const char * diff_track_attribute
The name of the attribute used for tracking diff changes.
Definition: config.hpp:686
void add_game_filter(game_filter_base *f)
Definition: info.cpp:306
void sort_users(bool by_name, bool by_relation)
Definition: info.cpp:396
This class represents the info a client has about a game on the server.
Definition: data.hpp:136
#define WRN_NG
Definition: info.cpp:31
#define g
Definition: glew.h:12730
bool operator()(const user_info *u1, const user_info *u2)
Definition: info.cpp:377
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
void process_gamelist(const config &data)
Process a full gamelist.
Definition: info.cpp:102
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:29
std::vector< user_info * > users_sorted_
Definition: info.hpp:111
std::vector< room_info > rooms_
Definition: info.hpp:104
void delete_games()
Definition: info.cpp:64
#define e
std::vector< user_info > users_
Definition: info.hpp:110
GLuint GLdouble GLdouble u2
Definition: glew.h:2972
std::string name
Definition: data.hpp:146
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503
room_info * get_room(const std::string &name)
Definition: info.cpp:254
const std::vector< user_info * > & users_sorted() const
Definition: info.cpp:420
bool process_gamelist_diff(const config &data)
Process a gamelist diff.
Definition: info.cpp:120
GLclampf f
Definition: glew.h:3024