Structure of your mod
Overview
Your mod is a single folder. It must always contain (at very least) an index.xml file. This is the "entry point" for
Penal Engineer to read and understand what your mod supplies, and where to locate additional files (textures,
scripts).
Folder structure
You may organize your content as you wish. The only requirement is to have the index.xml file at the root of your mod
folder.
Penal Engineer forbids your mod to refer to any content outside the mod root folder. All your mod content must be
confined within your mod folder, along with index.xml or at any depth of nested subfolders.
However, you can overcome this restriction in your local development if you cast spells like symbolic links, folder junctions or NTFS reparse points. Penal Engineer doesn't care of such low-level items, and obediently traverses through such wormholes you can deliberately leave in your filesystem. Of course, it's non-portable, and the standard mod installation process secures players from those hacks.
Example of a valid mod folder structure:
MyMod\
|--- index.xml
|--- textures\
|--- walls\
|--- brick\
|--- body_horizontal.png
|--- horizontal_junction.png
|--- vertical_junction.png
|--- L_TL.png
|--- L_TR.png
|--- cross.png
|--- flooring\
|--- grass_enhanced.png
|--- characters\
|--- undercover_prisoner.png
index.xml structure
Your index.xml must define:
- The mod metadata (mod ID, version, author, contact)
- Dependencies
- Permissions (for the time being it only regards claiming namespaces)
- Supplied content
You'll know about content definition from next chapters. For now, let us show a standard sample of an index.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Mod
xmlns="https://penalengineer.com/mod/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://penalengineer.com/mod/v1 https://penalengineer.com/mod/v1/schema.xsd"
Id="com.example.theniceguy.pe.MyMod"
Version="0.0.1">
<Metadata>
<Title>My Mod</Title>
<Author>
<Name>The Nice Guy</Name>
<Contacts>
<Website Href="https://theniceguy.example.com/">The Nice Guy's Blog</Website>
</Contacts>
</Author>
<Description>
This is an experimental mod to stretch the capabilities of **Penal Engineer**.
* Enhanced: grass
* New need on prisoners: to fight
* New entity: Undercover prisoner
</Description>
</Metadata>
<Dependencies />
<Permissions>
<ClaimNamespace Id="MyMod" />
<ClaimNamespace Id="TheNiceGuy" />
</Permissions>
<Content>
<Sprites>
<Sprite>
<NamespacedId Value="MyMod/Walls/Brick/body_horizontal" />
<Texture Path="walls/brick/body_horizontal.png" />
</Sprite>
<Sprite>
<NamespacedId Value="MyMod/Walls/Brick/body_vertical" />
<Texture Path="walls/brick/body_horizontal.png" />
<Rotation Value="90" />
</Sprite>
<!-- ...other sprites... -->
</Sprites>
<Prefabs>
<!-- All the fun begins here -->
</Prefabs>
</Content>
</Mod>
Let's dissect this sample.
Mod ID
You must define an identifier for your mod with the Id attribute at the root tag <Mod>. It shall identify all (or
most of) the content your mod brings with it.
The mod ID must not contain a slash (/). All other characters including whitespaces are permitted.
Your mod ID must be unique across all mods and plugins loaded with Penal Engineer. As such, the suggested convention is to use a reversed DNS for your mod. You might recognize this convention as coming from the Java world.
Version of mod
If distributing over Mod Yard, the version must be a SemVer string, so that the built-in update mechanism could compare version numbers and notify a player that they need to update.
Otherwise, Penal Engineer doesn't care of the format. Choose a convention that would allow users to understand whether they're running behind your development.
This is also a must-have attribute Version at the root tag <Mod> (even if you're writing a mod for yourself).
Metadata
Titleis a must.Author/Nameis a must.- Other tags are optional.
The sample above lists the exhaustive set of tags now supported.
Penal Engineer does not support rich formatting for now. But support of Markdown is envisaged.
Feel free to use Markdown inside tags. Even without a direct support by UI, Markdown per se looks pretty.
Dependencies
Here you may declare that some other mods or plugins must be loaded before taking yours.
You must specify this tag even if your mod doesn't have any dependency. In that case, just make it empty (as in the sample).
Permissions
This is an optional tag. It can be used to declare specific permissions your mod require.
Claiming namespace
As of now, only <ClaimNamespace> is supported. We already talked about namespaces in the previous chapter.
Your mod may only provide content (sprites, prefabs) with IDs lying in the namespaces your mod claimed.
Your mod always claims at least one namespace: a namespace with the same identifier as your mod ID.
In the sample above, your mod shall be allowed to provide content with such sample identifiers:
- ✅
com.example.theniceguy.pe.MyMod/GrassSprite– inherently because it's the mod ID - ✅
MyMod/GrassSprite– because of<ClaimNamespace> - ✅
TheNiceGuy/GrassSprite– likewise, because of<ClaimNamespace>
On the contrary, your mod shall fail to ship any new content with such ID:
- ❌
MainContent/UndercoverPrisoner
If you intend to patch alien prefabs (including ones of MainContent), you don't
need to claim their namespace(s). If you do, Penal Engineer shall reject your mod because it would claim a
conflicting namespace which is already claimed by the game itself.
Content
The <Content> tag itself must present, but may be empty.
It comprises two sections reflecting the large classes of items your mod can supply to Penal Engineer:
But hold on before jumping to the linked chapters! We need to talk first about basic concepts.