Skip to content
NordBots.
Back to MysteryCrates

MysteryCrates configuration

The MysteryCrates config.json controls how the plugin runs on your Ark Survival Ascended server. Every setting is listed below with what it does and its default value.

Open the configuration editorPrefer clicking to typing? Build the file with sliders and toggles.

Where it lives

Drop the file on your server at ArkApi/Plugins/MysteryCrates/config.json then reload the plugin or restart the server. Keep a backup before large changes.

Every setting

Language

Language: which text file I read for every player line and every command reply. It points at a file in the lang folder next to this config, so "en" loads lang/en.json. Want German? Copy lang/en.json to lang/de.json, change the words on the right of each line, keep every key and every {} spot exactly as it is, then set this to "de". Pick a code with no matching file and I fall back to English, so it is safe to try. Example: "de"

LangAutoFill

LangAutoFill: fills in the language lines a new build adds. Your file keeps its own order and its own wording. I only append the keys you do not have yet, in English, ready for you to translate when you feel like it. I write a .bak of your old file first, every time I change anything. A missing line already falls back to my built in English, so this saves you the hunt for what changed, it does not keep the server running. Set it to false to have your files left completely alone.

SenderName

SenderName: the name shown at the front of my chat lines. The default is empty (""), which leaves the game's built in "(SERVER):" prefix alone. Fill it in to brand your messages, so "Mystery Crates" reads "Mystery Crates: ...". Colour is kept, so a red warning stays red. Supports {map} for the map name and {server} for the server name. {server} takes the ServerName from discord.json when you set one there, and otherwise the name I work out for this server myself, see the Server block right below. Only chat lines use it. The pop up box shows no sender at all. Example: "Mystery Crates"

Server

Server: how I figure out which server I am running on. Matters most on a cluster, where one copy of this config goes to every map and each one still needs its own name in Discord posts and in the {server} tag. Most owners can leave this whole block alone, because the launch line already carries the answer.

Name
textempty
Name: a name typed here wins over everything else. I stop looking and use it as given. Leave it empty on a cluster, since every map would end up with the same one. Example: "NordBots PvP"
NameFromParams
list["-ServerName=","-serverkey=","-clustermap=","?SessionName="]
NameFromParams: with Name empty, I walk your server's launch line and take the first of these pieces that has something after it. The list ships covering the usual launchers. Your host passes the name some other way? Add that piece to the front of the list.
UseSessionName
togglefalse
UseSessionName: true lets me also try the session name the game reports in the browser when the launch line gave me nothing. Off by default, because plenty of hosts stuff that field with ads and long text nobody wants in an embed. When everything comes up empty I simply use the map name, so I always end up with something readable.
Id
textempty
Id: a short machine tag for this server, made of small letters, digits and hyphens. Leave it empty and I squeeze one out of the name on my own. Set it by hand only when two of your servers resolve to the same name and you need to tell them apart. Example: "island-pvp"

General

Debug
togglefalse
Debug: true writes the detail behind every decision to ArkApi.log. Which crate loaded, what a roll produced, what the points bridge answered, what went into the database. Keep it false for a quiet log. Turn it on when you are chasing something odd, or when support asks for it. It is chatty on a busy server, so turn it back off afterwards.

License

License: the block that switches Mystery Crates on. This is a paid plugin, so I check your key with the shop before I do anything at all. Read the next few lines even if you skip the rest of this file. Nothing works without them.

Key
textempty
Key: the license key you got when you bought Mystery Crates. It looks like NB-XXXXX-XXXXX-XXXXX-XXXXX. Copy it in whole, between the quotes, with no spaces on either end. Keep it to yourself, it belongs to you and one key runs one server box. What happens with no key, or with a key that is empty, wrong, expired, or turned off: I do nothing. Not a smaller version of me, nothing. The /crate command goes away, so does every admin command except the reload one, all my hooks come off, my crates unload and my storage shuts down. Your server itself is completely fine and every other plugin carries on. I write one plain line in ArkApi.log telling you what I found, and that is my whole day. A player who types /crate is told crates are switched off right now, nothing more. They do not see anything about keys or money, because that side is yours, not theirs. Fixing it never needs a restart. Paste your key in here, save the file, then run MysteryCrates.Reload from the server console or from RCON. That one command is always listening, even while I am switched off, on purpose, so you are never stuck. I pick the new key up, check it, and everything comes straight back with players still online. The first check is a quick call out to the shop when the server starts. I do not sit and wait on it, so a good key never slows your boot down by even a moment. If the shop is unreachable later, say your host has a network wobble, I keep running on the last good answer for up to 72 hours before I switch off, so a blip in the night costs you nothing. Moving to a new machine? Free the seat from your account on the website first, then start the plugin on the new box and it takes the seat there. Lost your key or need a hand? Get support at NordBots.cc. Example: "NB-A1B2C-D3E4F-G5H6I-J7K8L"

Commands

Crate
text"/crate"
Crate: the one word players type. Everything else is a sub action of it, so renaming this renames my whole chat surface in one edit and I never collide with another plugin. /crate what you are holding, your shards, one hint line /crate open <name> spend one crate and start a ladder /crate take keep the prize on the rung you are standing on /crate climb roll once for the next rung /crate pick <n> pick a sealed door on a doors rung /crate insure spend shards so your next miss does not drop you /crate reroll spend shards to reroll this rung's prize /crate forge <name> spend shards to mint one sealed crate /crate odds <name> the whole ladder with the real percentages /crate book [set] your collection /crate fair your seed hash, your client seed, your nonce /crate seed <text> set your client seed and reveal the old server seed /crate verify <id> the full receipt for one open /crate claim take anything I am holding for you Keep the leading slash. Example: "/box"
AllowCommandRewards
togglefalse
AllowCommandRewards: the main switch for command prizes. Read this whole block before you touch it. A crate reward of Type "command" runs a real console command on your server, so turning this on hands me the power to run console commands. That is why it starts off. While this is false I will not run a command prize, no matter what any crate file asks for. I hold the prize for the player instead, and if I cannot even do that I write a warning with the player and the reason so you can sort it out by hand. Nothing else in a crate changes. Turning it on does NOT let crates run whatever they like. The Allowlist below still decides. With this true and the Allowlist empty, the answer is still no to every command. Example: true
Allowlist
list[]
Allowlist: the only console commands a crate file is ever allowed to run. Empty ([]) means no crate can run any command at all. That is the safe default and the one I recommend. Put a command here only if you are happy for a crate to run it for a player. I look at the FIRST word of the command and nothing else. If that word is not on this list I refuse the reward, both when I load the crate file and again the moment it would have run. I name the crate file in the log when I refuse one, so you always know what asked for what. Write the first word on its own. Upper and lower case do not matter. Do not add arguments. Tokens: just before I run a command I swap in {eos} for the player's EOS id, and {name} or {player} for their character name. A character name is text the player picked, so I treat it that way. I drop control characters and double quotes from it, cut it to 64 characters, and then I check the first word one more time. A name can never change WHICH command runs, but remember a name can hold spaces, so only allow a command that is safe with an extra word. A longer list is more power for a crate file and less safety in a crate somebody sent you. Example: ["addpoints", "giveexptoplayer"]
LendStaffPowers
toggletrue
LendStaffPowers: whether I lend the player staff rights for the moment a command prize runs. A command runs through the player's own console, and the useful ones (handing out points or experience) are refused for a normal player, so most command prizes need this to work. When this is true I note the player's own admin and cheat flags, switch both on, run the one command, then set their flags back to exactly what they were. I put them back even when the command fails. The player never gets to type anything while the rights are up and they never keep them, but for that instant the command is running with full rights, so only ever allow a command you would be happy to run yourself. Set it to false if every command on your Allowlist is one a normal player could already run. A command that needs staff rights will then just do nothing. Default is true. Example: false

Ladder

Ladder: the take it or climb it loop. This is the heart of the plugin.

