Pol  Revision:cb584c9
uworld.cpp
Go to the documentation of this file.
1 
14 #include "uworld.h"
15 
16 #include <stddef.h>
17 #include <string>
18 
19 #include "../clib/clib_endian.h"
20 #include "../clib/logfacility.h"
21 #include "../clib/passert.h"
22 #include "globals/uvars.h"
23 #include "item/item.h"
24 #include "mobile/charactr.h"
25 #include "multi/multi.h"
26 
27 namespace Pol
28 {
29 namespace Core
30 {
32 {
33  Zone& zone = getzone( item->x, item->y, item->realm );
34 
35  passert( std::find( zone.items.begin(), zone.items.end(), item ) == zone.items.end() );
36 
37  item->realm->add_toplevel_item( *item );
38  zone.items.push_back( item );
39 }
40 
42 {
43  // Unregister the item if it is on a multi
44  if ( item->container == nullptr && !item->has_gotten_by() )
45  {
46  Multi::UMulti* multi = item->realm->find_supporting_multi( item->x, item->y, item->z );
47 
48  if ( multi != nullptr )
49  multi->unregister_object( item );
50  }
51 
52  Zone& zone = getzone( item->x, item->y, item->realm );
53 
54  ZoneItems::iterator itr = std::find( zone.items.begin(), zone.items.end(), item );
55  if ( itr == zone.items.end() )
56  {
57  POLLOG_ERROR.Format(
58  "remove_item_from_world: item 0x{:X} at {},{} does not exist in world zone ( Old Serial: "
59  "0x{:X} )\n" )
60  << item->serial << item->x << item->y << ( cfBEu32( item->serial_ext ) );
61 
62  passert( itr != zone.items.end() );
63  }
64 
65  item->realm->remove_toplevel_item( *item );
66  zone.items.erase( itr );
67 }
68 
70 {
71  Zone& zone = getzone( multi->x, multi->y, multi->realm );
72  zone.multis.push_back( multi );
73  multi->realm->add_multi( *multi );
74 }
75 
77 {
78  Zone& zone = getzone( multi->x, multi->y, multi->realm );
79  ZoneMultis::iterator itr = std::find( zone.multis.begin(), zone.multis.end(), multi );
80 
81  passert( itr != zone.multis.end() );
82 
83  multi->realm->remove_multi( *multi );
84  zone.multis.erase( itr );
85 }
86 
87 void move_multi_in_world( unsigned short oldx, unsigned short oldy, unsigned short newx,
88  unsigned short newy, Multi::UMulti* multi, Realms::Realm* oldrealm )
89 {
90  Zone& oldzone = getzone( oldx, oldy, oldrealm );
91  Zone& newzone = getzone( newx, newy, multi->realm );
92 
93  if ( &oldzone != &newzone )
94  {
95  ZoneMultis::iterator itr = std::find( oldzone.multis.begin(), oldzone.multis.end(), multi );
96  passert( itr != oldzone.multis.end() );
97 
98  oldzone.multis.erase( itr );
99  newzone.multis.push_back( multi );
100  }
101 
102  if ( multi->realm != oldrealm )
103  {
104  oldrealm->remove_multi( *multi );
105  multi->realm->add_multi( *multi );
106  }
107 }
108 
110 {
111  int count = 0;
112  for ( const auto& realm : gamestate.Realms )
113  count += realm->toplevel_item_count();
114  return count;
115 }
116 
118 {
119  int count = 0;
120  for ( const auto& realm : gamestate.Realms )
121  count += realm->mobile_count();
122  return count;
123 }
124 
125 // 4-17-04 Rac destroyed the world! in favor of splitting its duties amongst the realms
126 // World world;
127 
129 {
130  Zone& zone = getzone( chr->x, chr->y, chr->realm );
131 
132  auto set_pos = [&]( ZoneCharacters& set ) {
133  passert( std::find( set.begin(), set.end(), chr ) == set.end() );
134  set.push_back( chr );
135  };
136 
137  if ( chr->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
138  set_pos( zone.npcs );
139  else
140  set_pos( zone.characters );
141 
142  chr->realm->add_mobile( *chr, reason );
143 }
144 
145 // Function for reporting the whereabouts of chars which are not in their expected zone
146 // (hopefully will never be called)
148 
150 {
151  Zone& zone = getzone( chr->x, chr->y, chr->realm );
152 
153  auto clear_pos = [&]( ZoneCharacters& set ) {
154  auto itr = std::find( set.begin(), set.end(), chr );
155  if ( itr == set.end() )
156  {
158  chr, reason ); // Uh-oh, char was not in the expected zone. Find it and report.
159  passert( itr != set.end() );
160  }
161  chr->realm->remove_mobile( *chr, reason );
162  set.erase( itr );
163  };
164 
165  if ( !chr->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
166  clear_pos( zone.characters );
167  else
168  clear_pos( zone.npcs );
169 }
170 
171 void MoveCharacterWorldPosition( unsigned short oldx, unsigned short oldy, unsigned short newx,
172  unsigned short newy, Mobile::Character* chr,
173  Realms::Realm* oldrealm )
174 {
175  if ( oldrealm == nullptr )
176  oldrealm = chr->realm;
177 
178  // If the char is logged in (logged_in is always true for NPCs), update its position
179  // in the world zones
180  if ( chr->logged_in() )
181  {
182  Zone& oldzone = getzone( oldx, oldy, oldrealm );
183  Zone& newzone = getzone( newx, newy, chr->realm );
184 
185  if ( &oldzone != &newzone )
186  {
187  auto move_pos = [&]( ZoneCharacters& oldset, ZoneCharacters& newset ) {
188  auto oldset_itr = std::find( oldset.begin(), oldset.end(), chr );
189 
190  // ensure it's found in the old realm
191  passert( oldset_itr != oldset.end() );
192  // and that it's not yet in the new realm
193  passert( std::find( newset.begin(), newset.end(), chr ) == newset.end() );
194 
195  oldset.erase( oldset_itr );
196  newset.push_back( chr );
197  };
198 
199  if ( !chr->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
200  move_pos( oldzone.characters, newzone.characters );
201  else
202  move_pos( oldzone.npcs, newzone.npcs );
203  }
204  }
205 
206  // Regardless of online or not, tell the realms that we've left
207  if ( chr->realm != oldrealm )
208  {
211  }
212 }
213 
214 void MoveItemWorldPosition( unsigned short oldx, unsigned short oldy, Items::Item* item,
215  Realms::Realm* oldrealm )
216 {
217  if ( oldrealm == nullptr )
218  oldrealm = item->realm;
219 
220  Zone& oldzone = getzone( oldx, oldy, oldrealm );
221  Zone& newzone = getzone( item->x, item->y, item->realm );
222 
223  if ( &oldzone != &newzone )
224  {
225  ZoneItems::iterator itr = std::find( oldzone.items.begin(), oldzone.items.end(), item );
226 
227  if ( itr == oldzone.items.end() )
228  {
229  POLLOG_ERROR.Format(
230  "MoveItemWorldPosition: item 0x{:X} at old-x/y({},{} - {}) new-x/y({},{} - {}) does not "
231  "exist in world zone. \n" )
232  << item->serial << oldx << oldy << oldrealm->name() << item->x << item->y
233  << item->realm->name();
234 
235  passert( itr != oldzone.items.end() );
236  }
237 
238  oldzone.items.erase( itr );
239 
240  passert( std::find( newzone.items.begin(), newzone.items.end(), item ) == newzone.items.end() );
241  newzone.items.push_back( item );
242  }
243 
244  if ( oldrealm != item->realm )
245  {
246  oldrealm->remove_toplevel_item( *item );
247  item->realm->add_toplevel_item( *item );
248  }
249 }
250 
251 // If the ClrCharacterWorldPosition() fails, this function will find the actual char position and
252 // report
253 // TODO: check if this is really needed...
255 {
256  unsigned wgridx = chr->realm->grid_width();
257  unsigned wgridy = chr->realm->grid_height();
258 
259  std::string msgreason = "unknown reason";
260  switch ( reason )
261  {
263  msgreason = "Client Exit";
264  break;
266  msgreason = "NPC death";
267  break;
268  default:
269  break;
270  }
271 
272  POLLOG_ERROR.Format(
273  "ClrCharacterWorldPosition({}): mob (0x{:X},0x{:X}) supposedly at ({},{}) isn't in correct "
274  "zone\n" )
275  << msgreason << chr->serial << chr->serial_ext << chr->x << chr->y;
276 
277  bool is_npc = chr->isa( Core::UOBJ_CLASS::CLASS_NPC );
278  for ( unsigned zonex = 0; zonex < wgridx; ++zonex )
279  {
280  for ( unsigned zoney = 0; zoney < wgridy; ++zoney )
281  {
282  bool found = false;
283  if ( is_npc )
284  {
285  auto _z = chr->realm->zone[zonex][zoney].npcs;
286  found = std::find( _z.begin(), _z.end(), chr ) != _z.end();
287  }
288  else
289  {
290  auto _z = chr->realm->zone[zonex][zoney].characters;
291  found = std::find( _z.begin(), _z.end(), chr ) != _z.end();
292  }
293  if ( found )
294  POLLOG_ERROR.Format( "ClrCharacterWorldPosition: Found mob in zone ({},{})\n" )
295  << zonex << zoney;
296  }
297  }
298 }
299 // Dave added this for debugging a single zone
300 
302 {
303  try
304  {
305  ZoneItems& witem = realm->zone[x][y].items;
306 
307  for ( const auto& item : witem )
308  {
309  unsigned short wx, wy;
310  zone_convert( item->x, item->y, &wx, &wy, realm );
311  if ( wx != x || wy != y )
312  {
313  POLLOG_ERROR.Format( "Item 0x{:X} in zone ({},{}) but location is ({},{}) (zone {},{})\n" )
314  << item->serial << x << y << item->x << item->y << wx << wy;
315  return false;
316  }
317  }
318  }
319  catch ( ... )
320  {
321  POLLOG_ERROR.Format( "item integ problem at zone ({},{})\n" ) << x << y;
322  return false;
323  }
324  return true;
325 }
326 
327 
329 {
330  bool ok = true;
331  for ( auto& realm : gamestate.Realms )
332  {
333  unsigned int gridwidth = realm->grid_width();
334  unsigned int gridheight = realm->grid_height();
335 
336  for ( unsigned x = 0; x < gridwidth; ++x )
337  {
338  for ( unsigned y = 0; y < gridheight; ++y )
339  {
340  if ( !check_single_zone_item_integrity( x, y, realm ) )
341  ok = false;
342  }
343  }
344  }
345  return ok;
346 }
347 
349 {
350  // TODO: iterate through the object hash?
351  // for( unsigned i = 0; i < characters.size(); ++i )
352  //{
353  // Character* chr = characters[i];
354  // unsigned short wx, wy;
355  // w_convert( chr->x, chr->y, wx, wy );
356  // if (!world.zone[wx][wy].characters.count(chr))
357  // {
358  // cout << "Character " << chr->serial << " at " << chr->x << "," << chr->y << " is not in
359  // its zone." << endl;
360  // }
361  //}
362  for ( auto& realm : gamestate.Realms )
363  {
364  unsigned int gridwidth = realm->grid_width();
365  unsigned int gridheight = realm->grid_height();
366 
367  auto check_zone = []( Mobile::Character* chr, unsigned y, unsigned x ) {
368  unsigned short wx, wy;
369  zone_convert( chr->x, chr->y, &wx, &wy, chr->realm );
370  if ( wx != x || wy != y )
371  INFO_PRINT << "Character 0x" << fmt::hexu( chr->serial ) << " in a zone, but elsewhere\n";
372  };
373 
374  for ( unsigned x = 0; x < gridwidth; ++x )
375  {
376  for ( unsigned y = 0; y < gridheight; ++y )
377  {
378  for ( const auto& chr : realm->zone[x][y].characters )
379  check_zone( chr, y, x );
380  for ( const auto& chr : realm->zone[x][y].npcs )
381  check_zone( chr, y, x );
382  }
383  }
384  }
385 }
386 
387 // reallocates all vectors to fit the current size
389 {
390  for ( auto& realm : gamestate.Realms )
391  {
392  unsigned int gridwidth = realm->grid_width();
393  unsigned int gridheight = realm->grid_height();
394 
395  for ( unsigned x = 0; x < gridwidth; ++x )
396  {
397  for ( unsigned y = 0; y < gridheight; ++y )
398  {
399  realm->zone[x][y].characters.shrink_to_fit();
400  realm->zone[x][y].npcs.shrink_to_fit();
401  realm->zone[x][y].items.shrink_to_fit();
402  realm->zone[x][y].multis.shrink_to_fit();
403  }
404  }
405  }
406 }
407 }
408 }
bool check_single_zone_item_integrity(int, int, Realms::Realm *)
Definition: uworld.cpp:301
void remove_multi(const Multi::UMulti &multi)
Definition: realm.h:219
int get_toplevel_item_count()
Definition: uworld.cpp:109
void remove_toplevel_item(const Items::Item &item)
Definition: realm.h:210
void add_item_to_world(Items::Item *item)
Definition: uworld.cpp:31
void check_character_integrity()
Definition: uworld.cpp:348
int get_mobile_count()
Definition: uworld.cpp:117
void SetCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:128
#define cfBEu32(x)
Definition: clib_endian.h:43
bool logged_in() const
Definition: charactr.cpp:428
#define POLLOG_ERROR
Definition: logfacility.h:207
const std::string name() const
Definition: realm.cpp:124
void remove_item_from_world(Items::Item *item)
Definition: uworld.cpp:41
void add_multi_to_world(Multi::UMulti *multi)
Definition: uworld.cpp:69
ZoneCharacters characters
Definition: uworld.h:70
std::vector< Items::Item * > ZoneItems
Definition: uworld.h:66
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
void add_toplevel_item(const Items::Item &item)
Definition: realm.h:206
unsigned short grid_width() const
Definition: realm.cpp:105
void add_multi(const Multi::UMulti &multi)
Definition: realm.h:215
void optimize_zones()
Definition: uworld.cpp:388
unsigned short grid_height() const
Definition: realm.cpp:109
#define passert(exp)
Definition: passert.h:62
void remove_mobile(const Mobile::Character &chr, WorldChangeReason reason)
Definition: realm.cpp:228
Core::UContainer * container
Definition: item.h:256
void ClrCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:149
Zone & getzone(unsigned short x, unsigned short y, Realms::Realm *realm)
Definition: uworld.h:102
GameState gamestate
Definition: uvars.cpp:74
void add_mobile(const Mobile::Character &chr, WorldChangeReason reason)
Definition: realm.cpp:190
std::vector< Mobile::Character * > ZoneCharacters
Definition: uworld.h:64
void MoveCharacterWorldPosition(unsigned short oldx, unsigned short oldy, unsigned short newx, unsigned short newy, Mobile::Character *chr, Realms::Realm *oldrealm)
Definition: uworld.cpp:171
void zone_convert(unsigned short x, unsigned short y, unsigned short *wx, unsigned short *wy, const Realms::Realm *realm)
Definition: uworld.h:76
ZoneCharacters npcs
Definition: uworld.h:71
ZoneItems items
Definition: uworld.h:72
Realms::Realm * realm
Definition: baseobject.h:56
Core::Zone ** zone
Definition: realm.h:133
void move_multi_in_world(unsigned short oldx, unsigned short oldy, unsigned short newx, unsigned short newy, Multi::UMulti *multi, Realms::Realm *oldrealm)
Definition: uworld.cpp:87
bool isa(UOBJ_CLASS uobj_class) const
Definition: baseobject.h:99
ZoneMultis multis
Definition: uworld.h:73
void remove_multi_from_world(Multi::UMulti *multi)
Definition: uworld.cpp:76
#define INFO_PRINT
Definition: logfacility.h:223
Multi::UMulti * find_supporting_multi(unsigned short x, unsigned short y, short z) const
Definition: realmfunc.cpp:709
virtual void unregister_object(UObject *obj)
Definition: multis.cpp:62
void MoveItemWorldPosition(unsigned short oldx, unsigned short oldy, Items::Item *item, Realms::Realm *oldrealm)
Definition: uworld.cpp:214
Definition: berror.cpp:12
static void find_missing_char_in_zone(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:254
bool check_item_integrity()
Definition: uworld.cpp:328