docs(rust): record the RaidableBases helper spike (§11.4.4)
One base despawns alone; overrides go in at OpenEvent through a deep copy; lock-to-first-attacker is main-config only; an admin-given spot and height work through a copied profile (Clone() is shallow and leaked); the area check misses water; reloads drop Harmony patches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -823,10 +823,72 @@ The org lead answered the spike's three questions the same day:
|
||||
guarantees: the write is recorded, a reload is watched, and a failed load rolls back (D178, D179). The
|
||||
reload is `rb.reloadprofiles`, which the spike ran on both rigs, not a plugin reload.
|
||||
|
||||
**Still to settle in the build's own spike:** exactly which internal routine the helper calls to despawn one
|
||||
base, and which settings it can override after `Started`, on both editions. Also the one-at-a-time rule: the
|
||||
step refuses to spawn a second base of the same name on a server while a first one is waiting to start,
|
||||
because the free edition's bases have no ids to tell them apart.
|
||||
**Still to settle in the build's own spike:** the same helper questions on Carbon and on the paid edition.
|
||||
Also the one-at-a-time rule: while a first base of the same name is still waiting to start on a server, the
|
||||
step refuses to spawn a second one, because the free edition's bases have no ids to tell them apart.
|
||||
§11.4.4 may retire that rule.
|
||||
|
||||
#### 11.4.4 The helper spike (2026-09-28)
|
||||
|
||||
The org lead asked for two tests of a D168 helper before the build: can it despawn one base, and which
|
||||
settings can it override? A third question came with them: can an admin give the spot, meaning x, z and a
|
||||
height adjustment? The spike ran on the rust-oxide rig against the free edition, 3.2.0. Carbon and the paid
|
||||
edition are still to run (§11.4.2). Every finding below reaches RaidableBases' internals by reflection and a
|
||||
Harmony patch. None of it is public API, so the helper has to check the plugin's version at hello, as the
|
||||
zone helper does.
|
||||
|
||||
- **Despawning one base works.** The plugin keeps its live bases in a list on the plugin, and each base has
|
||||
its own `Despawn()`. Calling it on one base removed that base and no other. It fired the usual
|
||||
`OnRaidableBaseDespawn` and `OnRaidableBaseDespawned` hooks, so the bridge's feed sees nothing new.
|
||||
- **The helper can know exactly which base is the event's.** A Harmony postfix on the plugin's `OpenEvent`
|
||||
receives the new base object itself. The helper can tag it for the run at birth, instead of matching the
|
||||
position and spawn time `Started` reports afterwards (D204). The one-at-a-time rule above may then go,
|
||||
if the build confirms it on Carbon and the paid edition.
|
||||
- **Overrides go in at `OpenEvent`, not after `Started`.** At `OpenEvent` the base holds a reference to its
|
||||
profile's settings object, which every base of that profile shares. The helper swaps in a deep copy (a
|
||||
JSON round trip), changed for this spawn. The shared profile was checked afterwards and was untouched.
|
||||
Proven on the rig:
|
||||
- PvP on/off;
|
||||
- despawn minutes (inactive and total, via the profile's own "override config" switch);
|
||||
- NPCs on/off, and the scientist and murderer counts.
|
||||
- **Lock-to-first-attacker is not a profile setting.** It lives in RaidableBases' main config, in two
|
||||
pairs of switches (PvP and PvE): one pair for "Manual" bases, which is what `rbevent` and the helper
|
||||
spawn, and one pair for scheduled bases. A per-event lock would need a second Harmony patch, on the
|
||||
base's `BypassUseOwners()`. Not built; a question for the org lead.
|
||||
- **An admin-given spot works.** The helper builds the same spawn request the plugin's own "spawn where I
|
||||
look" command builds, from numbers instead of a player's view. It then calls the plugin's paste. Bases
|
||||
landed at the given x and z every time.
|
||||
- **Height has to go through a copy of the profile.** The plugin recomputes y at paste time from the
|
||||
ground (or water), plus the building's own height, plus the profile's paste height adjustment. It
|
||||
ignores any y it is handed, unless the profile forces a height. So the helper copies the profile:
|
||||
- an adjustment is added to the copy's paste height adjustment;
|
||||
- an absolute y turns on the copy's forced height.
|
||||
|
||||
Results, measured as the height of the base's building blocks:
|
||||
|
||||
| Request | Blocks at | Ground there |
|
||||
| --- | --- | --- |
|
||||
| no adjustment | 1–4 | −0.2 |
|
||||
| +5 | 6–9 | −1.1 |
|
||||
| absolute y = 30 | 31–34 | 0.5 |
|
||||
| a plain `rbevent` spawned right after | 1–4 | −0.2 |
|
||||
|
||||
**Trap:** the plugin's own `BuildingOptions.Clone()` is a shallow `MemberwiseClone`. The first run changed
|
||||
the height through that clone, and the change leaked into the shared profile: the next plain `rbevent`
|
||||
base spawned 35 m up. The height settings sit in a nested object, so the helper must copy that too, or
|
||||
use the same deep copy as the overrides. Nothing reached the file on disk, and `rb.reloadprofiles` reset
|
||||
the leak.
|
||||
- **The plugin's area check catches buildings, but not water.** Its safety check, run at an admin's spot,
|
||||
refused a player's building and refused an existing raid base. At 25 m away from the building it passed. A
|
||||
spot on the seabed 50 m under water also passed: the plugin tests water in its own location picker, not
|
||||
in this check. So an admin-given spot needs the helper's own water and terrain test as well as the
|
||||
plugin's check. The spike reported the check but did not enforce it; whether to enforce is a question
|
||||
for the org lead.
|
||||
- **A RaidableBases reload drops the helper's Harmony patches**, because the patched methods belong to the
|
||||
old assembly. The helper must re-patch in `OnPluginLoaded`, as the zone helper does for ZoneManager.
|
||||
- **After a server boot the plugin refuses every spawn for about 50 s**, until its log says "Grid
|
||||
initialization completed". This includes the helper's spawns. The step has to wait for that, not fail
|
||||
on it.
|
||||
|
||||
### 11.5 Protocol
|
||||
|
||||
|
||||
Reference in New Issue
Block a user