From a619ad37897c6ee985aa7bb0dadbd9bbc47c5a63 Mon Sep 17 00:00:00 2001 From: terkhen Date: Sun, 12 Jun 2011 20:50:03 +0000 Subject: (svn r22569) -Feature: [NewGRF] Persistent storage for towns. --- src/newgrf_house.cpp | 18 +++++++++++++- src/newgrf_industries.cpp | 12 ++++++--- src/newgrf_object.cpp | 19 +++++++++++++- src/newgrf_station.cpp | 18 +++++++++++++- src/newgrf_town.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++- src/newgrf_town.h | 7 +++--- src/table/newgrf_debug_data.h | 2 +- src/town_cmd.cpp | 3 +++ 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) { @@ -360,6 +360,21 @@ static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const R return NULL; } +/** + * 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(): * @@ -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 @@ -358,6 +358,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. */ @@ -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::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::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); -- cgit v1.2.3-54-g00ecf