Skip to content
Project X

Developer docs

Versioning

Three version numbers meet in a script. Mixing them up is the usual reason a script will not load, so it is worth five minutes.

The three numbers

NumberWhat it isNowWhere you set it
Client releaseWhat the client is called. Changes with every client update.1.0.79projectxClientVersion
Plugin API levelWhat the client offers scripts. Changes only when the API changes.2.7.0minClientVersion
Your script's versionYour build. Must change with every upload.yoursversion

The client release and the plugin API level are separate on purpose: the client was renumbered to 1.x without its API changing, and tying them together would have made every existing script incompatible.

minClientVersion

@PluginDescriptor(
        name = "My Cool Script",
        version = MyCoolPlugin.version,
        minClientVersion = "2.7.0",
        isExternal = true
)

Set it to the plugin API level that added the newest thing your script uses. A script written with the simple API (the bot package) needs 2.7.0, which first shipped in client 1.0.79:

Plugin APIFirst clientAdded
2.6.251.0.31ScriptPanel, ScriptPanelOverlay, SkillTracker
2.6.291.0.47ProjectX.withDirectInput, Prayers.flick, Prayers.flickQuickPrayer
2.6.301.0.49BoatNavigator; Walker.walkTo sails to targets at sea
2.6.311.0.56Script.reliability() and the util.reliability package
2.7.01.0.79The simple API: the bot package (Inventory, Objects.query(), Loadout and the rest)

The check compares numbers part by part, so 2.7.0 is newer than 2.6.9. Never put a client release such as 1.0.79 here: as an API level it is lower than anything the client offers, so it checks nothing. And isExternal = true must be set, or the check is skipped entirely.

When a player's client is too old

  • The client refuses to load the script and logs Plugin MyCoolPlugin needs plugin API 2.7.0 or higher; this client provides 2.6.31.
  • The plugin hub refuses to install it and asks the player to update their client.

The launcher keeps players on the latest client, so this mostly affects players who have not restarted in a while. Even so, do not raise minClientVersion further than you need.

A script that calls something newer than its minClientVersion loads on an older client and then fails with a NoSuchMethodError or NoClassDefFoundError the moment it reaches that call. Raising the number is what turns that crash into a clear refusal.

Building against the right client

projectxClientVersion in gradle.properties says which client jar you compile against. It has no effect on which clients can run your script, but it matters: ids such as ItemID, ObjectID and InterfaceID values are compile-time constants, and the compiler copies their values into your classes. Built against an old client, your jar carries the old values forever, even on a new client. After a client release that changes ids, bump the version, rebuild and upload. Releases are listed on GitHub.

Your script's version

Bump version in the descriptor for every build you upload. The store accepts each version once, and the client uses it to tell that a player's copy is out of date. Keep the constant you show in the stats panel and the one in the descriptor the same; the template uses one static final String for both.