<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://developer.vellocetsoftware.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DocumentationBot</id>
	<title>Vellocet Developer Community - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://developer.vellocetsoftware.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DocumentationBot"/>
	<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/wiki/Special:Contributions/DocumentationBot"/>
	<updated>2026-08-25T07:52:51Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Vellocet_Developer_Community:Community_portal&amp;diff=42</id>
		<title>Vellocet Developer Community:Community portal</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Vellocet_Developer_Community:Community_portal&amp;diff=42"/>
		<updated>2026-08-25T05:34:36Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki documents public modding tools and APIs for Vellocet games.&lt;br /&gt;
&lt;br /&gt;
== Page types ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Official guides&#039;&#039;&#039; explain supported workflows and are reviewed alongside game changes.&lt;br /&gt;
* &#039;&#039;&#039;Generated reference pages&#039;&#039;&#039; are produced from public SDK code and stored in the protected &amp;lt;code&amp;gt;Generated:&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
* &#039;&#039;&#039;Community pages&#039;&#039;&#039; collect tutorials, examples, troubleshooting, and practical knowledge from mod authors.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
Public account registration is closed while Vellocet completes outbound email, anti-abuse protection, and contribution terms. Vellocet staff can create editor accounts.&lt;br /&gt;
&lt;br /&gt;
Before editing, read the [[Vellocet Developer Community:Content policy|content policy]]. Use article talk pages for questions about a specific document and [[Help:Contents]] for wiki help.&lt;br /&gt;
&lt;br /&gt;
== Maintenance ==&lt;br /&gt;
&lt;br /&gt;
* [[Special:RecentChanges|Recent changes]]&lt;br /&gt;
* [[Special:NewPages|New pages]]&lt;br /&gt;
* [[Category:Draft documentation|Draft documentation]]&lt;br /&gt;
* [[Special:WantedPages|Wanted pages]]&lt;br /&gt;
* [[Special:BrokenRedirects|Broken redirects]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Upcoming_games&amp;diff=41</id>
		<title>Upcoming games</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Upcoming_games&amp;diff=41"/>
		<updated>2026-08-25T05:34:35Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Vellocet has not published authoring tools for its unannounced or unreleased games.&lt;br /&gt;
&lt;br /&gt;
Grimwar entities, package schemas, VSig features, and VMod APIs apply only to Grimwar. Shared tools are documented under [[Vellocet SDK]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Vellocet games]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=ANEURISM_IV&amp;diff=40</id>
		<title>ANEURISM IV</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=ANEURISM_IV&amp;diff=40"/>
		<updated>2026-08-25T05:34:34Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ANEURISM IV does not have a public authoring SDK or supported mod API. Grimwar package, VSig, and VMod instructions do not apply unless an ANEURISM IV page says otherwise.&lt;br /&gt;
&lt;br /&gt;
[[Category:ANEURISM IV]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar&amp;diff=39</id>
		<title>Grimwar</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar&amp;diff=39"/>
		<updated>2026-08-25T05:34:22Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
&lt;br /&gt;
Grimwar supports custom Unity maps, VSig map logic, VMod server scripts, addon packages, Steam Workshop maps, and community dedicated servers.&lt;br /&gt;
&lt;br /&gt;
== Start here ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Goal !! First document&lt;br /&gt;
|-&lt;br /&gt;
| Install the authoring tools || [[Vellocet SDK]]&lt;br /&gt;
|-&lt;br /&gt;
| Build a map || [[Grimwar/Mapping]]&lt;br /&gt;
|-&lt;br /&gt;
| Script map logic || [[Grimwar/VSig]]&lt;br /&gt;
|-&lt;br /&gt;
| Write server gameplay || [[Grimwar/VMod|VMod C# scripting]]&lt;br /&gt;
|-&lt;br /&gt;
| Install or select a package || [[Grimwar/Addons|Using addons]]&lt;br /&gt;
|-&lt;br /&gt;
| Publish a map || [[Grimwar/Steam Workshop addons|Steam Workshop publishing]]&lt;br /&gt;
|-&lt;br /&gt;
| Operate a community server || [[Grimwar/Dedicated servers]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Versions ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Component !! Version&lt;br /&gt;
|-&lt;br /&gt;
| Vellocet SDK || 1.0.3&lt;br /&gt;
|-&lt;br /&gt;
| Unity editor || 6000.3.17f1&lt;br /&gt;
|-&lt;br /&gt;
| SDK content schema || 3&lt;br /&gt;
|-&lt;br /&gt;
| Addon schema || 9&lt;br /&gt;
|-&lt;br /&gt;
| VMod API || 5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Packages built for an older rejected schema or a different VMod API must be rebuilt against the current SDK. Steam Workshop publishing currently accepts map-only Release packages; VMod packages use manual installation or the development overlay.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Upcoming_games&amp;diff=35</id>
		<title>Upcoming games</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Upcoming_games&amp;diff=35"/>
		<updated>2026-08-25T05:13:20Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page does not document unannounced games or unreleased interfaces. A game receives technical pages only after Vellocet publishes its authoring tools and compatibility boundary.&lt;br /&gt;
&lt;br /&gt;
Do not assume that a Grimwar entity, package schema, VSig feature, or VMod API works in another game. Shared tooling is documented under [[Vellocet SDK]]; runtime behavior belongs under the game that implements it.&lt;br /&gt;
&lt;br /&gt;
[[Category:Vellocet games]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=ANEURISM_IV&amp;diff=34</id>
		<title>ANEURISM IV</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=ANEURISM_IV&amp;diff=34"/>
		<updated>2026-08-25T05:13:19Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;No public ANEURISM IV authoring SDK or supported modding contract is documented here yet. Do not apply Grimwar package, VSig, or VMod instructions to ANEURISM IV unless a game-specific page explicitly says they are compatible.&lt;br /&gt;
&lt;br /&gt;
[[Category:ANEURISM IV]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Vellocet_SDK&amp;diff=33</id>
		<title>Vellocet SDK</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Vellocet_SDK&amp;diff=33"/>
		<updated>2026-08-25T05:13:17Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Notice|title=Version target|These instructions cover Vellocet SDK 1.0.3, Unity 6000.3.17f1, SDK content schema 3, addon schema 9, and Grimwar VMod API 5.}}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Vellocet SDK&#039;&#039;&#039; is the Unity authoring package for Grimwar maps and addon content. It installs the map compiler, entity markers, VSig tools, validation, spatial baking, custom audio support, and the addon exporter.&lt;br /&gt;
&lt;br /&gt;
== Install the SDK ==&lt;br /&gt;
&lt;br /&gt;
# Install the current SDK with the VSDK app.&lt;br /&gt;
# Open &#039;&#039;&#039;Window &amp;gt; Package Manager&#039;&#039;&#039; in Unity.&lt;br /&gt;
# Select &#039;&#039;&#039;+ &amp;gt; Add package from disk...&#039;&#039;&#039;.&lt;br /&gt;
# Open &amp;lt;code&amp;gt;SDKPackage/package.json&amp;lt;/code&amp;gt; inside the VSDK install folder.&lt;br /&gt;
# Use Unity &amp;lt;code&amp;gt;6000.3.17f1&amp;lt;/code&amp;gt; if Unity reports a version mismatch.&lt;br /&gt;
# When setup asks for SDK content, select the VSDK folder that contains &amp;lt;code&amp;gt;SDKPackage&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SDKContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Choose an addon export folder outside the Unity project.&lt;br /&gt;
# Install VSig editor support when prompted, then reload VS Code or restart Rider.&lt;br /&gt;
&lt;br /&gt;
Run &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Welcome &amp;amp; Setup&#039;&#039;&#039; to repeat setup. The SDK rejects map compilation and export in other Unity versions.&lt;br /&gt;
&lt;br /&gt;
== Keep authored and managed files separate ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Owner !! Rule&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt; || Map author || Put maps, materials, models, audio, and other original assets here.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assets/CustomContent/Maps&amp;lt;/code&amp;gt; || Map author || New SDK maps use this folder by default.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assets/VellocetSDK&amp;lt;/code&amp;gt; || VSDK and SDK sync || Do not edit these files. Copy an asset into &amp;lt;code&amp;gt;CustomContent&amp;lt;/code&amp;gt; before changing it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ProjectSettings/VellocetSdkContentOwnership.json&amp;lt;/code&amp;gt; || SDK sync || Commit this receipt in team projects. It preserves ownership and GUID migration state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Referenced custom assets are found during export and included in the addon package. SDK-owned Grimwar props remain shared references where the package format permits it.&lt;br /&gt;
&lt;br /&gt;
== SDK Workbench ==&lt;br /&gt;
&lt;br /&gt;
Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Workbench&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tab !! Use it for&lt;br /&gt;
|-&lt;br /&gt;
| Project || Link or sync the installed SDK content and manage VSig editor support.&lt;br /&gt;
|-&lt;br /&gt;
| Map || Create or prepare a scene, run map bakes, and inspect map state.&lt;br /&gt;
|-&lt;br /&gt;
| Entities || Find, place, and manage entity markers in loaded scenes.&lt;br /&gt;
|-&lt;br /&gt;
| Spatial || Bake and inspect the spatial octree and path probes.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Workbench quick actions can create a map, prepare the active scene, or open the Map Exporter. Preparing a scene adds the map contract and enables Probe Volumes when the current Unity project supports them.&lt;br /&gt;
&lt;br /&gt;
== Pick the right authoring path ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Goal !! Files and tools !! Guide&lt;br /&gt;
|-&lt;br /&gt;
| Build a map || Unity scene, entity markers, paired &amp;lt;code&amp;gt;.vsig&amp;lt;/code&amp;gt;, Map Exporter || [[Grimwar/Mapping|Map authoring]]&lt;br /&gt;
|-&lt;br /&gt;
| Script map logic || &amp;lt;code&amp;gt;.vsig&amp;lt;/code&amp;gt; and optional &amp;lt;code&amp;gt;.vsiglib&amp;lt;/code&amp;gt; modules || [[Grimwar/VSig|VSig guide]]&lt;br /&gt;
|-&lt;br /&gt;
| Write server gameplay || &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; sources || [[Grimwar/VMod|VMod scripting]]&lt;br /&gt;
|-&lt;br /&gt;
| Install or select content || Grimwar Addons screen or the server addon directory || [[Grimwar/Addons|Using addons]]&lt;br /&gt;
|-&lt;br /&gt;
| Publish a map || Release package and 1920 x 1080 Workshop thumbnail || [[Grimwar/Steam Workshop addons|Workshop publishing]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Maps and VMods use the same addon package format. An addon can contain a map, a VMod, audio, or a supported combination of those entries.&lt;br /&gt;
&lt;br /&gt;
== Sync SDK content after an update ==&lt;br /&gt;
&lt;br /&gt;
After VSDK updates the installed SDK, open &#039;&#039;&#039;SDK Workbench &amp;gt; Project&#039;&#039;&#039; and run &#039;&#039;&#039;Sync SDK Content&#039;&#039;&#039;. Sync keeps Unity GUIDs when managed assets move. When an asset must receive a new GUID, the content manifest supplies the old and new identities and the sync process rewrites references in creator-owned scenes, prefabs, materials, and assets.&lt;br /&gt;
&lt;br /&gt;
Older projects may still contain SDK files under &amp;lt;code&amp;gt;Assets/Art&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Assets/GameContent&amp;lt;/code&amp;gt;. Verified managed files move to &amp;lt;code&amp;gt;Assets/VellocetSDK&amp;lt;/code&amp;gt;. Modified legacy files move to &amp;lt;code&amp;gt;Assets/CustomContent/LegacySdkBackup&amp;lt;/code&amp;gt; with independent GUIDs.&lt;br /&gt;
&lt;br /&gt;
If sync reports an ownership error, stop and make a project backup before changing files. Do not delete the ownership receipt to force a clean state.&lt;br /&gt;
&lt;br /&gt;
== VSig editor support ==&lt;br /&gt;
&lt;br /&gt;
Open &#039;&#039;&#039;SDK Workbench &amp;gt; Project &amp;gt; VSig Editor Support&#039;&#039;&#039; or &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; VSig Editor Support...&#039;&#039;&#039;. The installer detects VS Code and Rider profiles and installs syntax support for &amp;lt;code&amp;gt;.vsig&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.vsiglib&amp;lt;/code&amp;gt;. The &#039;&#039;&#039;Auto&#039;&#039;&#039; option updates that editor integration when its packaged content changes.&lt;br /&gt;
&lt;br /&gt;
Editor support provides syntax coloring and file association. Unity and the Map Exporter remain the authority for parsing, type checks, entity contracts, and package validation.&lt;br /&gt;
&lt;br /&gt;
== Custom audio ==&lt;br /&gt;
&lt;br /&gt;
The SDK accepts WAV, Ogg Vorbis, and MP3 sources below &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt;. Create an &#039;&#039;&#039;Addon Audio Cue&#039;&#039;&#039; from &#039;&#039;&#039;Assets &amp;gt; Create &amp;gt; Vellocet &amp;gt; Audio&#039;&#039;&#039;, give it an addon-owned dotted ID, choose a playback template, and assign the source file.&lt;br /&gt;
&lt;br /&gt;
Map export includes cues referenced by &amp;lt;code&amp;gt;env_ambient&amp;lt;/code&amp;gt; markers. A VMod can ship cues through an &#039;&#039;&#039;Addon Audio Collection&#039;&#039;&#039; and the collection Inspector&#039;s &#039;&#039;&#039;Build Into Existing Mod Addon...&#039;&#039;&#039; action. The target folder must already contain a schema-current &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Supported templates are &amp;lt;code&amp;gt;Announcer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Sfx2D&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Sfx3D&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AmbientLoop&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;MusicLoop&amp;lt;/code&amp;gt;. The package contains source audio and &amp;lt;code&amp;gt;audio.json&amp;lt;/code&amp;gt;; authors do not build Wwise SoundBanks or WEM files.&lt;br /&gt;
&lt;br /&gt;
== Before exporting content ==&lt;br /&gt;
&lt;br /&gt;
* Save the scene and every referenced asset.&lt;br /&gt;
* Keep custom files below &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Resolve every entity and VSig diagnostic.&lt;br /&gt;
* Use a stable addon ID, map ID, and VMod ID. Do not recycle an ID for unrelated content.&lt;br /&gt;
* Export a Development package for local iteration.&lt;br /&gt;
* Export a Release package for distribution. Release map packages always build Windows client, macOS client, and Linux dedicated-server artifacts and require complete lighting and spatial bakes.&lt;br /&gt;
&lt;br /&gt;
[[Category:Vellocet SDK]] [[Category:Grimwar]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Dedicated_servers&amp;diff=32</id>
		<title>Grimwar/Dedicated servers</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Dedicated_servers&amp;diff=32"/>
		<updated>2026-08-25T05:13:13Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
Community dedicated servers use an isolated writable data directory for configuration, addons, state, cache, replays, and secrets. Game installation files remain read-only and replaceable.&lt;br /&gt;
&lt;br /&gt;
== Create the server data directory ==&lt;br /&gt;
&lt;br /&gt;
Assign a different absolute data directory to each server process:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
GrimwarServer --data-dir /srv/grimwar/community-1 --server-preflight-only&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The preflight checks the server runtime and creates missing operator files, then exits. A normal first launch creates the same layout. Existing operator files are not overwritten.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;--instance-id &amp;amp;lt;id&amp;amp;gt;&amp;lt;/code&amp;gt; instead when the default per-user server location is appropriate. &amp;lt;code&amp;gt;GRIMWAR_DATA_DIR&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GRIMWAR_INSTANCE_ID&amp;lt;/code&amp;gt; provide the corresponding environment settings. Do not point two running servers at one data directory.&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;cmdlhelp&amp;lt;/code&amp;gt; in server console for the command-line contract and &amp;lt;code&amp;gt;cfg_paths&amp;lt;/code&amp;gt; for the resolved install, data, config, secret, addon, replay, state, and cache paths.&lt;br /&gt;
&lt;br /&gt;
== Operator files ==&lt;br /&gt;
&lt;br /&gt;
The generated layout includes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server.cfg&amp;lt;/code&amp;gt; || Base non-secret server settings.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server.d/&amp;lt;/code&amp;gt; || Split non-secret configuration files.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/rulesets/&amp;lt;/code&amp;gt; || Operator-defined rulesets.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/modes/&amp;lt;/code&amp;gt; || Per-mode overrides.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/maps/&amp;lt;/code&amp;gt; || Per-map overrides.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/autoexec.cfg&amp;lt;/code&amp;gt; || Final non-secret overrides.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/rotation.json&amp;lt;/code&amp;gt; || Startup map and rotation selection.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server-addons.json&amp;lt;/code&amp;gt; || Workshop items, manual bindings, and collections.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/mods/&amp;lt;/code&amp;gt; || VMod Admin groups, users, and operator-owned mod configuration.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;secrets/server.secrets.cfg&amp;lt;/code&amp;gt; || Sensitive settings such as the RCON password.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;secrets/server.secrets.d/&amp;lt;/code&amp;gt; || Split sensitive configuration files.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The server applies &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;server.d&amp;lt;/code&amp;gt;, the selected ruleset, mode and map overrides, &amp;lt;code&amp;gt;autoexec.cfg&amp;lt;/code&amp;gt;, command-line overrides, secret files, then deployment overrides. Run authenticated &amp;lt;code&amp;gt;cfg_reload&amp;lt;/code&amp;gt; to reapply the stack.&lt;br /&gt;
&lt;br /&gt;
Keep passwords and tokens out of &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;. Sensitive commands found in an ordinary config layer are ignored.&lt;br /&gt;
&lt;br /&gt;
== Basic configuration ==&lt;br /&gt;
&lt;br /&gt;
Uncomment only the settings you need in &amp;lt;code&amp;gt;config/server.cfg&amp;lt;/code&amp;gt;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sv_ruleset casual&lt;br /&gt;
bot_quota 0&lt;br /&gt;
mp_timelimit 0&lt;br /&gt;
mp_roundtime 0&lt;br /&gt;
mp_winlimit 0&lt;br /&gt;
mp_maxrounds 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Community and listen servers default to the bundled &amp;lt;code&amp;gt;casual&amp;lt;/code&amp;gt; ruleset. A custom ruleset goes in &amp;lt;code&amp;gt;config/rulesets/&amp;amp;lt;name&amp;amp;gt;.cfg&amp;lt;/code&amp;gt; and may inherit another ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
// config/rulesets/community_plus.cfg&lt;br /&gt;
exec rulesets/casual.cfg&lt;br /&gt;
mp_allowspectators 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Select it with &amp;lt;code&amp;gt;sv_ruleset community_plus&amp;lt;/code&amp;gt;. During a live or overtime round, a change applies at the next round boundary unless &amp;lt;code&amp;gt;now&amp;lt;/code&amp;gt; is supplied.&lt;br /&gt;
&lt;br /&gt;
== Configure RCON ==&lt;br /&gt;
&lt;br /&gt;
Put RCON settings in &amp;lt;code&amp;gt;secrets/server.secrets.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
rcon_enable 1&lt;br /&gt;
rcon_password &amp;quot;use-a-long-unique-password&amp;quot;&lt;br /&gt;
rcon_port 27015&lt;br /&gt;
rcon_maxclients 3&lt;br /&gt;
rcon_timeout 30&lt;br /&gt;
rcon_failures 3&lt;br /&gt;
rcon_ban_time 300&lt;br /&gt;
rcon_log 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restrict access to the secret directory at the operating-system level. Expose the RCON TCP port only to administrator addresses or a private network. Do not reuse the server password or a Steam credential as the RCON password.&lt;br /&gt;
&lt;br /&gt;
== Configure map rotation ==&lt;br /&gt;
&lt;br /&gt;
The default &amp;lt;code&amp;gt;whitelist&amp;lt;/code&amp;gt; mode uses entries in file order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;listMode&amp;quot;: &amp;quot;whitelist&amp;quot;,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;as_compound&amp;quot;,&lt;br /&gt;
    &amp;quot;community_castle&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use internal map IDs from the package manifests. The server skips unavailable entries after addon synchronization and selects the first loadable entry. Startup fails when no entry can be loaded.&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;listMode&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;blacklist&amp;lt;/code&amp;gt; to rotate every registered map except the named entries:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;listMode&amp;quot;: &amp;quot;blacklist&amp;quot;,&lt;br /&gt;
  &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    &amp;quot;as_compound&amp;quot;,&lt;br /&gt;
    &amp;quot;community_ruins&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Blacklist expansion occurs after Workshop synchronization, so installed addon maps participate. Excluding every registered map is a startup error. Use &amp;lt;code&amp;gt;changelevel &amp;amp;lt;map&amp;amp;gt; [mode]&amp;lt;/code&amp;gt; from authenticated console or RCON for an immediate manual change.&lt;br /&gt;
&lt;br /&gt;
== Install Workshop maps ==&lt;br /&gt;
&lt;br /&gt;
Configure direct items and collections in &amp;lt;code&amp;gt;config/server-addons.json&amp;lt;/code&amp;gt;. Store all Steam IDs as JSON strings:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schemaVersion&amp;quot;: 1,&lt;br /&gt;
  &amp;quot;workshop&amp;quot;: {&lt;br /&gt;
    &amp;quot;depotId&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;items&amp;quot;: [&lt;br /&gt;
      &amp;quot;1234567890&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;manualItems&amp;quot;: [],&lt;br /&gt;
    &amp;quot;collections&amp;quot;: [&lt;br /&gt;
      &amp;quot;3456789012&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;items&amp;lt;/code&amp;gt; contains Workshop published-file IDs acquired by Steam. &amp;lt;code&amp;gt;collections&amp;lt;/code&amp;gt; contains collection IDs; the server expands and installs their child items. Clients subscribe only to the addon required by the current map, not the whole collection.&lt;br /&gt;
&lt;br /&gt;
Leave &amp;lt;code&amp;gt;depotId&amp;lt;/code&amp;gt; empty unless Vellocet support directs you to override it. Grimwar supplies the fixed dedicated-server depot value.&lt;br /&gt;
&lt;br /&gt;
=== Manually staged Workshop package ===&lt;br /&gt;
&lt;br /&gt;
An operator can place an exact Workshop Release package below &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/addons&amp;lt;/code&amp;gt; and bind it to the published item:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schemaVersion&amp;quot;: 1,&lt;br /&gt;
  &amp;quot;workshop&amp;quot;: {&lt;br /&gt;
    &amp;quot;depotId&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
    &amp;quot;items&amp;quot;: [],&lt;br /&gt;
    &amp;quot;manualItems&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;publishedFileId&amp;quot;: &amp;quot;1234567890&amp;quot;,&lt;br /&gt;
        &amp;quot;addonId&amp;quot;: &amp;quot;community_castle&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;collections&amp;quot;: []&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Put an identity in exactly one acquisition list. The staged package must match the exact build currently uploaded to the Workshop item. Replace it after every Workshop update. Clients still download the Steam item; they never receive files from the server&#039;s staged folder.&lt;br /&gt;
&lt;br /&gt;
== Install VMods ==&lt;br /&gt;
&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; and use the printed addon directory.&lt;br /&gt;
# Copy the complete VMod addon folder below &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/addons&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Restart, or run &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; while no scripted mode is active.&lt;br /&gt;
# Confirm the package with &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
VMod-only packages are server-only and are not currently acquired through Workshop. Admin users and groups live below &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/config/mods&amp;lt;/code&amp;gt;. See [[Grimwar/VMod|VMod scripting and administration]].&lt;br /&gt;
&lt;br /&gt;
== Startup and diagnostics ==&lt;br /&gt;
&lt;br /&gt;
Before opening the server publicly:&lt;br /&gt;
&lt;br /&gt;
# Run preflight with the production data directory and deployment port mapping.&lt;br /&gt;
# Start the server and confirm it reaches its ready/listening state.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;status -v&amp;lt;/code&amp;gt; and verify role, build, protocol, transport, map, mode, ruleset, data path, and player limit.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;cfg_paths&amp;lt;/code&amp;gt; and confirm the expected data and secret roots.&lt;br /&gt;
# Check that every rotation map is registered after Workshop synchronization.&lt;br /&gt;
# Join with a separate Steam account and test authentication, map delivery, round transition, and map change.&lt;br /&gt;
# Test RCON from an allowed administrator address.&lt;br /&gt;
&lt;br /&gt;
Useful log prefixes are &amp;lt;code&amp;gt;[ServerWorkshop]&amp;lt;/code&amp;gt; for server acquisition and activation, &amp;lt;code&amp;gt;[WorkshopDL]&amp;lt;/code&amp;gt; for exact client/server addon matching, &amp;lt;code&amp;gt;[SteamWorkshop]&amp;lt;/code&amp;gt; for Steam installation, &amp;lt;code&amp;gt;[ContentDL]&amp;lt;/code&amp;gt; for provider selection, and &amp;lt;code&amp;gt;[Net]&amp;lt;/code&amp;gt; for pre-login requirements. Set &amp;lt;code&amp;gt;net_log 2&amp;lt;/code&amp;gt; when per-addon network identities are needed.&lt;br /&gt;
&lt;br /&gt;
Back up the data directory before game or addon updates. It contains operator configuration, VMod state, source selections, bans, and other mutable server data. The game install directory is not a substitute for that backup.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Dedicated servers]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Steam_Workshop_addons&amp;diff=31</id>
		<title>Grimwar/Steam Workshop addons</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Steam_Workshop_addons&amp;diff=31"/>
		<updated>2026-08-25T05:13:11Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Current publishing boundary|Grimwar Workshop publishing accepts non-empty, map-only Release packages. A package containing VMods or another addon content kind cannot be published through this workflow.}}&lt;br /&gt;
&lt;br /&gt;
Steam Workshop is one source in Grimwar&#039;s addon catalog. The same package can be tested locally, published, subscribed to, selected, validated, and loaded without a separate Workshop format.&lt;br /&gt;
&lt;br /&gt;
== Prepare the map package ==&lt;br /&gt;
&lt;br /&gt;
# Finish local testing with a Development package.&lt;br /&gt;
# Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Map Exporter&#039;&#039;&#039;.&lt;br /&gt;
# Select &#039;&#039;&#039;Release&#039;&#039;&#039;. Release builds Windows client, macOS client, and Linux dedicated-server artifacts and requires complete lighting and spatial bakes.&lt;br /&gt;
# Assign &#039;&#039;&#039;Map Image (in-game)&#039;&#039;&#039; for the map browser.&lt;br /&gt;
# Assign separate &#039;&#039;&#039;Addon Thumbnail (Workshop)&#039;&#039;&#039; artwork. It must be a decodable 1920 x 1080 PNG or JPEG.&lt;br /&gt;
# Build the Release package and resolve every validator error.&lt;br /&gt;
&lt;br /&gt;
The exporter places the Workshop image at the addon root and records it as &amp;lt;code&amp;gt;addonThumbnail&amp;lt;/code&amp;gt;. A map&#039;s &amp;lt;code&amp;gt;map.thumbnail&amp;lt;/code&amp;gt; is separate and does not satisfy the Workshop requirement.&lt;br /&gt;
&lt;br /&gt;
Do not modify a Release folder after export. Grimwar validates the manifest, schema, compilation receipt, build ID, file paths, sizes, SHA-256 hashes, and platform payload before upload and again before mounting.&lt;br /&gt;
&lt;br /&gt;
== Test the unpublished package ==&lt;br /&gt;
&lt;br /&gt;
# Put the Release package in Grimwar&#039;s normal addon folder or an SDK overlay.&lt;br /&gt;
# Launch Grimwar and open &#039;&#039;&#039;Addons&#039;&#039;&#039;.&lt;br /&gt;
# Confirm the package is installed, valid, enabled, and offers &#039;&#039;&#039;Publish / Update&#039;&#039;&#039;.&lt;br /&gt;
# If another copy has the same addon ID, select &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; on the local Release build.&lt;br /&gt;
# Open &#039;&#039;&#039;Host&#039;&#039;&#039;. The Host tab rescans addon folders when entered.&lt;br /&gt;
# Select &#039;&#039;&#039;Test Map&#039;&#039;&#039; and exercise the packaged map.&lt;br /&gt;
&lt;br /&gt;
An unpublished package has no guest download source, so Grimwar restricts the session to &#039;&#039;&#039;Local&#039;&#039;&#039;. This is expected.&lt;br /&gt;
&lt;br /&gt;
== Publish a new item ==&lt;br /&gt;
&lt;br /&gt;
# Launch Grimwar through the Steam account that will own the Workshop item.&lt;br /&gt;
# Open &#039;&#039;&#039;Addons&#039;&#039;&#039; and select &#039;&#039;&#039;Publish / Update&#039;&#039;&#039; on the local map package.&lt;br /&gt;
# Enter the title, description, change note, and visibility. A new item defaults to &#039;&#039;&#039;Private&#039;&#039;&#039;.&lt;br /&gt;
# Review the linked Workshop terms and submit. Steam cannot cancel the upload after item submission begins.&lt;br /&gt;
# If Steam reports an unaccepted contributor agreement, open the agreement or item page from the result dialog and accept it.&lt;br /&gt;
# Inspect the item page before changing its visibility.&lt;br /&gt;
&lt;br /&gt;
The publisher uploads the complete addon directory and uses the addon thumbnail as the Workshop preview. It assigns the &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; tag plus Grimwar addon ID, schema, kind, and optional build metadata.&lt;br /&gt;
&lt;br /&gt;
== Update an existing item ==&lt;br /&gt;
&lt;br /&gt;
# Export a new Release package with the same addon ID.&lt;br /&gt;
# Start Grimwar with the same Steam account that created the item.&lt;br /&gt;
# Select the intended local copy with &#039;&#039;&#039;Use This Copy&#039;&#039;&#039;.&lt;br /&gt;
# Choose &#039;&#039;&#039;Publish / Update&#039;&#039;&#039;, supply an accurate change note, and submit.&lt;br /&gt;
# Wait for upload and subscribed-copy refresh to finish, then test the installed Workshop copy.&lt;br /&gt;
&lt;br /&gt;
The publication mapping is keyed by Steam user and addon ID. Before an update, Grimwar checks Steam ownership and item metadata and refuses an ambiguous match. A successful upload refreshes an installed subscribed copy; do not unsubscribe and resubscribe just to pick up the author&#039;s update.&lt;br /&gt;
&lt;br /&gt;
== Visibility and hosting access ==&lt;br /&gt;
&lt;br /&gt;
The least-public required Workshop item limits the Host screen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Workshop visibility !! Available hosting access&lt;br /&gt;
|-&lt;br /&gt;
| Private || Local only&lt;br /&gt;
|-&lt;br /&gt;
| Friends Only || Local, Friends Only, and Invite Only&lt;br /&gt;
|-&lt;br /&gt;
| Public or Unlisted || All Host access modes, subject to other required content&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Guest hosting also remains disabled while Steam requires the current contributor agreement. Grimwar checks that state again after upload.&lt;br /&gt;
&lt;br /&gt;
== Subscribe and use a map ==&lt;br /&gt;
&lt;br /&gt;
# Open [https://steamcommunity.com/app/4219460/workshop/ Grimwar Workshop] or select &#039;&#039;&#039;Browse Steam Workshop&#039;&#039;&#039; in the Addons screen.&lt;br /&gt;
# Subscribe to the map.&lt;br /&gt;
# Wait until Steam reports the item installed with no pending update.&lt;br /&gt;
# In Grimwar, confirm the package is valid and enabled.&lt;br /&gt;
# Use &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; if a local package with the same addon ID is selected.&lt;br /&gt;
# Host the map or join a server that advertises the same published-file ID and exact build ID.&lt;br /&gt;
&lt;br /&gt;
Joining occurs before Grimwar login completes. The client subscribes when necessary, waits for Steam installation, validates the Release package, mounts the exact candidate, and verifies the map came from that package. A failure stops the join instead of loading a different build.&lt;br /&gt;
&lt;br /&gt;
== Dedicated servers ==&lt;br /&gt;
&lt;br /&gt;
Dedicated servers list direct Workshop items, collections, or manual Workshop bindings in &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/config/server-addons.json&amp;lt;/code&amp;gt;. Put the installed map IDs in &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/config/rotation.json&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A manually staged server package can still advertise its Workshop item to clients, but the staged folder must be the exact Release build uploaded to that item. See [[Grimwar/Dedicated servers#Install Workshop maps|Install Workshop maps on a dedicated server]].&lt;br /&gt;
&lt;br /&gt;
== Publishing failures ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Symptom !! Check&lt;br /&gt;
|-&lt;br /&gt;
| No &#039;&#039;&#039;Publish / Update&#039;&#039;&#039; action || Select a local or SDK-overlay Release package. It must contain at least one content entry and every entry must be a map.&lt;br /&gt;
|-&lt;br /&gt;
| Thumbnail rejected || Supply a readable 1920 x 1080 PNG or JPEG as &amp;lt;code&amp;gt;addonThumbnail&amp;lt;/code&amp;gt;, not only a map image.&lt;br /&gt;
|-&lt;br /&gt;
| Package validation failed || Re-export Release and do not edit its manifest or files afterward.&lt;br /&gt;
|-&lt;br /&gt;
| Update ownership failed || Use the Steam account that owns the mapped item and confirm the addon ID has not changed.&lt;br /&gt;
|-&lt;br /&gt;
| Guests cannot join || Check item visibility, contributor-agreement state, selected source, exact build, and whether every required addon has a delivery source.&lt;br /&gt;
|-&lt;br /&gt;
| Old copy still loads || Select the intended source with &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; and wait for Steam&#039;s update state to clear.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
See [[Grimwar/Addons|Using addons]] for catalog conflicts and local installs.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Steam Workshop]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Server-side_modding&amp;diff=30</id>
		<title>Grimwar/Server-side modding</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Server-side_modding&amp;diff=30"/>
		<updated>2026-08-25T05:13:10Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Grimwar/VMod]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Server-side_C&amp;diff=29</id>
		<title>Grimwar/Server-side C</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Server-side_C&amp;diff=29"/>
		<updated>2026-08-25T05:13:09Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Grimwar/VMod]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Addons&amp;diff=28</id>
		<title>Grimwar/Addons</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Addons&amp;diff=28"/>
		<updated>2026-08-25T05:13:08Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Version target|These instructions cover addon schema 9 and the Grimwar addon catalog shipped with Vellocet SDK 1.0.3.}}&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;addon&#039;&#039;&#039; is the folder Grimwar discovers, validates, enables, and mounts. Maps, VMods, and addon-owned audio all use this package boundary. Do not install a loose scene, asset bundle, &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; file, or &amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt; by itself.&lt;br /&gt;
&lt;br /&gt;
== Package layout ==&lt;br /&gt;
&lt;br /&gt;
Every addon starts with &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
community.example/&lt;br /&gt;
  addon.json&lt;br /&gt;
  maps/&lt;br /&gt;
    as_example/&lt;br /&gt;
      compile-receipt.json&lt;br /&gt;
      StandaloneWindows64/&lt;br /&gt;
      StandaloneOSX/&lt;br /&gt;
      StandaloneLinux64/&lt;br /&gt;
  mod.json&lt;br /&gt;
  ExampleMod.csx&lt;br /&gt;
  audio/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manifest&#039;s &amp;lt;code&amp;gt;contents&amp;lt;/code&amp;gt; array declares each map, VMod, or other supported content entry. A mixed package can contain a map and the VMod that supplies its game mode. The complete folder remains one install and update unit.&lt;br /&gt;
&lt;br /&gt;
Use the SDK exporter to produce map packages. For VMods, follow [[Grimwar/VMod#What a VMod package contains|the VMod manifest format]]. Keep addon IDs stable between releases; a changed ID is a different addon rather than an update.&lt;br /&gt;
&lt;br /&gt;
== Use the Addons screen ==&lt;br /&gt;
&lt;br /&gt;
Open &#039;&#039;&#039;Addons&#039;&#039;&#039; from Grimwar&#039;s main menu. The library combines every discovered source and reports whether each candidate is installed, valid, enabled, current, or in conflict.&lt;br /&gt;
&lt;br /&gt;
The available actions depend on the source and package:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Action !! Result&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Enable&#039;&#039;&#039; / &#039;&#039;&#039;Disable&#039;&#039;&#039; || Changes whether the selected addon may be mounted.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; || Selects this physical copy when several sources provide the same addon ID.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Open Folder&#039;&#039;&#039; || Opens the install location for a disk-backed package.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;View on Steam&#039;&#039;&#039; || Opens the selected Workshop item.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Download/Update&#039;&#039;&#039; || Requests the current Workshop build from Steam.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Unsubscribe&#039;&#039;&#039; || Removes the Steam subscription. Steam controls final file removal.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Publish / Update&#039;&#039;&#039; || Publishes an eligible local map-only Release package.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
An invalid, incomplete, unavailable, or currently downloading candidate cannot be enabled or selected.&lt;br /&gt;
&lt;br /&gt;
== Sources and conflicts ==&lt;br /&gt;
&lt;br /&gt;
Grimwar groups physical copies by the &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;. Initial source priority is:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Priority !! Source !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 300 || SDK overlay || Read-only folder supplied with &amp;lt;code&amp;gt;--addon-root&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;GRIMWAR_ADDON_ROOT&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| 200 || Steam Workshop || Steam-managed client install.&lt;br /&gt;
|-&lt;br /&gt;
| 200 || Dedicated-server Workshop || Steam-managed or operator-staged server copy with a Workshop identity.&lt;br /&gt;
|-&lt;br /&gt;
| 100 || Manual or FastDL || Writable addon library below the active Grimwar data root.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Use This Copy&#039;&#039;&#039; overrides that priority and stores the selection in &amp;lt;code&amp;gt;state/addons.json&amp;lt;/code&amp;gt;. Only one valid copy of an addon ID is mounted. Built-in maps cannot be replaced by an addon, and a duplicate map ID that collides with built-in or already mounted content is rejected.&lt;br /&gt;
&lt;br /&gt;
If an edited local package appears to have no effect, check the Addons screen for another selected copy with the same ID.&lt;br /&gt;
&lt;br /&gt;
== Test an authored map ==&lt;br /&gt;
&lt;br /&gt;
# Export a Development package from the SDK Map Exporter.&lt;br /&gt;
# Put the package below Grimwar&#039;s addon directory, or start Grimwar with &amp;lt;code&amp;gt;--addon-root &amp;amp;lt;absolute-export-folder&amp;amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Open &#039;&#039;&#039;Addons&#039;&#039;&#039;, confirm the package is valid and enabled, and select &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; when necessary.&lt;br /&gt;
# Open &#039;&#039;&#039;Host&#039;&#039;&#039;. Entering or returning to the Host tab rescans addon folders.&lt;br /&gt;
# Select the map. If it has no guest download source, Grimwar sets Access to &#039;&#039;&#039;Local&#039;&#039;&#039; and changes the action to &#039;&#039;&#039;Test Map&#039;&#039;&#039;.&lt;br /&gt;
# Start the map and test the compiled package, not only the Unity authoring scene.&lt;br /&gt;
&lt;br /&gt;
Local test mode admits only the listen host. It creates no public listing or join string, disables invites, and rejects remote connections. This allows an unpublished map to run without pretending that clients can download it.&lt;br /&gt;
&lt;br /&gt;
== Install a Workshop map ==&lt;br /&gt;
&lt;br /&gt;
# Launch Grimwar through Steam.&lt;br /&gt;
# Open &#039;&#039;&#039;Addons&#039;&#039;&#039; and choose &#039;&#039;&#039;Browse Steam Workshop&#039;&#039;&#039;, or open [https://steamcommunity.com/app/4219460/workshop/ Grimwar Workshop].&lt;br /&gt;
# Subscribe to the map.&lt;br /&gt;
# Return to the Addons screen and wait for Steam&#039;s download and installation to finish.&lt;br /&gt;
# Enable the package if it is disabled.&lt;br /&gt;
# Open &#039;&#039;&#039;Host&#039;&#039;&#039; or join a server that requires the same Workshop build.&lt;br /&gt;
&lt;br /&gt;
Steam owns subscribed files and their updates. Grimwar validates and mounts Steam&#039;s installed folder directly. An installed item can remain visible from the local cache while Steam is offline, but subscription, update, and Workshop enable-state changes require Steam online.&lt;br /&gt;
&lt;br /&gt;
When joining a server, Grimwar downloads only the addon that owns the active map plus any session-wide requirements. Login completes only after every advertised package has the required addon ID and exact build ID and passes Release validation.&lt;br /&gt;
&lt;br /&gt;
== Install a VMod on a server ==&lt;br /&gt;
&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; from authenticated server console or RCON.&lt;br /&gt;
# Copy the complete folder containing &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt; into the printed &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/addons&amp;lt;/code&amp;gt; root.&lt;br /&gt;
# Restart the process, or run &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; while no scripted game mode is active.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt; and check that the VMod loaded without a compiler, capability, or dependency error.&lt;br /&gt;
&lt;br /&gt;
VMod-only packages are not currently publishable through Grimwar Workshop. Use manual installation or the SDK overlay. See [[Grimwar/VMod#Install and test a VMod|Install and test a VMod]].&lt;br /&gt;
&lt;br /&gt;
== Dedicated-server addon files ==&lt;br /&gt;
&lt;br /&gt;
The first server launch creates its operator-owned layout without replacing existing files. Relevant paths below the active data root are:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addons/&amp;amp;lt;addon-id&amp;amp;gt;/&amp;lt;/code&amp;gt; || Manual and FastDL-installed packages.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/server-addons.json&amp;lt;/code&amp;gt; || Workshop item IDs, manual Workshop bindings, collections, and the optional depot override.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config/rotation.json&amp;lt;/code&amp;gt; || Whitelist or blacklist of map IDs and optional game modes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;state/addons.json&amp;lt;/code&amp;gt; || Enabled candidates and explicit source selections.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cache/steam-workshop-server/&amp;lt;/code&amp;gt; || Steam-managed dedicated-server Workshop installs.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Use [[Grimwar/Dedicated servers#Install Workshop maps|Dedicated servers]] for &amp;lt;code&amp;gt;server-addons.json&amp;lt;/code&amp;gt;, manual bindings, and rotation examples.&lt;br /&gt;
&lt;br /&gt;
== Fix a package that does not load ==&lt;br /&gt;
&lt;br /&gt;
Check these in order:&lt;br /&gt;
&lt;br /&gt;
# The selected directory itself contains &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;; it is not one level above or below it.&lt;br /&gt;
# The package is complete and has not been copied while an export or Steam download is still running.&lt;br /&gt;
# The Addons screen marks the candidate valid and enabled.&lt;br /&gt;
# &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; points to the build you intend to test.&lt;br /&gt;
# The addon and content IDs do not collide with another installed package or built-in map.&lt;br /&gt;
# The package was rebuilt with the current schema and contains the platform artifact needed by this process.&lt;br /&gt;
# For a Release package, every declared file, size, SHA-256 hash, path, and compilation receipt is unchanged.&lt;br /&gt;
&lt;br /&gt;
The validator also rejects absolute or escaping paths, symbolic links or reparse points, unsupported file types, more than 8,192 files, and packages larger than 20 GiB.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Addons]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/VMod&amp;diff=27</id>
		<title>Grimwar/VMod</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/VMod&amp;diff=27"/>
		<updated>2026-08-25T05:13:03Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Version target|This guide covers VMod API 5 and addon schema 9. A server rejects packages built for another API or schema.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;VMod&#039;&#039;&#039; is Grimwar&#039;s server-authoritative C# mod runtime. The server compiles source with Roslyn C# 2.0 and runs the result through dotnow. Grimwar itself remains an IL2CPP build.&lt;br /&gt;
&lt;br /&gt;
A VMod can use the public &amp;lt;code&amp;gt;Grimwar.ModApi&amp;lt;/code&amp;gt; services. It cannot reference Unity, FishNet, Grimwar internals, arbitrary files, sockets, reflection, processes, or native code.&lt;br /&gt;
&lt;br /&gt;
== What a VMod package contains ==&lt;br /&gt;
&lt;br /&gt;
The addon folder is the install unit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
community.hello/&lt;br /&gt;
  addon.json&lt;br /&gt;
  mod.json&lt;br /&gt;
  HelloMod.csx&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; below a Unity project&#039;s &amp;lt;code&amp;gt;Assets&amp;lt;/code&amp;gt; folder so the editor recognizes C# without asking Unity to compile the file. A VMod kept outside Unity can use &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt; registers the folder with Grimwar&#039;s addon catalog:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schemaVersion&amp;quot;: 9,&lt;br /&gt;
  &amp;quot;id&amp;quot;: &amp;quot;community.hello&amp;quot;,&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;Hello Server&amp;quot;,&lt;br /&gt;
  &amp;quot;author&amp;quot;: &amp;quot;Ada&amp;quot;,&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,&lt;br /&gt;
  &amp;quot;distributionProfile&amp;quot;: &amp;quot;development&amp;quot;,&lt;br /&gt;
  &amp;quot;buildId&amp;quot;: &amp;quot;0123456789abcdef0123456789abcdef&amp;quot;,&lt;br /&gt;
  &amp;quot;createdUtc&amp;quot;: &amp;quot;2026-08-25T00:00:00Z&amp;quot;,&lt;br /&gt;
  &amp;quot;sdkVersion&amp;quot;: &amp;quot;1.0.3&amp;quot;,&lt;br /&gt;
  &amp;quot;unityVersion&amp;quot;: &amp;quot;6000.3.17f1&amp;quot;,&lt;br /&gt;
  &amp;quot;requires&amp;quot;: [],&lt;br /&gt;
  &amp;quot;contents&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;kind&amp;quot;: &amp;quot;mods&amp;quot;,&lt;br /&gt;
      &amp;quot;id&amp;quot;: &amp;quot;community.hello&amp;quot;,&lt;br /&gt;
      &amp;quot;title&amp;quot;: &amp;quot;Hello Server&amp;quot;,&lt;br /&gt;
      &amp;quot;mod&amp;quot;: { &amp;quot;manifest&amp;quot;: &amp;quot;mod.json&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The addon ID, content ID, and VMod ID must resolve to the same normalized ID. &amp;lt;code&amp;gt;requires&amp;lt;/code&amp;gt; contains addon IDs. Grimwar enables and loads required addons before the package that names them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt; defines the code entry point:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;id&amp;quot;: &amp;quot;community.hello&amp;quot;,&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Hello Server&amp;quot;,&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,&lt;br /&gt;
  &amp;quot;apiVersion&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;kind&amp;quot;: &amp;quot;addon&amp;quot;,&lt;br /&gt;
  &amp;quot;entryPoint&amp;quot;: &amp;quot;CommunityMods.HelloMod&amp;quot;,&lt;br /&gt;
  &amp;quot;sourceFiles&amp;quot;: [&amp;quot;HelloMod.csx&amp;quot;],&lt;br /&gt;
  &amp;quot;dependencies&amp;quot;: [],&lt;br /&gt;
  &amp;quot;permissions&amp;quot;: [],&lt;br /&gt;
  &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
  &amp;quot;serverOnly&amp;quot;: true&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Rule&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; || Stable ID up to 96 characters. Use lowercase letters, digits, dots, underscores, and hyphens.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;apiVersion&amp;lt;/code&amp;gt; || Must equal the server&#039;s current VMod API, currently &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;kind&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;addon&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;gameMode&amp;lt;/code&amp;gt;. Administrative host operations require &amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;entryPoint&amp;lt;/code&amp;gt; || Fully qualified, non-abstract class implementing &amp;lt;code&amp;gt;IMod&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sourceFiles&amp;lt;/code&amp;gt; || Relative &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; paths contained by this addon.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; || VMod IDs that must load first.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;permissions&amp;lt;/code&amp;gt; || Permission names the VMod may attach to its commands and menu items. This does not grant those permissions to players.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;serverOnly&amp;lt;/code&amp;gt; || Must be &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; in API 5.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Write the entry class ==&lt;br /&gt;
&lt;br /&gt;
This mod registers &amp;lt;code&amp;gt;hello&amp;lt;/code&amp;gt; for chat and authenticated consoles:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Grimwar.ModApi;&lt;br /&gt;
&lt;br /&gt;
namespace CommunityMods&lt;br /&gt;
{&lt;br /&gt;
    public sealed class HelloMod : IMod&lt;br /&gt;
    {&lt;br /&gt;
        private IModContext _context;&lt;br /&gt;
&lt;br /&gt;
        public void OnLoad(IModContext context)&lt;br /&gt;
        {&lt;br /&gt;
            _context = context;&lt;br /&gt;
            var result = context.Commands.Register(new ModCommandSpec&lt;br /&gt;
            {&lt;br /&gt;
                Name = &amp;quot;hello&amp;quot;,&lt;br /&gt;
                Description = &amp;quot;Say hello to the server.&amp;quot;,&lt;br /&gt;
                MinimumArguments = 0,&lt;br /&gt;
                MaximumArguments = 0,&lt;br /&gt;
                AllowChat = true,&lt;br /&gt;
                AllowConsole = true,&lt;br /&gt;
                ChatAliases = new[] { &amp;quot;hi&amp;quot; }&lt;br /&gt;
            }, &amp;quot;OnHello&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            if (!result.Success)&lt;br /&gt;
                throw new InvalidOperationException(result.Message);&lt;br /&gt;
&lt;br /&gt;
            context.Log.Write(&amp;quot;Hello Server loaded.&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        public void OnUnload()&lt;br /&gt;
        {&lt;br /&gt;
            _context = null;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        public void OnHello(IModCommandInvocation command)&lt;br /&gt;
        {&lt;br /&gt;
            var name = command.Caller == null&lt;br /&gt;
                ? &amp;quot;server console&amp;quot;&lt;br /&gt;
                : command.Caller.DisplayName;&lt;br /&gt;
            _context.Messages.Broadcast(&amp;quot;Hello from &amp;quot; + name + &amp;quot;!&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Registrations take a method name because delegates do not cross the interpreter boundary. Grimwar verifies the method before accepting the registration.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Registration !! Handler signature&lt;br /&gt;
|-&lt;br /&gt;
| Command || One &amp;lt;code&amp;gt;IModCommandInvocation&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
|-&lt;br /&gt;
| Event || One &amp;lt;code&amp;gt;ModEvent&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
|-&lt;br /&gt;
| Timer || One &amp;lt;code&amp;gt;ModTimerInvocation&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
|-&lt;br /&gt;
| VSig subscription || One &amp;lt;code&amp;gt;ModVSigEvent&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
|-&lt;br /&gt;
| Menu || One &amp;lt;code&amp;gt;ModMenuInvocation&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;OnUnload&amp;lt;/code&amp;gt; must clear references and release any VMod-owned state that is not already scoped through the host. Commands, event subscriptions, timers, effects, and dynamic modes are removed when the package unloads.&lt;br /&gt;
&lt;br /&gt;
== Public API services ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;IModContext&amp;lt;/code&amp;gt; supplies the following services:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Service !! Use&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Log&amp;lt;/code&amp;gt; || Namespaced server log messages.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Commands&amp;lt;/code&amp;gt; || Chat, local console, server console, and RCON commands with aliases, argument limits, and permissions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Players&amp;lt;/code&amp;gt; || Immutable player snapshots and selectors such as exact name, unique partial name, Steam ID, client ID, &amp;lt;code&amp;gt;@me&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;@random&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Messages&amp;lt;/code&amp;gt; || Broadcast or private chat, escaped colored segments, and major or minor HUD messages.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Menus&amp;lt;/code&amp;gt; || Server-owned numeric menus and shared VMod Admin entries.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Effects&amp;lt;/code&amp;gt; || Health, damage, slap, slay, timed damage or movement multipliers, weapon restrictions, and screen shake.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Audio&amp;lt;/code&amp;gt; || Play addon-owned audio globally, for one player, or at a world position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Admin&amp;lt;/code&amp;gt; || Permission checks, immunity-aware targeting, kick, ban, and unban for &amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt; packages.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;GameMode&amp;lt;/code&amp;gt; || Read mode state. The active &amp;lt;code&amp;gt;gameMode&amp;lt;/code&amp;gt; package can change teams, respawn players, and end rounds or matches.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Events&amp;lt;/code&amp;gt; || Player, combat, round, match, and mode-change subscriptions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Scheduler&amp;lt;/code&amp;gt; || One-shot and repeating callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Clock&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Random&amp;lt;/code&amp;gt; || Monotonic or Unix time and a per-VMod random source.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Storage&amp;lt;/code&amp;gt; || Sandboxed typed key/value data under the VMod&#039;s state directory.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VSig&amp;lt;/code&amp;gt; || Emit or subscribe to bounded VSig signals.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mods&amp;lt;/code&amp;gt; || Inspect loaded packages. Administrative VMods can request reloads.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ModPlayer&amp;lt;/code&amp;gt; and other API objects are snapshots. Keep the stable player ID and call &amp;lt;code&amp;gt;Players.Find&amp;lt;/code&amp;gt; again when current state matters.&lt;br /&gt;
&lt;br /&gt;
== Events and timers ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
public void OnLoad(IModContext context)&lt;br /&gt;
{&lt;br /&gt;
    _context = context;&lt;br /&gt;
&lt;br /&gt;
    var subscription = context.Events.Subscribe(&lt;br /&gt;
        ModEventKind.PlayerSpawned,&lt;br /&gt;
        &amp;quot;OnPlayerSpawned&amp;quot;);&lt;br /&gt;
    if (!subscription.Success)&lt;br /&gt;
        throw new InvalidOperationException(subscription.Message);&lt;br /&gt;
&lt;br /&gt;
    context.Scheduler.Once(5f, &amp;quot;OnTimer&amp;quot;, &amp;quot;startup&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPlayerSpawned(ModEvent value)&lt;br /&gt;
{&lt;br /&gt;
    if (value.Player != null)&lt;br /&gt;
        _context.Messages.Tell(value.Player.Id, &amp;quot;Welcome back.&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnTimer(ModTimerInvocation value)&lt;br /&gt;
{&lt;br /&gt;
    _context.Log.Write(value.TimerId + &amp;quot; fired with state &amp;quot; + value.State);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Combat events put the victim in &amp;lt;code&amp;gt;Player&amp;lt;/code&amp;gt; and a connected attacker or killer in &amp;lt;code&amp;gt;OtherPlayer&amp;lt;/code&amp;gt;. Read &amp;lt;code&amp;gt;Amount&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HealthAfter&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WeaponId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AbilityId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WasHeadshot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WasCritical&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;WasSuicide&amp;lt;/code&amp;gt; for scalar event data.&lt;br /&gt;
&lt;br /&gt;
Timers have a 50 ms minimum interval, a 24-hour maximum delay, and a limit of 256 timers per VMod. Cancel repeating timers when their owning activity ends.&lt;br /&gt;
&lt;br /&gt;
== Permissions ==&lt;br /&gt;
&lt;br /&gt;
A permission on &amp;lt;code&amp;gt;ModCommandSpec.Permission&amp;lt;/code&amp;gt; must also appear in &amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt;. The manifest declaration allows the VMod to ask for the permission; server admin configuration decides who has it.&lt;br /&gt;
&lt;br /&gt;
VMod Admin reads groups and users from &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/config/mods&amp;lt;/code&amp;gt;. A wildcard such as &amp;lt;code&amp;gt;admin.*&amp;lt;/code&amp;gt; grants one namespace. A leading minus sign is an explicit deny and wins over grants. Immunity prevents one administrator from targeting another administrator with the same or higher value.&lt;br /&gt;
&lt;br /&gt;
Do not put an RCON password or another secret in VMod source, manifests, or addon configuration.&lt;br /&gt;
&lt;br /&gt;
== Send signals to VSig ==&lt;br /&gt;
&lt;br /&gt;
Every VMod owns a source alias named &amp;lt;code&amp;gt;mod:&amp;amp;lt;mod-id&amp;amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
_context.VSig.Emit(&amp;quot;round_started&amp;quot;, _context.GameMode.ActiveId);&lt;br /&gt;
_context.VSig.EmitFrom(&lt;br /&gt;
    &amp;quot;mod:community.hello.stage&amp;quot;,&lt;br /&gt;
    &amp;quot;opened&amp;quot;,&lt;br /&gt;
    3,&lt;br /&gt;
    &amp;quot;sewer_gate&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom source must be the owned alias or a child below it. Payloads can contain at most eight null, string, Boolean, or numeric values. Send a 64-bit identifier such as a Steam ID as a string.&lt;br /&gt;
&lt;br /&gt;
A VMod can subscribe to a map signal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
context.VSig.Subscribe(&amp;quot;escape_trigger&amp;quot;, &amp;quot;on_executed&amp;quot;, &amp;quot;OnEscape&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
public void OnEscape(ModVSigEvent value)&lt;br /&gt;
{&lt;br /&gt;
    _context.Log.Write(value.SourceAlias + &amp;quot;.&amp;quot; + value.OutputName);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Grimwar/VSig#Signals shared with VMod|Signals shared with VMod]] for the map side.&lt;br /&gt;
&lt;br /&gt;
== Supported C# subset ==&lt;br /&gt;
&lt;br /&gt;
VMods can use ordinary control flow, classes, structs, enums, arrays, strings, &amp;lt;code&amp;gt;StringBuilder&amp;lt;/code&amp;gt;, and approved &amp;lt;code&amp;gt;System.Collections&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;System.Collections.Generic&amp;lt;/code&amp;gt; shapes.&lt;br /&gt;
&lt;br /&gt;
The validator rejects file and network I/O, reflection, processes, console or environment access, threads, tasks, Unity or Grimwar internals, native interop, unsafe code, &amp;lt;code&amp;gt;typeof&amp;lt;/code&amp;gt;, async methods, iterators, lambdas, LINQ queries, &amp;lt;code&amp;gt;try&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;catch&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;finally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;using&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;lock&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;foreach&amp;lt;/code&amp;gt;, precompiled DLLs, and extra assembly references. Use indexed &amp;lt;code&amp;gt;for&amp;lt;/code&amp;gt; loops and explicit cleanup.&lt;br /&gt;
&lt;br /&gt;
Compilation alone does not guarantee that an arbitrary generic combination exists in the IL2CPP host. Start with arrays, &amp;lt;code&amp;gt;List&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Dictionary&amp;amp;lt;string, T&amp;amp;gt;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;HashSet&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt; using types present in the public API and bundled examples.&lt;br /&gt;
&lt;br /&gt;
== Install and test a VMod ==&lt;br /&gt;
&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; through an authenticated server console or RCON session. Use the printed addon path instead of guessing a platform-specific data directory.&lt;br /&gt;
# Copy the complete addon folder into &amp;lt;code&amp;gt;&amp;amp;lt;data&amp;amp;gt;/addons&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Restart the server, or run &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; while no scripted game mode is active.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt; and confirm the package is loaded and not faulted.&lt;br /&gt;
# Exercise every chat and console alias with empty, quoted, invalid, and maximum-length arguments.&lt;br /&gt;
# Run the test again with a non-admin player when the VMod declares permissions.&lt;br /&gt;
# Reload it more than once and check that handlers, timers, commands, and effects do not duplicate.&lt;br /&gt;
&lt;br /&gt;
Useful server commands:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Result&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt; || Lists loaded and faulted VMods.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; || Refreshes addons and permissions, recompiles changed source, and reloads in dependency order.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vmod_runtime_reload_admins&amp;lt;/code&amp;gt; || Reloads admin groups and users without unloading VMods.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; || Prints addon, config, state, and compiler-cache roots.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sv_vmod_enabled 0&amp;lt;/code&amp;gt; || Disables the VMod runtime at startup.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The server refuses &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt; while a scripted game mode is active. Change to a native mode first.&lt;br /&gt;
&lt;br /&gt;
== Distribution rules ==&lt;br /&gt;
&lt;br /&gt;
VMod-only packages are currently installed manually or through the development overlay. Steam Workshop publishing accepts map-only Release packages and rejects packages that contain VMods. Server-only VMod source is not installed on remote players.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;--addon-root &amp;amp;lt;absolute-folder&amp;amp;gt;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;GRIMWAR_ADDON_ROOT&amp;lt;/code&amp;gt; during development to load a package directly. For ordinary installation, copy the complete folder containing &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;; a loose &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; file is never an installable VMod.&lt;br /&gt;
&lt;br /&gt;
Bundled examples are available in Grimwar&#039;s &amp;lt;code&amp;gt;StreamingAssets/Grimwar/Addons&amp;lt;/code&amp;gt; source tree. &amp;lt;code&amp;gt;grimwar.rtd&amp;lt;/code&amp;gt; is the smallest command and effect example. &amp;lt;code&amp;gt;grimwar.admin&amp;lt;/code&amp;gt; covers permissions and menus. &amp;lt;code&amp;gt;grimwar.zombie_mod&amp;lt;/code&amp;gt; is a scripted mode. &amp;lt;code&amp;gt;grimwar.quake_sounds&amp;lt;/code&amp;gt; combines server logic with addon-owned audio.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:VMod]] [[Category:Server modding]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/VSig&amp;diff=26</id>
		<title>Grimwar/VSig</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/VSig&amp;diff=26"/>
		<updated>2026-08-25T05:12:57Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Version target|This guide covers the VSig compiler and standard library included with Vellocet SDK 1.0.3.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;VSig&#039;&#039;&#039; is Grimwar&#039;s map-logic language. A VSig program listens to entity or game outputs, changes state, calls entity inputs, schedules work, and exchanges bounded signals with VMods. The Map Exporter validates and compiles it into the map package.&lt;br /&gt;
&lt;br /&gt;
Use VSig for map orchestration. Use an entity marker when the thing has a position, volume, renderer, collider, or native game behavior. Use [[Grimwar/VMod|VMod]] for server rules that need players, commands, persistent storage, permissions, or game-mode control.&lt;br /&gt;
&lt;br /&gt;
== Create the map script ==&lt;br /&gt;
&lt;br /&gt;
A map scene and its VSig source share a name and folder:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Assets/CustomContent/Maps/Range/Range.unity&lt;br /&gt;
Assets/CustomContent/Maps/Range/Range.vsig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a script with &#039;&#039;&#039;Assets &amp;gt; Create &amp;gt; Vellocet &amp;gt; SDK &amp;gt; VSig Script&#039;&#039;&#039;. A marker Inspector can also create or open the current scene&#039;s file and insert refs for selected entities.&lt;br /&gt;
&lt;br /&gt;
Install syntax support from &#039;&#039;&#039;SDK Workbench &amp;gt; Project &amp;gt; VSig Editor Support&#039;&#039;&#039;. Unity still performs the authoritative parse and validation.&lt;br /&gt;
&lt;br /&gt;
== First working script ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
scene &amp;quot;Example&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ref trigger: trigger_multiple match Triggers/Entrance&lt;br /&gt;
ref door: func_door match Doors/MainDoor&lt;br /&gt;
&lt;br /&gt;
var door_start: DoorEntityState = null&lt;br /&gt;
&lt;br /&gt;
once on map.ready:&lt;br /&gt;
    door_start = door.state&lt;br /&gt;
&lt;br /&gt;
on trigger.start_touch:&lt;br /&gt;
    door.open&lt;br /&gt;
&lt;br /&gt;
on trigger.end_touch_all:&lt;br /&gt;
    door.restore(door_start)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two &amp;lt;code&amp;gt;ref&amp;lt;/code&amp;gt; declarations bind authored markers to short aliases. &amp;lt;code&amp;gt;map.ready&amp;lt;/code&amp;gt; runs after server-side map entities are bound. The trigger&#039;s &amp;lt;code&amp;gt;start_touch&amp;lt;/code&amp;gt; output calls the door&#039;s &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; input. The script captures the starting door state once and restores it after the last toucher leaves.&lt;br /&gt;
&lt;br /&gt;
Marker Inspectors list the inputs, outputs, state type, and access rules for that entity class. Use that contract instead of guessing a signal name.&lt;br /&gt;
&lt;br /&gt;
== Refs and groups ==&lt;br /&gt;
&lt;br /&gt;
A ref can match one hierarchy path or a wildcard:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ref main_door: func_door match BuildingA/Door&lt;br /&gt;
ref spawn_doors: func_door match SpawnDoors/Door*&lt;br /&gt;
&lt;br /&gt;
group exits:&lt;br /&gt;
    main_door&lt;br /&gt;
    spawn_doors&lt;br /&gt;
&lt;br /&gt;
on round.post_round:&lt;br /&gt;
    exits.close&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An input sent to a wildcard ref or group broadcasts to every match. Property reads and state capture require exactly one entity.&lt;br /&gt;
&lt;br /&gt;
Stable GameObject names make refs readable and keep wildcard matches predictable. A marker&#039;s hidden runtime ID is managed by the SDK; VSig authoring uses the object hierarchy and entity class.&lt;br /&gt;
&lt;br /&gt;
== Values and expressions ==&lt;br /&gt;
&lt;br /&gt;
Primitive types are &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;. Entity state uses the state type declared by its marker contract. Durations accept seconds or milliseconds, including &amp;lt;code&amp;gt;1.5s&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;250ms&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
seed 1847&lt;br /&gt;
&lt;br /&gt;
const max_score: int = 10&lt;br /&gt;
var score: int = 0&lt;br /&gt;
var title: string = &amp;quot;Arena&amp;quot;&lt;br /&gt;
&lt;br /&gt;
on button.pressed:&lt;br /&gt;
    score = clamp(score + 1, 0, max_score)&lt;br /&gt;
    label.set_text(&amp;quot;{0}: {1}/{2}&amp;quot;, title, score, max_score)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Strings must be quoted. Declare and initialize map variables and module state before use. Handler parameters and procedure parameters are immutable; assign mutable data to a map &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt; or module &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Operators include arithmetic, comparisons, &amp;lt;code&amp;gt;and&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;or&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;not&amp;lt;/code&amp;gt;. Built-in functions include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;min&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;clamp&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;abs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floor&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ceil&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;round&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;lerp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;remap&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;random&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;random_int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;shuffle&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;choose&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;time&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;format&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;convar&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; conversions&lt;br /&gt;
&lt;br /&gt;
Without &amp;lt;code&amp;gt;seed&amp;lt;/code&amp;gt;, each map runtime starts with fresh random entropy. A declared seed makes random sequences repeatable. &amp;lt;code&amp;gt;shuffle(self, count)&amp;lt;/code&amp;gt; gives each module instance its own shuffle bag.&lt;br /&gt;
&lt;br /&gt;
== Conditions and matching ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
on counter.changed(value: float):&lt;br /&gt;
    if value &amp;gt;= 10:&lt;br /&gt;
        door.open&lt;br /&gt;
    elif value &amp;gt; 0:&lt;br /&gt;
        light.on&lt;br /&gt;
    else:&lt;br /&gt;
        light.off&lt;br /&gt;
&lt;br /&gt;
    match int(value):&lt;br /&gt;
        case 1:&lt;br /&gt;
            label.set_text(&amp;quot;one&amp;quot;)&lt;br /&gt;
        case 2:&lt;br /&gt;
            label.set_text(&amp;quot;two&amp;quot;)&lt;br /&gt;
        default:&lt;br /&gt;
            label.set_text(&amp;quot;many&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Indentation defines the statement block. A type mismatch, unknown name, invalid call, missing ref, or wrong handler payload is a compile error.&lt;br /&gt;
&lt;br /&gt;
== Procedures and schedules ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
def announce(message: string, delay: float = 0s):&lt;br /&gt;
    wait delay&lt;br /&gt;
    label.set_text(message)&lt;br /&gt;
&lt;br /&gt;
on round.live:&lt;br /&gt;
    call announce(&amp;quot;Fight!&amp;quot;, 0.25s)&lt;br /&gt;
    schedule heartbeat every 1s times 10:&lt;br /&gt;
        light.toggle&lt;br /&gt;
&lt;br /&gt;
on round.post_round:&lt;br /&gt;
    cancel heartbeat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;wait&amp;lt;/code&amp;gt; suspends the current handler or procedure. &amp;lt;code&amp;gt;schedule name after duration&amp;lt;/code&amp;gt; runs once. &amp;lt;code&amp;gt;schedule name every duration&amp;lt;/code&amp;gt; repeats, and &amp;lt;code&amp;gt;times&amp;lt;/code&amp;gt; limits the count. Starting a named schedule replaces the existing task with that name. Cancelling a task that is not running is safe.&lt;br /&gt;
&lt;br /&gt;
Cancel round-owned repeating work on &amp;lt;code&amp;gt;round.post_round&amp;lt;/code&amp;gt; or another lifecycle event that always closes the activity.&lt;br /&gt;
&lt;br /&gt;
== Reusable modules ==&lt;br /&gt;
&lt;br /&gt;
A module contains parameters, private state, inputs, outputs, procedures, and handlers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
module counter(start: float = 0, max_value: float = 10):&lt;br /&gt;
    state value: float = start&lt;br /&gt;
    output changed(value: float)&lt;br /&gt;
    output reached(value: float)&lt;br /&gt;
&lt;br /&gt;
    input add(amount: float = 1):&lt;br /&gt;
        value = min(value + amount, max_value)&lt;br /&gt;
        emit changed(value)&lt;br /&gt;
        if value &amp;gt;= max_value:&lt;br /&gt;
            emit reached(value)&lt;br /&gt;
&lt;br /&gt;
    input reset:&lt;br /&gt;
        value = start&lt;br /&gt;
        emit changed(value)&lt;br /&gt;
&lt;br /&gt;
use counter as captures(max_value = 3)&lt;br /&gt;
&lt;br /&gt;
ref capture_point: game_capture_point&lt;br /&gt;
ref exit: func_door&lt;br /&gt;
&lt;br /&gt;
on capture_point.captured:&lt;br /&gt;
    captures.add&lt;br /&gt;
&lt;br /&gt;
on captures.reached(value: float):&lt;br /&gt;
    exit.open&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Module parameters are immutable configuration. State is private mutable data and can be inspected as &amp;lt;code&amp;gt;instance.state_name&amp;lt;/code&amp;gt;. Inputs are typed procedures. Outputs carry typed payloads and work like entity outputs.&lt;br /&gt;
&lt;br /&gt;
Put shared modules in &amp;lt;code&amp;gt;.vsiglib&amp;lt;/code&amp;gt; files and import only the required module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
from &amp;quot;Packages/com.vellocet.sdk/Runtime/VSig/Libraries/Logic.vsiglib&amp;quot; use counter&lt;br /&gt;
use counter as captures(max_value = 5)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The standard logic library contains &amp;lt;code&amp;gt;counter&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;accumulator&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;relay&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;timer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;selector&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;random_selector&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sequence&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;latch&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;state_machine&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;debounce&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;cooldown&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These modules are compiled logic. They do not create GameObjects or network objects.&lt;br /&gt;
&lt;br /&gt;
== Spatial modules and logic_script ==&lt;br /&gt;
&lt;br /&gt;
A spatial module declares local refs and binds each instance to a scene hierarchy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
module gate:&lt;br /&gt;
    ref trigger: trigger_multiple&lt;br /&gt;
    ref door: func_door&lt;br /&gt;
&lt;br /&gt;
    on trigger.start_touch:&lt;br /&gt;
        door.open&lt;br /&gt;
&lt;br /&gt;
    input reset:&lt;br /&gt;
        door.close&lt;br /&gt;
&lt;br /&gt;
use gate as exits match Gates/Exit_*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A wildcard &amp;lt;code&amp;gt;use&amp;lt;/code&amp;gt; creates one module instance per matching root and a broadcast group named by the authored alias.&lt;br /&gt;
&lt;br /&gt;
Place a &amp;lt;code&amp;gt;logic_script&amp;lt;/code&amp;gt; marker when a designer should choose a module and its arguments in the scene Inspector. Select the &amp;lt;code&amp;gt;.vsiglib&amp;lt;/code&amp;gt;, module name, alias, arguments, and local-ref binding mode. The compiler expands the marker into the same form as a source-authored &amp;lt;code&amp;gt;use&amp;lt;/code&amp;gt;. It does not become a runtime entity.&lt;br /&gt;
&lt;br /&gt;
== Map and round lifecycle ==&lt;br /&gt;
&lt;br /&gt;
Lifecycle sources need no scene marker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
once on map.ready:&lt;br /&gt;
    doors.close&lt;br /&gt;
&lt;br /&gt;
on round.warmup:&lt;br /&gt;
    warmup_lights.enable&lt;br /&gt;
&lt;br /&gt;
on round.pre_round:&lt;br /&gt;
    round_timer.reset&lt;br /&gt;
&lt;br /&gt;
on round.live:&lt;br /&gt;
    round_timer.start&lt;br /&gt;
&lt;br /&gt;
on round.overtime:&lt;br /&gt;
    overtime_alarm.play&lt;br /&gt;
&lt;br /&gt;
on round.post_round:&lt;br /&gt;
    cancel heartbeat&lt;br /&gt;
&lt;br /&gt;
on round.intermission:&lt;br /&gt;
    doors.open&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Available lifecycle sources are &amp;lt;code&amp;gt;map.ready&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;round.warmup&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;round.pre_round&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;round.live&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;round.overtime&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;round.post_round&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;round.intermission&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;once on map.ready&amp;lt;/code&amp;gt; to capture an authored entity&#039;s initial state or perform setup that must run once per map load.&lt;br /&gt;
&lt;br /&gt;
== Safe server commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;server_command()&amp;lt;/code&amp;gt; sends one command through the server&#039;s content-accessible command boundary:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
once on map.ready:&lt;br /&gt;
    server_command(&amp;quot;mp_roundtime 3&amp;quot;)&lt;br /&gt;
    server_command(&amp;quot;sv_gravity -6&amp;quot;)&lt;br /&gt;
    server_command(&amp;quot;say Map rules loaded&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
on door.open:&lt;br /&gt;
    server_command(&amp;quot;gm_message major DOOR HAS BEEN OPENED&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server allows a curated set of match timing, chat or HUD messages, round completion, friendly fire, movement tuning, class enforcement, and weapon-slot rules. It rejects semicolons, newlines, secret-like identifiers, and commands without the &amp;lt;code&amp;gt;ContentAccessible&amp;lt;/code&amp;gt; flag. Any changed console variable is restored when the map unloads.&lt;br /&gt;
&lt;br /&gt;
Server operators can disable map commands with &amp;lt;code&amp;gt;sv_allow_content_commands 0&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;convar()&amp;lt;/code&amp;gt; reads use the same allowlist.&lt;br /&gt;
&lt;br /&gt;
== Signals shared with VMod ==&lt;br /&gt;
&lt;br /&gt;
VMods can emit a source under &amp;lt;code&amp;gt;mod:&amp;amp;lt;mod-id&amp;amp;gt;&amp;lt;/code&amp;gt;. Handle that signal like any other output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
on mod:community.hello.round_started(mode_id: string):&lt;br /&gt;
    status_label.set_text(&amp;quot;Mode: {0}&amp;quot;, mode_id)&lt;br /&gt;
&lt;br /&gt;
on mod:community.hello.stage.opened(index: int, gate_name: string):&lt;br /&gt;
    gate_counter.set(index)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first handler receives output &amp;lt;code&amp;gt;round_started&amp;lt;/code&amp;gt; from source &amp;lt;code&amp;gt;mod:community.hello&amp;lt;/code&amp;gt;. The second receives output &amp;lt;code&amp;gt;opened&amp;lt;/code&amp;gt; from child source &amp;lt;code&amp;gt;mod:community.hello.stage&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A VMod can subscribe to a map entity or module output by source alias and output name. This exchange carries scalar values only. It does not expose scene objects to VMod code.&lt;br /&gt;
&lt;br /&gt;
== Compile and debug ==&lt;br /&gt;
&lt;br /&gt;
Press Play for quick testing. The compiled VSig runtime Inspector shows validation state, live module state, scheduled tasks, and a bounded recent-event trace. Marker Inspectors can show signal routes and add selected refs or a group to the paired script.&lt;br /&gt;
&lt;br /&gt;
Before export:&lt;br /&gt;
&lt;br /&gt;
# Save the scene and VSig file.&lt;br /&gt;
# Resolve parser, type, ref, module, and entity-contract diagnostics.&lt;br /&gt;
# Check wildcard refs against the final hierarchy.&lt;br /&gt;
# Exercise each round-phase handler more than once.&lt;br /&gt;
# Confirm repeating schedules stop at the intended lifecycle boundary.&lt;br /&gt;
# Run &#039;&#039;&#039;Compile Scene&#039;&#039;&#039; in the Map Exporter before building the addon package.&lt;br /&gt;
&lt;br /&gt;
The exporter expands imported modules, validates the final program, and embeds a compact compiled program in the map. A Release export refuses incomplete required bakes or invalid VSig.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:VSig]] [[Category:Mapping]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Mapping&amp;diff=25</id>
		<title>Grimwar/Mapping</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Mapping&amp;diff=25"/>
		<updated>2026-08-25T05:12:55Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Version target|Map export requires Vellocet SDK 1.0.3 and Unity 6000.3.17f1. Release packages use addon schema 9.}}&lt;br /&gt;
&lt;br /&gt;
Grimwar maps are Unity scenes compiled and packaged by the Vellocet SDK. A map package can include custom assets, entity markers, VSig, audio, and platform-specific scene artifacts.&lt;br /&gt;
&lt;br /&gt;
== Create the scene ==&lt;br /&gt;
&lt;br /&gt;
# Complete [[Vellocet SDK#Install the SDK|SDK setup]].&lt;br /&gt;
# Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Workbench&#039;&#039;&#039;.&lt;br /&gt;
# Select &#039;&#039;&#039;Create New Map...&#039;&#039;&#039; and save the scene below &amp;lt;code&amp;gt;Assets/CustomContent/Maps&amp;lt;/code&amp;gt;.&lt;br /&gt;
# If you started from an existing scene, use &#039;&#039;&#039;Prepare Active Scene&#039;&#039;&#039;.&lt;br /&gt;
# Open the &#039;&#039;&#039;Map&#039;&#039;&#039; tab and resolve any missing map-contract or bake setup.&lt;br /&gt;
&lt;br /&gt;
Keep original content below &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt;. Do not modify &amp;lt;code&amp;gt;Assets/VellocetSDK&amp;lt;/code&amp;gt;; SDK sync owns that folder.&lt;br /&gt;
&lt;br /&gt;
The scene name becomes the default map slug. Rename it before other files or packages depend on that identity.&lt;br /&gt;
&lt;br /&gt;
== Build geometry ==&lt;br /&gt;
&lt;br /&gt;
Use ordinary Unity renderers, meshes, materials, terrain, colliders, and supported SDK assets. The exporter finds referenced custom assets and includes them in the addon.&lt;br /&gt;
&lt;br /&gt;
Use Unity&#039;s Transform tools as the final source of position, rotation, and scale. An area marker&#039;s scale is its world-space bounds. A scale of &amp;lt;code&amp;gt;(8, 3, 5)&amp;lt;/code&amp;gt; creates an &amp;lt;code&amp;gt;8 x 3 x 5&amp;lt;/code&amp;gt; volume; there is no separate size property or hidden multiplier.&lt;br /&gt;
&lt;br /&gt;
Avoid unnecessary high-poly collision meshes. Run the exporter collider audit and test player movement, projectiles, doors, and physics props against the compiled scene, not only the authoring scene.&lt;br /&gt;
&lt;br /&gt;
== Place entity markers ==&lt;br /&gt;
&lt;br /&gt;
Open the Workbench &#039;&#039;&#039;Entities&#039;&#039;&#039; tab. Markers turn authored positions, volumes, and objects into Grimwar runtime entities.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Prefix !! Purpose !! Examples&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;func_&amp;lt;/code&amp;gt; || Physical or interactive world objects || &amp;lt;code&amp;gt;func_door&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;func_rotate&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;func_tracktrain&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;func_button&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;trigger_&amp;lt;/code&amp;gt; || Reactive volumes || &amp;lt;code&amp;gt;trigger_multiple&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;trigger_hurt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;trigger_push&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;trigger_teleport&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;info_&amp;lt;/code&amp;gt; || Points and authored references || &amp;lt;code&amp;gt;info_player_spawn&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;info_teleport_destination&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;info_observer_point&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;env_&amp;lt;/code&amp;gt; || Audio, light, and effects || &amp;lt;code&amp;gt;env_ambient&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;env_light&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;env_explosion&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;env_screenshake&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logic_&amp;lt;/code&amp;gt; || Scene-configured VSig hosts || &amp;lt;code&amp;gt;logic_script&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;item_&amp;lt;/code&amp;gt; || Pickups || &amp;lt;code&amp;gt;item_pickup&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;game_&amp;lt;/code&amp;gt; || Rules and objectives || &amp;lt;code&amp;gt;game_capture_point&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game_crystal&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game_blitz_checkpoint&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Give marker GameObjects short, stable names. VSig refs use those names and hierarchy paths. The marker Inspector shows the entity&#039;s inputs, outputs, state, properties, and server or client access rules.&lt;br /&gt;
&lt;br /&gt;
=== Moving brushes ===&lt;br /&gt;
&lt;br /&gt;
The marker GameObject and its children are the geometry owned by &amp;lt;code&amp;gt;func_door&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;func_rotate&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;func_tracktrain&amp;lt;/code&amp;gt;. Parent intact prop prefabs, renderers, colliders, and child entities below the marker. Do not add an authoring Rigidbody, network component, or Transform constraint to the moving brush.&lt;br /&gt;
&lt;br /&gt;
The runtime mounts the hierarchy below one predicted kinematic body. Nested entities follow the mover, including entities below ordinary grouping objects. A nested continuous &amp;lt;code&amp;gt;func_rotate&amp;lt;/code&amp;gt; evaluates relative to its live parent pose, so wheels and fans can stay attached to a door or train.&lt;br /&gt;
&lt;br /&gt;
Keep a &amp;lt;code&amp;gt;func_tracktrain&amp;lt;/code&amp;gt; spline outside the train hierarchy and assign its &amp;lt;code&amp;gt;SplineContainer&amp;lt;/code&amp;gt; in the marker Inspector.&lt;br /&gt;
&lt;br /&gt;
== Add VSig logic ==&lt;br /&gt;
&lt;br /&gt;
The map script sits beside the scene and uses the same base filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Arena.unity&lt;br /&gt;
Arena.vsig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A marker Inspector can create the file, add refs for selected markers, build a group, and open the script. Use VSig to connect outputs to inputs, keep map state, schedule actions, and reuse logic modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ref button: func_button match ControlRoom/Button&lt;br /&gt;
ref door: func_door match ControlRoom/Door&lt;br /&gt;
&lt;br /&gt;
on button.pressed:&lt;br /&gt;
    door.open&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the [[Grimwar/VSig|VSig guide]] for refs, typed values, modules, lifecycle events, schedules, safe server commands, and VMod signals.&lt;br /&gt;
&lt;br /&gt;
== Bake map data ==&lt;br /&gt;
&lt;br /&gt;
Use the Workbench &#039;&#039;&#039;Map&#039;&#039;&#039; and &#039;&#039;&#039;Spatial&#039;&#039;&#039; tabs to run and inspect required bakes. The final package can contain lighting data, Probe Volume data, navigation, the spatial octree, and other compilation receipts used by the runtime validator.&lt;br /&gt;
&lt;br /&gt;
Development compile settings can skip lighting, the spatial octree, or both. A skipped octree is omitted from the compiled scene while the previous cached authoring asset remains available for a later bake. These options shorten iteration only.&lt;br /&gt;
&lt;br /&gt;
A Release package always requires complete lighting and spatial-octree bakes. It also builds every required desktop artifact. Do not distribute a Development package as a final release.&lt;br /&gt;
&lt;br /&gt;
== Set map and package identity ==&lt;br /&gt;
&lt;br /&gt;
Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Map Exporter&#039;&#039;&#039;. Select &#039;&#039;&#039;Addon&#039;&#039;&#039; workflow and choose the scene and export folder.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Meaning !! Example&lt;br /&gt;
|-&lt;br /&gt;
| Package ID || Stable addon identity used by the catalog || &amp;lt;code&amp;gt;community.sewer_escape&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Mode ID || Native or registered scripted mode || &amp;lt;code&amp;gt;grimwar.zombie_mod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Map prefix || Short naming convention || &amp;lt;code&amp;gt;zm&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Map slug || Author-controlled map name || &amp;lt;code&amp;gt;sewer_escape&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Final Map ID || Prefix and slug shown by the exporter || &amp;lt;code&amp;gt;zm_sewer_escape&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These identities are independent. Changing the default mode does not rename the map. Use &#039;&#039;&#039;Use selected mode&#039;s prefix&#039;&#039;&#039; when you intend to change the prefix.&lt;br /&gt;
&lt;br /&gt;
Set the title, author, version, in-game map image, and separate Workshop addon thumbnail. Workshop publishing requires a decodable 1920 x 1080 PNG or JPEG addon thumbnail; the in-game image does not replace it.&lt;br /&gt;
&lt;br /&gt;
== Compile and export ==&lt;br /&gt;
&lt;br /&gt;
Use &#039;&#039;&#039;Compile Scene&#039;&#039;&#039; to build a local compiled scene and catch errors before packaging.&lt;br /&gt;
&lt;br /&gt;
For routine iteration:&lt;br /&gt;
&lt;br /&gt;
# Select &#039;&#039;&#039;Development&#039;&#039;&#039;.&lt;br /&gt;
# Build only the platform targets needed for the current test.&lt;br /&gt;
# Leave required bakes enabled for the first complete pass, then use skip options only while changing unrelated content.&lt;br /&gt;
# Select &#039;&#039;&#039;Export Development Package&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For distribution:&lt;br /&gt;
&lt;br /&gt;
# Select &#039;&#039;&#039;Release&#039;&#039;&#039;.&lt;br /&gt;
# Install the Windows, macOS, and Linux Server Unity build-support modules if the exporter reports a missing target.&lt;br /&gt;
# Run &#039;&#039;&#039;Build Release Package&#039;&#039;&#039;.&lt;br /&gt;
# Keep the generated folder intact. The catalog validates its manifest, build ID, receipts, file sizes, hashes, paths, and platform payloads.&lt;br /&gt;
&lt;br /&gt;
The exporter writes into a staging directory first and publishes the package only after every selected target and integrity check succeeds.&lt;br /&gt;
&lt;br /&gt;
== Test the map in Grimwar ==&lt;br /&gt;
&lt;br /&gt;
# Export into Grimwar&#039;s addon directory or launch Grimwar with &amp;lt;code&amp;gt;--addon-root &amp;amp;lt;export-folder&amp;amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Open &#039;&#039;&#039;Addons&#039;&#039;&#039; from the main menu.&lt;br /&gt;
# Find the package, confirm it is valid and enabled, and select &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; if another copy has the same addon ID.&lt;br /&gt;
# Open &#039;&#039;&#039;Host&#039;&#039;&#039;. Returning to the Host tab rescans addon folders.&lt;br /&gt;
# If the map has no guest download source, Grimwar selects &#039;&#039;&#039;Local&#039;&#039;&#039; access and changes the main action to &#039;&#039;&#039;Test Map&#039;&#039;&#039;.&lt;br /&gt;
# Load the map and test spawns, objectives, all VSig paths, moving geometry, audio, lighting, navigation, and round transitions.&lt;br /&gt;
&lt;br /&gt;
Use [[Grimwar/Addons|Using addons]] for source conflicts and manual installs. Use [[Grimwar/Steam Workshop addons|Workshop publishing]] after the Release package passes local testing.&lt;br /&gt;
&lt;br /&gt;
== Map author checklist ==&lt;br /&gt;
&lt;br /&gt;
* Every custom asset lives below &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt; and has a valid reference from the scene or package.&lt;br /&gt;
* Marker names and hierarchy paths are stable.&lt;br /&gt;
* Volume scale, rotation, and parent scale match the intended runtime bounds.&lt;br /&gt;
* Moving-brush children are parented below the correct marker.&lt;br /&gt;
* VSig compiles without unknown refs, payload errors, type mismatches, or orphan schedules.&lt;br /&gt;
* Lighting, navigation, and spatial data were rebuilt after geometry changed.&lt;br /&gt;
* The Development package works through the Grimwar Addons and Host screens.&lt;br /&gt;
* The Release package contains all required platform targets and a Workshop thumbnail when it will be published.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Mapping]] [[Category:Vellocet SDK]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Getting_started&amp;diff=24</id>
		<title>Grimwar/Getting started</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar/Getting_started&amp;diff=24"/>
		<updated>2026-08-25T05:12:54Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
{{Notice|title=Version target|Use Vellocet SDK 1.0.3 with Unity 6000.3.17f1. Current packages use addon schema 9 and VMod API 5.}}&lt;br /&gt;
&lt;br /&gt;
Start with the result you want:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Goal !! Guide&lt;br /&gt;
|-&lt;br /&gt;
| Create a playable map || [[Grimwar/Mapping|Map authoring]]&lt;br /&gt;
|-&lt;br /&gt;
| Script doors, triggers, objectives, timers, and round logic || [[Grimwar/VSig|VSig]]&lt;br /&gt;
|-&lt;br /&gt;
| Write C# server gameplay, commands, or a game mode || [[Grimwar/VMod|VMod]]&lt;br /&gt;
|-&lt;br /&gt;
| Install, enable, select, or test a package || [[Grimwar/Addons|Using addons]]&lt;br /&gt;
|-&lt;br /&gt;
| Publish a map on Steam || [[Grimwar/Steam Workshop addons|Steam Workshop publishing]]&lt;br /&gt;
|-&lt;br /&gt;
| Run a community server || [[Grimwar/Dedicated servers|Dedicated servers]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Install the authoring tools ==&lt;br /&gt;
&lt;br /&gt;
# Install the current Vellocet SDK with the VSDK app.&lt;br /&gt;
# Install Unity &amp;lt;code&amp;gt;6000.3.17f1&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In Unity, open &#039;&#039;&#039;Window &amp;gt; Package Manager&#039;&#039;&#039; and select &#039;&#039;&#039;+ &amp;gt; Add package from disk...&#039;&#039;&#039;.&lt;br /&gt;
# Select &amp;lt;code&amp;gt;SDKPackage/package.json&amp;lt;/code&amp;gt; inside the VSDK install folder.&lt;br /&gt;
# Complete &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Welcome &amp;amp; Setup&#039;&#039;&#039;.&lt;br /&gt;
# Choose an addon export folder outside the Unity project.&lt;br /&gt;
# Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Workbench&#039;&#039;&#039; and confirm the Project tab reports current managed content.&lt;br /&gt;
&lt;br /&gt;
See [[Vellocet SDK#Install the SDK|Install the SDK]] for project paths, content sync, and editor support.&lt;br /&gt;
&lt;br /&gt;
== Build and test a first map ==&lt;br /&gt;
&lt;br /&gt;
# In SDK Workbench, select &#039;&#039;&#039;Create New Map...&#039;&#039;&#039; and save it below &amp;lt;code&amp;gt;Assets/CustomContent/Maps&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Add geometry, collision, at least one &amp;lt;code&amp;gt;info_player_spawn&amp;lt;/code&amp;gt;, and any required mode entities from the &#039;&#039;&#039;Entities&#039;&#039;&#039; tab.&lt;br /&gt;
# Give marker GameObjects stable names.&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;.vsig&amp;lt;/code&amp;gt; file beside the scene when the map needs scripted behavior.&lt;br /&gt;
# Open &#039;&#039;&#039;Tools &amp;gt; Vellocet &amp;gt; SDK &amp;gt; Map Exporter&#039;&#039;&#039;, set stable package and map IDs, and run &#039;&#039;&#039;Compile Scene&#039;&#039;&#039;.&lt;br /&gt;
# Export a Development package.&lt;br /&gt;
# Open Grimwar&#039;s &#039;&#039;&#039;Addons&#039;&#039;&#039; screen, enable the package, and select &#039;&#039;&#039;Use This Copy&#039;&#039;&#039; if another source has the same addon ID.&lt;br /&gt;
# Open &#039;&#039;&#039;Host&#039;&#039;&#039; and select &#039;&#039;&#039;Test Map&#039;&#039;&#039;. Test the exported scene, spawns, collision, logic, lighting, audio, and round transitions.&lt;br /&gt;
&lt;br /&gt;
Use a Release package only after the Development package works. Release export builds all required desktop artifacts and requires complete lighting and spatial bakes.&lt;br /&gt;
&lt;br /&gt;
== Build and test a first VMod ==&lt;br /&gt;
&lt;br /&gt;
# Create one addon folder with &amp;lt;code&amp;gt;addon.json&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt;, and a &amp;lt;code&amp;gt;.csx&amp;lt;/code&amp;gt; source file.&lt;br /&gt;
# Implement &amp;lt;code&amp;gt;Grimwar.ModApi.IMod&amp;lt;/code&amp;gt; and register one command in &amp;lt;code&amp;gt;OnLoad&amp;lt;/code&amp;gt;.&lt;br /&gt;
# On the test server, run &amp;lt;code&amp;gt;vmod_runtime_paths&amp;lt;/code&amp;gt; and copy the complete folder into the printed addons root.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;vmod_runtime_reload&amp;lt;/code&amp;gt;, then &amp;lt;code&amp;gt;vmod_runtime_list&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Invoke the command through chat and authenticated console, then reload the package again to check cleanup.&lt;br /&gt;
&lt;br /&gt;
The [[Grimwar/VMod#Write the entry class|minimal VMod]] contains working manifests and C# source. VMod packages are server-authoritative and are currently installed manually or through the development overlay.&lt;br /&gt;
&lt;br /&gt;
== Keep these boundaries straight ==&lt;br /&gt;
&lt;br /&gt;
* Original Unity assets belong below &amp;lt;code&amp;gt;Assets/CustomContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Assets/VellocetSDK&amp;lt;/code&amp;gt; is managed by SDK content sync.&lt;br /&gt;
* A Unity scene is authored content; the exported addon folder is what Grimwar installs.&lt;br /&gt;
* VSig controls map entities and map-local logic. VMod controls server gameplay through &amp;lt;code&amp;gt;Grimwar.ModApi&amp;lt;/code&amp;gt;.&lt;br /&gt;
* The complete addon folder is the install unit.&lt;br /&gt;
* Steam Workshop publishing currently accepts map-only Release packages. It does not accept a package containing VMods.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]] [[Category:Getting started]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
	<entry>
		<id>https://developer.vellocetsoftware.com/w/index.php?title=Grimwar&amp;diff=23</id>
		<title>Grimwar</title>
		<link rel="alternate" type="text/html" href="https://developer.vellocetsoftware.com/w/index.php?title=Grimwar&amp;diff=23"/>
		<updated>2026-08-25T05:12:53Z</updated>

		<summary type="html">&lt;p&gt;DocumentationBot: Publish SDK documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameNav}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;vellocet-eyebrow&amp;quot;&amp;gt;GRIMWAR DEVELOPER PORTAL&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These guides cover the public Grimwar content toolchain: Unity map authoring, VSig map logic, VMod server scripting, addon installation, Steam Workshop maps, and community dedicated servers.&lt;br /&gt;
&lt;br /&gt;
== Start here ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Goal !! First document&lt;br /&gt;
|-&lt;br /&gt;
| Install the authoring tools || [[Vellocet SDK]]&lt;br /&gt;
|-&lt;br /&gt;
| Build a map || [[Grimwar/Mapping]]&lt;br /&gt;
|-&lt;br /&gt;
| Script map logic || [[Grimwar/VSig]]&lt;br /&gt;
|-&lt;br /&gt;
| Write server gameplay || [[Grimwar/VMod|VMod C# scripting]]&lt;br /&gt;
|-&lt;br /&gt;
| Install or select a package || [[Grimwar/Addons|Using addons]]&lt;br /&gt;
|-&lt;br /&gt;
| Publish a map || [[Grimwar/Steam Workshop addons|Steam Workshop publishing]]&lt;br /&gt;
|-&lt;br /&gt;
| Operate a community server || [[Grimwar/Dedicated servers]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Current version boundary ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Component !! Version&lt;br /&gt;
|-&lt;br /&gt;
| Vellocet SDK || 1.0.3&lt;br /&gt;
|-&lt;br /&gt;
| Unity editor || 6000.3.17f1&lt;br /&gt;
|-&lt;br /&gt;
| SDK content schema || 3&lt;br /&gt;
|-&lt;br /&gt;
| Addon schema || 9&lt;br /&gt;
|-&lt;br /&gt;
| VMod API || 5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Packages built for an older rejected schema or a different VMod API must be rebuilt against the current SDK. Steam Workshop publishing currently accepts map-only Release packages; VMod packages use manual installation or the development overlay.&lt;br /&gt;
&lt;br /&gt;
[[Category:Grimwar]]&lt;/div&gt;</summary>
		<author><name>DocumentationBot</name></author>
	</entry>
</feed>