diff options
author | frosch <frosch@openttd.org> | 2010-05-01 13:01:21 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2010-05-01 13:01:21 +0000 |
commit | 77953032274c3bb49c8b22ff7a2767412586c5a7 (patch) | |
tree | 254b97e9037aec36599ddaa0e32e6ff0e388b5a9 | |
parent | 36850ba3e86fd9633ae0104caa0cb8b8aeecfc37 (diff) | |
download | openttd-77953032274c3bb49c8b22ff7a2767412586c5a7.tar.xz |
(svn r19743) -Fix: NewGrfs could access map bits of not yet constructed industries and houses during construction callbacks.
-rw-r--r-- | src/newgrf_house.cpp | 23 | ||||
-rw-r--r-- | src/newgrf_house.h | 2 | ||||
-rw-r--r-- | src/newgrf_industries.cpp | 13 | ||||
-rw-r--r-- | src/newgrf_industrytiles.cpp | 26 | ||||
-rw-r--r-- | src/newgrf_spritegroup.h | 1 | ||||
-rw-r--r-- | src/town_cmd.cpp | 2 |
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; } |