mirror of https://github.com/OpenTTD/OpenTTD
(svn r19743) -Fix: NewGrfs could access map bits of not yet constructed industries and houses during construction callbacks.
parent
36850ba3e8
commit
7795303227
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue