summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2010-05-01 13:01:21 +0000
committerfrosch <frosch@openttd.org>2010-05-01 13:01:21 +0000
commit77953032274c3bb49c8b22ff7a2767412586c5a7 (patch)
tree254b97e9037aec36599ddaa0e32e6ff0e388b5a9 /src
parent36850ba3e86fd9633ae0104caa0cb8b8aeecfc37 (diff)
downloadopenttd-77953032274c3bb49c8b22ff7a2767412586c5a7.tar.xz
(svn r19743) -Fix: NewGrfs could access map bits of not yet constructed industries and houses during construction callbacks.
Diffstat (limited to 'src')
-rw-r--r--src/newgrf_house.cpp23
-rw-r--r--src/newgrf_house.h2
-rw-r--r--src/newgrf_industries.cpp13
-rw-r--r--src/newgrf_industrytiles.cpp26
-rw-r--r--src/newgrf_spritegroup.h1
-rw-r--r--src/town_cmd.cpp2
6 files changed, 48 insertions, 19 deletions
diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp
index 1f53e2c73..3ca62f5bd 100644
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -99,20 +99,25 @@ void DecreaseBuildingCount(Town *t, HouseID house_id)
static uint32 HouseGetRandomBits(const ResolverObject *object)
{
- const TileIndex tile = object->u.house.tile;
- return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseRandomBits(tile);
+ /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */
+ TileIndex tile = object->u.house.tile;
+ assert(IsValidTile(tile) && (object->u.house.not_yet_constructed || IsTileType(tile, MP_HOUSE)));
+ return object->u.house.not_yet_constructed ? 0 : GetHouseRandomBits(tile);
}
static uint32 HouseGetTriggers(const ResolverObject *object)
{
- const TileIndex tile = object->u.house.tile;
- return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseTriggers(tile);
+ /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */
+ TileIndex tile = object->u.house.tile;
+ assert(IsValidTile(tile) && (object->u.house.not_yet_constructed || IsTileType(tile, MP_HOUSE)));
+ return object->u.house.not_yet_constructed ? 0 : GetHouseTriggers(tile);
}
static void HouseSetTriggers(const ResolverObject *object, int triggers)
{
- const TileIndex tile = object->u.house.tile;
- if (IsTileType(tile, MP_HOUSE)) SetHouseTriggers(tile, triggers);
+ TileIndex tile = object->u.house.tile;
+ assert(!object->u.house.not_yet_constructed && IsValidTile(tile) && IsTileType(tile, MP_HOUSE));
+ SetHouseTriggers(tile, triggers);
}
static uint32 GetNumHouses(HouseID house_id, const Town *town)
@@ -370,6 +375,7 @@ static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex ti
res->u.house.tile = tile;
res->u.house.town = town;
res->u.house.house_id = house_id;
+ res->u.house.not_yet_constructed = false;
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
@@ -383,15 +389,18 @@ static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex ti
res->grffile = (hs != NULL ? hs->grffile : NULL);
}
-uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile)
+uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed)
{
ResolverObject object;
const SpriteGroup *group;
+ assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE)));
+
NewHouseResolver(&object, house_id, tile, town);
object.callback = callback;
object.callback_param1 = param1;
object.callback_param2 = param2;
+ object.u.house.not_yet_constructed = not_yet_constructed;
group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->spritegroup, &object);
if (group == NULL) return CALLBACK_FAILED;
diff --git a/src/newgrf_house.h b/src/newgrf_house.h
index 6a6f40cb0..461ff177c 100644
--- a/src/newgrf_house.h
+++ b/src/newgrf_house.h
@@ -44,7 +44,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id);
void AnimateNewHouseTile(TileIndex tile);
void ChangeHouseAnimationFrame(const struct GRFFile *file, TileIndex tile, uint16 callback_result);
-uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile);
+uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed = false);
bool CanDeleteHouse(TileIndex tile);
diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp
index 5c3c0027a..9e50dd087 100644
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -345,18 +345,23 @@ static const SpriteGroup *IndustryResolveReal(const ResolverObject *object, cons
static uint32 IndustryGetRandomBits(const ResolverObject *object)
{
- return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random;
+ const Industry *ind = object->u.industry.ind;
+ assert(ind != NULL);
+ return ind->random;
}
static uint32 IndustryGetTriggers(const ResolverObject *object)
{
- return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random_triggers;
+ const Industry *ind = object->u.industry.ind;
+ assert(ind != NULL);
+ return ind->random_triggers;
}
static void IndustrySetTriggers(const ResolverObject *object, int triggers)
{
- if (object->u.industry.ind == NULL) return;
- object->u.industry.ind->random_triggers = triggers;
+ Industry *ind = object->u.industry.ind;
+ assert(ind != NULL && ind->index != INVALID_INDUSTRY);
+ ind->random_triggers = triggers;
}
static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type)
diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp
index 4ffdd2600..232343924 100644
--- a/src/newgrf_industrytiles.cpp
+++ b/src/newgrf_industrytiles.cpp
@@ -118,26 +118,35 @@ static const SpriteGroup *IndustryTileResolveReal(const ResolverObject *object,
static uint32 IndustryTileGetRandomBits(const ResolverObject *object)
{
const TileIndex tile = object->u.industry.tile;
- if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
- return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : Industry::GetByTile(tile)->random;
+ const Industry *ind = object->u.industry.ind;
+ assert(ind != NULL && IsValidTile(tile));
+ assert(ind->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
+
+ return (object->scope == VSG_SCOPE_SELF) ?
+ (ind->index != INVALID_INDUSTRY ? GetIndustryRandomBits(tile) : 0) :
+ ind->random;
}
static uint32 IndustryTileGetTriggers(const ResolverObject *object)
{
const TileIndex tile = object->u.industry.tile;
- if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
- return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : Industry::GetByTile(tile)->random_triggers;
+ const Industry *ind = object->u.industry.ind;
+ assert(ind != NULL && IsValidTile(tile));
+ assert(ind->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
+ if (ind->index == INVALID_INDUSTRY) return 0;
+ return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : ind->random_triggers;
}
static void IndustryTileSetTriggers(const ResolverObject *object, int triggers)
{
const TileIndex tile = object->u.industry.tile;
- if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return;
+ Industry *ind = object->u.industry.ind;
+ assert(ind != NULL && ind->index != INVALID_INDUSTRY && IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY));
if (object->scope == VSG_SCOPE_SELF) {
SetIndustryTriggers(tile, triggers);
} else {
- Industry::GetByTile(tile)->random_triggers = triggers;
+ ind->random_triggers = triggers;
}
}
@@ -194,6 +203,9 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2
ResolverObject object;
const SpriteGroup *group;
+ assert(industry != NULL && IsValidTile(tile));
+ assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
+
NewIndustryTileResolver(&object, gfx_id, tile, industry);
object.callback = callback;
object.callback_param1 = param1;
@@ -396,6 +408,8 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
{
ResolverObject object;
+ assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY));
+
IndustryGfx gfx = GetIndustryGfx(tile);
const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h
index c606e147d..32456d3eb 100644
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -319,6 +319,7 @@ struct ResolverObject {
TileIndex tile;
Town *town;
HouseID house_id;
+ bool not_yet_constructed; ///< True for construction check
} house;
struct {
TileIndex tile;
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 47bd8b219..0fb74a45d 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -2165,7 +2165,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
}
if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
- uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile);
+ uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile, true);
if (callback_res != CALLBACK_FAILED && GB(callback_res, 0, 8) == 0) continue;
}