mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 15:01:11 +02:00
fix(mod-api): validate active block storage
This commit is contained in:
@@ -913,8 +913,8 @@ M.VERMILION_DOCK = {
|
|||||||
-- the ship is long gone: erase her right away, and anyone who
|
-- the ship is long gone: erase her right away, and anyone who
|
||||||
-- still lands here is sent back out past the guard unless a mod
|
-- still lands here is sent back out past the guard unless a mod
|
||||||
-- explicitly permits this occupied map state. This hook surrounds
|
-- explicitly permits this occupied map state. This hook surrounds
|
||||||
-- only the ejection decision; the map's complete onEnter chain has
|
-- only the ejection decision; map-script registration and dispatch
|
||||||
-- already run and the departed ship remains erased.
|
-- stay unchanged, and the departed ship remains erased.
|
||||||
for _, b in ipairs(DOCK_SHIP_BLOCKS) do
|
for _, b in ipairs(DOCK_SHIP_BLOCKS) do
|
||||||
ow.map:setBlock(b.bx, b.by, b.water)
|
ow.map:setBlock(b.bx, b.by, b.water)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -247,6 +247,9 @@ or malformed active block returns `nil, "block unavailable"`. The caller must
|
|||||||
require every expected cell to match before changing presentation. This method
|
require every expected cell to match before changing presentation. This method
|
||||||
is Gen 1-only; Gold callers receive no parity promise for it.
|
is Gen 1-only; Gold callers receive no parity promise for it.
|
||||||
|
|
||||||
|
The same unavailable result covers missing or sparse active block storage and
|
||||||
|
an accessor result that does not match its validated active block slot.
|
||||||
|
|
||||||
### Conditional map occupancy
|
### Conditional map occupancy
|
||||||
|
|
||||||
`map.occupancy_allowed` is a narrow Gen 1 hook around a map script's vanilla
|
`map.occupancy_allowed` is a narrow Gen 1 hook around a map script's vanilla
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ Failure reasons are stable:
|
|||||||
| Coordinate is negative or outside the active map | `block coordinates out of bounds` |
|
| Coordinate is negative or outside the active map | `block coordinates out of bounds` |
|
||||||
| Active block data is absent or malformed | `block unavailable` |
|
| Active block data is absent or malformed | `block unavailable` |
|
||||||
|
|
||||||
|
The block slot and the active map accessor must both contain the same valid
|
||||||
|
nonnegative integer. Missing or sparse storage and inconsistent accessor data
|
||||||
|
return `block unavailable`.
|
||||||
|
|
||||||
Requiring the expected map ID and rejecting all ambiguous input lets a mod
|
Requiring the expected map ID and rejecting all ambiguous input lets a mod
|
||||||
compare every cell in its version-specific signature before it calls an
|
compare every cell in its version-specific signature before it calls an
|
||||||
existing mutation API. Red, Blue, and Yellow each use their own loaded map
|
existing mutation API. Red, Blue, and Yellow each use their own loaded map
|
||||||
|
|||||||
@@ -146,8 +146,13 @@ function WorldAPI:activeBlockAt(mapId, bx, by)
|
|||||||
if type(def.blocks) ~= "table" or type(map.blockAt) ~= "function" then
|
if type(def.blocks) ~= "table" or type(map.blockAt) ~= "function" then
|
||||||
return nil, "block unavailable"
|
return nil, "block unavailable"
|
||||||
end
|
end
|
||||||
|
local stored = def.blocks[by * def.width + bx + 1]
|
||||||
|
if not validBlockCoordinate(stored) or stored < 0 then
|
||||||
|
return nil, "block unavailable"
|
||||||
|
end
|
||||||
local ok, blockId = pcall(map.blockAt, map, bx, by)
|
local ok, blockId = pcall(map.blockAt, map, bx, by)
|
||||||
if not ok or not validBlockCoordinate(blockId) or blockId < 0 then
|
if not ok or not validBlockCoordinate(blockId) or blockId < 0
|
||||||
|
or blockId ~= stored then
|
||||||
return nil, "block unavailable"
|
return nil, "block unavailable"
|
||||||
end
|
end
|
||||||
return blockId
|
return blockId
|
||||||
|
|||||||
Reference in New Issue
Block a user