SkillAgentSearch skills...

Urcheon

An asset builder and package manager for Dæmon Engine based games like Unvanquished and other Quake 3 games.

Install / Use

/learn @DaemonEngine/Urcheon

README

Urcheon

Cute Granger
My lovely granger needs a tender knight to care for his little flower.

Description

ℹ️ Urcheon is purposed to manage and build source directories to produce game packages like Dæmon engine dpk packages or id Tech engines pk3 or pk4 packages.

The primary usage of this toolset is to build of Unvanquished game media files. It was initially developed and tested against the files from Interstellar Oasis.

ℹ️ The Esquirel tool is also shipped with Urcheon, which is a tool to do some common editions on .map and .bsp files. Esquirel is a bit id Tech 3 map and bsp format centric at this time.

How to run Urcheon and Esquirel

💡️ You may want to install the DaemonMediaAuthoringKit. The DaemonMediaAuthoringKit provides a convenient way to install Urcheon with its dependencies alongside some other usual edition tools (like the NetRadiant level editor). This makes easy to set-up a complete production environment.

If you're installing Urcheon separately, for example if you already own all tools required by Urcheon (see Dependencies), once you cloned this repository you can add this bin/ directory to your $PATH environment variable to run them easily.

Urcheon help

ℹ️ Urcheon is a game data package builder and packager. It converts files, compile maps, and produce distributables packages from them.

Type urcheon --help for generic help.

Creating a package source