DecideSeconds
number45
DecideSeconds: how long a player has to answer take or climb before I decide for them. When the clock runs out I always TAKE. I will never gamble for somebody who walked away. 45 is relaxed. A smaller number is snappier and tenser. A bigger number is kinder to players who are often mid fight when a crate opens. A crate file can set its own with "Decide". Example: 20
StepSeconds
decimal1.5
StepSeconds: the forced quiet between a reveal and the next prompt, in seconds. 1.5 gives a player time to read the prize before the question lands. A bigger number makes the reveal slower and more dramatic. Do NOT go under 1.1, because the game drops any chat line sent within one second of that player's last one, so a smaller number quietly eats my own text and players see half a reveal. Example: 2.5
MaxLiveOpens
number40
MaxLiveOpens: how many ladders may be running at the same time, server wide. 40 is generous for a 70 player server. Past this an open is refused with a plain message and the crate is NOT spent. A smaller number is a harder ceiling on the chat noise. A bigger one suits a busy cluster map. Each live ladder is a few dozen bytes, so this is about noise, not about memory. Example: 15

Reveal

Reveal: how a prize is shown.

Style
text"full"
Style: "full" paces the reveal, uses the pop up box and lets the moment breathe. "quick" is chat only with no pacing, which suits a server that wants the loot and not the show. A crate file can override this for itself with its own "Reveal" key. Example: "quick"
AnnounceFromRung
number3
AnnounceFromRung: reaching this rung or higher shouts to the whole server and earns its own Discord post. 3 means the top of a four rung crate is special and the bottom two stay quiet. A bigger number makes the shout rarer and louder. Set it to 99 to never shout at all. A crate file can override this with its own "Announce" block, and the shipped crates do. Example: 4

Fairness

Fairness: every player has a secret server seed whose SHA-256 hash I publish before their first open, a client seed they choose, and a nonce that counts up. Every roll is an HMAC of those three, so /crate verify can rebuild any open by hand.

ReseedAfterOpens
number500
ReseedAfterOpens: after this many opens I retire a player's server seed, show it next to the hash I already published, and mint a fresh one. That is what turns their past opens from "trust me" into "check it yourself". 500 is a good balance. A smaller number reveals sooner and proves faster. A bigger number means a heavy player waits longer before their history becomes checkable. Set it to 0 to never rotate on my own. Players can still rotate whenever they like with /crate seed, so 0 is not the same as never proving anything. Example: 100
AllowClientSeed
toggletrue
AllowClientSeed: true lets a player set their own client seed with /crate seed <text>, which is the part that proves I could not have picked the seed pair to suit myself. false locks every client seed to the player's EOS id. The proof still works, it is just weaker, so leave this true unless you have a reason not to.

Shards

Shards: my own little currency. It exists so the whole economy still runs on a server with no ArkShop installed.

PerMiss
number15
PerMiss: shards paid when a climb fails. This is the fallback a crate file uses when it does not set its own. 15 makes a bad night still worth something. A bigger number makes failing feel fine, which makes players climb more. A smaller number makes a miss really sting. Example: 5
PerDuplicate
number25
PerDuplicate: shards paid when a player pulls a Card they already own, instead of handing them the same card twice. Again a crate file may set its own. 25 keeps a collection from turning into a punishment. Raise it on a crate with a small card pool, because duplicates come fast there. Example: 50
InsureCost
number120
InsureCost: shards to make your NEXT miss this open not drop you. Once per open. 120 is roughly eight failed climbs of saving up. Cheaper means players always insure and the ladder loses its teeth. Dearer means insurance is a real decision. Example: 250
RerollCost
number80
RerollCost: shards to reroll the prize on the rung you are standing on, keeping the rung. 80 is about five misses. Each reroll gets its own step in the fairness receipt, so it can never be used to hide anything. A bigger number makes rerolling a treat. Example: 150
MaxRerollsPerOpen
number2
MaxRerollsPerOpen: how many times one open may be rerolled. 2 keeps a run moving. 0 turns rerolling off completely. A big number lets a rich player fish for the one prize they want, which usually reads as pay to win. Example: 0

Inventory

Inventory: what happens when a payout will not fit in a bag. This matters more than it sounds. The game silently creates NOTHING when a bag is at its cap, so a plugin that does not count first can void a top roll and never tell anybody. I count your free slots before I create a single item.

WhenFull
text"refuse"
WhenFull: pick one of three. "refuse" I do not resolve the open, your crate is NOT spent, and I tell you how many slots you need. This is the default and the one that never loses anything. "partial" I pay what fits and hold the rest for /crate claim. "hold" I pay nothing now and hold the whole lot for /crate claim. A player who is offline when something is owed to them always takes the hold path, whatever this says, so nothing is ever dropped on the floor. Example: "hold"
ReserveSlots
number1
ReserveSlots: free slots I leave alone, so a payout never fills a bag right to the brim. 1 is polite. A bigger number suits a server where people live at their slot cap and complain. 0 means I will happily fill the last slot. This only bites on a bag that has a real slot cap, like a vault or a dino. A normal player pack fills up by weight and has no slot cap at all, so there is nothing for me to hold back and this setting is skipped. Example: 5

Crates

Crates: how I read the crates folder. The loot itself lives in those files, not here. I read the folder at start up and again on MysteryCrates.Reload.

MaxRungs
number8
MaxRungs: the most rungs I will accept in one crate file. 8 is already a long ladder. A crate with more rungs than this is refused by name and every other crate still loads. A bigger number lets you build a twelve rung monster, but remember a player has to sit through every single prompt. A smaller number keeps every crate short. Example: 4

Rewards

=========================================================================================== Rewards: the one setting a crate reward needs from you rather than from its own file. Everything else about a prize is written in the crate file itself, so a crate you download brings its own loot and can never reach anything in here. The full guide with a worked example of every key is in crates/_example.jsonc. Here is the short list of what a prize can now do, so you know what is on offer before you open that file: A CREATURE PRIZE can say Male, Female or Random, can arrive neutered so it is a pet and not a breeding line, can come as a matched breeding pair, can be born with the wild stat points you choose, can arrive already wearing a saddle with its own quality, armor, durability and damage, and can be packed into a cryopod with the pod's clock set to as long as you like, up to thirty days. AN ITEM PRIZE can have its armor, durability, damage and quality word pinned to exact numbers, so a headline prize reads the same for every player who wins it, or rolled inside a range. ANY NUMBER a prize takes can be written as one exact number, or as two numbers in square brackets for a range, like "Level": [120, 180]. That works the same way everywhere, on the amount, the quality, the level, and on every saddle and item stat. ===========================================================================================

CryopodBlueprint
text"Blueprint'/Game/Extinction/CoreBlueprints/Weapons/PrimalItem_WeaponEmptyCryopod.PrimalItem_WeaponEmptyCryopod'"
CryopodBlueprint: the cryopod item I put a creature into when a crate reward asks for one. A crate reward of Type "dino" can say "Cryopod": true. When it does, I spawn the creature, set its stats, pack it into one of these, and drop the pod straight into the player's bag. Nothing appears in the world, so nobody loses a prize to a full base or a bad spawn spot. The value below is the normal game cryopod, the one every map already has since Extinction. Leave it exactly as it is and everything works. You only ever touch this line if your server runs a cryopod MOD and you would rather hand out the mod's pod, because that is the one your players already have a terminal or a fridge for. To point it at a mod pod, copy the mod item's blueprint path in whole, quotes and all. A mod path always starts with /Game/Mods/ and ends with the item name written twice, so it looks like this shape: Example: "Blueprint'/Game/Mods/<ModFolder>/<PodItem>.<PodItem>'" The mod's own store page, its spawn code list, or its item list gives you the real one. Get it wrong and nothing breaks and nobody loses a prize. I try to load the path, it does not load, so I set the creature down next to the player instead, tell them plainly that their creature is standing there, and write one warning in ArkApi.log naming the path I tried. Fix the line, run MysteryCrates.Reload, and the next pod works. Blank ("") is treated the same as leaving it alone, so I fall back to the game cryopod. How long a reward pod lasts is set in the crate file, not here, with "CryopodMinutes" next to the "Cryopod": true line. Leave that out and the pod keeps whatever clock the game gives a fresh one. Put a number on it and the player gets that many minutes to throw the creature out, so 43200 is thirty days and 60 is one hour of real time. Thirty days is the longest I will set. A short clock is a nice touch on a prize you want used rather than hoarded, and a long one is kinder to a player who wins something at three in the morning.

Earn

Earn: how players get crates by playing. Four of these are on out of the box, so the plugin starts paying out from the first wild rex somebody kills and you never type a give command. Each trigger has its own cooldown and its own daily cap, and each one switches itself off on its own if a game update ever renames the thing it watches. Every "Crate" value here is a crate FILE NAME, lowercased, with no .json on the end. crates/Bronze.json is "bronze".

