Guides › Development

What the catalog checks and reviewers look for

The steps

The workflow is in Publishing a package. This page covers what is checked at each step:

  1. Upload. You upload a zip on Publish a package. The site reads the zip and runs the automatic checks.
  2. Draft. If no check failed, the upload is kept as a draft. You add the source repository, the tag, the category and a changelog, then submit it.
  3. Review. A moderator reads the source at your tag, compares the files with your previous version, and decides.
  4. Publication. A published version appears in /packages/index.json. Its zip and icon are served next to the index and never change.

Before the checks run

The site refuses the upload outright in these cases:

Message Cause
"You have N submissions in review already. Wait for a decision first." Too many of your versions are In review.
"The file is larger than N MB." / "The file is too large or the upload broke off (limit N MB)." The size limit shown on the form.
"Choose a .zip file made with LonelyIce.exe --pkg pack." No file chosen.
"This is not a LonelyIce package: not a zip file." The file is not a zip.
"… too many files in the zip (N)." More than 20000 entries.
"… no plugin.json in the zip." No plugin.json at the root or in one top folder.
"… plugin.json is not valid JSON: …" Syntax errors, and also fields of the wrong type. For example, a depends value must be a string, core an object and platforms an array.

Automatic checks

Each check has a level. The page shows the level as a mark:

Mark Level Effect
OK ok The check passed.
INFO info A fact for the moderator.
WARN warn Does not stop the upload. The moderator sees it.
FAIL fail Stops the upload: "The package cannot be submitted yet. Fix the failed checks and upload it again."

In the messages below, … stands for the value from your package.

Manifest

Level Message Meaning
OK plugin.json is valid: id version
FAIL plugin.json has no id or version Both are required.
FAIL Package id "…" must be lowercase letters, digits, dots and dashes The id must be 2 to 64 characters of a-z 0-9 . - and start with a letter or digit.
FAIL The top folder "…" must be named after the id "…" The zip's single top folder must be the id, as --pkg pack writes it.
FAIL Version "…" must look like 1.2.3 Three numbers, digits only (Versions).
FAIL plugin.json has no "format"; the server refuses such a manifest. Add "format": 1 The server's plugin loader reads a missing format as 0 and skips the plugin (unsupported manifest format 0).
FAIL Unknown manifest format N; the server loads only format 1 The loader accepts exactly 1, the current format.
WARN plugin.json has no name; the catalog will show the id Add a localized name.
WARN plugin.json has no license Add a license, for example an SPDX identifier.
WARN plugin.json has no locales; a filter by language leaves the package out Add locales (Languages).
FAIL Unknown language "…" in locales (known: en, de, es, fr, ko, ru, zh-CN, zh-TW, or * for a plugin without texts) Use only those codes.

Files

Level Message Meaning
FAIL N file paths leave the plugin folder or are absolute Paths with .., a leading / or \, a : or a backslash.
FAIL N files are outside the plugin folder The zip has a top folder and also entries outside it.
FAIL Unpacked size is too large (N MB) More than 2 GB unpacked.

Server code

The site runs these checks on server and platforms. The launcher takes every package with platforms for server code and offers it only where core and the platform match, so platforms goes together with a server library.

Level Message Meaning
FAIL Unknown platform "…" (the core knows windows-x64, linux-x64, linux-arm64, macos-x64, macos-arm64) Each entry of platforms must be one of the platforms the core's plugin loader knows (AC_PLUGIN_PLATFORM).
FAIL A plugin with server code needs core.abi Add "core": { "abi": "lonelyice-ac-2" }.
FAIL A plugin with server code needs platforms List the platforms you ship.
OK Server build for platform: server/platform/file The library is where the loader looks.
FAIL Missing server build for platform: server/platform/file No library there. The file is <library>.dll on Windows and lib<library>.so / lib<library>.dylib elsewhere, with <library> from server.library.
FAIL platforms without server: … platforms without a server object. The launcher would hide the package everywhere its core does not match (and without core, everywhere). A plugin without a server library leaves platforms out.
INFO No server code: works with any core No server and no platforms.

Contents

