====== Packages ======
In Doomsday 2, resources are collected into [[packages]]. This article describes the Doomsday 2 package format and how you should go about creating your own packages.
===== Package format =====
A //Doomsday 2 package// can either be a folder or a ZIP archive. Regardless of the type, the file name must have a **.pack** extension. The package is also required to contain metadata that describes the contents of the package.
Below is an example of what a package might look like as a folder structure. This package is from one of the Doomsday test apps, and it contains 3D model and image files.
File structure:
net.dengine.test.glsandbox.pack/
info.dei
models/
boblampclean.md5anim
boblampclean.md5mesh
guard1_body.png
guard1_face.png
guard1_helmet.png
iron_grill.png
marine.md2
Marine_green.pcx
round_grill.png
testpic.png
The **info.dei** file has the following contents:
title: GLSandbox Test
version: 1.0
license: GPL 3+
tags: test
==== File name and identifier ====
**Naming conventions.** Here is a brief overview of the conventions used in package file names. These conventions are described in more detail elsewhere on this page.
* File extension must be **.pack**
* Prefer to use lower case letters
* Underscore is a special character (separates name from version number)
* Must have at least two components (dot-separated) — see also [[#subpackages]]
* Reverse domain name notation
**Package identifier.** The name of the package file/folder has a special meaning: it is used as the package's globally unique identifier. Being unique, the identifier can be used as-is in savegames or multiplayer games to record and share information about which packages are required or in use. Also, it is possible to compile a single repository of all available packages, and build a package manager interface for browsing and acquiring packages, without fear of identifier conflicts or other ambiguities. Note that the identifier is //case insensitive// (upper and lower case letters are not treated differently), however using lower case letters is recommended for consistency.
We have chosen to use [[http://en.wikipedia.org/wiki/Reverse_domain_name_notation|reverse domain name notation]] in package identifers. In other words, the package identifier also identifies the origin or creator of the package. In the case of the above example, the origin is //net.dengine//, i.e., the Doomsday project's web site. From a technical standpoint, this notation has the significant advantage of supporting hierarchies, providing a natural way to identify [[#subpackages]]. Another advantage is that the notation is compatible with alphabetic sorting, because the most general component is at the beginning of the identifier.
A package identifier is required to have at least two components. For example: //skyjake.example// is a valid identifier, but //example// is not. (The corresponding files might be named **skyjake.example.pack** and **example.pack**.)
**Alternative versions of packages.** Consider the package file name: **net.dengine.test.glsandbox.pack**. What if you have two versions of this package that need to co-exist in the same folder on a hard drive (or in an online repository)? It is possible to add a //free-form suffix// to the file name; for example:
net.dengine.test.glsandbox_1.2beta.pack
^^^^^^^
Anything following the left-most underscore (_) found in the package file name is excluded from the package identifier. Doomsday attempts to parse a version number from the part following the underscore.
**Folders and ZIPs.** A package may be either a regular folder or a ZIP archive. Likewise, subpackages contained within a package may be either regular folders or ZIP archives. At runtime, Doomsday accesses all ZIP archives as regular folders. Therefore, you can use whichever format is most suitable for your needs.
==== Metadata ====
Every package is required to have metadata. In practice, the metadata is a [[:Doomsday Script]] [[script:Record]] containing a set of required variables and any amount of other information.
**The Info file.** The root folder of the package must contain a file named **info.dei** or **Info**. This is the primary place where the package's metadata is defined. If this file is missing, the package will not be recognized as a package by Doomsday. The file uses the [[modding:ScriptedInfo]] syntax to specify a set of variables and functions that will be stored with the package at runtime.
**Required metadata.** The following four variables must be defined in the metadata for a package to be loadable by Doomsday.
^ Variable^ Description |
| ''title''| Human-readable name of the package. Normally this is the only name shown to the user. |
| ''version''| Version number of the package. Must be in the format //x//, //x.y//, or //x.y.z//, with //x//, //y// and //z// being numbers. |
| ''license''| Terms under which the package is being made available: determines who can legally distribute and/or modify the package contents (see [[package licensing]]). |
| ''tags''| Keywords/tags that apply to the package, as a white-space separated list of words. This is used for organizing larger collections of packages and for finding packages (see [[package tags]]). |
**__init__.ds script.** Additionally, a package may contain a script named **__init__.ds**. If present, this script is executed immediately after the **Info** file has been parsed, and the script will run with the package metadata as the global namespace; i.e., any variables defined in **Info** are available as global variables in the script. This way one can more conveniently add pure DS content like functions into the package metadata.
==== Scripting ====
**Globally available DS modules.** A package may contain [[:Doomsday Script]] modules that are made available for importing from all DS scripts. This is done by adding the ''importPath'' variable to the package metadata, for instance:
importPath
The import path must be specified as an array, which is why the angle brackets are used here (see [[modding:Info]] syntax). The end result is that the folder **modules** inside the package is added to the global DS import path, and its contents will be checked when someone tries to import a module in Doomsday Script. (Many of the //net.dengine// packages use this, for instance see //net.dengine.stdlib//.)
**Load/unload scripts.** When a package is loaded, Doomsday checks if the function ''onLoad()'' exists in the package metadata and automatically calls it. Similarly, the function ''onUnload()'' gets called right before the package is unloaded. This allows one to perform any relevant actions via [[:Doomsday Script]] at these times.
==== Subpackages ====
A subpackage is a package that is contained inside another package's root folder. For instance, this allows creating a larger collection of packages that can be distributed as a single file. From Doomsday's point of view, though, subpackages are treated just like any other package — they are not automatically loaded when the containing package is loaded. This makes subpackages mostly a convenience for the packager.
Let's examine the client's packages (omitting most of the contained files):
net.dengine.client.pack/
Info
defaultstyle.pack/
modules/
renderer.pack/
lensflares.pack/
testmodel.pack/
Here we have **.pack** folders inside the main //net.dengine.client// package. **defaultstyle.pack** is a subpackage whose identifier becomes **net.dengine.client.defaultstyle**: the containing package's identifier is used as a prefix.
The rule about **Info** remains: a package is only loadable if it has metadata. However, subpackaging still works without metadata. In the above example, you could omit the **Info** inside the root folder, and still be able to load //net.dengine.client.defaultstyle//.
It is allowed to place packages in other folders inside a package, however those will have to be named using their full identifiers as they are not treated as subpackages.
==== Dependencies ====
A package may require other packages to be loaded before it can be used. The required dependencies of a package are specified using the ''requires'' metadata variable. Doomsday will ensure that each listed required package is successfully loaded before loading the package itself.
requires
Packages may also be configured to be optional. The ''recommends'' variable lists the optional packages that are loaded by default, and the ''extras'' variable lists the packages that are not loaded by default.
recommends
extras
Below is a link to an example that demonstrates setting up dependencies between packages:
* {{file:dependency_example.zip}}
==== Assets ====
Packages may contain any kind of files and any amount of Doomsday Script. To let Doomsday know that the package contains something it can use (an //[[:assets|asset]]//), it has to defined in the metadata of the package. For example, an asset could be a [[assets:model|3D model]] that the renderer would use to represent a thing of a particular type.
Package assets are a generic mechanism in the sense that it builds on the Doomsday 2 file system and Doomsday Script, and leaves the interpretation of the asset definitions to whichever subsystem uses the asset.
All the assets provided by a package are defined in the package metadata. For instance, a 3D model asset definition could look like this:
asset model.thing.possessed {
path = "boblampclean.md5mesh"
}
The Info block type ''asset'' must be used when defining an asset. The asset identifier (''model.thing.possessed'') is used to declare what kind of asset is being defined. See [[assets:identifiers|Asset identifiers]] for more details.
==== DED definitions ====
Packages can contain [[:DED]] definitions that are only in effect when the package is loaded.
The ''defsPath'' metadata variable specifies which folder contains the DED files of the package. The path is relative to the root folder of the package. For example:
defsPath = "defs"
This would look for DED files in the folder **/defs** inside the package. Only this folder is checked — any DED files in subfolders are not automatically read. You can use the ''Include'' directive in DED files to read further DEDs from subfolders.
==== Icon image for the UI ====
Packages can provide an image file specifically meant for representing the package in GUIs. Simply place an image file called **icon.jpg** or **icon.png** in the root of a **.pack** package. The maximum allowed size for the image is 512x512 pixels. There is no other limitation for the resolution and aspect ratio (doesn’t have to be square; can be small). If you use a PNG image, it is allowed to have an alpha channel for a non-rectangular shape.
The package icon is not declared or affected by the package metadata in any way — only the presence of the **icon.jpg**/**icon.png** file in the package root is checked. This is primarily for efficiency: the UI may have hundreds of packages to manage, so fetching their icons needs to be as fast as possible.
===== Aliases and features =====
A package may have an alias, i.e., an identifier that is different from the one that is determined based on its file name. When such a package is loaded, the package appears under the **/packs** folder also under the alias in addition to its real identifier.
For instance, the shaders and images for lens flares are stored in the //net.dengine.client.renderer.lensflares// package. In its metadata, an alias has been defined:
alias: feature.lensflares
However, since the lens flare renderer accesses these resources using the identifer //feature.lensflares//, any other loaded package with this alias could be used instead, allowing the creation of altenative packages for the same purpose.
For more details about the feature packages used by Doomsday, see [[feature_packages]].
===== Creating a package =====
Here are a few notes that you should bear in mind when creating your own packages:
* **Pick the identifier of the package carefully.** If you own a domain name and distribute your packages on the domain, use that as the basis of the identifier (//net.dengine.doomsday//). If you don't have a domain, you could use your nickname/forum handle instead (//skyjake.coolstuff.mypackage//). The important thing is that it is unique, and it identifies you unambiguously.
* **Take advantage of subpackages and hierarchical organization.** This allows one to break a larger amount of data into more manageable components. For instance, common resources needed by several assets could be contained in a subpackage.
* **Meaningful title.** The title is the primary name presented to the user, so it should be concise. Don't put a version number in the title, as that is specified separately.
* **Tags.** It is important that packages are tagged using all the [[package_tags|relevant tags]] since that enables users to locate the package more easily.
* **Zipping.** When distributing a package, the top-level package folder should be zipped, and its extension should be **.pack** (NOT **.pack.zip**). However, when developing a package, it is likely easier to leave the package unzipped.
===== Loading packages =====
([[version:2.0]] →) The ''-file'' option can be used to load packages (together with ''-game'') or to register them for use at runtime in game profiles (without ''-game'').
The ''-pkg'' option can be used for loading packages at launch (together with ''-game'').
==== Knowing which packages are currently loaded ====
While it is unimportant to understand exactly how Doomsday manages packages at runtime, one detail should be noted. All the packages that are currently loaded (i.e., in use) appear inside the special **/packs** folder in the [[:fs|Doomsday 2 file system]]. This means that if a package needs to access to the contents of another package, it can do so via the path **/packs/(identifier)/**.
Assets appear under **/packs**, too. For example, given the asset above, the symbolic link **/packs/asset.model.thing.possessed** would be created, pointing to the package containing the asset. The model renderer would then be notified of the availability of this asset due to the existence of this link, and where to access the files and scripts associated with the asset. This guarantees that there is no ambiguity about which package offers which asset, even if many packages have variants of the asset — only the one linked under **/packs** will be used.
===== Implementation status (2.0 →) =====
The Doomsday 2 package system was first introduced in [[version:1.15]], however it is not yet used for all resources.
===== See also =====
* [[modding:Resource packaging guidelines]]
* The //net.dengine// packages are good examples of Doomsday 2 packages.
* ''-pkg'' option