WildKill
group
WildKill: killing a wild creature. This is the busiest thing I watch and it is built to be cheap. A boss pays the BossCrate at BossChance. A creature whose name tag is in Tags pays the normal Crate at Chance. Everything else pays nothing at all.
Enabled
toggletrue
Enabled: false and I stop watching creature deaths completely, which is one less hook.
Crate
text"bronze"
Crate: the crate a tagged kill pays. Example: "silver"
BossCrate
text"gold"
BossCrate: what a boss kill pays. Blank ("") means bosses pay the normal Crate instead. Example: ""
Tags
list["Rex","Spino","Giga","Therizino"]
Tags: which creatures count. These are the game's own name tags, not display names. Add "Argent" or "Bary" to widen it. An empty list ([]) means no normal kill ever pays and only bosses do. A longer list pays more often. Example: ["Rex", "Spino", "Giga", "Therizino", "Argent", "Bary"]
BossNames
list[]
BossNames: how I tell a boss from a normal creature. I read the creature's name tag and its display name and look for anything on this list. An empty list ([]) means I use my own built in list, which already covers the vanilla bosses: Broodmother, Megapithecus, Dragon, Manticore, Overseer, Rockwell, Moeder, Master Controller, Wyvern Queen, Dinopithecus King and the four Titans. Write your own list here to replace mine, which is what you want if a mod adds a boss I have never heard of. Anything you put here is matched whole against the name tag, or as part of the display name, and case does not matter. Example: ["Broodmother", "Megapithecus", "Dragon", "Overseer", "MyModBoss"]
Chance
number8
Chance: percent chance a tagged kill pays a crate. 8.0 is about one rex in twelve. A bigger number is a generous server. A smaller number makes crates feel earned. Example: 25.0
BossChance
number100
BossChance: percent chance a boss kill pays. 100.0 means always, which is rather the point of killing a boss. A smaller number makes even a boss a gamble. Example: 50.0
CooldownSeconds
number90
CooldownSeconds: the quiet time after a paying kill before another one can pay, per player. 90 stops a giga wiping a herd from printing a stack of crates. Bigger is stricter, smaller lets a good hunt pay more often. Example: 300
DailyCap
number12
DailyCap: the most crates one player can earn this way in a day. 0 means no cap. A smaller number keeps the very keen from running away with it. Example: 5
Tame
group
Tame: finishing a tame. The cheapest good trigger there is, because it happens a few times an hour at most.
Enabled
toggletrue
Enabled: false and I stop watching tames.
Crate
text"bronze"
Crate: the crate a qualifying tame pays. Example: "silver"
MinLevel
number60
MinLevel: the tamed creature's level must be at least this to pay anything. 60 keeps dodo farming out of it. Lower it on a low rates server, raise it on a boosted one where level 150 tames are normal. Example: 120
Chance
number35
Chance: percent chance a qualifying tame pays. 35.0 is about one tame in three. Bigger pays more often, smaller makes it a nice surprise. Example: 100.0
CooldownSeconds
number600
CooldownSeconds: quiet time per player after a paying tame. Bigger is stricter. Example: 1800
DailyCap
number6
DailyCap: most crates one player earns from tames in a day. 0 means no cap. Example: 3
Join
group
Join: logging in. It costs nothing to run, and it is the trigger that gets a brand new player playing on the first evening.
Enabled
toggletrue
Enabled: false and I stop watching logins, so none of the three below happen.
FirstJoinCrate
text"bronze"
FirstJoinCrate: what a player gets the very first time they ever join, once, forever. Blank ("") turns it off. This is the crate that teaches somebody what the plugin is, so point it at your friendliest one. Example: ""
StreakDays
number5
StreakDays: log in this many days in a row and get the StreakCrate, then the counter starts again. 5 is a working week. A bigger number makes the reward rarer and the streak harder to hold. A smaller number makes logging in feel worth it sooner. Example: 7
StreakCrate
text"silver"
StreakCrate: the crate paid when the streak lands. Make it better than the daily one. Example: "gold"
DailyCrate
textempty
DailyCrate: a crate for simply logging in each day. Blank ("") is off, and off is the default because it pays people for doing nothing. Fill it in on a casual server. Example: "bronze"
Playtime
group
Playtime: being online and actually playing. There is no hook for this at all, I just look at who is online once a second and count.
Enabled
toggletrue
Enabled: false and nobody earns crates from time online.
Crate
text"bronze"
Crate: the crate the playtime drip pays. Example: "silver"
IntervalMinutes
number60
IntervalMinutes: minutes of counted time for one crate. 60 is an hour of real play. A smaller number pays faster and floods wallets. A bigger number makes an hour mean something. Example: 120
OnlyRewardIfMoving
toggletrue
OnlyRewardIfMoving: true means a player parked at a screen earns nothing. This is the difference between rewarding play and rewarding an idle client.
IdleMoveThreshold
number200
IdleMoveThreshold: how far a player must move in a second to count as playing, in game units. 200.0 is about a walk. A smaller number means standing at a crafting bench counts. A bigger number means only real travel counts. Example: 50.0
DailyCap
number4
DailyCap: most crates one player earns from time online in a day. 0 means no cap. Example: 2
PvpKill
group
PvpKill: killing another player. OFF by default, because it is wrong for a PvE server and because kill trading is a real thing. I skip it entirely on a PvE server even when it is on.
Enabled
togglefalse
Enabled: true starts paying for player kills.
Crate
text"silver"
Crate: the crate a PvP kill pays. Example: "bronze"
SameVictimCooldownSeconds
number900
SameVictimCooldownSeconds: how long before killing the SAME player can pay again. 900 means two friends trading kills earn one crate every fifteen minutes between them, which is not worth their time. A bigger number is stricter still. Example: 3600
DailyCap
number6
DailyCap: most crates one player earns from PvP kills in a day. 0 means no cap. Example: 3

Season

Season: an optional label stamped on every wallet row, receipt and book entry I write.

Current
textempty
Current: your season tag, up to 16 characters. Blank ("") means no season, which is right for almost everybody. Change it when you wipe and start again, and old rows keep the old tag, so you can still look back at last season without mixing the two. Example: "S3"

Permissions

Permissions: gate who may use the crate commands. Needs Permissions.dll, and everything here is optional. The staff commands are console and RCON only, so they need no node at all. Whoever is holding the console already owns the server.

Enabled
toggletrue
Enabled: true runs the permission checks. false skips them and treats everyone as a normal player who may open crates.
UsePermission
textempty
UsePermission: leave "" so everyone can open crates. Set a node like "MysteryCrates.Use" to limit crates to the groups that hold it. A single crate can also demand its own node with the "Permission" key inside its own crate file, which is how you build a VIP only crate. If Permissions.dll is missing or will not answer, I let the player through, so a broken permissions install never locks your server out of its own crates. Example: "MysteryCrates.Use"

ArkShop

ArkShop: the points economy. Only used for rewards of Type "points" inside a crate file. Either shop plugin works here, ArkShop or WShop. The plugin runs perfectly with no shop at all, which is what shards are for.

Enabled
toggletrue
Enabled: true and I look for a points shop at start up and use it when it is there. false and I never touch it, so a crate reward of Type "points" pays nothing and says so.
Provider
text"Auto"
Provider: which shop plugin holds the points. "Auto" I knock on ArkShop first, then WShop, and use the one that answers. "ArkShop" only ArkShop.dll. "WShop" only WShop.dll. Auto suits nearly everyone. Name one if both shops live on this server.

Database

Database: where wallets, shards, seeds, receipts and the book live.

