mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r11138) -Codechange: prepare some subsystems for persistent storage for NewGRFs.
This commit is contained in:
parent
47dd4989a8
commit
c68c83dffa
|
@ -570,6 +570,9 @@
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_station.h">
|
RelativePath=".\..\src\newgrf_station.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\newgrf_storage.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_text.h">
|
RelativePath=".\..\src\newgrf_text.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -1121,6 +1124,9 @@
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_station.cpp">
|
RelativePath=".\..\src\newgrf_station.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\newgrf_storage.cpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_text.cpp">
|
RelativePath=".\..\src\newgrf_text.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
@ -991,6 +991,10 @@
|
||||||
RelativePath=".\..\src\newgrf_station.h"
|
RelativePath=".\..\src\newgrf_station.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\newgrf_storage.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_text.h"
|
RelativePath=".\..\src\newgrf_text.h"
|
||||||
>
|
>
|
||||||
|
@ -1715,6 +1719,10 @@
|
||||||
RelativePath=".\..\src\newgrf_station.cpp"
|
RelativePath=".\..\src\newgrf_station.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\newgrf_storage.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\newgrf_text.cpp"
|
RelativePath=".\..\src\newgrf_text.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -156,6 +156,7 @@ newgrf_industrytiles.h
|
||||||
newgrf_sound.h
|
newgrf_sound.h
|
||||||
newgrf_spritegroup.h
|
newgrf_spritegroup.h
|
||||||
newgrf_station.h
|
newgrf_station.h
|
||||||
|
newgrf_storage.h
|
||||||
newgrf_text.h
|
newgrf_text.h
|
||||||
newgrf_town.h
|
newgrf_town.h
|
||||||
newgrf_townname.h
|
newgrf_townname.h
|
||||||
|
@ -347,6 +348,7 @@ newgrf_industrytiles.cpp
|
||||||
newgrf_sound.cpp
|
newgrf_sound.cpp
|
||||||
newgrf_spritegroup.cpp
|
newgrf_spritegroup.cpp
|
||||||
newgrf_station.cpp
|
newgrf_station.cpp
|
||||||
|
newgrf_storage.cpp
|
||||||
newgrf_text.cpp
|
newgrf_text.cpp
|
||||||
newgrf_town.cpp
|
newgrf_town.cpp
|
||||||
newgrf_townname.cpp
|
newgrf_townname.cpp
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
#include "genworld.h"
|
#include "genworld.h"
|
||||||
|
#include "newgrf_storage.h"
|
||||||
|
|
||||||
const char *_cmd_text = NULL;
|
const char *_cmd_text = NULL;
|
||||||
|
|
||||||
|
@ -573,6 +574,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||||
|
|
||||||
_docommand_recursive = 0;
|
_docommand_recursive = 0;
|
||||||
_cmd_text = NULL;
|
_cmd_text = NULL;
|
||||||
|
ClearStorageChanges(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,6 +605,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||||
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
|
if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
|
||||||
_docommand_recursive = 0;
|
_docommand_recursive = 0;
|
||||||
_cmd_text = NULL;
|
_cmd_text = NULL;
|
||||||
|
ClearStorageChanges(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_NETWORK */
|
#endif /* ENABLE_NETWORK */
|
||||||
|
@ -643,6 +646,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||||
|
|
||||||
if (callback) callback(true, tile, p1, p2);
|
if (callback) callback(true, tile, p1, p2);
|
||||||
_cmd_text = NULL;
|
_cmd_text = NULL;
|
||||||
|
ClearStorageChanges(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
show_error:
|
show_error:
|
||||||
|
@ -656,6 +660,7 @@ callb_err:
|
||||||
|
|
||||||
if (callback) callback(false, tile, p1, p2);
|
if (callback) callback(false, tile, p1, p2);
|
||||||
_cmd_text = NULL;
|
_cmd_text = NULL;
|
||||||
|
ClearStorageChanges(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ void InitializeSpriteGroupPool()
|
||||||
_spritegroup_count = 0;
|
_spritegroup_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 _temp_store[0x110];
|
TemporaryStorageArray<uint, 0x110> _temp_store;
|
||||||
|
|
||||||
|
|
||||||
static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
|
static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
|
||||||
|
@ -98,7 +98,7 @@ static inline uint32 GetVariable(const ResolverObject *object, byte variable, by
|
||||||
case 0x1C: return object->last_value;
|
case 0x1C: return object->last_value;
|
||||||
case 0x20: return _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF;
|
case 0x20: return _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF;
|
||||||
|
|
||||||
case 0x7D: return _temp_store[parameter];
|
case 0x7D: return _temp_store.Get(parameter);
|
||||||
|
|
||||||
/* Not a common variable, so evalute the feature specific variables */
|
/* Not a common variable, so evalute the feature specific variables */
|
||||||
default: return object->GetVariable(object, variable, parameter, available);
|
default: return object->GetVariable(object, variable, parameter, available);
|
||||||
|
@ -137,9 +137,7 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust *adjust, U last_value,
|
||||||
case DSGA_OP_AND: return last_value & value;
|
case DSGA_OP_AND: return last_value & value;
|
||||||
case DSGA_OP_OR: return last_value | value;
|
case DSGA_OP_OR: return last_value | value;
|
||||||
case DSGA_OP_XOR: return last_value ^ value;
|
case DSGA_OP_XOR: return last_value ^ value;
|
||||||
case DSGA_OP_STO:
|
case DSGA_OP_STO: _temp_store.Store(value, last_value); return last_value;
|
||||||
if (value < lengthof(_temp_store)) _temp_store[value] = last_value;
|
|
||||||
return last_value;
|
|
||||||
case DSGA_OP_RST: return value;
|
case DSGA_OP_RST: return value;
|
||||||
default: return value;
|
default: return value;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +160,7 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||||
bool available = true;
|
bool available = true;
|
||||||
if (adjust->variable == 0x7E) {
|
if (adjust->variable == 0x7E) {
|
||||||
ResolverObject subobject = *object;
|
ResolverObject subobject = *object;
|
||||||
const SpriteGroup *subgroup = Resolve(adjust->subroutine, &subobject, false);
|
const SpriteGroup *subgroup = Resolve(adjust->subroutine, &subobject);
|
||||||
if (subgroup == NULL || subgroup->type != SGT_CALLBACK) {
|
if (subgroup == NULL || subgroup->type != SGT_CALLBACK) {
|
||||||
value = CALLBACK_FAILED;
|
value = CALLBACK_FAILED;
|
||||||
} else {
|
} else {
|
||||||
|
@ -175,7 +173,7 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||||
if (!available) {
|
if (!available) {
|
||||||
/* Unsupported property: skip further processing and return either
|
/* Unsupported property: skip further processing and return either
|
||||||
* the group from the first range or the default group. */
|
* the group from the first range or the default group. */
|
||||||
return Resolve(group->g.determ.num_ranges > 0 ? group->g.determ.ranges[0].group : group->g.determ.default_group, object, false);
|
return Resolve(group->g.determ.num_ranges > 0 ? group->g.determ.ranges[0].group : group->g.determ.default_group, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (group->g.determ.size) {
|
switch (group->g.determ.size) {
|
||||||
|
@ -216,11 +214,11 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol
|
||||||
|
|
||||||
for (i = 0; i < group->g.determ.num_ranges; i++) {
|
for (i = 0; i < group->g.determ.num_ranges; i++) {
|
||||||
if (group->g.determ.ranges[i].low <= value && value <= group->g.determ.ranges[i].high) {
|
if (group->g.determ.ranges[i].low <= value && value <= group->g.determ.ranges[i].high) {
|
||||||
return Resolve(group->g.determ.ranges[i].group, object, false);
|
return Resolve(group->g.determ.ranges[i].group, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Resolve(group->g.determ.default_group, object, false);
|
return Resolve(group->g.determ.default_group, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,19 +252,16 @@ static inline const SpriteGroup *ResolveRandom(const SpriteGroup *group, Resolve
|
||||||
mask = (group->g.random.num_groups - 1) << group->g.random.lowest_randbit;
|
mask = (group->g.random.num_groups - 1) << group->g.random.lowest_randbit;
|
||||||
index = (object->GetRandomBits(object) & mask) >> group->g.random.lowest_randbit;
|
index = (object->GetRandomBits(object) & mask) >> group->g.random.lowest_randbit;
|
||||||
|
|
||||||
return Resolve(group->g.random.groups[index], object, false);
|
return Resolve(group->g.random.groups[index], object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ResolverObject (re)entry point */
|
/* ResolverObject (re)entry point */
|
||||||
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object, bool first_call)
|
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object)
|
||||||
{
|
{
|
||||||
/* We're called even if there is no group, so quietly return nothing */
|
/* We're called even if there is no group, so quietly return nothing */
|
||||||
if (group == NULL) return NULL;
|
if (group == NULL) return NULL;
|
||||||
|
|
||||||
/* Zero the temporary storage to make sure there are no desyncs */
|
|
||||||
if (first_call) memset(_temp_store, 0, sizeof(_temp_store));
|
|
||||||
|
|
||||||
switch (group->type) {
|
switch (group->type) {
|
||||||
case SGT_REAL: return object->ResolveReal(object, group);
|
case SGT_REAL: return object->ResolveReal(object, group);
|
||||||
case SGT_DETERMINISTIC: return ResolveVariable(group, object);
|
case SGT_DETERMINISTIC: return ResolveVariable(group, object);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
#include "industry.h"
|
#include "industry.h"
|
||||||
|
#include "newgrf_storage.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a so-called newgrf "register".
|
* Gets the value of a so-called newgrf "register".
|
||||||
|
@ -16,9 +17,8 @@
|
||||||
*/
|
*/
|
||||||
static inline uint32 GetRegister(uint i)
|
static inline uint32 GetRegister(uint i)
|
||||||
{
|
{
|
||||||
assert(i < 0x110);
|
extern TemporaryStorageArray<uint, 0x110> _temp_store;
|
||||||
extern uint32 _temp_store[0x110];
|
return _temp_store.Get(i);
|
||||||
return _temp_store[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SpriteGroup;
|
struct SpriteGroup;
|
||||||
|
@ -243,7 +243,7 @@ struct ResolverObject {
|
||||||
|
|
||||||
|
|
||||||
/* Base sprite group resolver */
|
/* Base sprite group resolver */
|
||||||
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object, bool first_call = true);
|
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object);
|
||||||
|
|
||||||
|
|
||||||
#endif /* NEWGRF_SPRITEGROUP_H */
|
#endif /* NEWGRF_SPRITEGROUP_H */
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/** @file newgrf_storage.cpp Functionality related to the temporary and persistent storage arrays for NewGRFs. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "helpers.hpp"
|
||||||
|
#include "newgrf_storage.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
/** The changed storage arrays */
|
||||||
|
static std::set<BaseStorageArray*> _changed_storage_arrays;
|
||||||
|
|
||||||
|
void AddChangedStorage(BaseStorageArray *storage)
|
||||||
|
{
|
||||||
|
_changed_storage_arrays.insert(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearStorageChanges(bool keep_changes)
|
||||||
|
{
|
||||||
|
/* Loop over all changes arrays */
|
||||||
|
for (std::set<BaseStorageArray*>::iterator it = _changed_storage_arrays.begin(); it != _changed_storage_arrays.end(); it++) {
|
||||||
|
(*it)->ClearChanges(keep_changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And then clear that array */
|
||||||
|
_changed_storage_arrays.clear();
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/** @file newgrf_storage.h Functionality related to the temporary and persistent storage arrays for NewGRFs. */
|
||||||
|
|
||||||
|
#ifndef NEWGRF_STORAGE_H
|
||||||
|
#define NEWGRF_STORAGE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all NewGRF storage arrays. Nothing fancy, only here
|
||||||
|
* so we have a generalised class to use.
|
||||||
|
*/
|
||||||
|
struct BaseStorageArray
|
||||||
|
{
|
||||||
|
/** The needed destructor */
|
||||||
|
virtual ~BaseStorageArray() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the changes made since the last ClearChanges.
|
||||||
|
* This can be done in two ways:
|
||||||
|
* - saving the changes permanently
|
||||||
|
* - reverting to the previous version
|
||||||
|
* @param keep_changes do we save or revert the changes since the last ClearChanges?
|
||||||
|
*/
|
||||||
|
virtual void ClearChanges(bool keep_changes) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for persistent storage of data.
|
||||||
|
* On ClearChanges that data is either reverted or saved.
|
||||||
|
* @param TYPE the type of variable to store.
|
||||||
|
* @param SIZE the size of the array.
|
||||||
|
*/
|
||||||
|
template <typename TYPE, uint SIZE>
|
||||||
|
struct PersistentStorageArray : BaseStorageArray {
|
||||||
|
TYPE storage[SIZE]; ///< Memory to for the storage array
|
||||||
|
TYPE *prev_storage; ///< Memory to store "old" states so we can revert them on the performance of test cases for commands etc.
|
||||||
|
|
||||||
|
/** Simply construct the array */
|
||||||
|
PersistentStorageArray() : prev_storage(NULL)
|
||||||
|
{
|
||||||
|
memset(this->storage, 0, sizeof(this->storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** And free all data related to it */
|
||||||
|
~PersistentStorageArray()
|
||||||
|
{
|
||||||
|
free(this->prev_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores some value at a given position.
|
||||||
|
* If there is no backup of the data that backup is made and then
|
||||||
|
* we write the data.
|
||||||
|
* @param pos the position to write at
|
||||||
|
* @param value the value to write
|
||||||
|
*/
|
||||||
|
void Store(uint pos, TYPE value)
|
||||||
|
{
|
||||||
|
/* Out of the scope of the array */
|
||||||
|
if (pos >= SIZE) return;
|
||||||
|
|
||||||
|
/* The value hasn't changed, so we pretend nothing happened.
|
||||||
|
* Saves a few cycles and such and it's pretty easy to check. */
|
||||||
|
if (this->storage[pos] == value) return;
|
||||||
|
|
||||||
|
/* We do not have made a backup; lets do so */
|
||||||
|
if (this->prev_storage != NULL) {
|
||||||
|
this->prev_storage = MallocT<TYPE>(SIZE);
|
||||||
|
if (this->prev_storage == NULL) return;
|
||||||
|
|
||||||
|
memcpy(this->prev_storage, this->storage, sizeof(this->storage));
|
||||||
|
|
||||||
|
/* We only need to register ourselves when we made the backup
|
||||||
|
* as that is the only time something will have changed */
|
||||||
|
AddChangedStorage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->storage[pos] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value from a given position.
|
||||||
|
* @param pos the position to get the data from
|
||||||
|
* @return the data from that position
|
||||||
|
*/
|
||||||
|
TYPE Get(uint pos)
|
||||||
|
{
|
||||||
|
/* Out of the scope of the array */
|
||||||
|
if (pos >= SIZE) return 0;
|
||||||
|
|
||||||
|
return this->storage[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearChanges(bool keep_changes)
|
||||||
|
{
|
||||||
|
assert(this->prev_storage != NULL);
|
||||||
|
|
||||||
|
if (!keep_changes) {
|
||||||
|
memcpy(this->storage, this->prev_storage, sizeof(this->storage));
|
||||||
|
}
|
||||||
|
free(this->prev_storage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for temporary storage of data.
|
||||||
|
* On ClearChanges that data is always zero-ed.
|
||||||
|
* @param TYPE the type of variable to store.
|
||||||
|
* @param SIZE the size of the array.
|
||||||
|
*/
|
||||||
|
template <typename TYPE, uint SIZE>
|
||||||
|
struct TemporaryStorageArray : BaseStorageArray {
|
||||||
|
TYPE storage[SIZE]; ///< Memory to for the storage array
|
||||||
|
|
||||||
|
/** Simply construct the array */
|
||||||
|
TemporaryStorageArray()
|
||||||
|
{
|
||||||
|
memset(this->storage, 0, sizeof(this->storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores some value at a given position.
|
||||||
|
* @param pos the position to write at
|
||||||
|
* @param value the value to write
|
||||||
|
*/
|
||||||
|
void Store(uint pos, TYPE value)
|
||||||
|
{
|
||||||
|
/* Out of the scope of the array */
|
||||||
|
if (pos >= SIZE) return;
|
||||||
|
|
||||||
|
this->storage[pos] = value;
|
||||||
|
AddChangedStorage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value from a given position.
|
||||||
|
* @param pos the position to get the data from
|
||||||
|
* @return the data from that position
|
||||||
|
*/
|
||||||
|
TYPE Get(uint pos)
|
||||||
|
{
|
||||||
|
/* Out of the scope of the array */
|
||||||
|
if (pos >= SIZE) return 0;
|
||||||
|
|
||||||
|
return this->storage[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearChanges(bool keep_changes)
|
||||||
|
{
|
||||||
|
memset(this->storage, 0, sizeof(this->storage));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the changed storage array to the list of changed arrays.
|
||||||
|
* This is done so we only have to revert/save the changed
|
||||||
|
* arrays, which saves quite a few clears, etc. after callbacks.
|
||||||
|
* @param storage the array that has changed
|
||||||
|
*/
|
||||||
|
void AddChangedStorage(BaseStorageArray *storage);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the changes made since the last ClearStorageChanges.
|
||||||
|
* This is done for *all* storages that have been registered to with
|
||||||
|
* AddChangedStorage since the previous ClearStorageChanges.
|
||||||
|
*
|
||||||
|
* This can be done in two ways:
|
||||||
|
* - saving the changes permanently
|
||||||
|
* - reverting to the previous version
|
||||||
|
* @param keep_changes do we save or revert the changes since the last ClearChanges?
|
||||||
|
*/
|
||||||
|
void ClearStorageChanges(bool keep_changes);
|
||||||
|
|
||||||
|
#endif /* NEWGRF_STORAGE_H */
|
|
@ -61,6 +61,7 @@
|
||||||
#include "newgrf_config.h"
|
#include "newgrf_config.h"
|
||||||
#include "newgrf_house.h"
|
#include "newgrf_house.h"
|
||||||
#include "newgrf_commons.h"
|
#include "newgrf_commons.h"
|
||||||
|
#include "newgrf_storage.h"
|
||||||
#include "player_face.h"
|
#include "player_face.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "blitter/factory.hpp"
|
#include "blitter/factory.hpp"
|
||||||
|
@ -977,6 +978,8 @@ void SwitchMode(int new_mode)
|
||||||
* That check is enforced in DoCommand. */
|
* That check is enforced in DoCommand. */
|
||||||
void StateGameLoop()
|
void StateGameLoop()
|
||||||
{
|
{
|
||||||
|
ClearStorageChanges(false);
|
||||||
|
|
||||||
/* dont execute the state loop during pause */
|
/* dont execute the state loop during pause */
|
||||||
if (_pause_game) return;
|
if (_pause_game) return;
|
||||||
if (IsGeneratingWorld()) return;
|
if (IsGeneratingWorld()) return;
|
||||||
|
|
Loading…
Reference in New Issue