1
0
Fork 0

(svn r19743) -Fix: NewGrfs could access map bits of not yet constructed industries and houses during construction callbacks.

release/1.1
frosch 2010-05-01 13:01:21 +00:00
parent 36850ba3e8
commit 7795303227
6 changed files with 48 additions and 19 deletions

View File

@ -99,20 +99,25 @@ void DecreaseBuildingCount(Town *t, HouseID house_id)
static uint32 HouseGetRandomBits(const ResolverObject *object) static uint32 HouseGetRandomBits(const ResolverObject *object)
{ {
const TileIndex tile = object->u.house.tile; /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */
return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseRandomBits(tile); 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) static uint32 HouseGetTriggers(const ResolverObject *object)
{ {
const TileIndex tile = object->u.house.tile; /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */
return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseTriggers(tile); 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) static void HouseSetTriggers(const ResolverObject *object, int triggers)
{ {
const TileIndex tile = object->u.house.tile; TileIndex tile = object->u.house.tile;
if (IsTileType(tile, MP_HOUSE)) SetHouseTriggers(tile, triggers); 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) 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.tile = tile;
res->u.house.town = town; res->u.house.town = town;
res->u.house.house_id = house_id; res->u.house.house_id = house_id;
res->u.house.not_yet_constructed = false;
res->callback = CBID_NO_CALLBACK; res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0; 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); 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; ResolverObject object;
const SpriteGroup *group; const SpriteGroup *group;
assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE)));
NewHouseResolver(&object, house_id, tile, town); NewHouseResolver(&object, house_id, tile, town);
object.callback = callback; object.callback = callback;
object.callback_param1 = param1; object.callback_param1 = param1;
object.callback_param2 = param2; object.callback_param2 = param2;
object.u.house.not_yet_constructed = not_yet_constructed;
group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->spritegroup, &object); group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->spritegroup, &object);
if (group == NULL) return CALLBACK_FAILED; if (group == NULL) return CALLBACK_FAILED;

View File

@ -44,7 +44,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id);
void AnimateNewHouseTile(TileIndex tile); void AnimateNewHouseTile(TileIndex tile);
void ChangeHouseAnimationFrame(const struct GRFFile *file, TileIndex tile, uint16 callback_result); 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); bool CanDeleteHouse(TileIndex tile);

View File

@ -345,18 +345,23 @@ static const SpriteGroup *IndustryResolveReal(const ResolverObject *object, cons
static uint32 IndustryGetRandomBits(const ResolverObject *object) 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) 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) static void IndustrySetTriggers(const ResolverObject *object, int triggers)
{ {
if (object->u.industry.ind == NULL) return; Industry *ind = object->u.industry.ind;
object->u.industry.ind->random_triggers = triggers; assert(ind != NULL && ind->index != INVALID_INDUSTRY);
ind->random_triggers = triggers;
} }
static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type) static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type)

View File

@ -118,26 +118,35 @@ static const SpriteGroup *IndustryTileResolveReal(const ResolverObject *object,
static uint32 IndustryTileGetRandomBits(const ResolverObject *object) static uint32 IndustryTileGetRandomBits(const ResolverObject *object)
{ {
const TileIndex tile = object->u.industry.tile; const TileIndex tile = object->u.industry.tile;
if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; const Industry *ind = object->u.industry.ind;
return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : Industry::GetByTile(tile)->random; 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) static uint32 IndustryTileGetTriggers(const ResolverObject *object)
{ {
const TileIndex tile = object->u.industry.tile; const TileIndex tile = object->u.industry.tile;
if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; const Industry *ind = object->u.industry.ind;
return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : Industry::GetByTile(tile)->random_triggers; 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) static void IndustryTileSetTriggers(const ResolverObject *object, int triggers)
{ {
const TileIndex tile = object->u.industry.tile; 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) { if (object->scope == VSG_SCOPE_SELF) {
SetIndustryTriggers(tile, triggers); SetIndustryTriggers(tile, triggers);
} else { } 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; ResolverObject object;
const SpriteGroup *group; const SpriteGroup *group;
assert(industry != NULL && IsValidTile(tile));
assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
NewIndustryTileResolver(&object, gfx_id, tile, industry); NewIndustryTileResolver(&object, gfx_id, tile, industry);
object.callback = callback; object.callback = callback;
object.callback_param1 = param1; object.callback_param1 = param1;
@ -396,6 +408,8 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
{ {
ResolverObject object; ResolverObject object;
assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY));
IndustryGfx gfx = GetIndustryGfx(tile); IndustryGfx gfx = GetIndustryGfx(tile);
const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);

View File

@ -319,6 +319,7 @@ struct ResolverObject {
TileIndex tile; TileIndex tile;
Town *town; Town *town;
HouseID house_id; HouseID house_id;
bool not_yet_constructed; ///< True for construction check
} house; } house;
struct { struct {
TileIndex tile; TileIndex tile;

View File

@ -2165,7 +2165,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
} }
if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) { 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; if (callback_res != CALLBACK_FAILED && GB(callback_res, 0, 8) == 0) continue;
} }