Guides › Development

Versions, dependencies and platforms

Version numbers

The version is version in plugin.json. The LonelyIce catalog requires this form:

Rule Where it comes from
Three numbers, x.y.z, digits only (1.4.0, not 1.4, v1.4.0 or 1.4.0-beta) The upload check "Version … must look like 1.2.3".
Each upload is newer than the newest published version of the id The upload check "Version … is not newer than … in the catalog".
A version number is used once, for one core ABI. A published file never changes, a hidden (yanked) version number cannot be submitted again, and a rebuild for another ABI or with more platforms is a new version. The catalog keeps one package per version number ("Version … was published and is hidden", "This version number is already in review or published.").

The launcher compares versions part by part as numbers, so 1.10.0 is newer than 1.9.0. The full rules are in How the package manager works.

A new version is how players get anything from you. Every change needs one:

  • The launcher offers an update only when a catalog has a strictly newer version.
  • The server runs the database updater over plugin SQL only when a loaded plugin's version, its SQL file names or their contents change (or plugins or database connections change). A file edited in place is noticed, but players only get the edit with a new package, and that needs a new version (On the next server start).
  • A rebuild for a new core ABI needs a new version too (see Core ABI).

When to bump what

LonelyIce itself gives no meaning to the three numbers. Your dependents' ranges do: ^1.2 accepts every 1.x from 1.2.0 on and refuses 2.0.0, and ~1.2 accepts only 1.2.x. The table below is a recommendation that makes those ranges work for the people who depend on you.

Change Bump
Bug fix, translation, balance change, new SQL update file patch: 1.4.0 → 1.4.1
New feature, new setting or command, new platform build, rebuild for a new core ABI minor: 1.4.1 → 1.5.0
Something a dependent plugin or a player's setup relies on changes or goes away: exported functions or headers other plugins link against, config keys, named ids other plugins reference (@your.plugin/name), database tables other plugins read major: 1.5.0 → 2.0.0

Below 1.0.0, ranges are stricter: ^0.3.1 accepts only 0.3.x, and ^0.0.3 only 0.0.3. Move to 1.0.0 once other plugins depend on yours.

Dependencies

depends maps plugin ids to version ranges. Each value must be a string.

"depends": { "playerbots": "^1.0.0", "lonelyice.qol": ">=1.2.0 <2.0.0" }

What a dependency does:

When Effect
Upload to this catalog Every dependency must have a published version in the catalog that is in the range and that the launcher can install next to your package (built for your core ABI and each of your platforms, or without server code). A range the launcher cannot read fails the upload too (the checks). Publish your dependencies first.
Install The launcher installs the newest version of each dependency that fits every range, from all the player's catalogs. It keeps an installed version when it fits, and refuses an install or update that would take an enabled plugin out of its range (Resolving).
Disable, remove The launcher refuses to disable or remove a plugin while an enabled plugin needs it.
Server start Dependencies load first. A plugin whose dependency is missing, out of range or failed to load is skipped with a message (Debugging plugins).

Range syntax, as implemented (the complete table is in How the package manager works):

Write Means
^1.2.0 1.2.0 or newer, below 2.0.0
~1.2.0 1.2.0 or newer, below 1.3.0
>=1.2.0 <3.0.0, >=1.2.0,<3.0.0 both conditions (separate terms with a space or a comma)
1.2.x any 1.2 version
~1 any 1.x version
<=1.2 up to and including every 1.2.x
* any version

An operator may stand apart from its version (>= 1.0.0), ~> means ~, and a leading v and +build metadata are ignored. Not supported: || (1.x || 2.x), hyphen ranges (1.0.0 - 2.0.0) and pre-release suffixes (1.0.0-beta). The launcher, the server and this catalog read ranges the same way and refuse these.

Recommendation: depend on ^ of the version you built and tested against (^1.4.0). If your library links against the dependency's library, its exported functions must stay compatible, which is what its major version should tell you.

A disabled plugin does not count as a dependency: the launcher refuses to install or enable your plugin while a dependency is disabled, and names it ("enable it first"). It also refuses to disable a plugin that an enabled plugin needs.

Conflicts

conflicts lists plugin ids that must not be installed together with yours:

"conflicts": [ "someone.other-transmog" ]