Enabled
toggletrue
Enabled: true and I keep records. false and I do not start at all, which switches crates off, because a crate ladder with nothing to write to would lose a prize on the first restart. Leave this true unless you are testing something.
UseMySQL
togglefalse
UseMySQL: false is SQLite, a single file at data/MysteryCrates.db, with no setup of any kind. true is MySQL, which is what you want when several maps in a cluster should share one wallet, one shard balance and one book. Everything below TablePrefix is for MySQL only.
TablePrefix
text"mc_"
TablePrefix: the front of my five table names, so "mc_" gives mc_players, mc_wallet, mc_opens, mc_book and mc_hold. Change it if you run two instances against one database. Changing it after the fact makes fresh empty tables, it does not rename your old ones. Example: "crates2_"
Host
text"127.0.0.1"
Host, Port, User, Password, Database: your MySQL details. All ignored when UseMySQL is false. Example: "10.0.0.5"
Port
number3306
Example: 3307
User
textempty
Example: "arkuser"
Password
textempty
Example: "a long password"
Database
textempty
Example: "ark_cluster"
MysqlSSLMode
number-1
MysqlSSLMode: -1 leaves the client default alone, which is right unless your host told you otherwise. A bigger number asks for a stricter connection, and your host will tell you which one they want. Example: 1
MysqlTLSVersion
textempty
MysqlTLSVersion: blank ("") means the client default. Only fill this in if your host asked. Example: "TLSv1.2"
RecentOpensKept
number500
RecentOpensKept: how many receipts I keep per player before the oldest are pruned. 500 is plenty for any argument about a roll, and /crate verify reads from these. A bigger number keeps a longer history and a slightly bigger file. A smaller number keeps the table tidy and makes an old /crate verify come up empty. I clamp this between 50 and 20000, so anything outside that is pulled back inside. Example: 2000
MaxQueuedWrites
number20000
MaxQueuedWrites: how many pending saves I will hold before I start dropping the oldest and counting them in the log. 20000 is far more than a busy server ever queues. It only matters when a remote MySQL goes slow, and it stops that turning into runaway memory. A bigger number survives a longer database hiccup and uses more memory doing it. I clamp this between 500 and 200000. Example: 5000

Panel

Panel: the clickable crate window, drawn by the NordBots Companion UI mod. With the mod on your server, players get a window listing every crate they hold, each with its own Open button, plus a Top Openers board and the take or climb choice as buttons on the ladder. Every button press runs the very same code the typed command runs, so nothing can be done through the window that the chat command would refuse. No mod on the server? Nothing changes and this whole block sleeps. The mod is a nice extra, never a must have.

Enabled
toggletrue
Enabled: true means I look for the mod and offer the window. false means I never go looking at all, and crates stay chat only. Turn it off if you do not run the NordBots UI mod and want me doing nothing extra.
RowsPerPage
number10
RowsPerPage: how many crate rows fit on one page of the window. A player holding more kinds than this gets page buttons under the list. 12 is the most the window can carry, and I quietly trim anything higher. Example: 8
TopCount
number10
TopCount: how many players show on one page of the Top Openers board. Also capped at 12 so the window stays small enough to send. Example: 5
BuffTag
text"NordBotsUIBuff"
BuffTag: the tag on the buff the mod puts on every player. That buff is how my windows reach a player's screen, and the tag is how I spot it. Only change this if the mod itself changes.
BuffPath
text"NordBotsUI/Buff_NordBotsUI"
BuffPath: where inside the mod that buff lives. My backup way of finding it when the tag is missing. Leave it be unless the mod moves things around.
SingletonPath
text"Blueprint'/NordBotsUI/NordBotsUI_Singleton.NordBotsUI_Singleton'"
SingletonPath: where the mod's main actor sits. I read the mod's version number off it before I send anything. Leave it be unless the mod moves.
RequireHandshake
togglefalse
RequireHandshake: what I do when I cannot find a version number on the mod at all. false sends the window anyway and lets the mod skip anything it does not understand, which suits nearly every server. true holds every window back until I can read a matching version. A version that reads as the wrong number always stops the window, whatever this says.

ApiUtilsMod

ApiUtilsMod: shows my messages in a box on screen instead of plain chat, so a reveal actually lands. It needs the free "ASA API Utils" mod running on your server. Download it here: https://www.curseforge.com/ark-survival-ascended/mods/asa-api-utils Add mod id 955333 to your mod list, restart, and you are set. Optional. Crates work exactly the same without it, the reveals just show as plain text, and the log mentions once that the mod is missing.

Enabled
toggletrue
Enabled: true and I hand my messages to the mod. false and I keep using plain game text, even on a server that has the mod loaded.
BackdropColor
list[0,0,0,0.55]
BackdropColor: what the box behind the text looks like. Four numbers, [red, green, blue, how solid], each one from 0.0 to 1.0. A bigger last number is a heavier box, a smaller one lets the game show through. Set the last number to 0.0 and you get bare text with no box at all. Example: [0.1, 0.0, 0.15, 0.65] gives a dark purple box
ScreenPosition
text"Center"
ScreenPosition: the spot on screen the box appears in. Choose "Left", "Center" or "Right". Center works for almost everybody. Example: "Right"
TextAlign
text"Center"
TextAlign: how the words are lined up inside the box. Choose "Left", "Center" or "Right". Example: "Left"
TextScale
number1
TextScale: how large the text is drawn. 1.0 is the normal size. A bigger number makes a message shout. A smaller number makes it quiet and small. Above about 2.2 the text starts running off the sides on smaller screens. Example: 1.6
MessageSeconds
number6
MessageSeconds: how many seconds a box holds on screen before it fades. 6.0 gives a player time to read one line. A bigger number keeps it up longer, a smaller one clears it faster. Example: 10.0
AlsoShowInChat
toggletrue
AlsoShowInChat: leave true and every message goes out twice on purpose, once as the pop up box and once as an ordinary chat line that stays in the log. That matters here, because a player wants to scroll back and read what door three was holding. Set it false when you would rather have just the box and a tidy chat window.

MapName

MapName: how the map is written in player facing text and in the {map} tag. What the game hands me is a level file name such as "TheIsland_WP", which I clean up to "The Island" so it reads properly.

Pretty
toggletrue
Pretty: true takes off the "_WP" and puts the missing spaces back, so "ScorchedEarth_WP" comes out as "Scorched Earth". false keeps the raw name exactly as the game gives it.
Overrides
group
Overrides: your own label for a given map, handy for mod maps whose file name is nothing like the name people use. Raw name on the left, your name on the right, and it wins over Pretty. Example: { "TheCenter_WP": "Center", "Svartalfheim_WP": "Svartalfheim" }

The full commented config

This is a reading copy with notes. It is not valid JSON, so do not load it. Use the editor or the plain config.json instead.

