Running a server
Configuration
The settings live in plugins/RPEngine/config.yml, which the plugin writes
the first time it starts. Every setting has a working default. Many settings
apply on /rp reload; restart the server to be sure a change has taken effect.
When an update adds a setting your file should show you, RP Engine writes it
into your config.yml on the next start, explanation and all, without touching
anything else in the file. The old file is kept beside it as
config.yml.v<number>.bak, and the console says what changed.
Serving the pack#
host:
mode: upload
port: 8181
public-address: "http://127.0.0.1:8181"A player's game downloads a pack over HTTP, from a link the server sends it.
host.mode decides where that link points:
| Mode | How it works | Use it when |
|---|---|---|
upload (default) | Each pack is uploaded to ResourcePack AI's pack host (packs.resourcepack.ai), free, and players download it from there. A pack is only uploaded again when it changes. | Almost always. Nothing to open or configure, and it works behind a proxy and on any host. |
same-port | Your server serves the packs itself, on its Minecraft port. | You want nothing to leave your machine, and players connect to this server directly. |
own-port | Your server serves the packs itself, on a second port. | You want nothing to leave your machine and you run a proxy (Velocity, BungeeCord). You have to open the port and set the address. |
none | Packs are built into output/ but not served. | You host the zips yourself (a CDN, a web server). |
With upload, your packs are stored on our servers for as long as your
server uses them: one nothing has touched for 30 days is deleted, and only the
Minecraft client can download them. A pack can be at most 95 MB.
same-port does not work behind a proxy, because a proxy only passes
Minecraft through. The link it sends each player uses the address that player
joined with, so there is nothing to configure.
own-port uses the two other keys:
| Key | Default | What it does |
|---|---|---|
host.port | 8181 | The port it listens on. 0 picks a free one, which is only useful for testing |
host.public-address | http://127.0.0.1:8181 | The address a player's game downloads the pack from. Set it to your server's public IP or hostname and the port above, and open that port (on a hosting panel, allocate it to your server). The plugin cannot work this out itself behind a proxy or NAT |
With upload you can also keep a copy served from your own server, for any
player whose game cannot reach the pack host (a school or work network that
blocks it, say). Set host.fallback-on-download-failure: true along with
host.port and host.public-address as for own-port, and open that port.
A player whose download fails is sent your server's link instead, and so is
everybody while an upload is failing. It is read at startup.
An older config with public-address set and no host.mode stays on
own-port, and host.enabled: false means none.
When a player's game cannot download a pack, the console says which link it
was sent and what to check, once per restart. /rp bundles shows the link
each bundle is served at.
If the upload fails#
The console says
Could not upload main to the pack host (reason), so this server is serving it on its game port instead.
The reason in brackets says what went wrong. Usually it is one of:
- Your host blocks outgoing connections. The server has to reach
https://packs.resourcepack.ai. Ask your host to allow it, or serve the pack yourself (below). - The pack is over 95 MB. Make it smaller, or serve it yourself.
RP Engine tries the upload again on /rp reload, on a restart and every six
hours. Until then, players are sent the pack from your game port, which works
when they connect to this server directly.
Behind Velocity or BungeeCord the game port cannot serve a pack, because a
proxy only passes Minecraft through, so players get nothing until an upload
works. To be safe, set host.fallback-on-download-failure: true with a
host.port and host.public-address players can reach (open the port, or
allocate it on your hosting panel), or switch to host.mode: own-port and
skip the pack host entirely.
The pack and the join prompt#
pack:
description: "RP Engine"
# format: 46
default-bundle: "main"
prompt:
message: ""
force: false| Key | Default | What it does |
|---|---|---|
pack.description | RP Engine | Shown in the client's resource pack list, with the bundle name added |
pack.format | not set | Leave it unset; the plugin picks the right number for your version. Set it only when the startup log says your Minecraft is newer than this RP Engine, then update the plugin and remove it. See Minecraft versions |
default-bundle | main | The bundle every joining player is sent. Empty sends nothing, for a server that sends packs itself |
prompt.message | empty | Text shown when the client asks the player to accept the pack. Empty uses the game's own wording |
prompt.force | false | true disconnects a player who declines the pack |
How it talks#
chat:
icons: false
text-effects: true
prefix: "RPEngine"
colour:
prefix: "#3670f8"
brackets: "#555555"
body: "#aaaaaa"
accent: "#3670f8"
error: "#ff5555"
success: "#55ff55"Every line the plugin writes starts with [prefix], and the colours are
yours to change so it matches your server. accent colours names, counts and
codes, and the headings in /rp help. Colours are hex, with or without the
#; anything else falls back to the default.
Icons in chat#
chat.icons: true lets anybody with rpengine.chat.icons (every player, by
default) type :wave: in chat to draw the icon called
wave. Use :mypack:wave: where two packs use the same name. It is off by
default.
Text that is not an icon name is left exactly as typed, so 10:30, :) and
links are safe.
Text Effects in chat#
chat.text-effects: true (the default) lets players type
<fx:fire>hello</fx> in chat to write "hello" in the
Text Effect called fire. It needs
rpengine.chat.effects.all for every effect, or rpengine.chat.effects.<name>
for one, and both default to op. A tag somebody may not use stays as typed.
false turns it off for everybody.
Emotes#
emotes:
player-commands: true
bake-on-join: true
rigs: true
rig-days: 30
rig-players: 64
cast-permission: "rpengine.emote.cast"
nametag-see-through: false
held-item-pitch: 90.0
held-item-yaw: 0.0
held-item-roll: 0.0An emote plays on a rig: a copy of the player's skin, cut into parts, which is part of the pack.
| Key | Default | What it does |
|---|---|---|
player-commands | true | Registers /emote. Turn it off if another plugin already has /emote; /rp emote still works, and /emotereply is always registered |
rigs | true | Builds a rig for players who have joined, plus a shared default, so emotes and vehicle seats work without Studio. Needs Minecraft 1.21.4 or newer |
rig-days | 30 | Only players seen in this many days get a rig. Anybody else wears the default until they come back. 0 is no limit |
rig-players | 64 | The most players with a rig, newest first. Each is about 20 KB of every player's download. 0 is no limit |
bake-on-join | true | Rebuilds the rigs when somebody joins who has none yet. See below |
cast-permission | rpengine.emote.cast | The node needed to pull other players into an emote. Empty for no check |
nametag-see-through | false | Whether an emoting player's name shows through walls. Off, because a see-through name tends to vanish behind nearby models |
held-item-pitch, -yaw, -roll | 90, 0, 0 | Calibration for how a held item is turned in a rig's hand. You should not need these; if a held item looks wrong, please report it |
What bake-on-join does. A player the server has never seen has no rig,
so they appear as the default skin until the rigs are rebuilt. With this on,
the rebuild starts as soon as they join, and anybody else arriving within a few
seconds is covered by one follow-up build. Players who are already online are
not sent the new pack straight away (a new pack reloads their screen): they
get it the next time they are sent a pack anyway, such as on rejoining or with
/rp push. Until then they see the newcomer as the default. Turn it off to
choose the moment yourself; /rp reload always includes every rig that has
arrived.
Vanilla recipes#
items:
vanilla-recipes: falseWhether custom items count as the vanilla item they are made from in the
game's own recipes. Off, a tomato made from paper is not paper: it can't make
a book, cook in a furnace, go through a stonecutter or repair a tool on an
anvil. Your own recipes and other plugins' recipes work
either way. Set it to true to let every item in, or let in just one with
vanilla-recipes: true on the item.
Seats#
models:
seat-offset: 0.0Moves every seat on placed models up or down, in blocks. Positive is higher.
If everybody sits slightly too high or low on every chair, set the difference
here and /rp reload. You should not need it.
Vehicles#
vehicles:
seat-offset: 0.0
seat-forward: 0.0
debug-seats: false
push-players: false
collide: true
speedometer: true
mount-hint: true
seat-rig: true| Key | Default | What it does |
|---|---|---|
seat-offset | 0.0 | Moves every vehicle seat up (positive) or down, in blocks |
seat-forward | 0.0 | Moves every vehicle seat toward the front (positive) or back |
debug-seats | false | Once a second, reports where each rider actually ended up against where the plugin put them. For tracking down one seat that is out while others are fine |
push-players | false | Whether a moving vehicle shoves players out of the way. Mobs are always shoved, and vehicles always stop at walls |
collide | true | Whether vehicles bump into each other. The result depends on speed, angle and each vehicle's weight. Turn it off for a race track or a crowded car park |
speedometer | true | Shows the driver's speed above the hotbar in km/h, yellow while the tyres slide. A single vehicle can opt out; see the speedometer |
mount-hint | true | Tells somebody the controls once when they get in. Passengers are told which seat they took either way |
seat-rig | true | Shows occupants sitting or standing in their emote rig, even when the pack gives the seat no emote. Off shows ordinary players, which costs fewer entities on a full vehicle |
Which controls a vehicle uses depends on your server: Paper 1.21.4 and newer reads the movement keys, anything else steers by where the driver looks. See Minecraft versions.
Plants#
blocks:
tripwire-frozen: autoHow many plants fit depends on whether Paper has
frozen tripwire updates (block-updates.disable-tripwire-updates in
config/paper-global.yml): 32 if it has, 2 if not. auto reads Paper's
setting. true or false states it outright, for a server whose Paper config
lives somewhere else. Saying true when tripwire is not frozen makes
neighbouring plants turn into each other.
HUD overlays#
overlays:
refresh-ticks: 30 # 1 to 50
trigger-ticks: 2 # 1 to 20refresh-ticks is how often a HUD a player is wearing is re-sent, in ticks (20
a second). A value a plugin sets through the API is drawn on the next tick
whatever this says. This is for the placeholders the server works out itself,
like {health} and PlaceholderAPI's: lower makes those smoother, at one packet
per wearer per redraw. Above 50 the action bar starts to fade between redraws.
trigger-ticks is how often a HUD's state triggers, such as sneaking or
holding an item, are checked. 1 puts a HUD on or takes it off on the very tick
the player does the thing, for a minigame that needs it exact; 20 is once a
second. A check only sends a packet when the answer changes, so lowering it
costs very little.
VFX#
vfx:
max-sprites: 4000 # 0 for no limitHow many VFX sprites may be alive at once across the whole server. Each sprite is a display entity. When a new effect would go over it, the oldest effects playing end to make room, so a cast always plays. 4,000 is a few ms of tick time; see what it costs for measurements and what we recommend for busy and quiet servers.
Mob skills#
skills:
debug: falsedebug: true logs every skill line a custom mob runs, and
what it aimed at, to the console. It is for finding out why a skill did not
fire, and it is noisy, so leave it off otherwise.
Dialogs#
dialogs:
click-sound: "ui.button.click" # blank for none
click-volume: 0.25 # 0 to 1
click-pitch: 1.0 # 0.5 to 2A click on a dialog's picture makes no sound in the game, so the plugin plays this one. Any sound event works, the game's or one your pack adds. A Studio dialog can choose its own click sound, for the whole dialog or one piece, and that takes priority. A hand-written dialog can too:
shop:
json: shop.json
click-sound: { sound: block.note_block.chime, volume: 0.5, pitch: 1.5 }
click-sounds: # the clicks that run this command
- { command: "rp page mypack:shop.ranks", sound: entity.experience_orb.pickup }click-sound: "" silences a dialog's clicks.
Studio#
sync:
url: "wss://sync.resourcepack.ai/connect"
server-token: ""
edit:
enabled: true
url: "https://studio.resourcepack.ai"
distribution:
api-url: "https://studio.resourcepack.ai"
mode: contentNothing connects to Studio unless somebody runs /rp sync, /rp edit or
/rp distribute. Leave the URLs alone.
| Key | Default | What it does |
|---|---|---|
sync.server-token | empty | Only for a server the Studio account owner runs themselves. With a token, Studio can see who is online and push to them without a pairing code |
edit.enabled | true | false turns off /rp edit |
distribution.mode | content | Where a pack bound with /rp distribute goes. content keeps it in content/studio-<pack>/ and builds it into RP Engine's own pack. cdn sends it to each player on its own, the build for their version, and writes nothing to content/. Needs a restart |
Other plugins' shaders#
shaders:
merge: true
notify-players: trueSome plugins draw their HUD by replacing one of the game's core shaders, and the text shader is the usual one: BetterHud does, and so do Studio's HUD shader objects and the player heads in Studio dialogs. A player's game keeps only one copy of each core shader, from whichever pack is highest in their list, so without help only one of the two draws.
With merge: true, RP Engine reads the other plugin's pack from its folder,
combines its own text shader with theirs so both draw, and puts the result
inside its own pack. Players get no extra pack and no extra loading screen.
RP Engine's pack has to sit above the other plugin's, so when it has merged a shader, a joining player's packs wait up to three seconds for the other plugin's to arrive first. If it comes later than that, RP Engine sends its own again, on top. Some plugins (BetterHud among them) send theirs in a way that removes every other pack the player has, so without this RP Engine's would be gone.
The console says what happened, and so does chat for players with
rpengine.shaders.notify (ops), when it happens and when they join. Set
notify-players: false to keep it to the console:
- Merged: which plugin's shader, and on which Minecraft versions.
- Could not merge: which versions, and why. A plugin whose own shader cannot compile on a version gets this, because merging would only replace a working shader with a broken one. BetterHud 2.0.0 is one: its shader does not compile on 1.21.6 to 1.21.11, so update BetterHud.
- Shader clash: another core shader both packs replace. Only the text shader is merged, so for anything else, only one of the two draws.
RP Engine can merge its text shader with one other plugin's. If two other
plugins both replace it, it says so and merges neither. merge: false turns
merging off and leaves only the warnings.
Usage count#
telemetry:
enabled: trueEvery 30 seconds the plugin tells resourcepack.ai it is running, so we know
how many servers and players use RP Engine and its addons. It sends three
things: a random id it created the first time it started (kept in
plugins/RPEngine/server-id; delete the file and a new one is made), the
number of players online, and the names of installed plugins that depend on
RP Engine. No address, server name, version, player names or UUIDs, worlds or
content. A failed send is silently dropped.
enabled: false sends nothing at all, from the next restart.
Update check#
update-check: trueTells the console at startup, and players with rpengine.update (ops) when
they join, that a newer RP Engine is out.