Pol  Revision:cb584c9
decay.cpp
Go to the documentation of this file.
1 
11 #include "decay.h"
12 
13 #include <stddef.h>
14 
15 #include "../clib/esignal.h"
16 #include "../clib/logfacility.h"
17 #include "../plib/systemstate.h"
18 #include "gameclck.h"
19 #include "globals/state.h"
20 #include "globals/uvars.h"
21 #include "item/item.h"
22 #include "item/itemdesc.h"
23 #include "polcfg.h"
24 #include "polsem.h"
25 #include "realms/realm.h"
26 #include "scrdef.h"
27 #include "scrsched.h"
28 #include "syshook.h"
29 #include "ufunc.h"
30 #include "uoscrobj.h"
31 #include "uworld.h"
32 
33 
34 namespace Pol
35 {
36 namespace Core
37 {
54 
55 void decay_worldzone( unsigned wx, unsigned wy, Realms::Realm* realm )
56 {
57  Zone& zone = realm->zone[wx][wy];
60 
61  for ( ZoneItems::size_type idx = 0; idx < zone.items.size(); ++idx )
62  {
63  Items::Item* item = zone.items[idx];
64  if ( statistics )
65  {
66  if ( item->can_decay() )
67  {
68  const Items::ItemDesc& descriptor = item->itemdesc();
69  if ( !descriptor.decays_on_multis )
70  {
71  Multi::UMulti* multi = realm->find_supporting_multi( item->x, item->y, item->z );
72  if ( multi == nullptr )
74  }
75  else
77  }
78  }
79  if ( item->should_decay( now ) )
80  {
81  // check the CanDecay syshook first if it returns 1 go over to other checks
83  {
85  continue;
86  }
87 
88  const Items::ItemDesc& descriptor = item->itemdesc();
89  Multi::UMulti* multi = realm->find_supporting_multi( item->x, item->y, item->z );
90 
91  // some things don't decay on multis:
92  if ( multi != nullptr && !descriptor.decays_on_multis )
93  continue;
94 
95  if ( statistics )
97 
98  if ( !descriptor.destroy_script.empty() && !item->inuse() )
99  {
100  bool decayok = call_script( descriptor.destroy_script, item->make_ref() );
101  if ( !decayok )
102  continue;
103  }
104 
105  item->spill_contents( multi );
106  destroy_item( item );
107  --idx;
108  }
109  }
110 }
111 
112 
113 // this is used in single-thread mode only
115 {
116  static unsigned wx = ~0u;
117  static unsigned wy = 0;
118 
119  Realms::Realm* realm;
120  for ( auto itr = gamestate.Realms.begin(); itr != gamestate.Realms.end(); ++itr )
121  {
122  realm = *itr;
124  {
126 
127  unsigned gridwidth = realm->grid_width();
128  unsigned gridheight = realm->grid_height();
129 
130  if ( ++wx >= gridwidth )
131  {
132  wx = 0;
133  if ( ++wy >= gridheight )
134  {
135  wy = 0;
136  }
137  }
138  decay_worldzone( wx, wy, realm );
139  }
140  }
141 }
142 
148 
149 void decay_single_zone( Realms::Realm* realm, unsigned gridx, unsigned gridy, unsigned& wx,
150  unsigned& wy )
151 {
152  if ( ++wx >= gridx )
153  {
154  wx = 0;
155  if ( ++wy >= gridy )
156  {
157  wy = 0;
158  }
159  }
160  decay_worldzone( wx, wy, realm );
161 }
162 
163 void decay_thread( void* arg ) // Realm*
164 {
165  unsigned wx = ~0u;
166  unsigned wy = 0;
167  Realms::Realm* realm = static_cast<Realms::Realm*>( arg );
168 
169  unsigned gridwidth = realm->grid_width();
170  unsigned gridheight = realm->grid_height();
171 
172  unsigned sleeptime = ( 60 * 10L * 1000 ) / ( gridwidth * gridheight );
173  while ( !Clib::exit_signalled )
174  {
175  {
176  PolLock lck;
178  decay_single_zone( realm, gridwidth, gridheight, wx, wy );
180  }
181  // sweep entire world every 10 minutes
182  // (60 * 10 * 1000) / (96 * 64) -> (600000 / 6144) -> 97 ms
183 
184  pol_sleep_ms( sleeptime );
185  }
186 }
187 
188 void decay_thread_shadow( void* arg ) // Realm*
189 {
190  unsigned wx = ~0u;
191  unsigned wy = 0;
192  unsigned id = static_cast<Realms::Realm*>( arg )->shadowid;
193 
194  if ( gamestate.shadowrealms_by_id[id] == nullptr )
195  return;
196  unsigned gridwidth = gamestate.shadowrealms_by_id[id]->grid_width();
197  unsigned gridheight = gamestate.shadowrealms_by_id[id]->grid_height();
198 
199  unsigned sleeptime = ( 60 * 10L * 1000 ) / ( gridwidth * gridheight );
200  while ( !Clib::exit_signalled )
201  {
202  {
203  PolLock lck;
205  if ( gamestate.shadowrealms_by_id[id] == nullptr ) // is realm still there?
206  break;
207  decay_single_zone( gamestate.shadowrealms_by_id[id], gridwidth, gridheight, wx, wy );
209  }
210  // sweep entire world every 10 minutes
211  // (60 * 10 * 1000) / (96 * 64) -> (600000 / 6144) -> 97 ms
212 
213  pol_sleep_ms( sleeptime );
214  }
215 }
216 
217 bool should_switch_realm( size_t index, unsigned x, unsigned y, unsigned* gridx, unsigned* gridy )
218 {
219  (void)x;
220  if ( index >= gamestate.Realms.size() )
221  return true;
222  Realms::Realm* realm = gamestate.Realms[index];
223  if ( realm == nullptr )
224  return true;
225 
226  ( *gridx ) = realm->grid_width();
227  ( *gridy ) = realm->grid_height();
228 
229  // check if ++y would result in reset
230  if ( y + 1 >= ( *gridy ) )
231  return true;
232  return false;
233 }
234 
235 void decay_single_thread( void* arg )
236 {
237  (void)arg;
238  // calculate total grid count, based on current realms
239  unsigned total_grid_count = 0;
240  for ( const auto& realm : gamestate.Realms )
241  {
242  total_grid_count += ( realm->grid_width() * realm->grid_height() );
243  }
244  if ( !total_grid_count )
245  {
246  POLLOG_ERROR << "No realm grids?!\n";
247  return;
248  }
249  // sweep every realm ~10minutes -> 36ms for 6 realms
250  unsigned sleeptime = ( 60 * 10L * 1000 ) / total_grid_count;
251  sleeptime = std::max( sleeptime, 30u ); // limit to 30ms
252  bool init = true;
253  size_t realm_index = ~0u;
254  unsigned wx = 0;
255  unsigned wy = 0;
256  unsigned gridx = 0;
257  unsigned gridy = 0;
258  while ( !Clib::exit_signalled )
259  {
260  {
261  PolLock lck;
263  // check if realm_index is still valid and if y is still in valid range
264  if ( should_switch_realm( realm_index, wx, wy, &gridx, &gridy ) )
265  {
266  ++realm_index;
267  if ( realm_index >= gamestate.Realms.size() )
268  {
269  realm_index = 0;
270  if ( !init && Plib::systemstate.config.thread_decay_statistics )
271  {
278  POLLOG_INFO.Format(
279  "DECAY STATISTICS: decayed: max {} mean {} variance {} runs {} active max {} mean "
280  "{} variance {} runs {}\n" )
289  }
290  init = false;
291  }
292  wx = 0;
293  wy = 0;
294  }
295  else
296  {
297  if ( ++wx >= gridx )
298  {
299  wx = 0;
300  if ( ++wy >= gridy )
301  {
302  POLLOG_ERROR << "SHOULD NEVER HAPPEN\n";
303  wy = 0;
304  }
305  }
306  }
307  decay_worldzone( wx, wy, gamestate.Realms[realm_index] );
309  }
310  pol_sleep_ms( sleeptime );
311  }
312 }
313 }
314 }
bool empty() const
Definition: scrdef.h:41
void decay_thread_shadow(void *arg)
Definition: decay.cpp:188
void pol_sleep_ms(unsigned int millis)
Definition: polclock.cpp:46
unsigned int gameclock_t
Definition: gameclck.h:14
void update(double value)
Definition: clib_utils.cpp:16
bool should_decay(unsigned int gameclock) const
Definition: item.cpp:969
virtual Bscript::BObjectImp * make_ref() POL_OVERRIDE
Definition: uoscrobj.cpp:1628
SystemState systemstate
Definition: systemstate.cpp:12
bool should_switch_realm(size_t index, unsigned x, unsigned y, unsigned *gridx, unsigned *gridy)
Definition: decay.cpp:217
bool call(Bscript::BObjectImp *p0)
Definition: syshook.cpp:44
Core::PolConfig config
Definition: systemstate.h:43
SystemHooks system_hooks
Definition: uvars.h:190
#define POLLOG_INFO
Definition: logfacility.h:213
void decay_single_zone(Realms::Realm *realm, unsigned gridx, unsigned gridy, unsigned &wx, unsigned &wy)
[3] Decay Sweep Each 64x64 tile World Zone is checked for decay approximately once every 10 minutes ...
Definition: decay.cpp:149
size_t cycles_per_decay_worldzone
Definition: state.h:35
#define POLLOG_ERROR
Definition: logfacility.h:207
Core::ScriptDef destroy_script
Definition: itemdesc.h:102
bool call_script(const ScriptDef &script, Bscript::BObjectImp *param0)
Definition: scrsched.cpp:546
void destroy_item(Item *item)
Definition: ufunc.cpp:1538
ExportedFunction * can_decay
Definition: syshook.h:77
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
unsigned short grid_width() const
Definition: realm.cpp:105
virtual void spill_contents(Multi::UMulti *supporting_multi)
Definition: item.cpp:926
void decay_single_thread(void *arg)
Definition: decay.cpp:235
unsigned short grid_height() const
Definition: realm.cpp:109
size_t cycles_until_decay_worldzone
Definition: state.h:36
struct Pol::Core::StateManager::@8 decay_statistics
Clib::OnlineStatistics active_decay
Definition: state.h:59
void decay_worldzone(unsigned wx, unsigned wy, Realms::Realm *realm)
[1] Item Decay Criteria An Item is allowed to decay if ALL of the following are true: ...
Definition: decay.cpp:55
gameclock_t read_gameclock()
Reads the current value of the game clock.
Definition: gameclck.cpp:57
GameState gamestate
Definition: uvars.cpp:74
void polclock_checkin()
Definition: pol.cpp:520
StateManager stateManager
Definition: state.cpp:8
ZoneItems items
Definition: uworld.h:72
double variance() const
Definition: clib_utils.cpp:25
Core::Zone ** zone
Definition: realm.h:133
void restart_all_clients()
Definition: pol.cpp:505
Clib::OnlineStatistics decayed
Definition: state.h:58
bool inuse() const
Definition: item.h:314
const ItemDesc & itemdesc() const
Definition: item.cpp:127
Multi::UMulti * find_supporting_multi(unsigned short x, unsigned short y, short z) const
Definition: realmfunc.cpp:709
std::map< int, Realms::Realm * > shadowrealms_by_id
Definition: uvars.h:164
void decay_items()
Definition: decay.cpp:114
Definition: berror.cpp:12
std::atomic< bool > exit_signalled
bool thread_decay_statistics
Definition: polcfg.h:97
bool can_decay() const
Definition: item.cpp:964
void decay_thread(void *arg)
Definition: decay.cpp:163