{
  // MysteryCrates config notes. The comments in here break JSON on purpose, so the server never
  // reads this file. Make your real changes in config.json. This copy is the guide that explains
  // every line in it.
  //
  // Two files, two jobs:
  //   config.json          how the plugin behaves. Settings only. You are reading its guide.
  //   crates/<Name>.json   what a player can win. One file per crate. See crates/_example.jsonc.
  //
  // If you came looking for loot, blueprints or weights, you are in the wrong file. Go to crates/.
  // A crate file can never reach a webhook, a password or a command name. That is on purpose, so a
  // crate somebody posts in a Discord can add loot and nothing else.


  // Language: which text file I read for every player line and every command reply.
  // It points at a file in the lang folder next to this config, so "en" loads lang/en.json.
  // Want German? Copy lang/en.json to lang/de.json, change the words on the right of each line,
  // keep every key and every {} spot exactly as it is, then set this to "de".
  // Pick a code with no matching file and I fall back to English, so it is safe to try.
  // Example: "de"
  "Language": "en",

  // LangAutoFill: fills in the language lines a new build adds.
  // Your file keeps its own order and its own wording. I only append the keys you do not have yet,
  // in English, ready for you to translate when you feel like it. I write a .bak of your old file
  // first, every time I change anything. A missing line already falls back to my built in English,
  // so this saves you the hunt for what changed, it does not keep the server running.
  // Set it to false to have your files left completely alone.
  "LangAutoFill": true,

  // SenderName: the name shown at the front of my chat lines.
  // The default is empty (""), which leaves the game's built in "(SERVER):" prefix alone.
  // Fill it in to brand your messages, so "Mystery Crates" reads "Mystery Crates: ...".
  // Colour is kept, so a red warning stays red.
  // Supports {map} for the map name and {server} for the server name. {server} takes the
  // ServerName from discord.json when you set one there, and otherwise the name I work out
  // for this server myself, see the Server block right below.
  // Only chat lines use it. The pop up box shows no sender at all.
  // Example: "Mystery Crates"
  "SenderName": "",

  // Server: how I figure out which server I am running on.
  // Matters most on a cluster, where one copy of this config goes to every map and each one
  // still needs its own name in Discord posts and in the {server} tag. Most owners can leave
  // this whole block alone, because the launch line already carries the answer.
  "Server": {
    // Name: a name typed here wins over everything else. I stop looking and use it as given.
    // Leave it empty on a cluster, since every map would end up with the same one.
    // Example: "NordBots PvP"
    "Name": "",

    // NameFromParams: with Name empty, I walk your server's launch line and take the first of
    // these pieces that has something after it. The list ships covering the usual launchers.
    // Your host passes the name some other way? Add that piece to the front of the list.
    "NameFromParams": [
      "-ServerName=",
      "-serverkey=",
      "-clustermap=",
      "?SessionName="
    ],

    // UseSessionName: true lets me also try the session name the game reports in the browser
    // when the launch line gave me nothing. Off by default, because plenty of hosts stuff that
    // field with ads and long text nobody wants in an embed. When everything comes up empty I
    // simply use the map name, so I always end up with something readable.
    "UseSessionName": false,

    // Id: a short machine tag for this server, made of small letters, digits and hyphens.
    // Leave it empty and I squeeze one out of the name on my own. Set it by hand only when two
    // of your servers resolve to the same name and you need to tell them apart.
    // Example: "island-pvp"
    "Id": ""
  },

  "General": {
    // Debug: true writes the detail behind every decision to ArkApi.log. Which crate loaded, what a
    // roll produced, what the points bridge answered, what went into the database.
    // Keep it false for a quiet log. Turn it on when you are chasing something odd, or when support
    // asks for it. It is chatty on a busy server, so turn it back off afterwards.
    "Debug": false
  },

  // License: the block that switches Mystery Crates on.
  // This is a paid plugin, so I check your key with the shop before I do anything at all.
  // Read the next few lines even if you skip the rest of this file. Nothing works without them.
  "License": {
    // Key: the license key you got when you bought Mystery Crates.
    // It looks like NB-XXXXX-XXXXX-XXXXX-XXXXX. Copy it in whole, between the quotes, with no
    // spaces on either end. Keep it to yourself, it belongs to you and one key runs one server box.
    //
    // What happens with no key, or with a key that is empty, wrong, expired, or turned off:
    // I do nothing. Not a smaller version of me, nothing. The /crate command goes away, so does
    // every admin command except the reload one, all my hooks come off, my crates unload and my
    // storage shuts down. Your server itself is completely fine and every other plugin carries on.
    // I write one plain line in ArkApi.log telling you what I found, and that is my whole day.
    // A player who types /crate is told crates are switched off right now, nothing more. They do
    // not see anything about keys or money, because that side is yours, not theirs.
    //
    // Fixing it never needs a restart. Paste your key in here, save the file, then run
    // MysteryCrates.Reload from the server console or from RCON. That one command is always
    // listening, even while I am switched off, on purpose, so you are never stuck. I pick the new
    // key up, check it, and everything comes straight back with players still online.
    //
    // The first check is a quick call out to the shop when the server starts. I do not sit and
    // wait on it, so a good key never slows your boot down by even a moment. If the shop is
    // unreachable later, say your host has a network wobble, I keep running on the last good
    // answer for up to 72 hours before I switch off, so a blip in the night costs you nothing.
    //
    // Moving to a new machine? Free the seat from your account on the website first, then start
    // the plugin on the new box and it takes the seat there.
    // Lost your key or need a hand? Get support at NordBots.cc.
    // Example: "NB-A1B2C-D3E4F-G5H6I-J7K8L"
    "Key": ""
  },

  "Commands": {
    // Crate: the one word players type. Everything else is a sub action of it, so renaming this
    // renames my whole chat surface in one edit and I never collide with another plugin.
    //   /crate                 what you are holding, your shards, one hint line
    //   /crate open <name>     spend one crate and start a ladder
    //   /crate take            keep the prize on the rung you are standing on
    //   /crate climb           roll once for the next rung
    //   /crate pick <n>        pick a sealed door on a doors rung
    //   /crate insure          spend shards so your next miss does not drop you
    //   /crate reroll          spend shards to reroll this rung's prize
    //   /crate forge <name>    spend shards to mint one sealed crate
    //   /crate odds <name>     the whole ladder with the real percentages
    //   /crate book [set]      your collection
    //   /crate fair            your seed hash, your client seed, your nonce
    //   /crate seed <text>     set your client seed and reveal the old server seed
    //   /crate verify <id>     the full receipt for one open
    //   /crate claim           take anything I am holding for you
    // Keep the leading slash.
    // Example: "/box"
    "Crate": "/crate",

    // AllowCommandRewards: the main switch for command prizes. Read this whole block before you
    // touch it. A crate reward of Type "command" runs a real console command on your server, so
    // turning this on hands me the power to run console commands. That is why it starts off.
    // While this is false I will not run a command prize, no matter what any crate file asks for.
    // I hold the prize for the player instead, and if I cannot even do that I write a warning with
    // the player and the reason so you can sort it out by hand. Nothing else in a crate changes.
    // Turning it on does NOT let crates run whatever they like. The Allowlist below still decides.
    // With this true and the Allowlist empty, the answer is still no to every command.
    // Example: true
    "AllowCommandRewards": false,

    // Allowlist: the only console commands a crate file is ever allowed to run.
    // Empty ([]) means no crate can run any command at all. That is the safe default and the one I
    // recommend. Put a command here only if you are happy for a crate to run it for a player.
    // I look at the FIRST word of the command and nothing else. If that word is not on this list I
    // refuse the reward, both when I load the crate file and again the moment it would have run.
    // I name the crate file in the log when I refuse one, so you always know what asked for what.
    // Write the first word on its own. Upper and lower case do not matter. Do not add arguments.
    // Tokens: just before I run a command I swap in {eos} for the player's EOS id, and {name} or
    // {player} for their character name. A character name is text the player picked, so I treat it
    // that way. I drop control characters and double quotes from it, cut it to 64 characters, and
    // then I check the first word one more time. A name can never change WHICH command runs, but
    // remember a name can hold spaces, so only allow a command that is safe with an extra word.
    // A longer list is more power for a crate file and less safety in a crate somebody sent you.
    // Example: ["addpoints", "giveexptoplayer"]
    "Allowlist": [],

    // LendStaffPowers: whether I lend the player staff rights for the moment a command prize runs.
    // A command runs through the player's own console, and the useful ones (handing out points or
    // experience) are refused for a normal player, so most command prizes need this to work.
    // When this is true I note the player's own admin and cheat flags, switch both on, run the one
    // command, then set their flags back to exactly what they were. I put them back even when the
    // command fails. The player never gets to type anything while the rights are up and they never
    // keep them, but for that instant the command is running with full rights, so only ever allow
    // a command you would be happy to run yourself.
    // Set it to false if every command on your Allowlist is one a normal player could already run.
    // A command that needs staff rights will then just do nothing.
    // Default is true.
    // Example: false
    "LendStaffPowers": true
  },

  // Ladder: the take it or climb it loop. This is the heart of the plugin.
  "Ladder": {
    // DecideSeconds: how long a player has to answer take or climb before I decide for them.
    // When the clock runs out I always TAKE. I will never gamble for somebody who walked away.
    // 45 is relaxed. A smaller number is snappier and tenser. A bigger number is kinder to players
    // who are often mid fight when a crate opens. A crate file can set its own with "Decide".
    // Example: 20
    "DecideSeconds": 45,

    // StepSeconds: the forced quiet between a reveal and the next prompt, in seconds.
    // 1.5 gives a player time to read the prize before the question lands. A bigger number makes
    // the reveal slower and more dramatic. Do NOT go under 1.1, because the game drops any chat
    // line sent within one second of that player's last one, so a smaller number quietly eats my
    // own text and players see half a reveal.
    // Example: 2.5
    "StepSeconds": 1.5,

    // MaxLiveOpens: how many ladders may be running at the same time, server wide.
    // 40 is generous for a 70 player server. Past this an open is refused with a plain message and
    // the crate is NOT spent. A smaller number is a harder ceiling on the chat noise. A bigger one
    // suits a busy cluster map. Each live ladder is a few dozen bytes, so this is about noise, not
    // about memory.
    // Example: 15
    "MaxLiveOpens": 40
  },

  // Reveal: how a prize is shown.
  "Reveal": {
    // Style: "full" paces the reveal, uses the pop up box and lets the moment breathe.
    // "quick" is chat only with no pacing, which suits a server that wants the loot and not the
    // show. A crate file can override this for itself with its own "Reveal" key.
    // Example: "quick"
    "Style": "full",

    // AnnounceFromRung: reaching this rung or higher shouts to the whole server and earns its own
    // Discord post. 3 means the top of a four rung crate is special and the bottom two stay quiet.
    // A bigger number makes the shout rarer and louder. Set it to 99 to never shout at all.
    // A crate file can override this with its own "Announce" block, and the shipped crates do.
    // Example: 4
    "AnnounceFromRung": 3
  },

  // Fairness: every player has a secret server seed whose SHA-256 hash I publish before their first
  // open, a client seed they choose, and a nonce that counts up. Every roll is an HMAC of those
  // three, so /crate verify can rebuild any open by hand.
  "Fairness": {
    // ReseedAfterOpens: after this many opens I retire a player's server seed, show it next to the
    // hash I already published, and mint a fresh one. That is what turns their past opens from
    // "trust me" into "check it yourself".
    // 500 is a good balance. A smaller number reveals sooner and proves faster. A bigger number
    // means a heavy player waits longer before their history becomes checkable.
    // Set it to 0 to never rotate on my own. Players can still rotate whenever they like with
    // /crate seed, so 0 is not the same as never proving anything.
    // Example: 100
    "ReseedAfterOpens": 500,

    // AllowClientSeed: true lets a player set their own client seed with /crate seed <text>, which
    // is the part that proves I could not have picked the seed pair to suit myself.
    // false locks every client seed to the player's EOS id. The proof still works, it is just
    // weaker, so leave this true unless you have a reason not to.
    "AllowClientSeed": true
  },

  // Shards: my own little currency. It exists so the whole economy still runs on a server with no
  // ArkShop installed.
  "Shards": {
    // PerMiss: shards paid when a climb fails. This is the fallback a crate file uses when it does
    // not set its own.
    // 15 makes a bad night still worth something. A bigger number makes failing feel fine, which
    // makes players climb more. A smaller number makes a miss really sting.
    // Example: 5
    "PerMiss": 15,

    // PerDuplicate: shards paid when a player pulls a Card they already own, instead of handing
    // them the same card twice. Again a crate file may set its own.
    // 25 keeps a collection from turning into a punishment. Raise it on a crate with a small card
    // pool, because duplicates come fast there.
    // Example: 50
    "PerDuplicate": 25,

    // InsureCost: shards to make your NEXT miss this open not drop you. Once per open.
    // 120 is roughly eight failed climbs of saving up. Cheaper means players always insure and the
    // ladder loses its teeth. Dearer means insurance is a real decision.
    // Example: 250
    "InsureCost": 120,

    // RerollCost: shards to reroll the prize on the rung you are standing on, keeping the rung.
    // 80 is about five misses. Each reroll gets its own step in the fairness receipt, so it can
    // never be used to hide anything. A bigger number makes rerolling a treat.
    // Example: 150
    "RerollCost": 80,

    // MaxRerollsPerOpen: how many times one open may be rerolled.
    // 2 keeps a run moving. 0 turns rerolling off completely. A big number lets a rich player fish
    // for the one prize they want, which usually reads as pay to win.
    // Example: 0
    "MaxRerollsPerOpen": 2
  },

  // Inventory: what happens when a payout will not fit in a bag.
  // This matters more than it sounds. The game silently creates NOTHING when a bag is at its cap,
  // so a plugin that does not count first can void a top roll and never tell anybody.
  // I count your free slots before I create a single item.
  "Inventory": {
    // WhenFull: pick one of three.
    //   "refuse"   I do not resolve the open, your crate is NOT spent, and I tell you how many
    //              slots you need. This is the default and the one that never loses anything.
    //   "partial"  I pay what fits and hold the rest for /crate claim.
    //   "hold"     I pay nothing now and hold the whole lot for /crate claim.
    // A player who is offline when something is owed to them always takes the hold path, whatever
    // this says, so nothing is ever dropped on the floor.
    // Example: "hold"
    "WhenFull": "refuse",

    // ReserveSlots: free slots I leave alone, so a payout never fills a bag right to the brim.
    // 1 is polite. A bigger number suits a server where people live at their slot cap and complain.
    // 0 means I will happily fill the last slot.
    // This only bites on a bag that has a real slot cap, like a vault or a dino. A normal player
    // pack fills up by weight and has no slot cap at all, so there is nothing for me to hold back
    // and this setting is skipped.
    // Example: 5
    "ReserveSlots": 1
  },

  // Crates: how I read the crates folder. The loot itself lives in those files, not here.
  // I read the folder at start up and again on MysteryCrates.Reload.
  "Crates": {
    // MaxRungs: the most rungs I will accept in one crate file. 8 is already a long ladder.
    // A crate with more rungs than this is refused by name and every other crate still loads.
    // A bigger number lets you build a twelve rung monster, but remember a player has to sit
    // through every single prompt. A smaller number keeps every crate short.
    // Example: 4
    "MaxRungs": 8
  },

  // ===========================================================================================
  // Rewards: the one setting a crate reward needs from you rather than from its own file.
  //
  // Everything else about a prize is written in the crate file itself, so a crate you download
  // brings its own loot and can never reach anything in here. The full guide with a worked example
  // of every key is in crates/_example.jsonc. Here is the short list of what a prize can now do, so
  // you know what is on offer before you open that file:
  //
  //   A CREATURE PRIZE can say Male, Female or Random, can arrive neutered so it is a pet and not a
  //   breeding line, can come as a matched breeding pair, can be born with the wild stat points you
  //   choose, can arrive already wearing a saddle with its own quality, armor, durability and
  //   damage, and can be packed into a cryopod with the pod's clock set to as long as you like, up
  //   to thirty days.
  //
  //   AN ITEM PRIZE can have its armor, durability, damage and quality word pinned to exact numbers,
  //   so a headline prize reads the same for every player who wins it, or rolled inside a range.
  //
  //   ANY NUMBER a prize takes can be written as one exact number, or as two numbers in square
  //   brackets for a range, like "Level": [120, 180]. That works the same way everywhere, on the
  //   amount, the quality, the level, and on every saddle and item stat.
  // ===========================================================================================
  "Rewards": {
    // CryopodBlueprint: the cryopod item I put a creature into when a crate reward asks for one.
    //
    // A crate reward of Type "dino" can say "Cryopod": true. When it does, I spawn the creature,
    // set its stats, pack it into one of these, and drop the pod straight into the player's bag.
    // Nothing appears in the world, so nobody loses a prize to a full base or a bad spawn spot.
    //
    // The value below is the normal game cryopod, the one every map already has since Extinction.
    // Leave it exactly as it is and everything works. You only ever touch this line if your
    // server runs a cryopod MOD and you would rather hand out the mod's pod, because that is the
    // one your players already have a terminal or a fridge for.
    //
    // To point it at a mod pod, copy the mod item's blueprint path in whole, quotes and all.
    // A mod path always starts with /Game/Mods/ and ends with the item name written twice, so it
    // looks like this shape:
    // Example: "Blueprint'/Game/Mods/<ModFolder>/<PodItem>.<PodItem>'"
    // The mod's own store page, its spawn code list, or its item list gives you the real one.
    //
    // Get it wrong and nothing breaks and nobody loses a prize. I try to load the path, it does
    // not load, so I set the creature down next to the player instead, tell them plainly that
    // their creature is standing there, and write one warning in ArkApi.log naming the path I
    // tried. Fix the line, run MysteryCrates.Reload, and the next pod works.
    //
    // Blank ("") is treated the same as leaving it alone, so I fall back to the game cryopod.
    //
    // How long a reward pod lasts is set in the crate file, not here, with "CryopodMinutes" next to
    // the "Cryopod": true line. Leave that out and the pod keeps whatever clock the game gives a
    // fresh one. Put a number on it and the player gets that many minutes to throw the creature out,
    // so 43200 is thirty days and 60 is one hour of real time. Thirty days is the longest I will
    // set. A short clock is a nice touch on a prize you want used rather than hoarded, and a long
    // one is kinder to a player who wins something at three in the morning.
    "CryopodBlueprint": "Blueprint'/Game/Extinction/CoreBlueprints/Weapons/PrimalItem_WeaponEmptyCryopod.PrimalItem_WeaponEmptyCryopod'"
  },

  // Earn: how players get crates by playing. Four of these are on out of the box, so the plugin
  // starts paying out from the first wild rex somebody kills and you never type a give command.
  // Each trigger has its own cooldown and its own daily cap, and each one switches itself off on
  // its own if a game update ever renames the thing it watches.
  // Every "Crate" value here is a crate FILE NAME, lowercased, with no .json on the end.
  // crates/Bronze.json is "bronze".
  "Earn": {
    // WildKill: killing a wild creature. This is the busiest thing I watch and it is built to be
    // cheap. A boss pays the BossCrate at BossChance. A creature whose name tag is in Tags pays the
    // normal Crate at Chance. Everything else pays nothing at all.
    "WildKill": {
      // Enabled: false and I stop watching creature deaths completely, which is one less hook.
      "Enabled": true,

      // Crate: the crate a tagged kill pays.
      // Example: "silver"
      "Crate": "bronze",

      // BossCrate: what a boss kill pays. Blank ("") means bosses pay the normal Crate instead.
      // Example: ""
      "BossCrate": "gold",

      // Tags: which creatures count. These are the game's own name tags, not display names.
      // Add "Argent" or "Bary" to widen it. An empty list ([]) means no normal kill ever pays and
      // only bosses do. A longer list pays more often.
      // Example: ["Rex", "Spino", "Giga", "Therizino", "Argent", "Bary"]
      "Tags": ["Rex", "Spino", "Giga", "Therizino"],

      // BossNames: how I tell a boss from a normal creature. I read the creature's name tag and its
      // display name and look for anything on this list. An empty list ([]) means I use my own built
      // in list, which already covers the vanilla bosses: Broodmother, Megapithecus, Dragon,
      // Manticore, Overseer, Rockwell, Moeder, Master Controller, Wyvern Queen, Dinopithecus King
      // and the four Titans. Write your own list here to replace mine, which is what you want if a
      // mod adds a boss I have never heard of. Anything you put here is matched whole against the
      // name tag, or as part of the display name, and case does not matter.
      // Example: ["Broodmother", "Megapithecus", "Dragon", "Overseer", "MyModBoss"]
      "BossNames": [],

      // Chance: percent chance a tagged kill pays a crate. 8.0 is about one rex in twelve.
      // A bigger number is a generous server. A smaller number makes crates feel earned.
      // Example: 25.0
      "Chance": 8.0,

      // BossChance: percent chance a boss kill pays. 100.0 means always, which is rather the point
      // of killing a boss. A smaller number makes even a boss a gamble.
      // Example: 50.0
      "BossChance": 100.0,

      // CooldownSeconds: the quiet time after a paying kill before another one can pay, per player.
      // 90 stops a giga wiping a herd from printing a stack of crates. Bigger is stricter, smaller
      // lets a good hunt pay more often.
      // Example: 300
      "CooldownSeconds": 90,

      // DailyCap: the most crates one player can earn this way in a day. 0 means no cap.
      // A smaller number keeps the very keen from running away with it.
      // Example: 5
      "DailyCap": 12
    },

    // Tame: finishing a tame. The cheapest good trigger there is, because it happens a few times an
    // hour at most.
    "Tame": {
      // Enabled: false and I stop watching tames.
      "Enabled": true,

      // Crate: the crate a qualifying tame pays.
      // Example: "silver"
      "Crate": "bronze",

      // MinLevel: the tamed creature's level must be at least this to pay anything.
      // 60 keeps dodo farming out of it. Lower it on a low rates server, raise it on a boosted one
      // where level 150 tames are normal.
      // Example: 120
      "MinLevel": 60,

      // Chance: percent chance a qualifying tame pays. 35.0 is about one tame in three.
      // Bigger pays more often, smaller makes it a nice surprise.
      // Example: 100.0
      "Chance": 35.0,

      // CooldownSeconds: quiet time per player after a paying tame. Bigger is stricter.
      // Example: 1800
      "CooldownSeconds": 600,

      // DailyCap: most crates one player earns from tames in a day. 0 means no cap.
      // Example: 3
      "DailyCap": 6
    },

    // Join: logging in. It costs nothing to run, and it is the trigger that gets a brand new player
    // playing on the first evening.
    "Join": {
      // Enabled: false and I stop watching logins, so none of the three below happen.
      "Enabled": true,

      // FirstJoinCrate: what a player gets the very first time they ever join, once, forever.
      // Blank ("") turns it off. This is the crate that teaches somebody what the plugin is, so
      // point it at your friendliest one.
      // Example: ""
      "FirstJoinCrate": "bronze",

      // StreakDays: log in this many days in a row and get the StreakCrate, then the counter starts
      // again. 5 is a working week. A bigger number makes the reward rarer and the streak harder to
      // hold. A smaller number makes logging in feel worth it sooner.
      // Example: 7
      "StreakDays": 5,

      // StreakCrate: the crate paid when the streak lands. Make it better than the daily one.
      // Example: "gold"
      "StreakCrate": "silver",

      // DailyCrate: a crate for simply logging in each day. Blank ("") is off, and off is the
      // default because it pays people for doing nothing. Fill it in on a casual server.
      // Example: "bronze"
      "DailyCrate": ""
    },

    // Playtime: being online and actually playing. There is no hook for this at all, I just look at
    // who is online once a second and count.
    "Playtime": {
      // Enabled: false and nobody earns crates from time online.
      "Enabled": true,

      // Crate: the crate the playtime drip pays.
      // Example: "silver"
      "Crate": "bronze",

      // IntervalMinutes: minutes of counted time for one crate. 60 is an hour of real play.
      // A smaller number pays faster and floods wallets. A bigger number makes an hour mean
      // something.
      // Example: 120
      "IntervalMinutes": 60,

      // OnlyRewardIfMoving: true means a player parked at a screen earns nothing. This is the
      // difference between rewarding play and rewarding an idle client.
      "OnlyRewardIfMoving": true,

      // IdleMoveThreshold: how far a player must move in a second to count as playing, in game
      // units. 200.0 is about a walk. A smaller number means standing at a crafting bench counts.
      // A bigger number means only real travel counts.
      // Example: 50.0
      "IdleMoveThreshold": 200.0,

      // DailyCap: most crates one player earns from time online in a day. 0 means no cap.
      // Example: 2
      "DailyCap": 4
    },

    // PvpKill: killing another player. OFF by default, because it is wrong for a PvE server and
    // because kill trading is a real thing. I skip it entirely on a PvE server even when it is on.
    "PvpKill": {
      // Enabled: true starts paying for player kills.
      "Enabled": false,

      // Crate: the crate a PvP kill pays.
      // Example: "bronze"
      "Crate": "silver",

      // SameVictimCooldownSeconds: how long before killing the SAME player can pay again.
      // 900 means two friends trading kills earn one crate every fifteen minutes between them,
      // which is not worth their time. A bigger number is stricter still.
      // Example: 3600
      "SameVictimCooldownSeconds": 900,

      // DailyCap: most crates one player earns from PvP kills in a day. 0 means no cap.
      // Example: 3
      "DailyCap": 6
    }
  },

  // Season: an optional label stamped on every wallet row, receipt and book entry I write.
  "Season": {
    // Current: your season tag, up to 16 characters. Blank ("") means no season, which is right for
    // almost everybody. Change it when you wipe and start again, and old rows keep the old tag, so
    // you can still look back at last season without mixing the two.
    // Example: "S3"
    "Current": ""
  },

  // Permissions: gate who may use the crate commands. Needs Permissions.dll, and everything here is
  // optional. The staff commands are console and RCON only, so they need no node at all. Whoever is
  // holding the console already owns the server.
  "Permissions": {
    // Enabled: true runs the permission checks. false skips them and treats everyone as a normal
    // player who may open crates.
    "Enabled": true,

    // UsePermission: leave "" so everyone can open crates. Set a node like "MysteryCrates.Use" to
    // limit crates to the groups that hold it. A single crate can also demand its own node with the
    // "Permission" key inside its own crate file, which is how you build a VIP only crate.
    // If Permissions.dll is missing or will not answer, I let the player through, so a broken
    // permissions install never locks your server out of its own crates.
    // Example: "MysteryCrates.Use"
    "UsePermission": ""
  },

  // ArkShop: the points economy. Only used for rewards of Type "points" inside a crate file.
  // Either shop plugin works here, ArkShop or WShop. The plugin runs perfectly with no shop
  // at all, which is what shards are for.
  "ArkShop": {
    // Enabled: true and I look for a points shop at start up and use it when it is there.
    // false and I never touch it, so a crate reward of Type "points" pays nothing and says so.
    "Enabled": true,

    // Provider: which shop plugin holds the points.
    //   "Auto"    I knock on ArkShop first, then WShop, and use the one that answers.
    //   "ArkShop" only ArkShop.dll.
    //   "WShop"   only WShop.dll.
    // Auto suits nearly everyone. Name one if both shops live on this server.
    "Provider": "Auto"
  },

  // Database: where wallets, shards, seeds, receipts and the book live.
  "Database": {
    // Enabled: true and I keep records. false and I do not start at all, which switches crates off,
    // because a crate ladder with nothing to write to would lose a prize on the first restart.
    // Leave this true unless you are testing something.
    "Enabled": true,

    // UseMySQL: false is SQLite, a single file at data/MysteryCrates.db, with no setup of any kind.
    // true is MySQL, which is what you want when several maps in a cluster should share one wallet,
    // one shard balance and one book. Everything below TablePrefix is for MySQL only.
    "UseMySQL": false,

    // TablePrefix: the front of my five table names, so "mc_" gives mc_players, mc_wallet, mc_opens,
    // mc_book and mc_hold. Change it if you run two instances against one database.
    // Changing it after the fact makes fresh empty tables, it does not rename your old ones.
    // Example: "crates2_"
    "TablePrefix": "mc_",

    // Host, Port, User, Password, Database: your MySQL details. All ignored when UseMySQL is false.
    // Example: "10.0.0.5"
    "Host": "127.0.0.1",
    // Example: 3307
    "Port": 3306,
    // Example: "arkuser"
    "User": "",
    // Example: "a long password"
    "Password": "",
    // Example: "ark_cluster"
    "Database": "",

    // MysqlSSLMode: -1 leaves the client default alone, which is right unless your host told you
    // otherwise. A bigger number asks for a stricter connection, and your host will tell you which
    // one they want.
    // Example: 1
    "MysqlSSLMode": -1,

    // MysqlTLSVersion: blank ("") means the client default. Only fill this in if your host asked.
    // Example: "TLSv1.2"
    "MysqlTLSVersion": "",

    // RecentOpensKept: how many receipts I keep per player before the oldest are pruned.
    // 500 is plenty for any argument about a roll, and /crate verify reads from these.
    // A bigger number keeps a longer history and a slightly bigger file. A smaller number keeps the
    // table tidy and makes an old /crate verify come up empty.
    // I clamp this between 50 and 20000, so anything outside that is pulled back inside.
    // Example: 2000
    "RecentOpensKept": 500,

    // MaxQueuedWrites: how many pending saves I will hold before I start dropping the oldest and
    // counting them in the log. 20000 is far more than a busy server ever queues.
    // It only matters when a remote MySQL goes slow, and it stops that turning into runaway memory.
    // A bigger number survives a longer database hiccup and uses more memory doing it.
    // I clamp this between 500 and 200000.
    // Example: 5000
    "MaxQueuedWrites": 20000
  },

  // Discord: these settings now live in discord.json, in this same folder, so webhook
  // lines stop crowding this file. Same keys as before: Enabled, WebhookURL, AlertWebhookURL, AlertPingHere, Username, ServerName, BatchSeconds, PostsPerMinute, DefaultRoute, Routes, Events, Digest, Backoff.
  // No discord.json yet? I make one at boot from whatever I find. A Discord block left
  // in this config still works too, though discord.json has the last word on any key
  // both of them carry.

  // Panel: the clickable crate window, drawn by the NordBots Companion UI mod.
  // With the mod on your server, players get a window listing every crate they hold,
  // each with its own Open button, plus a Top Openers board and the take or climb
  // choice as buttons on the ladder. Every button press runs the very same code the
  // typed command runs, so nothing can be done through the window that the chat
  // command would refuse. No mod on the server? Nothing changes and this whole block
  // sleeps. The mod is a nice extra, never a must have.
  "Panel": {
    // Enabled: true means I look for the mod and offer the window. false means I never
    // go looking at all, and crates stay chat only. Turn it off if you do not run the
    // NordBots UI mod and want me doing nothing extra.
    "Enabled": true,

    // RowsPerPage: how many crate rows fit on one page of the window. A player holding
    // more kinds than this gets page buttons under the list. 12 is the most the window
    // can carry, and I quietly trim anything higher.
    // Example: 8
    "RowsPerPage": 10,

    // TopCount: how many players show on one page of the Top Openers board. Also
    // capped at 12 so the window stays small enough to send.
    // Example: 5
    "TopCount": 10,

    // BuffTag: the tag on the buff the mod puts on every player. That buff is how my
    // windows reach a player's screen, and the tag is how I spot it. Only change this
    // if the mod itself changes.
    "BuffTag": "NordBotsUIBuff",

    // BuffPath: where inside the mod that buff lives. My backup way of finding it when
    // the tag is missing. Leave it be unless the mod moves things around.
    "BuffPath": "NordBotsUI/Buff_NordBotsUI",

    // SingletonPath: where the mod's main actor sits. I read the mod's version number
    // off it before I send anything. Leave it be unless the mod moves.
    "SingletonPath": "Blueprint'/NordBotsUI/NordBotsUI_Singleton.NordBotsUI_Singleton'",

    // RequireHandshake: what I do when I cannot find a version number on the mod at
    // all. false sends the window anyway and lets the mod skip anything it does not
    // understand, which suits nearly every server. true holds every window back until
    // I can read a matching version. A version that reads as the wrong number always
    // stops the window, whatever this says.
    "RequireHandshake": false
  },

  // ApiUtilsMod: shows my messages in a box on screen instead of plain chat, so a reveal actually
  // lands. It needs the free "ASA API Utils" mod running on your server.
  // Download it here: https://www.curseforge.com/ark-survival-ascended/mods/asa-api-utils
  // Add mod id 955333 to your mod list, restart, and you are set.
  // Optional. Crates work exactly the same without it, the reveals just show as plain text, and the
  // log mentions once that the mod is missing.
  "ApiUtilsMod": {
    // Enabled: true and I hand my messages to the mod. false and I keep using plain game text, even
    // on a server that has the mod loaded.
    "Enabled": true,

    // BackdropColor: what the box behind the text looks like. Four numbers,
    // [red, green, blue, how solid], each one from 0.0 to 1.0.
    // A bigger last number is a heavier box, a smaller one lets the game show through.
    // Set the last number to 0.0 and you get bare text with no box at all.
    // Example: [0.1, 0.0, 0.15, 0.65]  gives a dark purple box
    "BackdropColor": [0.0, 0.0, 0.0, 0.55],

    // ScreenPosition: the spot on screen the box appears in.
    // Choose "Left", "Center" or "Right". Center works for almost everybody.
    // Example: "Right"
    "ScreenPosition": "Center",

    // TextAlign: how the words are lined up inside the box.
    // Choose "Left", "Center" or "Right".
    // Example: "Left"
    "TextAlign": "Center",

    // TextScale: how large the text is drawn. 1.0 is the normal size.
    // A bigger number makes a message shout. A smaller number makes it quiet and small.
    // Above about 2.2 the text starts running off the sides on smaller screens.
    // Example: 1.6
    "TextScale": 1.0,

    // MessageSeconds: how many seconds a box holds on screen before it fades.
    // 6.0 gives a player time to read one line. A bigger number keeps it up longer, a smaller one
    // clears it faster.
    // Example: 10.0
    "MessageSeconds": 6.0,

    // AlsoShowInChat: leave true and every message goes out twice on purpose, once as the pop up box
    // and once as an ordinary chat line that stays in the log. That matters here, because a player
    // wants to scroll back and read what door three was holding.
    // Set it false when you would rather have just the box and a tidy chat window.
    "AlsoShowInChat": true
  },

  // MapName: how the map is written in player facing text and in the {map} tag.
  // What the game hands me is a level file name such as "TheIsland_WP", which I clean up to
  // "The Island" so it reads properly.
  "MapName": {
    // Pretty: true takes off the "_WP" and puts the missing spaces back, so "ScorchedEarth_WP"
    // comes out as "Scorched Earth". false keeps the raw name exactly as the game gives it.
    "Pretty": true,

    // Overrides: your own label for a given map, handy for mod maps whose file name is nothing like
    // the name people use. Raw name on the left, your name on the right, and it wins over Pretty.
    // Example: { "TheCenter_WP": "Center", "Svartalfheim_WP": "Svartalfheim" }
    "Overrides": {}
  }
}