refactor(spawners): replace DynamicJson with typed SpawnerDto records (#2505)
## Summary Removes the dated `DynamicJson` JSON helper and migrates spawner JSON (de)serialization to a polymorphic `record SpawnerDto` hierarchy. `DynamicJson` was the last remaining consumer (regions moved off it in #1400). The key correctness improvement: **System.Text.Json deserializes plain DTO records, never a live `Item`.** Previously, deserializing directly into an `Item` meant STJ constructed world-registered objects *before* the data was validated — a malformed/hand-edited spawn file could leave orphaned spawner Items in the world save. Now a parse failure is GC-only; `dto.ToSpawner()` constructs the spawner only from a fully-validated DTO and self-cleans on failure. ## What changed - **New:** `SpawnerDto` (abstract) + `SpawnerDataDto` / `RegionSpawnerDto` / `ProximitySpawnerDto`, each marked with a reusable `[JsonDiscoverableType]` opt-in attribute. Auto-discovered at the `Configure` phase — no manual registration list (avoids the regions `Register<T>()` footgun), open to custom spawner subtypes. - **Symmetric mapping:** `BaseSpawner.ToDto()` (export) ⇄ `SpawnerDto.ToSpawner()` (import). `ToSpawner()` deletes-and-rethrows on any failure, so the importer can never orphan an Item. - **`SpawnerJsonSerializer`** wires `$type` polymorphism on the `SpawnerDto` root with loud collision/constructibility validation. - **Import/export commands** rewired to the typed DTO path (reflection `FindTypeByName`/`CreateInstance` removed). - **Data migration:** the 109 `Distribution/Data/Spawns/**` files moved from `"type"`→`"$type"` and legacy `homeRange`→`spawnBounds`. The runtime still *reads* legacy `homeRange` for external files. The `homeRange→spawnBounds` formula is proven equivalent to the runtime conversion (`BoundsEquivalenceTests`, hr=0/1/3/7). - **Deleted:** `Projects/Server/Json/DynamicJson.cs`. Sparse export output matches the legacy `ToJson` (nullable DTO properties + `WhenWritingNull`). Binary world-save serialization is untouched. ## Tests - DTO round-trip per spawner type; sparse-default omission; legacy `homeRange` read; export/import file round-trip. - `Import_MalformedFile_LeaksNoWorldItems` — proves a mid-array parse failure constructs zero world Items. - `AllSpawnFilesLoadTests` — every migrated spawn file deserializes and builds. - Duplicate-discriminator validation. - UOContent.Tests 485/485, Server.Tests 710/710, build clean. ## Follow-up (not in this PR) `Rectangle3DConverter.Write` (in `Projects/Server/`) omits `z1/z2` when `Start.Z == -128`, so a future server-side export of a `homeRange`-style spawner round-trips depth 256→255. Pre-existing and out of scope here (Server change); the migrated data reads correctly. Worth a separate small converter PR.
This commit is contained in:
parent
a26219c837
commit
d8a64f3316
135 changed files with 7654 additions and 6079 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
[
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "0034e4c4-162c-4569-bd5d-9faef725ecd5",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2054, 516, 0],
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "046e36ec-faf1-4f5f-8f8f-4cf50e2ba3ef",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1938, 1408, 0],
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "065cdc7b-b2ce-4339-b45c-c96f4a734723",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5618, 2744, 0],
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "0b3ccf5f-b1e6-4cd7-a1f7-b4662fe4ff9a",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1070, 2320, 0],
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "0b82556d-2f5d-4fa0-b53e-fc95ed035b3f",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1286, 504, 0],
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "0d10ddc0-6866-4c69-945e-830fe9fa18c5",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5674, 3120, 0],
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "11579f1f-1437-48f9-9061-a409f8468750",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1566, 1140, 0],
|
||||
|
|
@ -161,7 +161,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "16af2efe-3319-4812-9089-2fe793653f21",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1114, 1416, 0],
|
||||
|
|
@ -184,7 +184,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "1853a130-1967-4711-bb38-522e045b5820",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1514, 1584, 0],
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "1bafedf2-97d4-484d-9ef3-4597666765ce",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2854, 816, 0],
|
||||
|
|
@ -230,7 +230,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "21879949-0b91-42cc-ad2d-7b616b27ad05",
|
||||
"name": "Spawner (229)",
|
||||
"location": [342, 1464, 0],
|
||||
|
|
@ -253,7 +253,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "2fe931f6-6f60-411c-a235-dcc4b9cb9fc2",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1934, 2328, 0],
|
||||
|
|
@ -276,7 +276,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "36a65d30-bbb1-4476-9336-302ca764c41b",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1658, 236, 0],
|
||||
|
|
@ -299,7 +299,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "39aee7f8-373f-4191-b349-f5c9bb367abd",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2930, 3476, 0],
|
||||
|
|
@ -322,7 +322,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "3a6221c9-7105-4707-aaa1-8e9005016a6b",
|
||||
"name": "Spawner (229)",
|
||||
"location": [718, 1180, 0],
|
||||
|
|
@ -345,7 +345,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "3c91dce8-087c-4dff-96bf-6d2f32ff57b9",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2750, 368, 0],
|
||||
|
|
@ -368,7 +368,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "3fe88456-6018-41e4-b9af-a129a1025651",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3602, 2948, 0],
|
||||
|
|
@ -391,7 +391,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "40ea761c-a1da-48b7-9663-0571df9a28cc",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1078, 2772, 0],
|
||||
|
|
@ -414,7 +414,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "4144faa9-61d4-47fa-be5c-665e94989f9c",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1466, 3032, 0],
|
||||
|
|
@ -437,7 +437,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "4394742a-5799-4d8c-9d29-11753415b5b5",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1122, 3524, 0],
|
||||
|
|
@ -460,7 +460,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "450db427-aea5-48a7-95f4-36f2e64d4aec",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2374, 652, 0],
|
||||
|
|
@ -483,7 +483,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "472b629a-65dc-4e26-a728-19a1dc715740",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4590, 1448, 0],
|
||||
|
|
@ -506,7 +506,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "4f547881-9057-4530-bacd-f2d8b8d3918a",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2522, 84, 0],
|
||||
|
|
@ -529,7 +529,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "50c090e2-807c-4a99-a467-a0430a8cc232",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2734, 2168, 0],
|
||||
|
|
@ -552,7 +552,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "51190b84-1742-4bea-ab6e-9387c4ff0efa",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4426, 1028, 0],
|
||||
|
|
@ -575,7 +575,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "54855ff6-f02b-4bc4-a803-455719541850",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5934, 3436, 0],
|
||||
|
|
@ -598,7 +598,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "54bb9a76-f991-425d-9b3a-20310659b1dd",
|
||||
"name": "Spawner (229)",
|
||||
"location": [702, 1752, 0],
|
||||
|
|
@ -621,7 +621,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "59cfb257-99a9-4a1d-9220-8aeb3712dd60",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3538, 2536, 0],
|
||||
|
|
@ -644,7 +644,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "6813adda-8875-4603-9a78-57aab7688e56",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5326, 2492, 0],
|
||||
|
|
@ -667,7 +667,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "6a796506-6692-420c-bc95-cd7fcf99d1b9",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2062, 964, 0],
|
||||
|
|
@ -690,7 +690,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "7a28f716-9fa0-4686-ad8c-ca1e7ab1a9e3",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1582, 2028, 0],
|
||||
|
|
@ -713,7 +713,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "7eaf59ab-e769-4772-aaa3-06d741e424ae",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1490, 2472, 0],
|
||||
|
|
@ -736,7 +736,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "821fbdbf-ae39-4073-adb0-17e2e9ee87aa",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2082, 60, 0],
|
||||
|
|
@ -759,7 +759,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "8255d504-90e7-4ca3-a2bd-1cdfc72983f7",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1846, 3260, 0],
|
||||
|
|
@ -782,7 +782,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "8553a096-7a8e-4f69-accf-401bfef947fb",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5474, 3904, 0],
|
||||
|
|
@ -805,7 +805,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "870cd346-44a3-45cd-b8f2-b65543021467",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3198, 504, 0],
|
||||
|
|
@ -828,7 +828,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "8c69fc76-ecf7-4282-84c1-9fa5cecda213",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2474, 3956, 0],
|
||||
|
|
@ -851,7 +851,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "96d35be0-ba86-4f2e-8c27-2ef75a684c93",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5926, 3888, 0],
|
||||
|
|
@ -874,7 +874,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "9b42e3cb-2224-4516-9fe2-165a19bcda3d",
|
||||
"name": "Spawner (229)",
|
||||
"location": [366, 900, 0],
|
||||
|
|
@ -897,7 +897,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "9f1da2ac-4a31-415d-99c6-76921de812b0",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4282, 3700, 0],
|
||||
|
|
@ -920,7 +920,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "ab7cf0fc-e53d-4f1b-a6f6-7c9bc21df8df",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1694, 688, 0],
|
||||
|
|
@ -943,7 +943,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "abb85eaf-f92e-41a0-a6cf-8c0bfab71e30",
|
||||
"name": "Spawner (229)",
|
||||
"location": [642, 2216, 0],
|
||||
|
|
@ -966,7 +966,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "b0d2917b-3296-4811-bf68-c9eb6fac7f2b",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5234, 3068, 0],
|
||||
|
|
@ -989,7 +989,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "b229c260-ee7d-4aab-bacf-3e974e2e8934",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4166, 584, 0],
|
||||
|
|
@ -1012,7 +1012,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "b745dd5f-b8ef-4950-baef-569e80994036",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2226, 3532, 0],
|
||||
|
|
@ -1035,7 +1035,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "b89e1c55-2a8a-4e42-aa92-5718f3699c0f",
|
||||
"name": "Spawner (229)",
|
||||
"location": [746, 636, 0],
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "c012739f-6a97-413c-b2bd-249fd2b7e51f",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1410, 3796, 0],
|
||||
|
|
@ -1081,7 +1081,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "c4d5ac68-9b53-488f-94bd-6e6d1dec3493",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5462, 3452, 0],
|
||||
|
|
@ -1104,7 +1104,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "cd38b465-2ed5-4634-ae0a-e8b2ab38c2d4",
|
||||
"name": "Spawner (229)",
|
||||
"location": [2490, 1096, 0],
|
||||
|
|
@ -1127,7 +1127,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "cdd876a8-1378-4ccd-8f12-9cdac9c3487a",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4570, 3340, 0],
|
||||
|
|
@ -1150,7 +1150,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "d233e91c-82d3-4130-a747-2be35a3c7e55",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1134, 964, 0],
|
||||
|
|
@ -1173,7 +1173,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "d276b701-845a-4648-ba54-fde4f1a7d725",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3994, 328, 0],
|
||||
|
|
@ -1196,7 +1196,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "d3bf2b6e-3947-4a69-9600-04527ef88ff1",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3130, 116, 0],
|
||||
|
|
@ -1219,7 +1219,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "dbc82493-6b0c-46a7-a243-e0cb875f4bcf",
|
||||
"name": "Spawner (229)",
|
||||
"location": [5966, 2456, 0],
|
||||
|
|
@ -1242,7 +1242,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "dd4c385d-b00e-47ab-a6bc-f2cb490c9567",
|
||||
"name": "Spawner (229)",
|
||||
"location": [6042, 2916, 0],
|
||||
|
|
@ -1265,7 +1265,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "e0199ccf-a3a0-4888-9939-42b7a5ad553a",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1150, 1876, 0],
|
||||
|
|
@ -1288,7 +1288,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "e17f7124-9255-4f70-94b4-c6716544873d",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3674, 1216, 0],
|
||||
|
|
@ -1311,7 +1311,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "f229444f-13ea-4dba-aa0e-d0a4bd0887ee",
|
||||
"name": "Spawner (229)",
|
||||
"location": [1850, 2796, 0],
|
||||
|
|
@ -1334,7 +1334,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "f5544628-f982-40f3-b44a-f5db0507a62e",
|
||||
"name": "Spawner (229)",
|
||||
"location": [4710, 3796, 0],
|
||||
|
|
@ -1357,7 +1357,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "Spawner",
|
||||
"$type": "Spawner",
|
||||
"guid": "f55cc26e-f8f2-47cc-9af0-ccd026d9a18d",
|
||||
"name": "Spawner (229)",
|
||||
"location": [3714, 2152, 0],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue