changeset 17784:ebbbd5ad03d2 draft

(svn r22569) -Feature: [NewGRF] Persistent storage for towns.
author terkhen <terkhen@openttd.org>
date Sun, 12 Jun 2011 20:50:03 +0000 (2011-06-12)
parents 1719e5568a82
children cbd020284e09
files src/newgrf_house.cpp src/newgrf_industries.cpp src/newgrf_object.cpp src/newgrf_station.cpp src/newgrf_town.cpp src/newgrf_town.h src/table/newgrf_debug_data.h src/town_cmd.cpp
diffstat 8 files changed, 126 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -259,7 +259,7 @@
 	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 @@
 }
 
 /**
+ * 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 @@
 	res->SetTriggers   = HouseSetTriggers;
 	res->GetVariable   = HouseGetVariable;
 	res->ResolveReal   = HouseResolveReal;
+	res->StorePSA      = HouseStorePSA;
 
 	res->u.house.tile     = tile;
 	res->u.house.town     = town;
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -191,7 +191,7 @@
 			return UINT_MAX;
 		}
 
-		return TownGetVariable(variable, parameter, available, t);
+		return TownGetVariable(variable, parameter, available, t, object->grffile);
 	}
 
 	if (industry == NULL) {
@@ -385,7 +385,13 @@
 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 @@
 	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) {
--- a/src/newgrf_object.cpp
+++ b/src/newgrf_object.cpp
@@ -224,7 +224,7 @@
 
 	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 @@
 }
 
 /**
+ * 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 @@
 	res->SetTriggers   = ObjectSetTriggers;
 	res->GetVariable   = ObjectGetVariable;
 	res->ResolveReal   = ObjectResolveReal;
+	res->StorePSA      = ObjectStorePSA;
 
 	res->u.object.o    = o;
 	res->u.object.tile = tile;
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -275,7 +275,7 @@
 			return UINT_MAX;
 		}
 
-		return TownGetVariable(variable, parameter, available, t);
+		return TownGetVariable(variable, parameter, available, t, object->grffile);
 	}
 
 	if (st == NULL) {
@@ -517,6 +517,21 @@
 }
 
 
+/**
+ * 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 @@
 	res->SetTriggers   = StationSetTriggers;
 	res->GetVariable   = StationGetVariable;
 	res->ResolveReal   = StationResolveReal;
+	res->StorePSA      = StationStorePSA;
 
 	res->u.station.st       = st;
 	res->u.station.statspec = statspec;
--- 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 @@
 		/* 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 @@
 	*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);
+}
--- 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 */
--- a/src/table/newgrf_debug_data.h
+++ b/src/table/newgrf_debug_data.h
@@ -433,7 +433,7 @@
 	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 = {
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -95,6 +95,9 @@
 		}
 	}
 
+	/* 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);