The two sides check it differently:

  • The launcher checks both directions: it refuses to install or enable your package while a listed plugin is enabled or chosen in the same install, and it refuses to install or enable a plugin that an enabled plugin's conflicts names. A disabled plugin counts for neither side.
  • The server, at start, skips each plugin whose conflicts names a plugin it has.

Declare conflicts on your side. If you maintain both plugins, declare them on both sides.

The LonelyIce catalog copies conflicts into its index, and the entry --pkg pack prints for a catalog of your own carries them too.

Multi-platform packages

platforms lists the builds a package carries, one server/<platform>/ folder each:

your.plugin/
  plugin.json                          "platforms": [ "windows-x64", "linux-x64" ]
  server/windows-x64/your_plugin.dll
  server/linux-x64/libyour_plugin.so
Platform Library file
windows-x64 <library>.dll
linux-x64, linux-arm64 lib<library>.so
macos-x64, macos-arm64 lib<library>.dylib

To make one package from several builds:

  1. Build the plugin on each platform against the LonelyIce core of the same release, with that platform's toolchain (Plugin format).
  2. Copy each build's server/<platform>/ folder into one plugin folder.
  3. List exactly those platforms in platforms.
  4. Pack that folder once with LonelyIce.exe --pkg pack.

The upload fails with "Missing server build for …" when a listed platform has no library.

The launcher offers a package only on the platforms it lists. Adding a platform later means a new version, because a published version cannot change.

A plugin without server code (data, SQL, patch recipes, addons, settings only) has neither server nor platforms. The catalog reports "No server code: works with any core", and the launcher offers it everywhere. Do not list platforms without a library: the launcher then treats the package as server code and offers it only where core matches, so the catalog refuses the upload ("platforms without server").

Core ABI

core.abi names the binary interface your library was built against. lonelyice-ac-2 is the AC_PLUGIN_ABI of current LonelyIce releases. The LonelyIce build sets it (First plugin). C++ plugins share classes and the runtime with the core, so a library only works with the core it was compiled against. The ABI name is fixed per release and changes whenever a core change can break existing libraries (Plugin format).

The ABI is checked at every stage:

Where Check
Upload A plugin with server needs core.abi, and the value must be one the launcher releases use ("Core ABI … is not one the launcher releases use (lonelyice-ac-2)").
Catalog The launcher offers a package with platforms only when its core equals the launcher's own ABI.
Server start core.abi of the manifest, and the ABI and platform the library reports, must equal the server's. Otherwise the plugin is not loaded: built for core <abi>, this server is <abi>.

Do not edit core.abi by hand to make an old build load. The library reports its own ABI, and the server refuses the mismatch.

When the ABI changes

A LonelyIce release with a new ABI changes what players see:

  • Its launcher no longer offers packages built for the old ABI.
  • Installed plugins built for the old ABI are not loaded (built for core lonelyice-ac-1, this server is lonelyice-ac-2), and neither are the plugins that depend on them.
  • Players get your plugin back through Updates once you publish a rebuild.

To publish the rebuild:

  1. Update your build tree to the new LonelyIce release.
  2. Rebuild the plugin on every platform you ship.
  3. Set core.abi to the new name. The rebuilt libraries report it themselves.
  4. Raise version. The catalog refuses the same number, and launchers only offer strictly newer versions.
  5. Pack, upload and submit as usual (Publishing a package). Also rebuild and republish any dependency you own, first.

Older versions stay in the catalog's index. A launcher still on the old ABI keeps finding them and ignores the new one. A later fix for the old ABI would still need a number above the rebuild's, because every upload must be newer than the newest published version. The catalog also accepts it only while the old ABI is still listed as supported.

Languages

locales lists the languages your plugin's texts are translated into: chat and gossip texts, *_locale rows, localized strings in patch recipes, addons and launcher settings. The format is in Plugin format.

Code Language
en English
de German
es Spanish
fr French
ko Korean
ru Russian
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
* The plugin has no texts of its own (a database backend, a rule change). It matches every language.
Situation Effect
Unknown code The upload fails, and --pkg pack refuses it.
No locales Warning "plugin.json has no locales; a filter by language leaves the package out". Players who filter the catalog by language (Plugins page, --pkg available --locale, the catalog on this site) do not see the package.
Language with only a few texts translated Leave it out (Plugin format).

locales does not affect installation. A player can install a package in any language, and the launcher shows name and description in its own language, then en, then any. Give at least en in every localized string.