So you want to make a package, in this example we create a simple resource package that contains a text file. We will name this package res-helloworld. The DPK specifications reserves the _ character as a version separator (can't be used in package name or version string).

We create a folder named res-helloworld_src.dpkdir and enter it:

mkdir res-helloworld_src.dpkdir
cd res-helloworld_src.dpkdir

This will be a package for the Unvanquished game so let's configure it this way:

mkdir .urcheon
echo 'unvanquished' > .urcheon/game.txt

We need the package to ship some content, let's add a simple text file:

mkdir about
echo 'Hello world!' > about/helloworld.txt

Basic package tutorial

Now we can build the package, this will produce another dpkdir you can use with your game, with files being either copied, converted or compiled given the need.

It will be stored as res-helloworld_src.dpkdir/build/_pakdir/pkg/res-helloworld_test.dpkdir, you can tell the game engine to use res-helloworld_src.dpkdir/build/_pakdir/pkg as a pakpath to be able to find the package (example: daemon -pakpath res-helloworld_src.dpkdir/build/_pakdir/pkg).

urcheon build

Then we can produce the distributable dpk package.

It will be stored as res-helloworld_src.dpkdir/build/pkg/map-castle_<version>.dpk. The version will be computed by Urcheon (see below).

You can tell the game engine to use res-helloworld_src.dpkdir/build/_pakdir/pkg as a pakpath to be able to find the package (example: daemon -pakpath res-helloworld_src.dpkdir/build/_pakdir/pkg).

urcheon package

We can also pass the dpkdir path to Urcheon, this way:

cd ..
urcheon build res-helloworld_src.dpkdir
urcheon package res-helloworld_src.dpkdir

Building in an arbitrary folder

As you noticed with our previous example, the built files were produced within the source dpkdir, with this layout:

res-helloworld_src.dpkdir/build/_pakdir/pkg/res-helloworld_test.dpkdir
res-helloworld_src.dpkdir/build/pkg/res-helloworld_<version>.dpk

You may not want this, especially if you want to build many package and want to get a single build directory. You can use the --build-prefix <path> option to change that, like that:

urcheon --build-prefix build build res-helloworld_src.dpkdir
urcheon --build-prefix build package res-helloworld_src.dpkdir

You get:

build/_pakdir/pkg/res-helloworld_test.dpkdir
build/pkg/res-helloworld_<version>.dpk

Special case of prepared dpkdir

Some packages need to be prepared before being built. This is because some third-party software requires some files to exist in source directories, for example map editors and compilers.

Urcheon can produce .shader material files or model formats and others in source directory with the prepare command, for such package, the build and package routine is:

urcheon prepare <dpkdir>
urcheon build <dpkdir>
urcheon package <dpkdir>

Package collection tutorial

A package collection is a folder containing a src subdirectory full of source dpkdirs.

Let's create a package collection, enter it and create the basic layout:

mkdir PackageCollection
cd PackageCollection

To tell Urcheon this folder is a package collection, you just need to create the .urcheon/collection.txt file, it just has to exist, en empty file is enough:

mkdir .urcheon
touch .urcheon/collection.txt

Then we create two packages, they must be stored in a subdirectory named src:

mkdir pkg

mkdir pkg/res-package1_src.dpkdir
mkdir pkg/res-package1_src.dpkdir/.urcheon
echo 'unvanquished' > pkg/res_package1_src.dpkdir/.urcheon/game.txt
mkdir pkg/res-package1_src.dpkdir/about
echo 'Package 1' > pkg/res_package1_src.dpkdir/about/package1.txt

mkdir pkg/res-package2_src.dpkdir
mkdir pkg/res-package2_src.dpkdir/.urcheon
echo 'unvanquished' > pkg/res_package2_src.dpkdir/.urcheon/game.txt
mkdir pkg/res-package2_src.dpkdir/about
echo 'Package 2' > pkg/res_package1_src.dpkdir/about/package2.txt

urcheon build pkg/*.dpkdir
urcheon package pkg/*.dpkdir

You'll get this layout:

build/_pakdir/pkg/res-package1_test.dpkdir
build/_pakdir/pkg/res-package2_test.dpkdir
build/pkg/res-package1_<version>.dpk
build/pkg/res-package2_<version>.dpk

You'll be able to use build/_pakdir/pkg or build/pkg as pakpath to make the game engine able to find those packages, example: daemon -pakpath PackageCollection/build/_pakdir/pkg or daemon -pakpath PackageCollection/build/pkg.

Delta package building

Urcheon can produce partial packages relying on older versions of the same package. To be able to do that you need to have your dpkdirs stored in git repositories with version computed from git repositories.

You pass the old reference with the --reference build option followed by the git reference (for example a git tag), this way:

urcheon build --reference <tag> <dpkdir>
urcheon package <dpkdir>

Dealing with multiple collections

When building dpkdirs from a collection requiring dpkdirs from another collection, one can set the PAKPATH environment variable this way (the separator is ; on Windows and : on every other operating system):

export PAKPATH='Collection1/pkg:Collection2/pkg:Collection3/pkg'

or (Windows):

set PAKPATH='Collection1/pkg;Collection2/pkg;Collection3/pkg'

Real life examples

Here we clone the UnvanquishedAssets repository, prepare, build and package it:

git clone --recurse-submodules \
   https://github.com/UnvanquishedAssets/UnvanquishedAssets.git

urcheon prepare UnvanquishedAssets/pkg/*.dpkdir
urcheon build UnvanquishedAssets/pkg/*.dpkdir
urcheon package UnvanquishedAssets/pkg/*.dpkdir

We can load the Unvanquished game with the stock plat23 map this way:

daemon -pakpath UnvanquishedAssets/build/pkg +devmap plat23

Here we build and package delta Unvanquished packages for res- and tex- packages, only shipping files modified since Unvanquished 0.52.0, and full packages for map ones:

urcheon prepare UnvanquishedAssets/pkg/*.dpkdir
urcheon build --reference unvanquished/0.54.1 \
    UnvanquishedAssets/pkg/res-*.dpkdir \
    UnvanquishedAssets/pkg/tex-*.dpkdir
urcheon build UnvanquishedAssets/pkg/map-*.dpkdir
urcheon package UnvanquishedAssets/pkg/*.dpkdir

Here we clone the InterstellarOasis and build it.

Since it needs to access dpkdirs from UnvanquishedAssets, we set UnvanquishedAssets/pkg as a pakpath using the PAKPATH environment variable.

We also need the UnvanquishedAsset/pkg folder to be prepared, but there is no need to prepare InterstellarOasis/pkg, only build and package it:

git clone --recurse-submodules \
   https://github.com/InterstellarOasis/InterstellarOasis.git

export PAKPATH=UnvanquishedAssets/pkg

urcheon prepare UnvanquishedAssets/pkg/*.dpkdir
urcheon build InterstellarOasis/pkg/*.dpkdir
urcheon package InterstellarOasis/pkg/*.dpkdir

Given both UnvanquishedAssets and InterstellarOasis are built, one can load the Unvanquished game with the third-party atcshd map this way:

daemon -pakpath UnvanquishedAssets/build/pkg InterstellarOasis/build/pkg +devmap atcshd

DPK version computation

Urcheon knows how to write the DPK version string, computing it if needed.

The recommended way is to store the dpkdir as a git repository, preferably one repository per dpkdir. Doing this unlock all abilities of Urcheon. It will be able to compute versions from git tag and do delta paks (partial DPK relying on older versions of it).

If the dpkdir is not a git repository, Urcheon provides two ways to set the version string.

One way is to write the version string in the .urcheon/version.txt file, like this:

echo '0.1' > .urcheon/version.txt

Urcheon does not implement delta packaging when doing this way (it may be implementable though).

Another way is to set the version string in the dpkdir name.

For example: res-helloworld_0.1.dpkdir

This is the least recommended method if you care about version control. Urcheon will never implement delta packaging for this (it's a

View on GitHub
GitHub Stars13
CategoryDevelopment
Updated3d ago
Forks1

Languages

Python

Security Score

95/100

Audited on Mar 27, 2026

No findings