Pol  Revision:cb584c9
uworld.h
Go to the documentation of this file.
1 
10 #ifndef UWORLD_H
11 #define UWORLD_H
12 
13 #ifndef __UOBJECT_H
14 #include "uobject.h"
15 #endif
16 #ifndef ITEM_H
17 #include "item/item.h"
18 #endif
19 #ifndef MULTI_H
20 #include "multi/multi.h"
21 #endif
22 #ifndef __CHARACTR_H
23 #include "mobile/charactr.h"
24 #endif
25 #include <algorithm>
26 #include <vector>
27 
28 #include "../clib/passert.h"
29 #include "../clib/rawtypes.h"
30 #include "../plib/realmdescriptor.h"
32 #include "realms/realm.h"
33 #include "uconst.h"
34 #include "zone.h"
35 
36 namespace Pol
37 {
38 namespace Core
39 {
40 void add_item_to_world( Items::Item* item );
42 
43 void add_multi_to_world( Multi::UMulti* multi );
44 void remove_multi_from_world( Multi::UMulti* multi );
45 void move_multi_in_world( unsigned short oldx, unsigned short oldy, unsigned short newx,
46  unsigned short newy, Multi::UMulti* multi, Realms::Realm* oldrealm );
47 
48 void SetCharacterWorldPosition( Mobile::Character* chr, Realms::WorldChangeReason reason );
49 void ClrCharacterWorldPosition( Mobile::Character* chr, Realms::WorldChangeReason reason );
50 void MoveCharacterWorldPosition( unsigned short oldx, unsigned short oldy, unsigned short newx,
51  unsigned short newy, Mobile::Character* chr,
52  Realms::Realm* oldrealm );
53 
54 void SetItemWorldPosition( Items::Item* item );
55 void ClrItemWorldPosition( Items::Item* item );
56 void MoveItemWorldPosition( unsigned short oldx, unsigned short oldy, Items::Item* item,
57  Realms::Realm* oldrealm );
58 
60 int get_mobile_count();
61 
62 void optimize_zones();
63 
64 typedef std::vector<Mobile::Character*> ZoneCharacters;
65 typedef std::vector<Multi::UMulti*> ZoneMultis;
66 typedef std::vector<Items::Item*> ZoneItems;
67 
68 struct Zone
69 {
70  ZoneCharacters characters;
71  ZoneCharacters npcs;
72  ZoneItems items;
73  ZoneMultis multis;
74 };
75 
76 inline void zone_convert( unsigned short x, unsigned short y, unsigned short* wx,
77  unsigned short* wy, const Realms::Realm* realm )
78 {
79  passert( x < realm->width() );
80  passert( y < realm->height() );
81 
82  ( *wx ) = x >> Plib::WGRID_SHIFT;
83  ( *wy ) = y >> Plib::WGRID_SHIFT;
84 }
85 
86 inline void zone_convert_clip( int x, int y, const Realms::Realm* realm, unsigned short* wx,
87  unsigned short* wy )
88 {
89  if ( x < 0 )
90  x = 0;
91  if ( y < 0 )
92  y = 0;
93  if ( (unsigned)x >= realm->width() )
94  x = realm->width() - 1;
95  if ( (unsigned)y >= realm->height() )
96  y = realm->height() - 1;
97 
98  ( *wx ) = static_cast<unsigned short>( x >> Plib::WGRID_SHIFT );
99  ( *wy ) = static_cast<unsigned short>( y >> Plib::WGRID_SHIFT );
100 }
101 
102 inline Zone& getzone( unsigned short x, unsigned short y, Realms::Realm* realm )
103 {
104  passert( x < realm->width() );
105  passert( y < realm->height() );
106 
107  return realm->zone[x >> Plib::WGRID_SHIFT][y >> Plib::WGRID_SHIFT];
108 }
109 
110 namespace
111 {
112 struct CoordsArea;
113 }
114 // Helper functions to iterator over world items in given realm an range
115 // takes any function with only one open parameter
116 // its recommended to use lambdas even if std::bind can also be used, but a small benchmark showed
117 // that std::bind is a bit slower (compiler can optimize better lambdas)
118 // Usage:
119 // WorldIterator<PlayerFilter>::InRange(...)
120 
121 // main struct, define as template param which filter to use
122 template <class Filter>
124 {
125  template <typename F>
126  static void InRange( u16 x, u16 y, const Realms::Realm* realm, unsigned range, F&& f );
127  template <typename F>
128  static void InVisualRange( const UObject* obj, F&& f );
129  template <typename F>
130  static void InBox( u16 x1, u16 y1, u16 x2, u16 y2, const Realms::Realm* realm, F&& f );
131 
132 protected:
133  template <typename F>
134  static void _forEach( const CoordsArea& coords, const Realms::Realm* realm, F&& f );
135 };
136 
137 enum class FilterType
138 {
139  Mobile, // iterator over npcs and players
140  Player, // iterator over player
141  OnlinePlayer, // iterator over online player
142  NPC, // iterator over npcs
143  Item, // iterator over items
144  Multi // iterator over multis
145 };
146 
147 // Filter implementation struct,
148 // specializations for the enum values are given
149 template <FilterType T>
150 struct FilterImp
151 {
152  friend struct WorldIterator<FilterImp<T>>;
153 
154 protected:
155  template <typename F>
156  static void call( Core::Zone& zone, const CoordsArea& coords, F&& f );
157 };
158 
159 // shortcuts for filtering
166 
167 namespace
168 {
169 // template independent code
170 struct CoordsArea
171 {
172  // structure to hold the world and shifted coords
173  CoordsArea( u16 x, u16 y, const Realms::Realm* realm, unsigned range ); // create from range
174  CoordsArea( u16 x1, u16 y1, u16 x2, u16 y2, const Realms::Realm* realm ); // create from box
175  bool inRange( const UObject* obj ) const;
176 
177  // shifted coords
182 
183 private:
184  void convert( int xL, int yL, int xH, int yH, const Realms::Realm* realm );
185 
186  // plain coords
187  int _xL;
188  int _yL;
189  int _xH;
190  int _yH;
191 };
192 }
194 // imp
195 namespace
196 {
197 CoordsArea::CoordsArea( u16 x, u16 y, const Realms::Realm* realm, unsigned range )
198 {
199  convert( x - range, y - range, x + range, y + range, realm );
200  _xL = x - range;
201  if ( _xL < 0 )
202  _xL = 0;
203  _yL = y - range;
204  if ( _yL < 0 )
205  _yL = 0;
206  _xH = x + range;
207  _yH = y + range;
208 }
209 
210 CoordsArea::CoordsArea( u16 x1, u16 y1, u16 x2, u16 y2, const Realms::Realm* realm )
211 {
212  convert( x1, y1, x2, y2, realm );
213  _xL = x1;
214  _yL = y1;
215  _xH = x2;
216  _yH = y2;
217 }
218 
219 bool CoordsArea::inRange( const UObject* obj ) const
220 {
221  return ( obj->x >= _xL && obj->x <= _xH && obj->y >= _yL && obj->y <= _yH );
222 }
223 
224 void CoordsArea::convert( int xL, int yL, int xH, int yH, const Realms::Realm* realm )
225 {
226  zone_convert_clip( xL, yL, realm, &wxL, &wyL );
227  zone_convert_clip( xH, yH, realm, &wxH, &wyH );
228  passert( wxL <= wxH );
229  passert( wyL <= wyH );
230 }
231 } // namespace
232 
233 template <class Filter>
234 template <typename F>
235 void WorldIterator<Filter>::InRange( u16 x, u16 y, const Realms::Realm* realm, unsigned range,
236  F&& f )
237 {
238  if ( realm == nullptr )
239  return;
240  CoordsArea coords( x, y, realm, range );
241  _forEach( coords, realm, std::forward<F>( f ) );
242 }
243 template <class Filter>
244 template <typename F>
246 {
247  InRange( obj->toplevel_owner()->x, obj->toplevel_owner()->y, obj->toplevel_owner()->realm,
248  RANGE_VISUAL, std::forward<F>( f ) );
249 }
250 template <class Filter>
251 template <typename F>
252 void WorldIterator<Filter>::InBox( u16 x1, u16 y1, u16 x2, u16 y2, const Realms::Realm* realm,
253  F&& f )
254 {
255  if ( realm == nullptr )
256  return;
257  CoordsArea coords( x1, y1, x2, y2, realm );
258  _forEach( coords, realm, std::forward<F>( f ) );
259 }
260 
261 template <class Filter>
262 template <typename F>
263 void WorldIterator<Filter>::_forEach( const CoordsArea& coords, const Realms::Realm* realm, F&& f )
264 {
265  for ( u16 wx = coords.wxL; wx <= coords.wxH; ++wx )
266  {
267  for ( u16 wy = coords.wyL; wy <= coords.wyH; ++wy )
268  {
269  Filter::call( realm->zone[wx][wy], coords, f );
270  }
271  }
272 }
273 
274 // specializations of FilterImp
275 
276 template <>
277 template <typename F>
278 void FilterImp<FilterType::Mobile>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
279 {
280  for ( auto& chr : zone.characters )
281  {
282  if ( coords.inRange( chr ) )
283  f( chr );
284  }
285  for ( auto& npc : zone.npcs )
286  {
287  if ( coords.inRange( npc ) )
288  f( npc );
289  }
290 }
291 
292 template <>
293 template <typename F>
294 void FilterImp<FilterType::Player>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
295 {
296  for ( auto& chr : zone.characters )
297  {
298  if ( coords.inRange( chr ) )
299  f( chr );
300  }
301 }
302 
303 template <>
304 template <typename F>
305 void FilterImp<FilterType::OnlinePlayer>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
306 {
307  for ( auto& chr : zone.characters )
308  {
309  if ( chr->has_active_client() )
310  {
311  if ( coords.inRange( chr ) )
312  f( chr );
313  }
314  }
315 }
316 
317 template <>
318 template <typename F>
319 void FilterImp<FilterType::NPC>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
320 {
321  for ( auto& npc : zone.npcs )
322  {
323  if ( coords.inRange( npc ) )
324  f( npc );
325  }
326 }
327 
328 template <>
329 template <typename F>
330 void FilterImp<FilterType::Item>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
331 {
332  for ( auto& item : zone.items )
333  {
334  if ( coords.inRange( item ) )
335  f( item );
336  }
337 }
338 
339 template <>
340 template <typename F>
341 void FilterImp<FilterType::Multi>::call( Core::Zone& zone, const CoordsArea& coords, F&& f )
342 {
343  for ( auto& multi : zone.multis )
344  {
345  if ( coords.inRange( multi ) )
346  f( multi );
347  }
348 }
349 }
350 }
351 #endif
u16 wyH
Definition: uworld.h:181
void SetItemWorldPosition(Items::Item *item)
int get_toplevel_item_count()
Definition: uworld.cpp:109
int _xH
Definition: uworld.h:189
void ClrItemWorldPosition(Items::Item *item)
static void call(Core::Zone &zone, const CoordsArea &coords, F &&f)
void add_item_to_world(Items::Item *item)
Definition: uworld.cpp:31
int get_mobile_count()
Definition: uworld.cpp:117
FilterImp< FilterType::OnlinePlayer > OnlinePlayerFilter
Definition: uworld.h:162
u16 wyL
Definition: uworld.h:179
void SetCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:128
const unsigned WGRID_SHIFT
FilterImp< FilterType::Mobile > MobileFilter
Definition: uworld.h:160
static void InRange(u16 x, u16 y, const Realms::Realm *realm, unsigned range, F &&f)
Definition: uworld.h:235
FilterType
Definition: uworld.h:137
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
unsigned short u16
Definition: rawtypes.h:26
int _xL
Definition: uworld.h:187
void zone_convert_clip(int x, int y, const Realms::Realm *realm, unsigned short *wx, unsigned short *wy)
Definition: uworld.h:86
#define RANGE_VISUAL
Definition: uconst.h:72
#define F(x, y, z)
FilterImp< FilterType::NPC > NPCFilter
Definition: uworld.h:163
static void _forEach(const CoordsArea &coords, const Realms::Realm *realm, F &&f)
Definition: uworld.h:263
FilterImp< FilterType::Multi > MultiFilter
Definition: uworld.h:165
u16 wxH
Definition: uworld.h:180
std::vector< Multi::UMulti * > ZoneMultis
Definition: uworld.h:65
unsigned short height() const
Definition: realm.h:245
void optimize_zones()
Definition: uworld.cpp:388
#define passert(exp)
Definition: passert.h:62
virtual UObject * toplevel_owner()
Definition: uobject.cpp:234
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
FilterImp< FilterType::Player > PlayerFilter
Definition: uworld.h:161
int _yL
Definition: uworld.h:188
static void InVisualRange(const UObject *obj, F &&f)
Definition: uworld.h:245
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
int _yH
Definition: uworld.h:190
ZoneItems items
Definition: uworld.h:72
Realms::Realm * realm
Definition: baseobject.h:56
FilterImp< FilterType::Item > ItemFilter
Definition: uworld.h:164
unsigned short width() const
Definition: realm.h:241
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
ZoneMultis multis
Definition: uworld.h:73
u16 wxL
Definition: uworld.h:178
void remove_multi_from_world(Multi::UMulti *multi)
Definition: uworld.cpp:76
void MoveItemWorldPosition(unsigned short oldx, unsigned short oldy, Items::Item *item, Realms::Realm *oldrealm)
Definition: uworld.cpp:214
Definition: berror.cpp:12
static void InBox(u16 x1, u16 y1, u16 x2, u16 y2, const Realms::Realm *realm, F &&f)
Definition: uworld.h:252