The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
data.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 "filesystem.hpp"
20 #include "formula/string_utils.hpp"
21 #include "gettext.hpp"
22 #include "log.hpp"
23 #include "map/map.hpp"
24 #include "map/exception.hpp"
25 #include "terrain/type_data.hpp"
26 #include "wml_exception.hpp"
27 
28 #include <iterator>
29 #include <boost/make_shared.hpp>
30 #include <boost/shared_ptr.hpp>
31 
32 static lg::log_domain log_config("config");
33 #define ERR_CF LOG_STREAM(err, log_config)
34 static lg::log_domain log_engine("engine");
35 #define WRN_NG LOG_STREAM(warn, log_engine)
36 
37 static lg::log_domain log_lobby("lobby");
38 #define DBG_LB LOG_STREAM(info, log_lobby)
39 #define LOG_LB LOG_STREAM(info, log_lobby)
40 #define ERR_LB LOG_STREAM(err, log_lobby)
41 
43  const std::string& user,
44  const std::string& message)
45  : timestamp(timestamp), user(user), message(message)
46 {
47 }
48 
49 chat_log::chat_log() : history_()
50 {
51 }
52 
53 void chat_log::add_message(const time_t& timestamp,
54  const std::string& user,
55  const std::string& message)
56 {
57  history_.push_back(chat_message(timestamp, user, message));
58 }
59 
60 
62 {
63  add_message(time(nullptr), user, message);
64 }
65 
67 {
68  history_.clear();
69 }
70 
71 room_info::room_info(const std::string& name) : name_(name), members_(), log_()
72 {
73 }
74 
75 bool room_info::is_member(const std::string& user) const
76 {
77  return members_.find(user) != members_.end();
78 }
79 
81 {
82  members_.insert(user);
83 }
84 
86 {
87  members_.erase(user);
88 }
89 
91 {
92  members_.clear();
93  for(const auto & m : data.child_range("member"))
94  {
95  members_.insert(m["name"]);
96  }
97 }
98 
100  : name(c["name"])
101  , game_id(c["game_id"])
102  , relation(ME)
103  , state(game_id == 0 ? LOBBY : GAME)
104  , registered(c["registered"].to_bool())
105  , observing(c["status"] == "observing")
106 {
107  update_relation();
108 }
109 
110 void user_info::update_state(int selected_game_id,
111  const room_info* current_room /*= nullptr*/)
112 {
113  if(game_id != 0) {
114  if(game_id == selected_game_id) {
115  state = SEL_GAME;
116  } else {
117  state = GAME;
118  }
119  } else {
120  if(current_room != nullptr && current_room->is_member(name)) {
121  state = SEL_ROOM;
122  } else {
123  state = LOBBY;
124  }
125  }
126  update_relation();
127 }
128 
130 {
131  if(name == preferences::login()) {
132  relation = ME;
133  } else if(preferences::is_ignored(name)) {
134  relation = IGNORED;
135  } else if(preferences::is_friend(name)) {
136  relation = FRIEND;
137  } else {
138  relation = NEUTRAL;
139  }
140 }
141 
142 namespace
143 {
144 
145 std::string make_short_name(const std::string& long_name)
146 {
147  if(long_name.empty())
148  return "";
149  std::string sh;
150  bool had_space = true;
151  for(size_t i = 1; i < long_name.size(); ++i) {
152  if(long_name[i] == ' ') {
153  had_space = true;
154  } else if(had_space && long_name[i] != '?') {
155  sh += long_name[i];
156  had_space = false;
157  }
158  }
159  return sh;
160 }
161 
162 } // end anonymous namespace
163 
165  : mini_map()
166  , id(game["id"])
167  , map_data(game["map_data"])
168  , name(game["name"])
169  , scenario()
170  , remote_scenario(false)
171  , map_info()
172  , map_size_info()
173  , era()
174  , era_short()
175  , gold(game["mp_village_gold"])
176  , support(game["mp_village_support"])
177  , xp(game["experience_modifier"].str() + "%")
178  , vision()
179  , status()
180  , time_limit()
181  , vacant_slots(lexical_cast_default<int>(game["slots"],
182  0)) // Can't use to_int() here.
183  , current_turn(0)
184  , reloaded(game["savegame"].to_bool())
185  , started(false)
186  , fog(game["mp_fog"].to_bool())
187  , shroud(game["mp_shroud"].to_bool())
188  , observers(game["observer"].to_bool(true))
189  , shuffle_sides(game["shuffle_sides"].to_bool(true))
190  , use_map_settings(game["mp_use_map_settings"].to_bool())
191  , verified(true)
192  , password_required(game["password"].to_bool())
193  , have_era(true)
194  , have_all_mods(true)
195  , has_friends(false)
196  , has_ignored(false)
197  , display_status(NEW)
198 {
199  std::string turn = game["turn"];
200  if(!game["mp_era"].empty()) {
201  const config& era_cfg
202  = game_config.find_child("era", "id", game["mp_era"]);
203  utils::string_map symbols;
204  symbols["era_id"] = game["mp_era"];
205  if(era_cfg) {
206  era = era_cfg["name"].str();
207  era_short = era_cfg["short_name"].str();
208  if(era_short.empty()) {
209  era_short = make_short_name(era);
210  }
211  } else {
212  have_era = !game["require_era"].to_bool(true);
213  era = vgettext("Unknown era: $era_id", symbols);
214  era_short = "?" + make_short_name(era);
215  verified = false;
216  }
217  } else {
218  era = _("Unknown era");
219  era_short = "??";
220  verified = false;
221  }
222  map_info = era;
223 
224  if(!game.child_or_empty("modification").empty()) {
225  for(const config &cfg : game.child_range("modification")) {
226  if (cfg["require_modification"].to_bool(false)) {
227  const config &mod = game_config.find_child("modification", "id",
228  cfg["id"]);
229  if (!mod) {
230  have_all_mods = false;
231  break;
232  }
233  }
234  }
235  }
236 
237  if(map_data.empty()) {
238  map_data = filesystem::read_map(game["mp_scenario"]);
239  }
240 
241  if(map_data.empty()) {
242  map_info += " — ??×??";
243  } else {
244  try
245  {
246  gamemap map(boost::make_shared<terrain_type_data>(game_config), map_data);
247  // mini_map = image::getMinimap(minimap_size_, minimap_size_, map,
248  // 0);
249  std::ostringstream msi;
250  msi << map.w() << utils::unicode_multiplication_sign << map.h();
251  map_size_info = msi.str();
252  map_info += " — " + map_size_info;
253  }
255  {
256  ERR_CF << "illegal map: " << e.message << std::endl;
257  verified = false;
258  }
259  catch(twml_exception& e)
260  {
261  ERR_CF << "map could not be loaded: " << e.dev_message << '\n';
262  verified = false;
263  }
264  }
265  map_info += " ";
266  if(!game["mp_scenario"].empty()) {
267  // check if it's a multiplayer scenario
268  const config* level_cfg = &game_config.find_child("multiplayer",
269  "id",
270  game["mp_scenario"]);
271  if(!*level_cfg) {
272  // check if it's a user map
273  level_cfg = &game_config.find_child("generic_multiplayer",
274  "id",
275  game["mp_scenario"]);
276  }
277  if(*level_cfg) {
278  scenario = (*level_cfg)["name"].str();
279  map_info += scenario;
280  // reloaded games do not match the original scenario hash,
281  // so it makes no sense to test them, they always would appear
282  // as remote scenarios
283  if(!reloaded) {
284  if(const config& hashes
285  = game_config.child("multiplayer_hashes")) {
286  std::string hash = game["hash"];
287  bool hash_found = false;
288  for(const auto & i : hashes.attribute_range())
289  {
290  if(i.first == game["mp_scenario"] && i.second == hash) {
291  hash_found = true;
292  break;
293  }
294  }
295  if(!hash_found) {
296  remote_scenario = true;
297  map_info += " — ";
298  map_info += _("Remote scenario");
299  verified = false;
300  }
301  }
302  }
303  } else {
304  utils::string_map symbols;
305  symbols["scenario_id"] = game["mp_scenario"];
306  scenario = vgettext("Unknown scenario: $scenario_id", symbols);
307  map_info += scenario;
308  verified = false;
309  }
310  } else {
311  scenario = _("Unknown scenario");
312  map_info += scenario;
313  verified = false;
314  }
315  if(reloaded) {
316  map_info += " — ";
317  map_info += _("Reloaded game");
318  verified = false;
319  }
320 
321  if(!turn.empty()) {
322  started = true;
323  int index = turn.find_first_of('/');
324  if(index > -1) {
325  const std::string current_turn_string = turn.substr(0, index);
326  current_turn = lexical_cast<unsigned int>(current_turn_string);
327  }
328  status = _("Turn ") + turn;
329  } else {
330  started = false;
331  if(vacant_slots > 0) {
333  _n("Vacant Slot:", "Vacant Slots:", vacant_slots))
334  + " " + game["slots"];
335  }
336  }
337 
338  if(fog) {
339  vision = _("Fog");
340  if(shroud) {
341  vision += "/";
342  vision += _("Shroud");
343  }
344  } else if(shroud) {
345  vision = _("Shroud");
346  } else {
347  vision = _("none");
348  }
349  if(game["mp_countdown"].to_bool()) {
350  time_limit = game["mp_countdown_init_time"].str() + "+"
351  + game["mp_countdown_turn_bonus"].str() + "/"
352  + game["mp_countdown_action_bonus"].str();
353  } else {
354  time_limit = "";
355  }
356 }
357 
359 {
360  return have_era && have_all_mods && !started && vacant_slots > 0;
361 }
362 
364 {
365  return (have_era && have_all_mods && observers)
367 }
368 
370 {
371  switch(display_status) {
372  case game_info::CLEAN:
373  return "clean";
374  case game_info::NEW:
375  return "new";
376  case game_info::DELETED:
377  return "deleted";
378  case game_info::UPDATED:
379  return "updated";
380  default:
381  ERR_CF << "BAD display_status " << display_status << " in game "
382  << id << "\n";
383  return "?";
384  }
385 }
386 
388 {
389 }
390 
392 {
393  for(auto f : filters_)
394  {
395  delete f;
396  }
397 }
398 
400 {
401  filters_.push_back(f);
402 }
403 
405 {
406  for(auto f : filters_)
407  {
408  delete f;
409  }
410  filters_.clear();
411 }
412 
414 {
415  for(auto f : filters_)
416  {
417  if(!f->match(game))
418  return false;
419  }
420  return true;
421 }
422 
424 {
425  const std::string& s1 = game.map_info;
426  const std::string& s2 = game.name;
427  return std::search(s1.begin(),
428  s1.end(),
429  value_.begin(),
430  value_.end(),
431  chars_equal_insensitive) != s1.end()
432  || std::search(s2.begin(),
433  s2.end(),
434  value_.begin(),
435  value_.end(),
436  chars_equal_insensitive) != s2.end();
437 }
static lg::log_domain log_lobby("lobby")
std::string status
Definition: data.hpp:158
child_itors child_range(const std::string &key)
Definition: config.cpp:613
bool fog
Definition: data.hpp:165
const char * display_status_string() const
Definition: data.cpp:369
void clear()
Definition: data.cpp:404
std::string map_info
Definition: data.hpp:149
bool started
Definition: data.hpp:164
std::vector< game_filter_base * > filters_
Definition: data.hpp:235
This class represents the information a client has about a room.
Definition: data.hpp:65
std::string era()
const GLfloat * c
Definition: glew.h:12741
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::deque< chat_message > history_
Definition: data.hpp:59
std::string time_limit
Definition: data.hpp:159
void clear()
Definition: data.cpp:66
static lg::log_domain log_engine("engine")
bool can_observe() const
Definition: data.cpp:363
const std::string unicode_multiplication_sign
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
game_display_status display_status
Definition: data.hpp:184
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
bool shroud
Definition: data.hpp:166
bool empty() const
Definition: config.cpp:1105
To lexical_cast(From value)
Lexical cast converts one type to another.
Definitions for the interface to Wesnoth Markup Language (WML).
user_relation relation
Definition: data.hpp:127
std::string vision
Definition: data.hpp:157
std::string scenario
Definition: data.hpp:147
bool observers
Definition: data.hpp:167
game_info(const config &c, const config &game_config)
Definition: data.cpp:164
bool match(const game_info &game) const
Definition: data.cpp:423
bool have_era
Definition: data.hpp:172
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
std::string map_size_info
Definition: data.hpp:150
user_state state
Definition: data.hpp:128
bool chars_equal_insensitive(char a, char b)
Definition: util.hpp:206
room_info(const std::string &name)
Definition: data.cpp:71
std::map< std::string, t_string > string_map
bool is_friend(const std::string &nick)
GLuint id
Definition: glew.h:1647
#define ERR_CF
Definition: data.cpp:33
int w() const
Effective map width.
Definition: map.hpp:105
chat_message(const time_t &timestamp, const std::string &user, const std::string &message)
Create a chat message.
Definition: data.cpp:42
bool match(const game_info &game) const
Definition: data.cpp:413
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated...
Encapsulates the map of the game.
Definition: map.hpp:37
static UNUSEDNOWARN std::string _n(const char *str1, const char *str2, int n)
Definition: gettext.hpp:86
int game_id
Definition: data.hpp:126
bool have_all_mods
Definition: data.hpp:173
bool remote_scenario
Definition: data.hpp:148
bool is_member(const std::string &user) const
Definition: data.cpp:75
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
std::string map_data
Definition: data.hpp:145
bool is_ignored(const std::string &nick)
size_t vacant_slots
Definition: data.hpp:160
std::string read_map(const std::string &name)
std::string login()
void add_member(const std::string &user)
Definition: data.cpp:80
void add_message(const time_t &timestamp, const std::string &user, const std::string &message)
Definition: data.cpp:53
void update_relation()
Definition: data.cpp:129
int h() const
Effective map height.
Definition: map.hpp:108
bool reloaded
Definition: data.hpp:163
Game configuration data as global variables.
Definition: build_info.cpp:38
GLuint index
Definition: glew.h:1782
std::string era_short
Definition: data.hpp:152
size_t i
Definition: function.cpp:1057
chat_log()
Definition: data.cpp:49
void append(game_filter_base *f)
Takes ownership.
Definition: data.cpp:399
Declarations for File-IO.
void process_room_members(const config &data)
Definition: data.cpp:90
std::string vgettext(const char *msgid, const utils::string_map &symbols)
GLuint const GLchar * name
Definition: glew.h:1782
void remove_member(const std::string &user)
Definition: data.cpp:85
std::set< std::string > members_
Definition: data.hpp:94
const GLdouble * m
Definition: glew.h:6968
This class represents the info a client has about a game on the server.
Definition: data.hpp:136
static bool timestamp
Definition: log.cpp:46
To lexical_cast_default(From a, To def=To())
Definition: util.hpp:103
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 update_state(int selected_game_id, const room_info *current_room=nullptr)
Definition: data.cpp:110
config & find_child(const std::string &key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:1010
Standard logging facilities (interface).
virtual ~game_filter_stack()
Definition: data.cpp:391
std::string message
Definition: exceptions.hpp:29
static lg::log_domain log_config("config")
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
unsigned int current_turn
Definition: data.hpp:162
#define e
user_info(const config &c)
Definition: data.cpp:99
void chat_message(std::string const &caption, std::string const &msg)
Displays a message in the chat window.
Definition: lua_api.cpp:48
bool verified
Definition: data.hpp:170
std::string name
Definition: data.hpp:146
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
Helper class, don't construct this directly.
std::string era
Definition: data.hpp:151
GLsizei const GLcharARB ** string
Definition: glew.h:4503
bool can_join() const
Definition: data.cpp:358
GLclampf f
Definition: glew.h:3024