Changelog
0.4.0
- New
Server/TeleportSpread config (default 2m, 0 disables): when several admins "Go to"
the same player, each now lands at a different point on a ring around them instead of
stacking on top of the target and each other.
- New "Map" button next to the X/Y/Z coordinate fields (teleport picker and the Players
tab's own coordinate row) — click a spot on the in-game map to fill the fields instead
of typing coordinates. Closes the Admin Forge window while the map is up so nothing
overlaps, and reopens it after the click.
- "Bring" now goes through the same server-resolved path as "Go to" instead of a
separate, client-computed position — it gets the spread-out-admins fix too (no longer
stacks the brought player exactly on top of you) and no longer silently no-ops when it
can't confirm the target's position.
- Window border/tooltip-strip flicker while dragging: fixed by switching the window to
GUI.Window (not GUILayout.Window) and snapping its remembered position to whole
pixels — GUILayout.Window silently discards a rounded position every frame.
- Window/DimTextColor now also applies to the plain toolbar captions ("Search", "Count",
the drag hint, etc.) that previously ignored it. Its default is now black (was grey);
default window opacity is now 0.8 (was 1, fully solid).
- Items/Creatures "Mod" filter is a type-to-filter + cycle button now (same UX as World
tab's Weather picker), not a row of one button per mod.
- Effects tab: vanilla/modded distinction, plus the same "Mod" filter, for status effects
added by mods that ship their own.
- Fixed the Mod filter's cycle button showing the next candidate instead of the one it
had just applied — clicking one mod would immediately relabel the button with a
different mod's name while still (correctly) filtering to the one you clicked, reading
as if the wrong mod's entries had appeared.
- Modded creatures never got a mod name (so the Creatures "Mod" filter row never appeared),
because the attribution diff read
ZNetScene.instance, which is still null for the whole
Awake prefix chain — exactly where most mods add their prefabs outside the common
modding framework's own path. It now uses the instance the Awake was actually called on.
Item attribution happened to work around this by accident; status effects and creatures
did not.
- "Go to" landed every admin at the exact same offset from the target player instead of
spreading them out (the spread angle was seeded from a value that's a constant for
every admin); "Bring" failed outright ("target player position is not available") when
the admin doing it was the listen-server host, and could in rare cases pull the wrong
player instead. Both were teleport-resolution bugs on the server side.
- The mod-filter row (Items/Creatures/Effects) could throw an IMGUI "pushing more GUIClips
than popping" error the instant you clicked into the Origin toolbar, and the window
could overflow past its own bottom edge once the row appeared, especially at the
minimum window height.
DimTextColor now falls back to the default like its description already claimed,
instead of showing broken markup for an unparsable value.
- Mod-name attribution for third-party content no longer goes stale after
the catalog it's attached to reloads (world change, late-loading mod), and no longer
merges two unrelated mods that both embed the same shared helper library under one
fake name.
- The Mod filter's cycle button could still relabel itself away from the active filter
by a second path: typing a search that filters the active mod itself out of the match
list left the button showing a different candidate while the item/creature/effect list
stayed filtered to the old one. Clears the active filter (back to "All") when that
happens, instead of leaving the two disagreeing.
- Players/Raise skill failed outright ("Method not found: void .Character.Message(...)")
for every skill, vanilla ones included, on any setup carrying a mod built on a
commonly-embedded skill-management helper library. That library's
Harmony prefix on
Skills.CheatRaiseSkill holds a call to a Character.Message
overload vanilla no longer has, and Mono resolves it while JIT-compiling the prefix —
so it throws before the prefix can even decide the skill isn't one of its own. Raise
now does the level change itself through public API and never calls CheatRaiseSkill,
so it no longer depends on that method being patch-free.
- Mod attribution could overwrite an already-known owner with "unattributed" if
ObjectDB.Awake ran a second time in the same session and re-added a prefab/effect of
the same name through a patch call that couldn't be attributed — now skipped instead of
clobbering a good value with nothing.
- Fixed a rare crash ("can only be called from the main thread") when a text-color config
value changed off the main thread (e.g. a config-file reload) instead of via the F1
manager — the stale GUI skin it leaves behind is now cleaned up from the next GUI frame
instead of destroyed on the spot.
0.3.2
- Player target picker is a click-to-select grid with a filter box now, not a cycle button
0.3.1
0.3.0
- Despawn: a mob spawned moments earlier could be "resurrected" a second later — its
destroy RPC beat its own create RPC to the server, which then ignored the destroy
and synced the mob back ("mobs reappear / press despawn twice"). Fixed by pulling
each ZDO out of the sector index immediately (so
ZNetScene can't re-instantiate
it before the destroy broadcast lands) plus one delayed re-sweep ~1.5 s after each
despawn for anything that still slipped through. Runs on the target player's client
(a dedicated server doesn't instantiate creatures, so a server-side sweep sees
nothing).
- Post-review hardening: the world / event commands now
reject NaN / out-of-bounds payloads and unknown environment names, the
env
override toast only shows to admins, cross-player actions echo a confirmation to
the admin, the weather list rebuilds on a world change, PositionPicker no
longer flips its control set mid-frame, the client tag table clears on
disconnect, and one failed Harmony patch no longer aborts the whole mod. New
Server/PlayerTags toggle; minimum window size raised to 560×560.
- Player name tags: a per-player tag (text + colour) driven by a server-side
BepInEx/config/ValheimAdminForge.tags.json (keyed by SteamID64) — a client can't
tag itself. The server broadcasts a characterZDOID -> tag table; each client
renders it on the head-plate / hover name, in chat, and in the Players tab. Edits
to the file apply within ~2 s, and the tag survives death / respawn.
- Players tab: Die action (kill the selected target; blocked by god mode, like
the console command).
- World tab: time of day, weather (from
EnvMan.m_environments), wind, and the
natural-spawn toggle are broadcast to every client (they're process-local
overrides that don't sync on their own); time skip (advance shared net time, or
jump to next morning), time scale, and a global-key editor run on the server.
New ExecutionSite.AllClients for the broadcast.
- Events tab: the random-event list is built dynamically from
RandEventSystem
(mod events included). Start an event at yourself / at a player / at coordinates,
Stop, or Random — all run on the server (the vanilla event command is
onlyServer and unreachable from a dedicated-server client). Detail card shows
biome, duration, range, what it spawns, and required global keys (missing ones
flagged). Header shows the active event with a Stop button.
- Internal:
IAdminCommand.Site (ExecutionSite.TargetClient / Server) so the
dispatcher knows whether to forward a command to a client or run it in the server
process. Shared AnchorMode enum for the "at me / at target / coords" picker.
- Creatures tab: the creature list is built dynamically from
ZNetScene —
vanilla and mod-added creatures appear with no per-mod code, same as the item
catalog. Search, vanilla/modded filter, detail panel (faction, base health, boss,
tameable). Spawn with count / star level / tamed / health override / spread,
at yourself, at another player, or at coordinates — the server resolves the
position and caps the count (Server/MaxCreatureSpawn); bosses need
Server/AllowBossSpawn. Force-tamed non-tameable creatures go passive instead of
spamming a vanilla warning.
- Creatures tab Despawn block: remove creatures / ground items / fish / birds
around a player without killing them — no loot, no death, no progress or event
credit. Filter by enemies / tamed / all, prefab name, minimum star level. Players
and tombstones are never touched; radius capped by
Server/MaxDespawnRadius.
Claims ZDO ownership first, so it clears objects owned by other clients (vanilla
removedrops / removefish don't).
- Players tab: the "send to coordinates" row now uses the same target picker as the
rest of the mod instead of its own separate one.
- Player admin actions (Players tab): god, ghost, fly, nocost, heal, puke, repair
all, clean inventory, explore / reset map, raise / reset skill, and radius sweeps
(kill all / kill enemies / kill tame / tame / aggravate) — applied to the shared
target (self or any online player). Freefly toggles the local camera only. Each
mirrors the vanilla console command of the same name, most of which a dedicated
server denies to clients. Radius sweeps are capped by
Server/MaxActionRadius.
- Listen-server (host + friends) parity. Cross-player give / effect / teleport on a
non-dedicated host now applies to the actual target instead of the host, and the
post-teleport ghost cleanup broadcasts from the host too. Previously only tested on
dedicated, where the host is headless.
- Server drops unidentified and rate-exceeding requests silently (per-peer limit) — a
spammy client can no longer flood the server log.
ItemCatalog no longer permanently discards items whose localized name didn't resolve
(e.g. a mod that registers its localization late); it falls back to the internal name,
matching the status-effect catalog. Catalog version bumps on invalidation, not on lazy
rebuild.
- Internal: shared
LazyCatalog / CatalogLoc skeleton behind both catalogs and a
FilteredList helper behind the Items / Effects tabs, so the upcoming Creatures tab
doesn't fork the pattern a third time (~100 fewer lines).
- Admin permission is enforced once in the RPC dispatcher instead of being repeated in
every command.
- Docs, dead code, and minor allocation/redraw cleanups.
Server/StrictItemCheck now
documented as also gating status effects.
0.2.0
- Effects tab: status effects discovered from
ObjectDB, with optional duration/power and
a Clear button.
- Players tab: teleport to a player, bring a player, send any player to coordinates.
Server resolves target positions (works even when map-sharing is off). Instant vs
loading-screen teleport with freeze protection; post-teleport ghost cleanup.
- Target picker on the Items and Effects tabs (self / any online player).
- Item catalog now drops unresolved/cut-content entries; localized names and descriptions.
- Client↔server handshake reports the admin verdict and warns on a mod-version mismatch.
- RPC handlers are exception-guarded; diagnostic logging moved to Debug level.
0.1.0
- Item catalog built dynamically from
ObjectDB (vanilla + modded), with search,
categories, vanilla/modded filter, sort, detail panel and quantity stepper.
- Server-authoritative give: per-connection RPC, admin check against the real socket
identity,
IAdminCommand extension point.
- IMGUI window (Insert), input capture while open.