Configuration
ShadowOptimizer
Find out what is eating your TPS, then do something about it.
Where the files are
plugins/ShadowOptimizer/ The plugin creates them on first start and updates them by itself on new versions, keeping your changes.
Applying changes
/sopt reload Reloads the files without restarting the server.
No setting found
Try another word, or search every plugin.
Settings
The files that decide how the plugin behaves. Start here.
config.yml
General settings 117 settings
config.ymlplugins/ShadowOptimizer/config.yml File notes
UPDATES: when a new version changes this file, it is moved to the new version for you. Everything you changed or added is carried over; the settings you never touched take the new defaults. Your previous file is kept in backup/<date>/, and if something could not be carried over (an option that no longer exists, a value of a different kind) you find it in PORTING-<version>.txt, with what to do.
A wrong value blocks nothing: it is replaced by the factory one and reported in the console at startup, with the path and what was expected.
Where things live:
config.yml this file
lang/*.yml the messages (updated the same way: the texts you
rewrote stay yours)
menus/*.yml the layout of the screens
health.yml written by us, read by the panel. Do not editconfig-version1core1 keyserver-id"auto"The name of this server in the TPS history.
Only matters when several servers write to the same MySQL: it is the column that keeps the graphs apart. "auto" uses the machine name and the port, which two servers on one machine cannot share.
The TPS monitor
One scheduled task, once a second, reading four numbers the server already keeps up to date on its own. The cost is indistinguishable from zero, and that is not a detail: a plugin that measures lag cannot afford to produce any.
monitor2 keyscount-every15How many samples between counting entities and chunks too.
This is the only read that costs anything: it means asking every world how many entities it holds. A count every fifteen seconds answers the same question as one every second and costs a fifteenth. Raise it if you have many worlds; there is no reason to lower it.
history-hours72How many hours of history to keep in the database.
One row per minute, so 1440 rows a day: 72 hours is a little over four thousand rows, which is nothing. Raise it if you want to answer "since when has it been getting worse?" over weeks instead of days.
The diagnostics
The part that answers the real question: not "how many TPS do I have" but "what are they depending on". It is also the only expensive thing this plugin does, which is why it does not do it continuously.
diagnostics5 keysbackground-scan-minutes5How many minutes between background scans.
It exists only so that whoever opens the GUI finds a report ready instead of a few seconds of waiting. Set 0 for none: on-demand scans keep working.
Note: cleanup.items.world-limit needs this above zero, because the per-world item count is refreshed by this scan and by nothing else.
chunks-per-tick48How many chunks to look at per tick.
The scan takes a few seconds instead of one tick, and that is on purpose. Raising it makes the scan faster and more noticeable: on a server already in trouble that is exactly the wrong trade.
max-chunks20000The hard ceiling of chunks to look at in one pass.
A network of ten worlds can have a hundred thousand chunks loaded. Past this number the scan stops: the first twenty thousand rows of a ranking contain the culprit anyway.
The budget is shared FAIRLY between worlds: each gets a slice, and whatever is left over goes to the ones that were cut. Otherwise the main world - always first in the list - would take the whole budget and the others would never be looked at at all.
entries25How many rows each ranking has. 25 is more than enough to find a culprit.
diagnostics.profiler3 keysThe sampler: which plugin is eating the tick.
This is the feature no free anti-lag has, and it works by looking ten times a second at WHERE the thread running the game currently is. It is not a stopwatch wrapped around other plugins' events: that road is invasive, it breaks when Paper renames a private field, and it costs the most exactly when the server is already struggling.
enabledtruesample-interval-ms100How many milliseconds between looks.
100 means ten samples a second, so 36,000 in an hour: enough for the percentages to be stable. Lowering it makes the estimate finer and starts to cost; raising it makes it noisy.
tick-thread-names["Server thread", "Region Scheduler", Folia]The names of the threads that run the game.
Only worth touching on an exotic server build that names them differently. The comparison is "the name starts with".
Cleanup
Here is the difference from ClearLag, and there is only one: IT MERGES FIRST. Forty stacks of cobble on the ground become five full stacks, and the cobble is still there. Only what is genuinely left useless gets removed, with a warning that can be seen.
Keep reading
NEVER removed: anything with a name, a tamed animal, a mob wearing equipment, anyone inside or riding a vehicle, anything the game itself marked persistent, anything on a lead, a villager somebody has traded with, and no armour stand, painting or item frame - somebody built a decoration out of those. And nothing carrying another plugin's data.
cleanup11 keysenabledtrueinterval-minutes15How many minutes between passes.
broadcasttrueWhether to announce the warning and the result in chat.
Leave it on. Half the staff reports on a server running an anti-lag come from things vanishing without notice, and a warning nobody sees is not a warning.
warning-seconds[60, 30, 10]How many seconds ahead to warn. The pass starts after the last one.
Keep reading
One entry per warning, in seconds before the pass. Put as many or as few as you like and at whatever spacing: [30] is a single warning half a minute ahead, [120, 20] is two, [60, 30, 10] is what ships.
An EMPTY list means no warning at all, and the pass runs silently. That is a legitimate choice on a server where cleanup never takes anything anyone cares about. Deleting the key instead brings back the three factory values - the empty list and the missing key are two different things on purpose.
Whatever you choose here, the RESULT is always announced when a warning was given, even when nothing was removed. Counting down three times and then going quiet leaves whoever read it wondering whether their things are still there, which is the question the warning existed to remove.
A warning longer than cleanup.interval-minutes would arrive before the previous pass: the plugin says so in the console and leaves it be.
chunks-per-tick32How many chunks to handle per tick.
exempt-worlds[ ]Worlds cleanup never enters.
This is the ONLY thing that switches cleanup off for a world: leave it empty and every loaded world is covered, the ones other plugins create at runtime included.
ShadowGames arenas exclude themselves while a match is running: there is no need to list them here.
foreign-metadata-keys[MythicMob, shopkeeper, NPC, citizens-npc, supplierNPC, pet, MyPet, quest_mob]+5
Other plugins' metadata that marks an entity as "theirs".
The PersistentDataContainer and the scoreboard tags can be enumerated and are always checked. Bukkit metadata cannot: the interface only lets you ask for a key by name. Hence this list, which grows without recompiling. It is the least elegant part of the plugin and it is the best the API allows.
ignored-data-keys[ ]Other plugins' data that does NOT make an entity "theirs".
Some plugins write a note on ordinary mobs just to remember how they were born (a spawn egg, a spawner) - ShadowBattlePass and ShadowQuests do it so that kills of farm mobs don't count. Those mobs are still ordinary mobs and the cleanup removes them: the two keys of the suite are always in this list, add here the ones of other plugins that do the same. Format: namespace:key, as /data get entity shows it.
cleanup.items4 keysmergetrueMerge before removing. This is the step that makes the plugin different from every other one: switch it off and it becomes a ClearLag.
removetrueRemove the items on the ground: ALL of them, however fresh, except
- the materials in never-remove below (plus the factory list), - items that carry another plugin's data: crate keys, vouchers, custom items (they are recognised by that data, nothing to list).
A name written on an item does not save it. The countdown before the pass (warning-seconds) is the warning to pick things up.
world-limit600How many ground items to tolerate in ONE world before stepping in right away. Zero switches the threshold off.
Keep reading
The interval above is meant for the normal case: every so many minutes we walk through and tidy up. It is worth nothing when a world fills up in two minutes - a farm that breaks, somebody emptying a double chest, a generator left running - because there the problem starts and does its damage inside a single interval, and by the end of the round the server has already spent ten minutes dropping twenty thousand items.
With this threshold the world that is drowning gets served at once, and ON ITS OWN: the pass is limited to that world, the others pay nothing. Whoever is there gets a warning a few seconds ahead; anyone elsewhere is not disturbed at all.
The rules do not change: it still merges first, and still removes only what would have been removed anyway. A low threshold does not make cleanup more aggressive, it makes it more timely.
The count comes from the background scan, so this threshold needs diagnostics.background-scan-minutes above zero. If that is zero the plugin writes it in the console and switches this off, instead of leaving it here doing nothing.
600 is on by default and deliberately high: a healthy world never gets there, so this only fires when something has actually gone wrong - a farm that broke, a generator left running. Lower it if your worlds are small, set 0 to switch it off.
never-remove[BEACON, CONDUIT, HEART_OF_THE_SEA]Materials never removed, however old.
This list is ADDED to the factory one, which already holds netherite, elytra, totems, the dragon egg, beacons, enchanted golden apples, nether stars and every shulker box.
cleanup.mobs5 keysremovetrueRemove the mobs: ALL of them - natural, from spawn eggs, from spawners - wherever they are and whoever is near, except
- the types in never-remove below (plus the factory list: animals people breed, villagers, golems, bosses...), - mobs with a name tag, tamed, on a leash, in a vehicle, - other plugins' mobs (their data, or foreign-metadata-keys above).
only-hostilefalseLimit removal to hostile mobs.
OFF by default, because there is now something better: the list below. "Hostiles only" is wrong in two directions. It leaves out bats and squid, which are not hostile and which nobody breeds: on a server with an ocean those are thousands of untouchable entities. And it does not tell a cow from a villager, which are both passive and have nothing else in common.
Turn it on only if you prefer the blunt rule to the precise one.
never-remove[ ]Mob types NEVER removed, however old.
Keep reading
This list answers one question only: did somebody spend time on it? Animals get bred, villagers get traded with, golems get built, bosses get summoned once. Everything else comes back on its own the following night.
This list is ADDED to the factory one, which already holds every breedable and tameable animal, villagers, wandering traders, golems and the four bosses. Add here only what you need on top, for example another plugin's custom mob.
replace-defaultsfalseSet true to NOT start from the factory list.
For anyone who wants to take something OFF that list - for example to clean cows too, on a server where nobody breeds. It has to be said on purpose: deleting somebody's livestock by accident is exactly the defect this plugin exists in order not to have.
max-per-type{ }How many mobs of ONE precise type to tolerate in a world.
Keep reading
This is the valve that makes protecting animals safe. Cows are never touched, fine - but ten thousand cows in a world is a server problem, not livestock. With a ceiling, the excess above that number becomes removable again, and the rest does not.
It applies to the types protected by the list above TOO, and it is the only thing that overrides them. It does not override the three safety rules: a mob with a player nearby, or too young, or in an excluded world is still left alone. The cows of a farm the owner is standing in stay where they are, and get thinned out once they leave.
Zero is legitimate and means "I want none of these in this world". Empty - as it is now - means no ceiling at all.
Example:
max-per-type: COW: 60 SHEEP: 60 CHICKEN: 40 IRON_GOLEM: 20
cleanup.projectiles2 keysremovetrueArrows and the like with no owner left.
min-age-seconds60Spawn caps
How many of each creature a chunk may hold. The per-chunk limits below count everything together; this looks at the KIND. A preset gives a ceiling per family - hostile, animal, water, ambient, other - and any single type can have its own number on top.
Keep reading
NORMAL is the game as it is, with a ceiling that stops the one farm that would have brought the server down. HIGH is for a machine with room to spare, MEDIUM and LOW squeeze harder when the server starts to feel a hundred players.
Caps apply on the way in: nothing that exists is removed, the next one is not born. Eggs, breeding, commands and what other plugins spawn on purpose are never counted or refused - the cap is for what the world spawns by itself, which is the only spawning nobody asked for.
spawn-caps5 keysenabledtruepresetNORMALHIGH | NORMAL | MEDIUM | LOW, or the name of a preset you write below.
spawn-caps.presets1 keyPer family, per chunk. -1 = no cap. The built-in numbers, for the record:
HIGH hostile 28, animal 24, water 20, ambient 14, other 28 NORMAL hostile 18, animal 16, water 14, ambient 10, other 18 MEDIUM hostile 12, animal 12, water 10, ambient 7, other 12 LOW hostile 7, animal 8, water 6, ambient 4, other 7
Write a preset here to change its numbers, or invent a new one.
spawn-caps.presets.CUSTOM5 keyshostile18animal16water14ambient10other18spawn-capsper-typeOne entity type, its own cap, whatever the preset says (-1 = none).
ZOMBIE: 10
COW: 24
count-cache-ms1000How long a chunk's count is trusted before it is counted again.
Per-chunk limits
A world with twenty thousand entities spread out causes no trouble at all. The same world with twenty thousand entities inside three chunks is unplayable. The chunk is the right unit because it is the unit the game itself thinks in.
Keep reading
Limits APPLY ON THE WAY IN: what is already there stays. Whoever built a farm of a thousand chickens keeps it; the thousand-and-first chicken simply is not born.
limits12 keysenabledtruemax-entities300-1 on any entry means "no limit".
max-mobs200max-items200max-hoppers64Hoppers.
They are the most expensive thing a player can build without noticing: each one checks every tick whether there is something to move above it, even when it is empty and even when nobody is around.
Over the limit they are NOT blocked: they are slowed down. Blocking them would break somebody's farm without touching a single block; slowing them leaves it working, just slower.
hopper-slowdown4One transfer in how many gets through, over the limit.
count-cache-ms1000How many milliseconds to reuse a chunk's count for.
Counting a chunk's entities on every spawn means counting them twenty times a second for the same chunk. One second is short enough for the limit to work and enormous compared to how often spawns happen.
hopper-cache-ms30000The same, for hoppers. Nobody places forty a second.
compact-every-ms2000At most how often to compact the items of a chunk that went past max-items.
The item limit never cancels anything: when a chunk is over the threshold, the identical stacks already there are merged and the new item is born anyway. On a farm producing without pause, without this ceiling it would compact dozens of times a second - which would make the anti-lag plugin the thing producing the lag.
warn-stafftrueWhether to tell anyone holding shadowoptimizer.notify in chat when a chunk reaches its limit. The message has a cooldown of its own, declared in the language file.
Different limits per world
One section per world. Values you leave out are inherited from the general ones above: change one without copying the others.
limitsworldsThe section name is the world name. If it matches no loaded world, you find it written in the console at startup with the exact path: the section is still read and simply never matches anything, which is how a typo here manages to go unnoticed for months.
The check runs once the server is up and not during our own startup, because a world manager loads its worlds after us: warning earlier would mean warning about worlds that are on their way.
Example: the minigame arena, where nothing should spawn.
arena: max-mobs: 0 max-items: 500
Example: the spawn, where no mobs are needed.
spawn: max-mobs: 20
Different limits per region
Needs ShadowRegions or WorldGuard. The id is the region's, in lowercase. A region always beats a world.
With no region plugin installed these sections never fire, and that is said in the console once.
limitsregionspublic_farm: max-mobs: 500 max-hoppers: 200
The emergency brake
/<command> panic [minutes]. It does not fix the problem: it buys time. It switches off the three things that can make the situation worse on their own, without any player doing anything.
The event handlers are registered only while panic is on: on a normal server this section costs exactly zero.
panic4 keysdefault-minutes5How many minutes it lasts when you do not say.
stop-explosionstrueChain explosions.
stop-redstonetrueRedstone. This is a big thing to do to a server, which is why panic is switched on by hand, lasts a few minutes and is announced in chat.
stop-natural-spawntrueNatural spawning and spawner spawning. Eggs, commands, breeding and plugins keep working: those are things a player asked for, and blocking them would make the server look broken.
Stacking
Mobs of the same type that end up near each other become a single entity with a counter above its head. Fifty zombies in a chunk become one entity: the cost to the server is one fiftieth, and the fifty zombies are all still there, in count and in loot.
Keep reading
They split when hit: the blow never reaches the stack, a single mob comes out of it and that is the one that takes it. Loot, experience and quests therefore work as if the stack were not there.
stacking3 keysstacking.entities11 keysenabledtruemax-size100Up to how many mobs in one stack.
The ceiling is not for the server: it is for the player. Killing a stack of a thousand means a thousand hits on the same spot, and at that point the farm is not playable any more.
radius6.0Within how many blocks to look for a partner.
Small on purpose. A large radius merges mobs the player sees as separate - the one in front and the one round the corner - and what it feels like is monsters "disappearing".
show-counter-from2From how many upwards to write the counter above the head.
name-format"<gray>x<count> <white><type>"How the counter is written. MiniMessage format. Players read this, so it may stay in the server language.
same-age-onlytrueA baby does not join a stack of adults.
same-name-onlytrueTwo mobs with different names never merge. A name is how a player says "this one is mine".
never-stack[COW, MOOSHROOM, SHEEP, PIG, CHICKEN, RABBIT, GOAT, BEE, HORSE, DONKEY, MULE, LLAMA, TRADER_LLAMA, CAMEL, STRIDER, TURTLE, AXOLOTL, FROG, TADPOLE, SNIFFER, ARMADILLO, PANDA, FOX, OCELOT, POLAR_BEAR, HOGLIN, WOLF, CAT, P …+51
Types that never stack.
Keep reading
The question here is a different one from cleanup: not "did somebody spend time on it", but "is it interacted with one at a time?". A stack is one thing with a number above its head: perfect for a swarm of zombies, which you just hit.
It is no good at all for breeding, and that is the glaring case: TWO COWS MERGED INTO ONE DO NOT MATE. You hand over the wheat, you feed one of them, and the player is left wondering why it does not work - with no message, because as far as the game is concerned nothing strange happened.
This list is ADDED to the factory one, which excludes everything that gets bred, tamed, traded with or summoned once. Monsters, fish and bats stay stackable, and those are exactly the ones that pile up in their thousands: all of stacking's gain and none of its damage.
There is no need to list other plugins' mobs: an entity carrying somebody else's data is never touched, regardless.
The list below is written out in full on purpose: what the plugin protects has to be readable without opening the jar. Adding a line protects one more type; DELETING a line does not unprotect anything, because the same list is built into the plugin - for that, set replace-defaults to true just below.
People breed these. Two cows merged into one do not mate.
People tame these: they have an owner and a name.
People trade with these, or build them.
Summoned once.
Not creatures, so they would never reach the stacker anyway - but the list is here to be read, and a boat or a minecart with somebody's things inside is just as out of the question.
Everything NOT on that list stacks, hostile or not: bats, squid, fish and every monster. Those are also exactly the ones that pile up in their thousands, so that is where the whole gain is.
replace-defaultsfalseSet true to NOT start from the factory list.
This is the switch that makes the list above the only truth, and it is the only way to REMOVE a type from it - for example to stack cows too, on a server where nobody breeds. It has to stay an explicit choice: whoever flips it without knowing finds out from the players, not from the log.
worlds[ ]Worlds where mob stacking applies. Empty means all of them.
also-stack-from[SPAWNER_EGG, DISPENSE_EGG]Spawns that were "wanted" and stack anyway.
Keep reading
Natural spawns, raids and reinforcements always stack. Mobs born from a command, a plugin, breeding or a thrown chicken egg never do: those are single on purpose. In between sit the spawn eggs - the thing a farm is built with - and a creeper farm that does not stack is the exact load this plugin exists to remove. So the eggs are in by default. Leave this line out to keep that; write the list to choose for yourself (an empty list means eggs stay single too). Values are the game's spawn reasons: SPAWNER_EGG, DISPENSE_EGG, COMMAND, CUSTOM, BREEDING, EGG.
stacking.items7 keysenabledtruemax-amount4096Up to how many units in one pile.
High, because here there is nobody to keep entertained: 4096 cobble in a single entity is 64 fewer entities and nobody notices.
Do not raise it to a million: if you ever uninstall the plugin, the piles stay as ordinary items with their VISIBLE amount, and the excess is lost. At this value what gets lost is cobble.
radius3.0show-counter-from2From how many units the counter is written above the pile. 2 means every pile that is more than one thing says how many it is - a dropped stack of 32 too, not only a pile that outgrew 64.
name-format"<gray>x<count> <white><item>"never-stack[ ]Materials that never merge.
There is no need to list items with different enchantments or names: the comparison is the game's own and looks at every component. Two swords with different enchantments never merge, and there is no option here that could change that.
worlds[ ]stacking.drops4 keysper-tick24How many drops to deliver per tick.
A stack of fifty skeletons dying all at once produces two hundred and fifty entities. Spawning them in the same tick would be the problem this plugin solves, caused by the plugin itself.
max-queued20000The queue ceiling. If something kills ten thousand mobs in one command, losing drops beats filling memory. It is written in the console when it happens, and it has never happened for a legitimate reason.
max-multiplier500The maximum loot multiplier for a stack that dies all at once. That only happens when something bypasses damage: /kill, the void, a plugin removing entities.
multiply-experiencetrueWhether to multiply experience too.
Direct pickup - what a block drops goes into the bag, not on the floor
direct-pickup5 keysEvery dropped item is a real entity: it is born, it is sent to every player nearby, it falls, it looks for other piles to merge with, it gets chased, and then it dies. Over a mining session that is thousands of entities appearing and disappearing to deliver things that were going into that same inventory anyway. With this on they are never born at all.
Keep reading
It is off by default on purpose. It changes how the game feels, and a performance plugin does not get to make that call for the person who owns the server.
What does NOT change: nothing is ever destroyed. Whatever does not fit in the inventory falls on the ground exactly as it always has.
Blocks whose drops another plugin has taken over - ShadowCustomizer's custom blocks, for one - keep dropping on the floor. That is not an oversight: the alternative is collecting them twice.
enabledfalseworlds[ ]Only in these worlds. Empty = everywhere.
never-collect[ ]Materials that always fall on the ground, even with this on.
The case this exists for is a block whose drop is the point of the animation - something you want to see land.
permission''Who gets it. Empty = everybody.
Fill it in and it becomes a rank perk: "shadowoptimizer.pickup".
creative-toofalseIn creative you already have everything, so by default this does not apply there: it only fills the bag with rubbish.
Safe drop - the first Q asks, the second one throws
Q is next to W
A netherite pickaxe with Fortune III going into the void while running is not a rare slip: it is the most common way to lose hours of play on any server, and there is nothing to be done afterwards - the item is gone and nobody brings it back.
Keep reading
With this on, the first press throws nothing: it warns. The second one, within a few seconds, throws for real. Anyone who means it presses twice and never notices; anyone who brushed the key while running still has the tool in hand.
The confirmation belongs to THAT item, not to the player: confirming the pickaxe does not leave the sword unprotected for a few seconds - which would be a protection that switches off exactly while somebody is hammering Q in a hurry.
It does not protect against everything and does not pretend to: death, a full inventory and plugins that throw things on your behalf are other roads and stay open. This covers the one walked every day.
safe-drop8 keysenabledtrueOn for everybody. A player who does not want it turns it off for themselves with /safedrop off (remembered in safe-drop-players.yml).
protect-damageabletrueAnything that wears out: tools, weapons, armour, bows, elytra.
protect-enchantedtrueAnything enchanted, even when it is not a tool. An enchanted book is worth as much as the sword it will end up on.
protect-namedfalseAnything a player has renamed. Off by default: a renamed stack of dirt would start asking questions too.
always-protect[ ]Always protected, whatever the three switches above say.
never-protect[ ]Never protected, even when they say so.
confirm-seconds5How long the second Q has to arrive.
worlds[ ]Only in these worlds. Empty = everywhere.
Spawners
Instead of spawning four mobs four times a minute, it spawns ONE that stands for sixteen and pushes the spawner's next round forward in proportion. The farm's rhythm is identical - same mobs per minute, same loot - and the entities created are one sixteenth.
Keep reading
It works by leaning on mob stacking: with that switched off this section does nothing, because a batch of sixteen without stacking would be sixteen entities born at once, which is the opposite.
spawners6 keysenabledtruebase-batch4How big a batch is for a spawner on its own.
max-batch16The ceiling, even with many spawners grouped together.
group-in-chunktrueTreat the spawners of one chunk as a single one.
This is what turns sixty spawners across two chunks into two events instead of sixty.
nearby-cap64How many mobs of the same type around a spawner before stopping it.
The count adds up stack sizes: a stack of fifty counts as fifty, otherwise the limit would defeat itself precisely thanks to the optimisation.
nearby-radius16Within how many blocks to count.
Where the history goes
This database gets one row a minute with the average TPS, and one row per cleanup pass. Everything else lives in memory and dies on restart, because those are questions about the server RIGHT NOW.
storage5 keysstorage.mysql7 keysenabledfalsefalse = local H2 database inside plugins/ShadowOptimizer/data/. Nothing to install: the plugin works the moment it is copied in.
MySQL is good for one thing: seeing the TPS of every server on a network in a single graph.
host127.0.0.1port3306databaseshadowoptimizerusernamerootpassword""parameters"useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&characterEncoding=utf8"storagetable-prefix"so_"Table prefix.
fallback-to-localtrueMySQL configured but unreachable: with true the plugin says so in the console and falls back to the local file, so the server still starts.
storage.pool5 keysmaximum-pool-size4Small on purpose: this plugin writes one row a minute. A pool of ten connections for two inserts is memory thrown away.
minimum-idle1connection-timeout-ms10000idle-timeout-ms600000max-lifetime-ms1800000storage.h21 keyauto-serverfalseLets another process (a web panel, say) open the same H2 file while the server is running. Rarely needed.
Messages
This is the one place where language is a setting rather than a rule. Everything the plugin reads - keys, sections, commands - is English; everything a player reads lives in lang/ and follows this.
messages2 keysdefault-locale"en_US"The language used when no better one is found.
Ships with en_US and it_IT. Set "it_IT" here for an Italian server.
follow-client-localetrueFollow the language each player set in their client.
With two languages shipped this means an English speaker reads English without doing anything. A missing key falls back to the default language, key by key: an incomplete translation still works.
Integrations
All optional. The plugin starts and works on a server with nothing else of the suite installed, and when a piece switches off because another plugin is missing that is written in the console once.
integrations1 keyintegrations.shadowcontrol2 keyspublish-healthtrueWrite health.yml in our folder, so the panel can show the server's health next to the updates.
publish-seconds30How many seconds between rewrites.
bStats
It answers one question, and not out of curiosity: which Minecraft version can be dropped. Without that number the answer is an opinion, and getting it wrong means breaking two hundred people's server in an afternoon.
Keep reading
What is sent, every 30 minutes (https://bstats.org): that this server runs ShadowOptimizer, the plugin, Minecraft/Paper and Java versions, the operating system, the number of CPU cores, how many players are online (a number, nothing else), a random serverUuid that identifies nothing, and whether the history is on the local file or MySQL.
No player data leaves at all: no names, no UUIDs, no addresses, no coordinates.
false switches it off for this plugin only. enabled: false in plugins/bStats/config.yml, the file shared by every bStats plugin on this server, switches it off for all of them at once.
metrics1 keyenabledtrueDiagnostics of the plugin itself
debug1 keylog-sqlfalseWrite every SQL query to the console. That is for us, not for you.
Languages
The texts the plugin shows to players, one file per language.
lang/
Texts and messages 2 files
lang/plugins/ShadowOptimizer/lang/ File notes
This is the ONLY kind of file whose values are written in a language. Everything the plugin reads - config keys, sections, commands - is English. Everything a player reads lives here.
MiniMessage format. Placeholders are written <like_this>. A key missing from your copy of a file is read from the same language inside the plugin first; a language the plugin does not ship falls back here, key by key: an incomplete translation still works.
A message is either a plain string or a small map:
key: text: "<red>Text" channel: ACTION_BAR # CHAT | ACTION_BAR | TITLE | SUBTITLE | NONE sound: block.note_block.bass volume: 0.7 pitch: 0.8 cooldown: "2s" # per-player anti-spam
Lists are multi-line messages: the lore of a GUI item, a help block.
THE <label> PLACEHOLDER Never write the command by hand. <label> is replaced at runtime with the label Paper's registrar actually granted us: /lag and /sopt are short, convenient aliases and therefore the first ones another plugin may already have taken. On start-up the console says which one was granted and which one was lost.
COMMAND NAMES INSIDE THESE TEXTS STAY IN ENGLISH. Only the description around them is translated: a guide, a video or a line pasted into a ticket has to work on any server, whatever language it runs in.
UPDATES: a new version moves this file to the new texts for you. The lines you rewrote stay yours; the ones you never touched get the new wording. Your previous file is kept in backup/<date>/.
Every message the plugin shows to players, one file per language. The keys are not listed one by one: here are the files, how many texts they hold and the placeholders they use.
| File | Language | Texts |
|---|---|---|
lang/en_US.yml reference | English | 255 |
lang/it_IT.yml | Italiano | 255 |
Most used placeholders
The plugin replaces them with the right value: leave them written as they are.
<prefix><label><count><n><page><pages><chunks><minutes><merged><state><millis><name><share><radius>
Message groups
prefix1common20command7health4status6diagnose29cleanup42limits12panic8stacking9spawners2history5gui105safe-drop5