Developer Hardware IDs Inventory
Stable device identity across save/load: the single-schema gregID system plus the EntityInventory.
gregID: exactly one schema
Section titled “gregID: exactly one schema”Format: gregID:<Type>:<12HEX> (implementation: HardwareIdPersistencePatch, Greg*IdAssignPatch classes, HWID SYSTEM ACTIVE boot line, [gregCore][HwId] logs).
- Assign live at
Start/Awake:GregSwitchIdAssignPatch,GregPatchPanelIdAssignPatch,GregServerIdAssignPatch. Any foreign ID converts exactly once — no coexistence logic. CleanIdstrips only numericGetInstanceIDsuffixes; lettered user names (Core_Switch_A) survive.- Heal on load (
GregNetworkIdHealingonWaypointInitializationSystem.LoadNetworkState): rewritesswitchID / patchPanelID / serverIDand cable endpoints, per-entry null-guarded (one bad entry never aborts healing), dedups logs by ID string, thenRequestRouteEvaluation(). Raw↔display mapping persists viaSaveSystem.displayToRawMap. - Display separation:
gameObject.namestays vanilla;Server.UpdateServerScreenUI/NetworkSwitch.UpdateScreenUIscrub tokens. Players never see agregID. - Guard:
IncompatibleModGuardscansRegisteredMelonsat init + scene load andUnpatchSelfs the old standalone 404-PersistentID mod (log + one toast per session).
Legacy GregHardwareID : MonoBehaviour / HardwareIDManager (UniqueID, PrefabID) still exists in gregCore.Core but is superseded — target gregID.
EntityInventory (GregEntityInventory)
Section titled “EntityInventory (GregEntityInventory)”On load, everything present in the save is inventoried: servers, switches, routers, firewalls, patch panels, cables, SFP modules, LACP groups. Each entry gets a stable, player-invisible UID:
- Servers / switches / patch panels reuse their
gregID. - Cables / LACP use deterministic UIDs derived from vanilla IDs.
- Routers / firewalls / SFP persist via sidecar (
greg_inventory.<save>.tsv, index-shift repair via hint).
Drive things directly: TryFindLive, TryGetUid, GetAll, Rebuilt event. Control via MelonPreferences gregCore.EntityInventory (Enabled=true, VerboseLogging=false, DumpOnRebuild=false) + Dump() / Verify().
Rack positions (RackPatch)
Section titled “Rack positions (RackPatch)”Vanilla Rack.IsPositionAvailable is hollow (false) — the prefix keeps _usedPositions<rackHash, HashSet<int>> with MarkPositionUsed / Free / ClearRack / GetUsedCount, emitting greg.RACK.*. Lua:
greg.rack.get_all() / greg.rack.count()greg.rack.is_position_available(rackId, position)greg.rack.get_used_count(rackId)greg.rack.mark_used(rackId, position) / greg.rack.mark_free(rackId, position)Rules for mod authors
Section titled “Rules for mod authors”- Address devices by inventory UID /
gregID— never by screen label or scene name. - Expect healing: your load path must tolerate rewritten IDs and re-request routing where needed.
- Null-guard every entry you iterate — mirror the healer’s discipline.
- Never invent a second ID scheme; never ship the old PersistentID mod alongside gregCore.
- Keep
gameObject.namevanilla — put identity in ID fields + inventory, not display names.