Releases: ghstwhl/XPortalNetworksTribesPins
Release list
3.1.1
Summary
Docs-only patch. The docs now present the mod with a single hero screenshot, and no image they
display is hosted in someone else's repository.
Bumps the mod to 3.1.1 — PATCH: no code, config or behaviour change.
Base: main (v3.1.0). This is the only delta on top of the released 3.1.0.
What changed
One hero screenshot instead of three (README.md)
- "Portal Configuration UI", "Network Selection Window" and "Destination Network Selection" — three
separate windows of the same feature — are replaced by a single "Opposing Tribe Views" image,
images/split-tribe-view.png.
No image is hot-linked from another repository (README.md, Docs/Modules/20Features.t4,
Docs/Modules/11HeaderGitHub.t4, Docs/SolutionDir/README.md, and the hand-mirrored
Docs/README.Nexus.bbcode / Docs/SolutionDir/Package/Release/README.md)
- The Advanced Portals illustration was served from
SpikeHimself/XPortal— removed; the paragraph
simply ends where its picture was. - The Thunderstore badge was served from
SpikeHimself/resources— removed; "Where to Download"
keeps its existing Thunderstore bullet, which is what the badge linked to anyway. - The keyhints screenshot now points at this repository's own
images/ui-keyhints-small.png, which
was already committed here, instead of another project's copy of the same image. - This is about images, not links: the credits, the original mod, Jotunn, BepInEx, Advanced
Portals and the Nexus pages are all still linked exactly as before, and the Vapok Gaming avatar
stays as it is.
Unreferenced images deleted (images/)
- 15 files, about 2.1 MB, that nothing pointed at once the hero image was consolidated: the three
superseded UI screenshots, both Advanced Portals illustrations, the retired Nexus "buy me a coffee"
and Survival Servers banners, and the older single-shot UI images
(configuration.png,defaultportal.png,dropdown.png,hover.png,pingmapdisabled.png,
showonmap.png,ui-keyhints.png,connect-explore-header.jpeg,xportal networks icon.jpeg). - What is left is what the docs use:
controller.gif,icon.png,ui-keyhints-small.png, and the
newsplit-tribe-view.png.
Version and changelog
- 3.1.0 is already released (tag
v3.1.0onmain), so the docs bullets that had been written under
the 3.1.0 entry move into a new# 3.1.1 - Documentation Presentation & Asset Cleanupentry in
Docs/PATCHNOTES.mdandCHANGELOG.md; the released 3.1.0 entry is otherwise untouched, and the
released 3.0.4 entry keeps its historical "(badge + link)" wording. - Version bumped in
ModInfo.cs,manifest.jsonandDocs/SolutionDir/Package/Release/manifest.json.
Diff
8 files changed, 11 insertions(+), 40 deletions(-), excluding images/; plus 15 image deletions and
1 addition (images/split-tribe-view.png).
Verification
tools/Build.ps1→BUILD OK - XPortalNetworks 3.1.1 (Release); the script also re-validated the
version/manifest sync and the package JSON (13 files OK).- Image-reference audit across every
.md/.bbcode/.t4/.tt: the only hot-linked images are
controller.gif,ui-keyhints-small.pngandsplit-tribe-view.png— all from this repository. - No runtime testing needed: no code, config or behaviour change.
Deployment notes
- Everyone should update together. The mod declares
NetworkCompatibility(EveryoneMustHaveMod, VersionStrictness.Patch), so even though 3.1.1 changes
nothing at runtime, 3.1.0 and 3.1.1 peers are reported as incompatible. This is also why the bump
is a patch rather than a docs-only no-op. - A Thunderstore upload is needed for the store README change to appear on the listing.
Reviewer notes
images/split-tribe-view.pngis currently untracked — it must be included in the commit, or the new
hero image 404s on GitHub and Thunderstore. The 15 deletions are already staged in the working tree.- A stale local branch named
3.1.1(at50a9b83, the pre-fixup 3.1.0 state) collides with this
version's name and should be deleted or renamed before the PR branch is created. Docs/SolutionDir/Package/Release/CHANGELOG.mdis an inherited upstream artifact (still at v1.2.24)
and is deliberately untouched.
Version 3.1.0
Takes main from 3.0.1 to 3.1.0. Headline is the new portal hammer-removal
restrictions; the branch also carries the 3.0.2 - 3.0.4 documentation passes.
Portal removal restrictions (3.1.0)
Two server-owned settings, each a complete rule on its own, cumulative when both are on:
RestrictPortalRemovalToCreator(renamed fromRestrictPortalRemoval): only the player who
placed the portal may remove it with the hammer. It never looks at portal networks. Now on by
default (it used to default to off).RestrictPortalRemovalToUsable(new): only a player allowed to use the portal may remove it,
reusing the check that already gates the portal configuration panel - the portal's own network must
be Global, unrestricted, or one they are a member of, and a private portal may only be removed by its
owner. It reads the portal's own network and privacy, never its destination's. On by default.- Together: every enabled rule has to be satisfied, so enabling one never loosens the other. With
both on (the default) a player may only remove a portal they placed and may still use. - Admins: neither rule gives the host or server admins a free pass on its own - the bypass is the
gatedAdminsSeeAllNetworksnotion, so with that setting off (the default) a portal an admin cannot
open is also one they cannot hammer. - Structural damage (mobs, decay) is unaffected, and portals keep decaying exactly as before: a new
WearNTear.CanBeRemovedpostfix keeps the owner-side wear simulation out of the player-facing rule,
which is what allowed the old unconditional host/admin short-circuit to go.
Two defects were found and fixed during development, both via manual in-game testing: an unconditional
host/admin short-circuit that defeated the new rule on the host, and additive (OR) semantics that let
the creator clause override the usable rule.
Documentation (3.0.2 - 3.0.4)
- 3.0.4 - Live Store Links:
README.mdgains a Where to Download section and loses the stale
"Automatic (Not currently available)" heading;Docs/SolutionDir/README.mdlists both live locations
and drops a leftover "Nexus Mods" reference (this fork has no Nexus page);urlThisModThunderstore
now builds the currentthunderstore.io/c/valheim/p/<team>/<package>/URL. - 3.0.3 - Documentation Naming Consistency: one rule for the name -
XPortalNetworksTribesPinsis
the technical identity (plugin name, store/repo name, URLs) and "XPortal Networks Tribes Pins" is the
human name used in prose. AddsMod.Info.HumanName/thisModHumanName, switches the doc templates
to it, and refreshes the tracked generated docs and issue templates that still carried the pre-3.0.0
names. - 3.0.2 - Portal Network Docs Correction: the READMEs no longer claim custom networks live in
xportal_networks.json, plus mod-name and typo corrections. - Housekeeping:
.gitignoreignores.vscode/settings.json, and the repository instructions title
uses the current mod name.
Upgrade notes
- Renamed key:
RestrictPortalRemoval->RestrictPortalRemovalToCreator. An existing value is
carried over to the new key (XPortalNetworksConfig.MigrateRenamedBool); the old line is left behind
as an inert key that can be deleted. - Changed defaults: both removal settings now default to enabled. An upgrading server keeps its own
value for the renamed key, but one that never set it will now restrict hammer removal. - Versioning: the renamed config option and the flipped default are MAJOR-level under the repo's
own versioning rules; kept as 3.1.0 because the release is not yet published. - No ZDO key, RPC or network-protocol changes. The plugin declares
NetworkCompatibility(EveryoneMustHaveMod, VersionStrictness.Patch)- "mods must have the same Patch
version" - so server and clients should be updated together.
Verification
tools/Build.ps1:BUILD OK - XPortalNetworks 3.1.0 (Release).- Manual in-game test on a self-hosted server: with
AdminsSeeAllNetworksoff, a portal on a network
the host is not a member of can neither be opened ('E') nor removed with the build hammer. Verified
working.
Portals Teams Pins Oh My!
Portal map pins, independent plugin identity & config-driven portal networks (v2.2.0 → v3.0.1)
Summary
This PR rolls up the portal-network rework, a new client-side map-pin feature, a full plugin re-identification, and the tooling/docs updates that go with them.
New: portal map pins, built directly into the mod (no companion mod), with two new client-local toggles.
New: portal networks (names + allow lists) moved into the server-owned BepInEx config, so Jotunn ServerSync distributes them and they can be managed in-game instead of by editing a JSON file on the server.
New: networks can be restricted to specific players ("tribe networks"), with admin bypass.
Changed: the fork now has its own plugin GUID/Name, GitHub home and Thunderstore identity.
Breaking for multiplayer: server and clients must update together (see Breaking changes & upgrade notes).
Versions in this range: 2.2.0 (MINOR) → 2.4.0 (MINOR) → 2.6.0 (MINOR) → 3.0.0 (MAJOR) → 3.0.1.
v2.2.0 — Implementation of Teams for Portal Networks
Adds support for portal networks that are restricted to specified players.
Dynamically reloads xportal_networks.json, so the server does not need to be restarted when network allow lists change.
Defaults to admins having the same portal restrictions, but this can be changed in the config file.
Adds support for Jotunn ServerSync of configuration settings.
v2.4.0 — Portal Networks in the Server Config
Portal networks (names and allow lists) move out of the standalone xportal_networks.json file and into the server-owned BepInEx config, which Jotunn's ServerSync distributes to every client. Networks and membership can now be managed from inside the game instead of editing files on the server.
Mod
XPortalNetworksConfig: new Portal Networks section with, for ids 1–15, Network Name and Network Allow List (comma-separated player ids). Both carry ConfigurationManagerAttributes.IsAdminOnly, so ServerSync pushes them to clients and only server admins/host may change them. Empty name keeps a slot unused; empty list means the network is open to everyone. Added GetNetworkName / GetNetworkAllowList / HasAnyNetworkDefined / ApplyImportedNetworks.
CustomNetworks: definitions are now built from the config via RebuildFromConfig() (called on every SettingChanged), with ParseAllowListSetting() for the list format. ResetSession() rebuilds instead of clearing. A pre-2.4.0 xportal_networks.json is imported once by InitializeServer() → ImportLegacyJsonIfNeeded(), and only when no network is configured yet, so in-game edits are never overwritten.
XPortalNetworksConfig.LocalConfigChanged rebuilds the network list rather than re-pushing it; XPortalNetworks no longer calls CustomNetworks.ServerTick() or ShutdownServer().
Removed (ServerSync replaces them)
The per-client network RPC: RPC_CustomNetworks / _RequestCustomNetworks, the queued re-send helpers, SendToClient.CustomNetworks, SendToServer.RequestCustomNetworks, ClientEvents.RPC_CustomNetworks and ServerEvents.RPC_RequestCustomNetworks. AdminSync is untouched.
The JSON pipeline in CustomNetworks: FileSystemWatcher, main-thread polling and debounce (ServerTick / DetectFileChange / UpdateFileBaseline / MarkReloadPending), embedded-template seeding (EnsureDefaultConfigExists), ReloadFromDiskAndBroadcast and the distribution helpers (PackForClient / ApplyFromServer / BroadcastToAllPeers).
XPortalNetworks/xportal_networks.json and its entry.
Docs/SolutionDir/README.tt (see Docs below).
Build and tooling
Build.ps1 no longer JSON-validates the networks file (translations only).
README.md documents which docs are generated from which T4 template, which are hand-maintained, and how to regenerate.
copilot-instructions.md: the MAJOR-level example now refers to portal-network config incompatibilities instead of the removed JSON format.
Docs
25Configuration.t4 completed: it was missing DefaultPrivatePortal, RestrictPortalRemoval, AdminsSeeAllNetworks, the Portal Networks entries and the two [Local Config] toggles; the generated Nexus bbcode and package README, plus the README settings lists, now match the actual config.
T4 modules (10Header, 11HeaderGitHub, 20Features, 25Configuration, 90InstallationDev) use the assembly-derived thisModName / thisModGitHubRepo instead of hard-coded "XPortal" and the original SpikeHimself/XPortal banner URL, so a regeneration no longer reintroduces pre-rename branding.
Regenerated README.Nexus.bbcode and README.md: correct mod name, vapok.mods.xportalnetworks.cfg path, banner and Nexus/Thunderstore/GitHub links. Diffed before overwriting — no hand-written content lost.
README.md is explicitly hand-maintained (its template was removed): it is a hybrid of generated and hand-written sections, so regenerating it would have deleted the configuration and installation sections.
Behaviour changes to note
xportal_networks.json is read once for migration and then ignored; it can be deleted.
Allow lists now reach every client (previously names only for permitted networks). Server-side enforcement of portal edits and links is unchanged.
The config RPC removal means mixed mod versions cannot interoperate; VersionStrictness.Patch already requires identical builds on server and client.
Versioning
2.4.0 (MINOR: new config options and in-game management, backwards compatible via the one-time import) in ModInfo.cs, manifest.json and manifest.json, with entries in PATCHNOTES.md and CHANGELOG.md.
Verified with Build.ps1: BUILD OK - XPortalNetworks 2.4.0 (Release), 541,184 bytes, 13 JSON files validated.
v2.6.0 — Portal Map Pins, project home move & new Thunderstore identity
Version bump 2.5.0 → 2.6.0 (MINOR: new feature + new config options, backwards compatible).
Portal map pins (new feature — PortalMapPins.cs, Patches/Minimap.cs)
Builds in the standalone "XPortal Shared Map Pins" mod by buldosik, so no companion mod is needed and the standalone one must now be removed to avoid duplicate pins.
Pins are purely local map data: nothing is written to the world, nothing is sent over the network, vanilla player pins are untouched, and the pins are never saved to the map file (save: false, ownerID: 0).
Visibility mirrors the destination dropdown: Global network, tribe networks you are a member of (or may bypass as admin via AdminsSeeAllNetworks), public portals on personal networks, and your own private portals. Other players' private portals and restricted networks are never pinned, so the map cannot reveal portals you have no access to.
Dedicated Minimap.PinType registered right after the vanilla enum, so the legend toggles are not hijacked. The marker is the game's own portal map icon (located in Minimap.m_icons by sprite name, as the standalone mod found it) tinted the standalone mod's bright blue (0.4, 0.8, 1), with its generated white ring as the no-portal-sprite fallback. Because Minimap.UpdatePins re-colours every marker, the new Minimap_UpdatePins postfix re-applies the colour after each pass (the standalone mod needed the same patch).
Reconcile runs every 5 seconds and is marked dirty immediately by KnownPortalsManager AddOrUpdate / Remove / Reset, by network-list changes and by config changes (including the synchronized PingMapDisabled and AdminsSeeAllNetworks), so renamed/moved/destroyed portals stay current and pins deleted on the map come back. Pins reset on world load and on destroy.
No pins at all while the server has PingMapDisabled enabled, so a no-map server stays no-map.
New [Local Config] settings (XPortalNetworksConfig.cs)
Show Portal Map Pins (default on) turns the pins off again.
Show Network In Pin Name (default off) prefixes a pin with its network, e.g. [Trade Hub] North Base.
Both are client-local preferences and are not synchronized from the server.
Project home move & publishing identity (ModInfo.cs, both manifests, docs)
GitHubRepo → ghstwhl/XPortalNetworksTribesPins, Author → ghstwhl, and the Thunderstore team/package (NorCal_Nerds / XPortalNetworksTribesPins) is declared once in ModInfo.cs and drives the generated install links and the package staging folder.
No identity change where it matters: the plugin GUID, the plugin Name (the portal ZDO keys and RPC names derive from it) and the config file name are unchanged, so existing worlds, settings and multiplayer compatibility are unaffected. Vapok/XPortalNetworks stays credited as the base this project continues, and NexusId still points at the upstream page until this fork has one of its own.
Build tooling & docs
Build.ps1 emits a second artifact named after the version (XPortalNetworks-.zip) alongside XPortalNetworks-release.zip; README.md documents both.
csproj copies through a PackageFolder property (Team-Package, overridden by Build.ps1) instead of the hard-coded -Vapok suffix, for both the Release package and the dev-plugins copy.
Docs: READMEs, the .t4 templates and the tracked generated outputs (README.Nexus.bbcode, package README/manifest) document the new settings and the map-pin feature; REFERENCES.md adds the ported mod (which declares no licence, so it is credited explicitly) and records the BepInEx v5-lts fork provenance. buldosik is credited in Credits & Acknowledgements.
Terminology
Shared portal networks are now described as tribe networks (was: team networks) in code comments and documentation — wording only, with no behaviour, config or localization changes. Entries for already-released versions keep their original wording.
v3.0.0 — Independent Plugin Identity: own GUID/Name, legacy data migration, Vapok dependency dropped
Version bump 2.6.0 → 3.0.0 (MAJOR: plugin identity, RPC/ZDO keys and config file name change, so older peers are no longer compatible).
Plugin identity (ModInfo.cs)
GUID is now ghostwheel.mods.xportalnetworkstribespins (was vapok.mods.xportalnetworks), so the fork no longer registers under the upstream author's namespace in BepInEx/Jotunn; HarmonyGUID follows automatically.
N...