Import Management
The plugin can import a CSV of rooms to bulk-reorganise the navigation tree: move many rooms to new paths at once and update their difficulty and tags, directly from the running server. The CSV uses the exact format produced by the Export command, so the usual workflow is: export, edit the file, import it back.
Import from CSV command​
- Put the CSV file in
plugins/LEPlayServerUtils/import/(the folder is created on first use). - Type
/. import csv "<file>"(admin only). It can also be run from the server console.
CSV format​
Semicolon-separated, UTF-8: path;description;difficulty;tags;accessConditions. Text cells may be
double-quoted (inner quotes doubled); the header line is optional and is detected robustly (a leading
UTF-8 BOM or requoted header cells added by a spreadsheet round-trip are tolerated, so the header is never
imported as a data row, and an older four-column CSV without accessConditions still imports). Tags are
separated by , or ,, in any order. Each room is identified by its description (its unique name);
the path is the target position in the tree (including an automatically numbered path such as
solo.1.3).
The accessConditions column is a JSON array of a portal's access conditions, e.g.
[{"type":"levelsSolved","count":3,"path":"solo"},{"type":"isAuthor"}]. It is produced and consumed
primarily by the le-room-organizer tool.
What it does, line by line​
For every line whose room (description) exists:
- Move the room to its target
path:- if the target is free, the room is moved there;
- if the target is occupied, the occupying room is parked in the community lobby to free it (the community lobby is automatically enlarged if it is full), then the move proceeds. Rooms swap and longer dependency chains/cycles are resolved automatically.
- A room that is occupying a target but is absent from the CSV is parked permanently in the community lobby (it keeps a slot, so the lobby may stay enlarged).
- Difficulty is applied when the field is a number in
[0,1]and differs from the current value. - Tags are set to the listed tags; unknown tags are reported and ignored (the others still apply).
- Access conditions are applied from the
accessConditionsJSON: a blank cell leaves them unchanged,[]clears them, and a non-empty array replaces the whole list. The replacement is all-or-nothing — if any condition targets an unstable (auto-numbered) path it is refused, the list is left unchanged, and the recap names the room and the faulty path.
A move still proceeds when a portal access condition depends on a level path it would change, but the recap warns you and names the dependent condition(s): review or re-pin them afterwards, as such a condition may now point at the wrong level.
At the end, the community lobby is shrunk back as far as possible (it cannot shrink past the rooms that had to be parked permanently).
Empty rows: "this slot must be empty"​
The CSV is not fully declarative. A missing row means "leave this portal as is" (the import is non-destructive). Only an explicitly empty row acts:
- A row is an empty assertion when its
pathis filled and its four trailing cells (description,difficulty,tags,accessConditions) are all empty. To vacate a slot, clear those cells but keep thepath.
| Row | Behaviour |
|---|---|
path is a direct community-lobby slot (community.N) | ignored silently (the lobby is managed automatically) |
| non-community, target slot already empty | silent no-op (the no-edit round-trip case) |
| non-community, target slot occupied | the occupying room is evicted to a free community slot (growing the lobby if needed), reported as a change |
description empty but difficulty, tags or accessConditions still filled | error "inconsistent row", no action (guards an accidental cell clear) |
same path is both asserted empty and the destination of a move row | non-blocking error; the move wins, the assertion is ignored |
A community sub-hub child (community.X.Y) is not a direct lobby slot, so it follows the
non-community rule (eviction), not the silent-ignore rule.
Disabled (room-less) portals are reference / round-trip only. They appear in the export as path;;;
rows so the file stays a faithful image of the tree; on import they are read-only — typing a brand-new
description on a disabled row does not create a room (matching is by description against existing
rooms). A no-edit export → import round-trip therefore produces zero error.
Robustness​
- A faulty line never stops the import; every issue is collected in a recap.
- Only one import can run at a time.
- The recap (number of moves, changes, issues, lobby increases/decreases, and any sections left enlarged) is shown in chat when a player launched it, and is always written to the server console.
Automatic cleanup​
So the import/ folder does not grow without bound, it is pruned automatically after each import or
export command: files older than one month are deleted, and the folder is then
capped to its 10 most recent files. Any file whose name (extension included) contains save
(case-insensitive) is always kept — rename a file to e.g. ...save....csv to pin it permanently.