summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorterkhen <terkhen@openttd.org>2011-06-12 20:50:03 +0000
committerterkhen <terkhen@openttd.org>2011-06-12 20:50:03 +0000
commita619ad37897c6ee985aa7bb0dadbd9bbc47c5a63 (patch)
tree95db697b7650bab2fadc89e43c2e5697bf6040b6
parent7ffc8c0173cea7b364636e4a0686e72947095a9a (diff)
downloadopenttd-a619ad37897c6ee985aa7bb0dadbd9bbc47c5a63.tar.xz
(svn r22569) -Feature: [NewGRF] Persistent storage for towns.
-rw-r--r--src/newgrf_house.cpp18
-rw-r--r--src/newgrf_industries.cpp12
-rw-r--r--src/newgrf_object.cpp19
-rw-r--r--src/newgrf_station.cpp18
-rw-r--r--src/newgrf_town.cpp58
-rw-r--r--src/newgrf_town.h7
-rw-r--r--src/table/newgrf_debug_data.h2
-rw-r--r--src/town_cmd.cpp3
8 files changed, 126 insertions, 11 deletions
diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp
index fd0281e4e..1ec391c51 100644
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -259,7 +259,7 @@ static uint32 HouseGetVariable(const ResolverObject *object, byte variable, byte
HouseID house_id = object->u.house.house_id;
if (object->scope == VSG_SCOPE_PARENT) {
- return TownGetVariable(variable, parameter, available, town);
+ return TownGetVariable(variable, parameter, available, town, object->grffile);
}
switch (variable) {
@@ -361,6 +361,21 @@ static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const R
}
/**
+ * Store a value into the persistent storage of the object's parent.
+ * @param object Object that we want to query.
+ * @param pos Position in the persistent storage to use.
+ * @param value Value to store.
+ */
+void HouseStorePSA(ResolverObject *object, uint pos, int32 value)
+{
+ /* Houses have no persistent storage. */
+ if (object->scope != VSG_SCOPE_PARENT || object->u.house.not_yet_constructed) return;
+
+ /* Pass the request on to the town of the house */
+ TownStorePSA(object->u.house.town, object->grffile, pos, value);
+}
+
+/**
* NewHouseResolver():
*
* Returns a resolver object to be used with feature 07 spritegroups.
@@ -372,6 +387,7 @@ static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex ti
res->SetTriggers = HouseSetTriggers;
res->GetVariable = HouseGetVariable;
res->ResolveReal = HouseResolveReal;
+ res->StorePSA = HouseStorePSA;
res->u.house.tile = tile;
res->u.house.town = town;
diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp
index 7a06fbc38..35f853712 100644
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -191,7 +191,7 @@ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte par
return UINT_MAX;
}
- return TownGetVariable(variable, parameter, available, t);
+ return TownGetVariable(variable, parameter, available, t, object->grffile);
}
if (industry == NULL) {
@@ -385,7 +385,13 @@ static void IndustrySetTriggers(const ResolverObject *object, int triggers)
void IndustryStorePSA(ResolverObject *object, uint pos, int32 value)
{
Industry *ind = object->u.industry.ind;
- if (object->scope != VSG_SCOPE_SELF || ind->index == INVALID_INDUSTRY) return;
+ if (ind->index == INVALID_INDUSTRY) return;
+
+ if (object->scope != VSG_SCOPE_SELF) {
+ /* Pass the request on to the town of the industry. */
+ TownStorePSA(ind->town, object->grffile, pos, value);
+ return;
+ }
if (ind->psa == NULL) {
/* There is no need to create a storage if the value is zero. */
@@ -459,7 +465,7 @@ uint32 IndustryLocationGetVariable(const ResolverObject *object, byte variable,
TileIndex tile = object->u.industry.tile;
if (object->scope == VSG_SCOPE_PARENT) {
- return TownGetVariable(variable, parameter, available, industry->town);
+ return TownGetVariable(variable, parameter, available, industry->town, object->grffile);
}
switch (variable) {
diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp
index 6b19f6d8f..dcd9c26a4 100644
--- a/src/newgrf_object.cpp
+++ b/src/newgrf_object.cpp
@@ -224,7 +224,7 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, byt
if (object->scope == VSG_SCOPE_PARENT) {
/* Pass the request on to the town of the object */
- return TownGetVariable(variable, parameter, available, (o == NULL) ? ClosestTownFromTile(tile, UINT_MAX) : o->town);
+ return TownGetVariable(variable, parameter, available, (o == NULL) ? ClosestTownFromTile(tile, UINT_MAX) : o->town, object->grffile);
}
/* We get the town from the object, or we calculate the closest
@@ -359,6 +359,22 @@ static const SpriteGroup *GetObjectSpriteGroup(const ObjectSpec *spec, const Obj
}
/**
+ * Store a value into the persistent storage of the object's parent.
+ * @param object Object that we want to query.
+ * @param pos Position in the persistent storage to use.
+ * @param value Value to store.
+ */
+void ObjectStorePSA(ResolverObject *object, uint pos, int32 value)
+{
+ /* Objects have no persistent storage. */
+ Object *o = object->u.object.o;
+ if (object->scope != VSG_SCOPE_PARENT || o == NULL) return;
+
+ /* Pass the request on to the town of the object */
+ TownStorePSA(o->town, object->grffile, pos, value);
+}
+
+/**
* Returns a resolver object to be used with feature 0F spritegroups.
*/
static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0)
@@ -368,6 +384,7 @@ static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Objec
res->SetTriggers = ObjectSetTriggers;
res->GetVariable = ObjectGetVariable;
res->ResolveReal = ObjectResolveReal;
+ res->StorePSA = ObjectStorePSA;
res->u.object.o = o;
res->u.object.tile = tile;
diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp
index 25dc06440..07ed47af8 100644
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -275,7 +275,7 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by
return UINT_MAX;
}
- return TownGetVariable(variable, parameter, available, t);
+ return TownGetVariable(variable, parameter, available, t, object->grffile);
}
if (st == NULL) {
@@ -517,6 +517,21 @@ static const SpriteGroup *StationResolveReal(const ResolverObject *object, const
}
+/**
+ * Store a value into the persistent storage of the object's parent.
+ * @param object Object that we want to query.
+ * @param pos Position in the persistent storage to use.
+ * @param value Value to store.
+ */
+void StationStorePSA(ResolverObject *object, uint pos, int32 value)
+{
+ /* Stations have no persistent storage. */
+ BaseStation *st = object->u.station.st;
+ if (object->scope != VSG_SCOPE_PARENT || st == NULL) return;
+
+ TownStorePSA(st->town, object->grffile, pos, value);
+}
+
static void NewStationResolver(ResolverObject *res, const StationSpec *statspec, BaseStation *st, TileIndex tile)
{
res->GetRandomBits = StationGetRandomBits;
@@ -524,6 +539,7 @@ static void NewStationResolver(ResolverObject *res, const StationSpec *statspec,
res->SetTriggers = StationSetTriggers;
res->GetVariable = StationGetVariable;
res->ResolveReal = StationResolveReal;
+ res->StorePSA = StationStorePSA;
res->u.station.st = st;
res->u.station.statspec = statspec;
diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp
index 230c416bb..c177406ab 100644
--- a/src/newgrf_town.cpp
+++ b/src/newgrf_town.cpp
@@ -12,6 +12,8 @@
#include "stdafx.h"
#include "debug.h"
#include "town.h"
+#include "newgrf.h"
+#include "newgrf_spritegroup.h"
/**
* This function implements the town variables that newGRF defines.
@@ -19,9 +21,10 @@
* @param parameter unused
* @param available will return false if ever the variable asked for does not exist
* @param t is of course the town we are inquiring
+ * @param caller_grffile #GRFFile of the entity asking for a town variable.
* @return the value stored in the corresponding variable
*/
-uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t)
+uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t, const GRFFile *caller_grffile)
{
switch (variable) {
/* Larger towns */
@@ -33,6 +36,23 @@ uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t)
/* Town index */
case 0x41: return t->index;
+ /* Get a variable from the persistent storage */
+ case 0x7C: {
+ /* Check the persistent storage for the GrfID stored in register 100h. */
+ uint32 grfid = GetRegister(0x100);
+ if (grfid == 0xFFFFFFFF) {
+ if (caller_grffile == NULL) return 0;
+ grfid = caller_grffile->grfid;
+ }
+
+ std::list<PersistentStorage *>::iterator iter;
+ for (iter = t->psa_list.begin(); iter != t->psa_list.end(); iter++) {
+ if ((*iter)->grfid == grfid) return (*iter)->GetValue(parameter);
+ }
+
+ return 0;
+ }
+
/* Town properties */
case 0x80: return t->xy;
case 0x81: return GB(t->xy, 8, 8);
@@ -106,3 +126,39 @@ uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t)
*available = false;
return UINT_MAX;
}
+
+/**
+ * Store a value in town persistent storage.
+ * @param t Town owning the persistent storage.
+ * @param caller_grffile #GRFFile of the entity that wants to use the storage.
+ * @param pos Position to write at.
+ * @param value Value to write.
+ * @return the value stored in the corresponding variable
+ */
+void TownStorePSA(Town *t, const GRFFile *caller_grffile, uint pos, int32 value)
+{
+ assert(t != NULL);
+ /* We can't store anything if the caller has no #GRFFile. */
+ if (caller_grffile == NULL) return;
+
+ /* Check the persistent storage for the GrfID stored in register 100h. */
+ uint32 grfid = GetRegister(0x100);
+
+ /* A NewGRF can only write in the persistent storage associated to its own GRFID. */
+ if (grfid == 0xFFFFFFFF) grfid = caller_grffile->grfid;
+ if (grfid != caller_grffile->grfid) return;
+
+ /* Check if the storage exists. */
+ std::list<PersistentStorage *>::iterator iter;
+ for (iter = t->psa_list.begin(); iter != t->psa_list.end(); iter++) {
+ if ((*iter)->grfid == grfid) {
+ (*iter)->StoreValue(pos, value);
+ return;
+ }
+ }
+
+ /* Create a new storage. */
+ PersistentStorage *psa = new PersistentStorage(grfid);
+ psa->StoreValue(pos, value);
+ t->psa_list.push_back(psa);
+}
diff --git a/src/newgrf_town.h b/src/newgrf_town.h
index 090b3b67e..1489d1b1d 100644
--- a/src/newgrf_town.h
+++ b/src/newgrf_town.h
@@ -15,8 +15,9 @@
#include "town_type.h"
/* Currently there is no direct town resolver; we only need to get town
- * variable results from inside stations, house tiles and industry tiles. */
-
-uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t);
+ * variable results from inside stations, house tiles and industries,
+ * and to check the town's persistent storage. */
+uint32 TownGetVariable(byte variable, byte parameter, bool *available, Town *t, const GRFFile *caller_grffile);
+void TownStorePSA(Town *t, const GRFFile *caller_grffile, uint pos, int32 value);
#endif /* NEWGRF_TOWN_H */
diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h
index 5bed44310..0a5cfb9f0 100644
--- a/src/table/newgrf_debug_data.h
+++ b/src/table/newgrf_debug_data.h
@@ -433,7 +433,7 @@ class NIHTown : public NIHelper {
const void *GetInstance(uint index)const { return Town::Get(index); }
const void *GetSpec(uint index) const { return NULL; }
void SetStringParameters(uint index) const { this->SetSimpleStringParameters(STR_TOWN_NAME, index); }
- uint Resolve(uint index, uint var, uint param, bool *avail) const { return TownGetVariable(var, param, avail, Town::Get(index)); }
+ uint Resolve(uint index, uint var, uint param, bool *avail) const { return TownGetVariable(var, param, avail, Town::Get(index), NULL); }
};
static const NIFeature _nif_town = {
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index e1c013a44..0a4d2e14b 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -95,6 +95,9 @@ Town::~Town()
}
}
+ /* Clear the persistent storage list. */
+ this->psa_list.clear();
+
DeleteSubsidyWith(ST_TOWN, this->index);
DeleteNewGRFInspectWindow(GSF_FAKE_TOWNS, this->index);
CargoPacket::InvalidateAllFrom(ST_TOWN, this->index);