mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 15:01:11 +02:00
fix(mod-api): fail closed on malformed map blocks
This commit is contained in:
+9
-2
@@ -272,12 +272,19 @@ mod.hooks:wrap("map.occupancy_allowed", function(next, game, ctx)
|
||||
end)
|
||||
```
|
||||
|
||||
With no wrapper, the hook allocates no context and vanilla behavior is byte-for-
|
||||
byte unchanged. A throwing wrapper is isolated by the normal hook bus. A nil,
|
||||
With no wrapper, the hook allocates no context and vanilla behavior is
|
||||
unchanged. A throwing wrapper is isolated by the normal hook bus. A nil,
|
||||
string, number, table, or other malformed final answer fails closed. Disabling
|
||||
or uninstalling the permitting mod therefore restores vanilla ejection without
|
||||
changing the S.S. Anne story flag or restoring the ship.
|
||||
|
||||
Normal hook-chain ownership applies: a wrapper that does not call `next`
|
||||
intentionally owns the final answer and does not run lower-priority wrappers.
|
||||
Permission wrappers must call `next` as shown above to compose. A noncompliant
|
||||
wrapper that returns false without calling `next` safely denies occupancy and
|
||||
can suppress downstream permission by this standard rule. A malformed answer
|
||||
also fails closed and cannot force occupancy.
|
||||
|
||||
## Party ordering
|
||||
|
||||
Companion UIs and alternate party screens can call
|
||||
|
||||
@@ -56,6 +56,12 @@ true when either downstream or its own narrow rule permits occupancy. The hook
|
||||
does not replace `MapScripts` registration, merging, or dispatch, and does not
|
||||
change the departure flag or reconstruct the ship.
|
||||
|
||||
As with every wrapper hook, a callback that does not call `next` intentionally
|
||||
owns the final answer and does not run lower-priority callbacks. Permission
|
||||
wrappers must call downstream to compose. A false, non-forwarding wrapper
|
||||
safely denies occupancy and can suppress downstream permission by this normal
|
||||
rule. A malformed final result also fails closed and cannot permit occupancy.
|
||||
|
||||
The call is guarded by `Runtime.wantsHook`, so an empty chain allocates no
|
||||
context and follows the prior branch exactly.
|
||||
|
||||
@@ -108,7 +114,8 @@ The parity gate must prove:
|
||||
- one permission wrapper can allow occupancy without removing the ship-erasure
|
||||
work or any map handler;
|
||||
- multiple cooperative wrappers preserve downstream permission;
|
||||
- absent, throwing, nil, false, and malformed hook answers fail closed;
|
||||
- absent, throwing, nil, false, malformed, and non-forwarding hook answers fail
|
||||
closed according to the normal wrapper-chain rule;
|
||||
- Red, Blue, and Yellow contexts keep their version identity separate;
|
||||
- disabling or removing the owner restores vanilla behavior without a save
|
||||
migration;
|
||||
|
||||
+10
-4
@@ -136,12 +136,18 @@ function WorldAPI:activeBlockAt(mapId, bx, by)
|
||||
return nil, "invalid block coordinates"
|
||||
end
|
||||
local def = map.def
|
||||
if not def or type(def.width) ~= "number" or type(def.height) ~= "number"
|
||||
or bx < 0 or by < 0 or bx >= def.width or by >= def.height then
|
||||
if not def or not validBlockCoordinate(def.width) or def.width <= 0
|
||||
or not validBlockCoordinate(def.height) or def.height <= 0 then
|
||||
return nil, "block unavailable"
|
||||
end
|
||||
if bx < 0 or by < 0 or bx >= def.width or by >= def.height then
|
||||
return nil, "block coordinates out of bounds"
|
||||
end
|
||||
local blockId = map:blockAt(bx, by)
|
||||
if not validBlockCoordinate(blockId) or blockId < 0 then
|
||||
if type(def.blocks) ~= "table" or type(map.blockAt) ~= "function" then
|
||||
return nil, "block unavailable"
|
||||
end
|
||||
local ok, blockId = pcall(map.blockAt, map, bx, by)
|
||||
if not ok or not validBlockCoordinate(blockId) or blockId < 0 then
|
||||
return nil, "block unavailable"
|
||||
end
|
||||
return blockId
|
||||
|
||||
Reference in New Issue
Block a user