feat(admin): IsAGRoom (IsRRO) toggle on room props, for the editable-Rec-Royale experiment

The Maker Pen permission check runs a room precondition that looks the
current room up in AGRoomRuntimeConfig — a table baked into the client's
resources.assets — and returns a per-original boolean. Rec Center and
Stunt Runner allow creation there; Rec Royale does not, so no blob, role or
server response can grant the pen while the client treats the room as
that original. The table is consulted only for rooms with IsRRO (our
IsAGRoom) set.

Expose IsAGRoom on rooms/{id}/props (+ a checkbox on the General tab) so a
CLONE of Rec Royale can be flipped to a non-original with a real save
attached; whether the client still loads the baked Frontier scene for a
non-original is what that experiment answers. docs/admin.md explains the
gate and the two possible outcomes.
This commit is contained in:
Alexa
2026-09-28 00:34:56 +03:00
parent d7b1722abd
commit 6605f61047
3 changed files with 45 additions and 1 deletions
@@ -165,6 +165,7 @@ function GeneralTab({ room, onSaved }: { room: RoomDetail; onSaved: () => void }
const [description, setDescription] = useState(room.description);
const [accessibility, setAccessibility] = useState(room.accessibility);
const [cloningAllowed, setCloningAllowed] = useState(room.cloningAllowed);
const [isAGRoom, setIsAGRoom] = useState(room.isAGRoom);
const [tagsCsv, setTagsCsv] = useState(room.tagsCsv);
const [hotScore, setHotScore] = useState(String(room.hotScore));
const [imageName, setImageName] = useState(room.imageName);
@@ -176,6 +177,7 @@ function GeneralTab({ room, onSaved }: { room: RoomDetail; onSaved: () => void }
setDescription(room.description);
setAccessibility(room.accessibility);
setCloningAllowed(room.cloningAllowed);
setIsAGRoom(room.isAGRoom);
setTagsCsv(room.tagsCsv);
setHotScore(String(room.hotScore));
setImageName(room.imageName);
@@ -193,6 +195,7 @@ function GeneralTab({ room, onSaved }: { room: RoomDetail; onSaved: () => void }
Description: description,
Accessibility: accessibility,
CloningAllowed: cloningAllowed,
IsAGRoom: isAGRoom,
TagsCsv: tagsCsv,
HotScore: Number.isFinite(hot) ? hot : undefined,
ImageName: imageName,
@@ -283,6 +286,14 @@ function GeneralTab({ room, onSaved }: { room: RoomDetail; onSaved: () => void }
/>
<span>Cloning allowed</span>
</label>
<label className="flex items-center gap-2 text-sm" title="What the client reads as IsRRO. On: load the baked scene from the client's assets and consult the client's built-in per-original table (which forbids creation in Rec Royale). Off: treat as a custom room — roles and blob decide. Flip a CLONE of an original off to test editable Rec Royale.">
<input
type="checkbox"
checked={isAGRoom}
onChange={e => setIsAGRoom(e.target.checked)}
/>
<span>Rec Room Original (IsRRO) — baked scene + client creation table</span>
</label>
<div className="flex gap-2 pt-2 border-t border-ink-800">
<button onClick={save} disabled={busy} className="btn-primary text-xs">
{busy ? 'Saving…' : 'Save changes'}