Level Message Meaning
INFO Native code: N libraries — read the source at the tag Counts .dll, .so, .dylib and .exe files.
INFO N SQL files Counts .sql files.
INFO N client files (addons, patch files) Counts files under client/.
FAIL Contains game client archives (.MPQ) The package contains an .MPQ file. Remove it.
WARN Contains N files that look like extracted client data (DBC, maps, models); client changes go through patch recipes Counts .dbc, .adt, .wdt, .wmo, .m2, .skin, .vmtree, .vmtile, .mmap and .mmtile files. Change game data with patch recipes.
OK No game client archives or extracted client data
WARN No icon.png — the catalog shows a letter instead No PNG named icon.png in the plugin folder.
INFO No icon.png — the icon of version is kept Replaces the warning when your published version has an icon.

Catalog

These checks compare the upload with the catalog.

Level Message Meaning
OK … is a new package id; it will be yours The first upload claims the id.
WARN Third-party ids are usually author.feature (reverse-domain style) A new id without a dot.
FAIL … belongs to …; only its owner can publish new versions Someone else owns the id.
OK You can publish … You own the id.
FAIL Could not check the package id, try again later A server problem. Upload again.
FAIL Version … is not newer than … in the catalog; every upload needs a new version number, also a rebuild for another core ABI or with more platforms Compared with the newest published version, not counting hidden ones. The catalog keeps one package per version number, so the same version cannot be published again for another ABI or with other platforms.
OK Version … is newer than …
FAIL Version … is already in review; withdraw it first, or use a new version This version is already In review.
FAIL Version … was published and is hidden; every upload needs a new version number, … A hidden (yanked) version keeps its number.
OK / FAIL Core ABI … is supported / Core ABI … is not one the launcher releases use (…) Runs whenever core.abi is set. The accepted list is currently lonelyice-ac-2.
OK Dependency id range: version in the catalog fits The newest published version in the range that a launcher can install next to your package.
FAIL Dependency … is not in the catalog Every depends id needs a published version here. Publish your dependencies first.
FAIL Dependency id "…": unknown range syntax: … The range is not one the launcher reads (see below). `
FAIL Dependency id range: no published version is in this range (the catalog has …) The dependency is published, but no published version fits the range. Hidden versions do not count.
FAIL Dependency id range: no version in this range is built for abi on platforms (in range: …) Your package has server code: for each of its platforms, some version in the range must have no server code or be built for your core.abi and that platform, or the launcher on that platform cannot install the dependency.
FAIL Dependency id range: no version in this range is built for a core the launcher releases use (in range: …) Your package has no server code, and every version in the range is built for a core ABI no longer supported.

Ranges are read the way the launcher reads them. Comparators separated by spaces or commas must all hold; there is no ||.

Range Means
* (or empty) any version
1.2.3, =1.2.3 exactly 1.2.3
1.2, 1.2.x >=1.2.0 <1.3.0
1, 1.x >=1.0.0 <2.0.0
>=1.2 >=1.2.0
>1.2.3 / >1.2 newer than 1.2.3 / >=1.3.0
<1.2 <1.2.0
<=1.2 <1.3.0 (every 1.2.x is included)
~1.2.3 / ~1.2 / ~1 >=1.2.3 <1.3.0 / >=1.2.0 <1.3.0 / >=1.0.0 <2.0.0
^1.2.3 / ^0.2.3 / ^0.0.3 >=1.2.3 <2.0.0 / >=0.2.3 <0.3.0 / >=0.0.3 <0.0.4
>=1.2.0 <2.0.0, >=1.2.0,<2.0.0 both conditions

No check reads conflicts, a LICENSE file, README.md or the source repository. Moderators look at those.

The draft

A draft shows what the site found: id, version, the version in the catalog, name, description, core ABI, platforms, languages, dependencies, file count and SHA-256. It also shows the checks. An upload you never submit is deleted after a day, together with an id that only that upload had claimed.

Field Prefilled with Refused with
Repository The repository given with the id's previous submission (or stored for the id). Otherwise homepage when it is a repository on github.com, gitlab.com or codeberg.org. Never source.repo: for a wrapped module that is the module, not your wrapper, and a previous repository or homepage equal to it is skipped too, leaving the field empty. "Give the https address of the public repository, e.g. https://github.com/you/your-plugin". It must be an https address with at least an owner and a name.
Tag or commit v<version> (never source.commit, the wrapped module's commit) "Give the tag or commit the zip was built from". It must be non-empty, at most 128 characters, with no spaces.
Category The id's category, or Other "Choose a category". It must be one of Bots, Gameplay, Economy, Interface and client, Data storage, Tools, Other.
What changed "Keep it under 5000 characters". Markdown is allowed.
Rights checkbox: "The source is public, and I may publish it under its license" "Confirm that the source is public and you may publish it"

Submit for review moves the draft to In review. Discard upload deletes it.

What reviewers look at

The moderation page shows a submission with:

Section What the moderator sees
Header The id and version, the submitter, and whether this is a new package or an update from a version. It links to the source at your tag (/tree/<tag>) and has Download zip. On GitHub it also has Compare with previous version, a compare view between the previous version's tag and yours.
Automatic checks The same list you saw, with its warnings.
Files compared with the previous version Every added (+), changed (~) and removed (−) file against the newest published version, and a count of unchanged ones. A file counts as changed when its size or CRC differs. Libraries are tagged native code and .sql files SQL.
Changelog Your "What changed".
Author Your GitHub login, member since, number of published and rejected versions.
Package Owner, category, the version in the catalog, downloads.
Manifest Core ABI, platforms, languages, dependencies, license, size.

The site states these rules on the publish pages:

  • Open source only. The code at the tag must build into the files you upload.
  • No game client files. Client changes go through patch recipes.
  • No ads, telemetry or code downloaded at run time.
  • One id per plugin. Third parties use author.feature.

The source link, the compare link and the file comparison are what a moderator uses to check the first rule. Keep a version's changes visible between two tags.

Decisions

A moderator picks one of three decisions. The decision form also has a Category field, preset to the category you chose. The moderator's choice wins: it is stored with the decision and becomes the package's category, whichever decision is taken, so a resubmission starts from it.

Button Status What happens
Approve and publish Published The zip and icon go public, and the version enters the index. The package's repository is taken from this submission, and its category is the one on the decision form.
Request changes Changes requested A note tells you what to change. Upload a fixed zip of the same version and submit it again ("Submit again" on your submissions), and the earlier submission is closed.
Reject Rejected A note gives the reason. The version will not be published.

A note is required for Request changes and Reject. Notes are shown under the submission on Your packages → Submissions.

Status Meaning
Draft Uploaded, not submitted. Only you see it.
In review Waiting for a moderator. Withdraw takes it back.
Changes requested Fix it and upload the same version again (Submit again), or Withdraw it.
Rejected Not published.
Withdrawn Taken back by you, or closed by a resubmission.
Published In the catalog and the index.
Hidden Yanked.

Yank. A moderator can Hide a published version on the package's Versions tab, and Show brings it back. A hidden version is left out of index.json, so launchers stop offering it. Its zip stays downloadable, and players who installed it keep it, because the launcher offers only newer versions. The number of a hidden version cannot be submitted again, so publish a fix as a new version. The owner and moderators still see hidden versions on the Versions tab.

Checklist before you upload

Items marked Required are enforced by a check, stated as a rule on the publish pages, or needed for the package to work in the launcher and the server. The others are recommended.

Item
Required plugin.json has "format": 1, a lowercase id, and an x.y.z version newer than your last published one.
Required The zip is made with LonelyIce.exe --pkg pack and not repacked by hand, so the top folder is the id and the debug and link files (.pdb, .ilk, .exp, .lib, .a) are left out.
Required With server code: core.abi is lonelyice-ac-2, and platforms lists exactly the server/<platform>/ builds in the zip, each one of windows-x64, linux-x64, linux-arm64, macos-x64, macos-arm64 (Multi-platform packages).
Required Without server code: no server and no platforms (platforms alone fails the upload).
Required Every depends range is valid launcher syntax, and this catalog has a published version in it, built for your core ABI and each of your platforms (or without server code).
Required No .MPQ files. locales uses only known codes.
Required The source is in a public repository, and the tag you give builds into the uploaded files.
Recommended A license in plugin.json, and the license text as LICENSE in the plugin folder (it is part of the package layout).
Recommended A 64×64 icon.png in the plugin folder.
Recommended A README.md in the plugin folder. It becomes the package page's overview (up to 256 KB of Markdown, raw HTML is dropped). Without it the page shows the description.
Recommended name and description localized with at least en, and locales for the languages you really translated.
Recommended homepage pointing at the repository the zip is built from, so the draft form is prefilled on the first upload (later uploads reuse the repository of the previous submission).
Recommended A tag named v<version> pushed before you submit.
Recommended No extracted client data (DBC, maps, models). Use patch recipes.
Recommended Install the packed zip from a local catalog and start the server once, so you know it loads (Debugging plugins).