Install, staff-command, permission, configuration, storage and recovery reference for server operators. For how the professions play (XP, skill trees, capstones, boosts and rewards) see the Scuffed Professions gameplay guide.
- Plugin version: 0.25.80-pre.8 (plugin name
ScuffedProfessions)
Requirements
| Plugin | Version | Type |
|---|---|---|
| Hytale server | ≥ 0.7.0-pre.0 and < 0.8.0 | Required |
| EndlessLevelingCore | ≥ 12.6.1 | Required |
| LuckPerms | ≥ 5.5.0 | Required |
| Farming (Hytale) | any | Optional |
| FarmingPlus | any | Optional |
| AnglersAlmanac | any | Optional |
| ScuffedProtection | any | Optional |
| ScuffedNPCs | any | Optional |
| Perfect Dodges | any | Optional |
| EndlessForged | any | Optional |
| EndlessMarriage | any | Optional |
| EndlessGuilds | any | Optional |
| EndlessDurability | any | Optional |
| BetterLootBox | any | Optional |
| EndlessRifts | any | Optional |
| EndlessEliteMobs | any | Optional |
| EndlessFates | any | Optional |
The plugin refuses to load without LuckPerms. It ships its own asset pack (blocks, items, models, UI pages and language files) inside the jar.
Tamework (Alec's Animal Husbandry), the Condensed Crops pack, PlaceholderAPI and an economy plugin are detected at runtime and are not in the manifest. Without them the matching features are simply unavailable (see Integrations).
First boot writes every default file under mods/ScuffedProfessions/. Existing files are never overwritten by a restart, so hand edits survive.
Admin & Staff Commands
All commands live under /professions (alias /prof). The command tree is opened to normal players so the player pages work, and every admin command checks in code for operator status or the scuffedprofessions.admin permission (see Permissions). From the console the admin commands are allowed and each use writes an [SP][AUDIT] line to the log.
General
| Command | Description |
|---|---|
/professions admin | Open the Admin View page (player only) |
/professions reload | Reload every configuration table, packs and language caches. Replies with one short result; a malformed JSON file refuses the reload before anything applies |
/professions debugcurve | Print the live XP curve (base, scale, cap, post-cap step), sample level costs and the curve self-check |
/professions admin glint | Chest glint counters (writes per second, total, drops, lookups, lookup time) |
/professions admin metrics [skill] | Actions per hour, XP per hour and players per profession |
/professions admin announce <text> | Send one line to this server and the rest of the network |
Player XP and progression
| Command | Description |
|---|---|
/professions admin xp <player> <skill> <get|set|add|reset> [amount] | Read or edit profession XP. Adding XP can pay level rewards, setting XP does not replay level-up effects |
/professions admin skill <skill> <key> <value> | Edit a live per-profession setting. Keys: enabled, xpmultiplier, fortune, rarefinds, statrows, durability, gates (inherit clears the override) |
/professions admin perk <player> <profession> <optionId> | Restore one valid tree choice, obeying the current level and pick limits |
/professions admin claims reset <player> [skill] | Clear tree claims for a player (every profession when the skill is left out). Run it twice within 10 seconds to confirm. Charges and grants no reset credits |
/professions admin transcend <player> <skill> <set|clear> | Set or clear the Transcended flag. clear needs the same 10 second double confirmation. Works on offline players |
/professions admin resets balance <player> <profession> | Show a player's reset credit balance |
/professions admin resets give <player|all> <profession> <count> [--txn <receipt>] | Grant tree reset credits. Repeat a partial or uncertain grant with the same receipt and amount; saved grants are not paid twice. all covers currently known players, offline profiles included |
/professions admin diagnose <player> <profession> | Levels, choices, pending deliveries and server-local recovery state |
/professions admin reconcile <player> <profession> | Retry already-owed work for an online player and refresh passives and unlocks. Does not replay ambiguous command rewards or refund money |
/professions admin index rebuild | Rescan stored profiles for the player name index |
/professions admin leaderboard rebuild | Rescan storage and rebuild the leaderboard ranking |
Capstones
| Command | Description |
|---|---|
/professions admin capstone <player> <skill> <grant|revoke|reissue|info> | Grant, revoke, reissue or inspect a numbered capstone. revoke and reissue need the command repeated within 10 seconds |
/professions admin capstones <skill> | List who holds each number of a profession's capstone |
/professions admin capstonehistory <profession> <number> [--page <n>] | Recorded changes to one numbered capstone on this server (6 entries per page) |
/professions admin capstonerepair <profession> <number> <recipient|revoke> "<reason>" | Preview a reassignment or revocation. Reason is 1 to 500 characters |
/professions admin capstoneconfirm <token> | Apply your unchanged preview within 60 seconds |
Boosts
| Command | Description |
|---|---|
/professions admin boost list | Running boosts and the retained purchase ledger |
/professions admin boost start <skill|all> <multiplier> <minutes> [by <name>] [--txn <id>] [--label <text>] | Start a server-wide boost. --label takes the rest of the line, so put it last |
/professions admin boost grant <template> <player> [<profession>] [--txn <id>] | Start a boost bought from the store. This is what a store package runs |
/professions admin boost stop <id|profession|all> | Stop a purchase by id, every boost on a profession, or all. Later totals are recalculated; no money is refunded |
/professions admin boost orders | Unresolved in-game payment intents |
/professions admin boost resolveorder <order> <paid|not-paid> "<reason>" | Record a decision after checking the economy ledger. It never charges or refunds money |
The same four commands list, start, stop and grant also work as /professions boost <subcommand>, from the console too.
Backups, recovery and balance tools
| Command | Description |
|---|---|
/professions admin backup now | Create and verify a manual checkpoint |
/professions admin backup list | Latest ten usable checkpoints |
/professions admin backup info <set|latest> | Verify checksums and show counts and scope |
/professions admin backup restore <set> <player|all> <profession|all> <fields> "<reason>" [--network-offline true] | Preview a selective restore. fields is xp, tree, transcend, resets, a comma list, or all |
/professions admin backup confirm <token> | Apply your own preview within 120 seconds |
/professions admin backup releasehold <player> "<reason>" [--network-offline true] | Release a recovered missing profile after reviewing receipts and custody |
/professions admin vaporisation history <player UUID|all> | Last 20 A/S-tier Vaporiser destructions (retained 30 days or 5,000 records) |
/professions admin vaporisation inspect <id> · preview <id> | Show a record and what a restore would repay |
/professions admin vaporisation restore <id> | Restore a completed record. The original owner must be online here, have room in their main inventory, and hold the repayment in the lowest-tier core |
/professions admin evidence [--profession <skill>] [--days <n>] | XP-per-minute evidence report and balance suggestions; also writes reports/xp-evidence.txt and .csv |
/professions admin evidence reset [--profession <skill>] | Start the XP evidence log fresh. Run it twice within 10 seconds |
/professions admin resetandcompensate | Preview an XP reduction for XP earned under looser settings (see XP reset campaign) |
/professions admin resetandcompensate confirm <token> | Apply your preview within 120 seconds |
Player-run staff commands
These three run in game only (they need a player sender) and check for admin access:
| Command | Description |
|---|---|
/professions artifact <list|inspect|recover|revoke|grant|resetritual> <id> | Relic and revival incense ledger. <id> is an artifact UUID, held for the item in your hand, - for list, a kind for grant (Gaia, Drum, Lantern, Orrery, Seeds, Provisions, Ritual) or a player UUID for resetritual (clears the 30 minute incense crafting cooldown). Recover and revoke change the generation so older copies stop working |
/professions rewardclaims <list|retry|settle|recover> <online player UUID> <reward id or -> | Inspect or resolve a saved tier reward delivery. retry can duplicate a key if the first delivery succeeded, so check BetterLootBox history first |
/professions rejuvinator <inspect|delivered|cancel> <player UUID> | Review an interrupted Rejuvinator purchase. It issues no items and refunds nothing |
Test tools
The /professions test subcommands change only your own character: /professions test <profession> <level> and /professions test level <profession> <level> set your XP to that profession level (1 to 100, capped by curve.cap), /professions test threshold <profession> <level> sets your XP one point below that level (level 2 up), and /professions test kit delivers a cooking test kit (tools, ingredients and recipe scrolls). Bare /professions test prints this usage. They grant no level-up rewards. They work only when testing.commands is true in config.json (default false) and the sender is an admin or holds scuffedprofessions.test. Keep them off on live servers.
Permissions
Nodes are declared in code. The plugin writes no permission block to a manifest.
| Node | Effect |
|---|---|
scuffedprofessions.admin | All admin commands and Admin View. Operators always pass |
scuffedprofessions.use | Lets a player reset a tree with /professions reset <profession>. Without it, players use the Reset button on the profession page. Operators always pass |
scuffedprofessions.test | Use the test tools (together with testing.commands) |
Notes:
- Wildcard and negated nodes (
scuffedprofessions.*,-scuffedprofessions.admin) are read the way the engine reads them. - A provider failure reads as "no access", never as access.
- The
/professions,/professions leaderboard,/professions boost,/professions attuneand/alchemycommands need no node. The first four are opened to thehytale:Adventurergroup. - Titles: master titles use the node
endlesslink.title.master_<profession>, granted through LuckPerms when the player reaches 100. - Shop unlocks: Building level rewards write LuckPerms nodes named
shop.unlock.<set>(see Building shop unlocks). The plugin only ever removes nodes it granted itself. - Boost templates can carry their own
permissionnode for in-game purchase.
Configuration
All files are under mods/ScuffedProfessions/. Admin View exposes the common values in the normal professions menu, edits go into a draft and apply on Apply, stale drafts are refused, and dated backups keep older revisions. Hand edits need /professions reload. Provider and startup settings may need a restart.
| File | Controls |
|---|---|
config.json | Enabled professions, XP multipliers and curve, boosts, anti-farm guards, feedback, integrations, exploration, storage |
xp/<PROFESSION>.json | Per-profession action, item and block XP tables (MINING.json and so on) |
rewards/<profession>.json | Tiers, pick counts, options, fixed rewards, rare finds, capstones |
gates.json | Level requirements on supported crafting and use actions |
cooking.json, alchemy.json, drops.json | Recipes, tuning, custom ingredient sources |
relics.json, excavation.json | Relic odds and issuance windows, GAIA, exposed finds, restoration, artifact contents |
keepsakes.json, reforge.json, vaporiser.json | Tool replacement, Smithing reforge, salvage |
capstones.json, capstone_world.json | Capstone fees and placed effects |
exploration-places.json | Operator-defined landmarks (starts empty) |
text.json, lang/ | Wording and language overrides |
packs/ | Optional content packs |
xp-reset.json | XP reset campaign window (see below) |
settings_sync.json | Written by the settings sync; records what the server last agreed |
Migrations back up the previous file next to it (for example config.json.pre-antifarm-guards.bak, *.pre-base-xp-v<version>.bak). Earned XP, levels, choices, claims and running boosts are never rewritten by a migration. Keep rewards.preserveOnMigrate on if you plan to merge changed reward defaults by hand.
Core settings (config.json)
| Key | Default | Meaning |
|---|---|---|
curve.base / curve.scale / curve.cap | 300 / 200 / 100 | XP curve. Level 100 needs about 11 million cumulative XP at these values. Base 1 to 1,000,000, scale 0 to 1,000,000, cap 2 to 1,000 |
curve.postCapStep | 0 | XP per level after Transcend. 0 derives it from the level 99 to 100 step |
skills.<SKILL>.enabled | true | A disabled skill keeps its stored data but earns nothing and is hidden |
skills.<SKILL>.xpMultiplier | see below | Multiplier on the profession's XP table |
skills.<SKILL>.fortuneEnabled / rareFindsEnabled / durabilityEnabled | true | Per-profession switches for fortune, rare finds and durability tree lines |
skills.<SKILL>.statRowsEnabled | false | Whether legacy attribute rows in the profession's tree are offered. The reviewed stamina and health choices stay available either way |
skills.<SKILL>.gatesEnabled | unset | Overrides gates.enabled for one profession |
routing.blockBreakPriority | MINING, WOODCUTTING, EXCAVATION, FARMING | Which skill claims a broken block, first match wins. A -1 row in an earlier skill stops later ones |
worlds.<world> | none | Per-world xpMultiplier and disabledProfessions. A key also matches every instance of that world (instance-<key>-...) |
transcend.enabled | true | Show the Transcend button |
transcend.announce | true | Chat line when someone Transcends |
transcend.announceScope | network | network (every linked server) or server |
leaderboard.enabled | true | Leaderboard page and rank placeholders |
leaderboard.refreshSeconds | 600 | How stale a rank may get |
leaderboard.maxPlayers | 5000 | Ceiling on one scan |
integrations.endlessQuests.enabled | true | Publish profession counters for EndlessQuests external-counter quests |
gates.enabled | false | Master switch for gates.json level gates |
gates.notifyCooldownMs | 2000 | Minimum gap between refusal messages to one player |
ui.sounds / ui.hudPopups / ui.levelUpToast | true | Feedback switches |
ui.soundVolume | 0.35 | 0 to 1 |
ui.soundCooldownSeconds | 4.0 | 0 to 300 |
floatingXp.enabled / floatingXp.size | true / 1.0 | Floating XP icon and its size (0.4 to 5) |
debug | false | Verbose logging, including per-press building lines |
testing.commands | false | Enable the test tools |
xp.repairEmptyTables | true | Replace an XP table that parses to zero entries with the bundled default (old file kept as .empty.bak). Set intentionallyEmpty inside a table to keep it empty |
xp.richYieldPercentile | 60 | Percentile used by rich-yield tree lines |
Default xpMultiplier per profession: Mining 4, Woodcutting 0.6, Excavation 10.5, Farming 0.33, Fishing 10, Building 15, Smithing 0.65, Alchemy 3, Cooking 54, Husbandry 150, Exploration 2, Acrobatics 10. Values accept any finite number from 0 up; there is no upper clamp, and 0 pays nothing. A gain under one point is kept and added to the player's next gain. The shipped XP tables use MMOSkillTree 1.6.0 values as their base, with ore, wood and crop tiers scaled by this mod.
Profession-specific settings
| Key | Default | Meaning |
|---|---|---|
farming.handPickShare | 0.25 | Share of a crop's row paid for a ripe crop picked by hand (0 to 1; 0 disables) |
farming.areaFullCrops | 6 | Tiles of one area-tool swing that pay in full (1 to 1,024) |
farming.areaExtraShare | 0.25 | Share paid for later tiles in the same swing (0 to 1) |
farming.registerVanillaHarvestCodec | true | Wrap vanilla's HarvestCrop interaction so right-click harvests pay |
farming.breakEventExcludedPrefixes | ["Plant_Crop_"] | Block ids that never pay through the break event |
fishing.failXp | 0 | Raw XP for a failed catch |
fishing.levelPowerBonus | 2.0 | Fishing power added to the Almanac roll at the level cap (0 to 10). Providers without a power-aware roll ignore it and log once |
building.claimSplit.ownClaim / wilderness / otherClaim / unknownProvider | 1.0 / 0.5 / 0.0 / 0.5 | Multiplier on Building XP by where the block lands |
building.recentPlacements.size / windowSeconds / radius | 128 / 600 / 1 | Recycle-debt window: breaking a paid placement within the window holds back the builder's future Building XP |
building.bulkPlacement.enabled | true | Drag and fast-click guard |
building.bulkPlacement.mode | enforce | enforce, or observe to log what it would cut while paying as before |
building.bulkPlacement.dragCellShare | 0.035 | Share paid for each further block of a drag, or a press sooner than the interval |
building.bulkPlacement.minFullPressIntervalMs | 1500 | Minimum gap between full-paid presses |
building.bulkPlacement.pressWindow / sameBlockPresses / sameBlockFactor | 24 / 20 / 0.85 | If 20 of the last 24 presses used one block, each pays 85% |
smithing.benchIds | Furnace, Weapon_Bench, Armor_Bench, Armory, Workbench | Bench ids whose crafts pay Smithing |
smithing.refundEnabled | true | Server-wide switch for the Frugal Smith option |
alchemy.benchIds | Alchemybench | Bench ids whose crafts pay Alchemy |
cooking.stationBlockIds | SP_Cooking_Station | Blocks a cook can start a pot on |
cooking.fire.decay / rise / fall / stoke / drift / driftInterval | 0.60 / 0.20 / 0.10 / 0.12 / 0.16 / 2.6 | Heat-feel tuning, ranges 0.02-4, 0.02-2, 0.01-2, 0.01-2, 0-0.4, 0.2-30. Out of range values are ignored with a warning |
acrobatics.minFallDamage | 5.0 | Least fall damage that pays |
acrobatics.maxCreditedDamage | 60.0 | Most damage one fall is paid for (on a 100 point health pool) |
acrobatics.perfectDodgeEnabled / perfectDodgeInPvp | true / true | Dodge XP switches (needs Perfect Dodges) |
acrobatics.dodgeHourlyXpCap | 20000 | Hard ceiling on dodge XP per player per hour; 0 removes it |
collapse.enabled | true | Extra credit for felled logs and area tools. False disables both |
collapse.areaToolExtraXpFraction | 0.05 | Share a Prisma area-tool extra block pays (0 to 1) |
collapse.radius / verticalRange / gapMs / maxBlocks | 6 / 64 / 1500 / 256 | Bomb and fire attribution window |
collapse.maxLifetimeMs | 8000 | Tree snapshot lifetime (up to 4,096 connected logs) |
remotePull.enabled / maxRadius | true / 5 | Supply Reach and the Supply Network capstone. Radius ceiling is 5 and EndlessGuilds clamps it again |
refining.enabled / maxSpeed | true / 3.0 | Faster Refining. benches maps Furnace, Salvagebench to smithing and Tannery to husbandry |
craftingCapstone.enabled / level / professions / announce | true / 100 / smithing, alchemy, cooking / true | The Supply Network capstone, granted once ever |
rewards.rejuvinatorLevel | 90 | Mining and Farming threshold for the Rejuvinator (multiple of 10, 10 to 100) |
rewards.preserveOnMigrate | false | Keep an old reward file live instead of migrating it |
rewards.crateKeyCommand | lootbox givekey {player} mythos 1 | Console command a $crateKey reward row runs. Empty turns those rows off |
rewards.crateKeyName / crateKeyIcon | Mythos Key | Display name and icon for that reward |
rareFinds.purseXpPerPayment | 24000 | XP per coin payment at a 1% Rare Finds card. purseMin 12000, purseMax 18000 (0 turns payments off), purseRoundTo 100, purseFullXpPerMinute 2000, purseExtraShare 0.1. Nothing rolls without an economy plugin |
Exploration
| Key | Default | Meaning |
|---|---|---|
exploration.hourlyXpCap | 0 | Ceiling on raw repeat XP per player per hour; 0 means none. First discoveries bypass it |
exploration.chestDailyCap | 60 | Paid chest deliveries per player per UTC day |
exploration.riftSources | gate, fate_zone | Wave-completion source ids that count. An empty list disables them |
exploration.questIdPrefixes | world_ | Quest ids eligible for Exploration XP |
exploration.receiptDays | 30 | Age at which receipts of retired chest fills expire |
exploration.maxOpenedPerWorld / maxPlacedPerWorld | 200000 / 50000 | Bounds on the chest ledgers |
exploration.chestTierLevels, chestTierWeights, chestDungeonTierWeights, chestBlockMinTiers, chestSalt, chestTierLoot, chestSwap, chestOpenParticle | shipped | Chest tier and loot tables for E to S. Chest tiers never restrict ordinary loot by level |
exploration.content.* | shipped | World and instance allow-lists, quest, dungeon and raid source rows, maxVolumeChunks, and glint.enabled (12 block radius, 6 seconds between player writes) |
Fate Zone clears take their rank from the run's level band when EndlessFates exposes it: E below level 25, C below 60, A from 60. The limits are exploration.content.earlyLevelLimit (25) and exploration.content.lateLevelStart (60). A claim that spends a Fate charge pays the action row fate_complete_<rank> (shipped 750, 1,500, 3,000 for E, C, A), a claim with no charge or XP only pays fate_assist_<rank> (125, 250, 500), and the first clear of a rank pays fate_first_<rank> instead (4,500, 9,000, 18,000). These rows live in xp/EXPLORATION.json and are raw XP before the multiplier. To add landmarks, edit exploration-places.json. Each places entry has world, a permanent id, nameKey, tier (E to S), and min and max arrays of three coordinates. Keep ids stable when changing bounds. Earned-chest, clear and quest reward queues are stored under exploration-pending. Keep them in server backups.
Anti-farm guards (antifarm)
Several guards are kept in memory only: they survive a relog but not a restart.
| Key | Default | Meaning |
|---|---|---|
antifarm.miningRepeatPositionMinutes | 30 | A mined position pays once in this window (0 to 10,080; 0 disables) |
antifarm.tameCooldownMinutes | 1440 | Re-taming the same animal pays once in this window (0 to 43,200) |
antifarm.landingSpotMinutes | 10 | A survived fall pays once per player per 8 by 8 column (0 disables) |
antifarm.animalCredit.feed / harvest / breeding | 9 / 1 / 1 | Minutes before the same animal pays the same Husbandry action again for its owner (0 turns one off). At most 4,096 animals per owner |
antifarm.tripwire.enabled | true | Backstop per player and action over any 60 seconds, counted in final XP |
antifarm.tripwire.perMinute | see below | Limit per action. A missing action or 0 is not watched |
antifarm.ledger.enabled | true | Placed-block ledger: blocks placed by a player or worker pay no XP when broken in the window |
antifarm.ledger.expiryMinutes | 120 | Window length |
antifarm.ledger.maxEntriesPerWorld | 200000 | Soonest-expiring entries are evicted past this |
antifarm.ledger.exemptItemPrefixes | ["Plant_Seeds_"] | Items not recorded, so crops grown from seeds always pay |
antifarm.diminishing.* | off | Shared fade (windowMinutes 60, fullCount 20000, decaySpan 20000, floor 0.5) and perSkill overrides. Off for every skill by default |
antifarm.pace.<SKILL> | none | Optional per-minute budget: the first fullPerMinute units pay in full and the rest pay extraShare. No skill ships one |
Default perMinute tripwire limits are 40,000 for COOKING:dish, FISHING:catch, HUSBANDRY:feed, HUSBANDRY:harvest, HUSBANDRY:breeding, HUSBANDRY:combat, ACROBATICS:fall, SMITHING:vaporiser and FARMING:harvest, and 120,000 for SMITHING:craft. A trip pays up to the limit, pays nothing beyond it and logs one WARN line naming the player. Furnace and other processing payouts and first-time awards are never counted.
XP evidence and balancing
Each server logs its own XP payouts by player, profession and method (break:Ore_..., craft:..., area:, collapse:, fall:) for 14 UTC days in xp_evidence.json. /professions admin evidence turns that into suggested table or multiplier changes and writes reports/xp-evidence.txt and .csv (rewritten every hour). The suggestions are Cut (a method would take players to 100 faster than the floor), Lower or Raise (typical pace outside the target range), Review and Collect (not enough players yet).
| Key | Default | Meaning |
|---|---|---|
xpEvidence.enabled | true | Record payouts |
xpEvidence.retainDays | 14 | Days kept |
xpEvidence.windowDays | 7 | Default report window |
xpEvidence.bridgeMinutes | 5 | Gaps up to this count as continuous work |
xpEvidence.floorHours | 10 | No single method should reach level 100 faster than this |
xpEvidence.targetMinHours / targetMaxHours | 100 / 200 | Target time to level 100 for a typical player. targetHours.<SKILL> overrides per skill as [min, max] |
xpEvidence.minMinutes / minMethodMinutes / minPlayers | 30 / 10 / 3 | Thresholds for counting a player, a method and a suggestion |
After changing a table row or pace budget, run /professions admin evidence reset [--profession <skill>] twice within 10 seconds so old play does not blend in. A multiplier change needs no reset.
First finds (firsts)
| Key | Default | Meaning |
|---|---|---|
firsts.enabled | true | Gathering, crafting and taming first-find bonuses |
firsts.<kind> | ore 20, wood 10, crop 10, fish 10, dish 5, brew 5, animal 5, chest 0.5, rift 0.5 | Base XP multiplier for that kind; 0 disables it. Chest and rift firsts use the Exploration action rows instead |
firsts.catalog.<kind> | automatic | Restrict a kind to a list of canonical ids (Wood_Oak, Plant_Crop_Carrot, a loot id for fish). An empty array disables the catalog |
Provider catalogs refresh within 30 seconds after startup and on reload. Only current eligible finds count toward the displayed percentage.
Storage settings
| Key | Default | Meaning |
|---|---|---|
storage.sharedBackend | true | Use the Endless Leveling shared backend when it offers one. False forces the local database |
storage.namespace | scuffedprofessions | Servers share data only with servers on the same namespace |
storage.syncXpSettings | true | Keep every skill's xpMultiplier and antifarm.pace rows the same across servers on the shared backend. A change reaches the others within about a minute. The file before the first write is kept as config.json.pre-settings-sync.bak |
storage.retryMillis | 60000 | Retry delay after a storage failure (5,000 to 3,600,000) |
storage.localFile | professions.db | Local database file name |
Boosts and store setup
A boost is never personal. Whoever buys it, every player gets the extra XP and the buyer is credited on the HUD badge and in the announcement.
Key (boosts.*) | Default | Meaning |
|---|---|---|
maxMultiplier | 2.0 | The most XP can be multiplied by, all boosts together |
maxDurationMinutes | 1440 | Longest single purchase. Several purchases can add up to more |
stacking | multiply | Purchases multiply the current rate. Legacy add and highest settings are ignored |
inGamePurchase | false | Let players buy templates with in-game coin using /professions boost <name> |
storeUrl / storeLine | empty / Buy a boost for everyone at {0} | Address and line shown on the Boosts page and in /professions boost |
networkWide | true | Run every boost on every server sharing the backend (restart to apply) |
syncSeconds | 10 | How often a server reads the shared table (2 to 300) |
txnRetentionDays | 30 | How long a transaction id is remembered |
announceStart / announceEnd | true | Chat announcements |
templates | profession_60, all_60 | Each has skill (a profession id, * or choose), multiplier (1.15), minutes (60), label, and for in-game buying price, cooldownMinutes, permission |
Store commands for a purchase (run as an offline command; the buyer need not be online):
professions boost grant all_60 {username} --txn {transaction}
professions boost grant profession_60 {username} cooking --txn {transaction}
- Always pass
--txn. It is the replay guard: the same transaction id delivers one purchase across servers, and a retry on another server is refused. A--txnvalue that still contains{or}is ignored with an[SP][AUDIT] ... UNUSABLE --txn idline and the boost starts without protection. - Purchases multiply the running rate and add their time: at 1.15x with 30 minutes left, another purchase gives 1.3225x for 90 minutes. The fifth purchase reaches the 2x cap and further purchases only add time.
- Renewing within ten minutes of expiry multiplies the previous rate and starts a fresh hour. The gap pays normal XP.
- If the shared backend is down, a paid purchase waits in
boost_queue.jsonand starts on every server with its full time once the table answers. An unreadable queue is kept asboost_queue.json.unreadable-<time>with a SEVERE log line. - Each server records used transaction ids in
boost_txns.txttoo, so a replay during an outage is still refused. - Reply lines start with
Started #<id>,Already started,Recorded(saved, starts when the table answers, do not refund),WARNING: --txn id ignoredorFAILED: .... After fixing aFAILEDpackage, run the corrected command by hand with the same--txnvalue. - Stopping a boost does not refund money. Upgrade every participating server together; an older jar does not understand cumulative totals.
Content packs
A pack adds to the profession tables without editing the files in mods/ScuffedProfessions/. Another mod can ship a pack inside its jar, or you can drop loose files in. Packs are read at boot and on every reload, and the log lists the files used and any problems.
- Inside any
.jaror.zipinmods/, atServer/ScuffedProfessions/<Kind>/<name>.json. - Loose, at
mods/ScuffedProfessions/packs/<pack>/<Kind>/<name>.json.
<Kind> is XpMaps, Rewards, Drops or Vaporiser. Packs apply after your own files: jars and zips in file-name order, then loose packs in folder-name order. Every file may set "mode": add (default, merges key by key, pack wins on a clash, lists are added to) or replace (discards that section of your file and uses the pack's).
| Kind | Purpose |
|---|---|
XpMaps | { "skill": "mining", "entries": { "Ore_Mithril": 90 }, "actions": { } }. A key matches an exact id first, then the longest key ending in _ that the id starts with, then the longest key the id contains. A negative value claims the id and pays nothing |
Rewards | rareFind entries and levelRewards rows for one profession, at any level. Row types: item, command (needs a description), title, blessing, unlock, bonus, fortune, rare_find, xp_bonus, durability, stat |
Drops | Ingredient and scroll drops: mobs, bosses, raids, events, chests, fishing, hoard, each entry with item, chance (0 to 1) and optional min, max |
Vaporiser | rarity rows (item id to a rarity number) merged into vaporiser.json. Packs cannot set baseWorthLowest or the payout formulas |
Reward row notes:
"repeatable": truefires the row again on every climb after Transcend (blessings repeat by default)."scope"on acommand,titleorblessingrow isnetwork(paid once for the whole network on the server where the player levelled) orserver(paid on each server). Commands and blessings default to per-server, titles to network. Items are always per server. Any other word is an error.- Command rows replace
{player},{user}or%player%with the player's name. "retroactive": truegrants a newly introduced row to players who passed the threshold earlier.
ScuffedProfessions ships a few packs of its own (Alchemy reagents and herbs in rare finds, level 90 finds, reagent drops, Alchemy refining XP, and two Drops packs). A pack of yours with "mode": "replace" overrides them.
Building shop unlocks
At certain Building levels a player earns a LuckPerms node shop.unlock.<set>. Nothing is locked until your shop listings ask for the node.
| Level | Node | Suggested contents |
|---|---|---|
| 10 | shop.unlock.builders_woodwork | Branches, roots and leaves |
| 20 | shop.unlock.builders_corner | Royal Magic furniture, cloth roofing and roofs |
| 30 | shop.unlock.lost_civilization | The Human Ruins set |
| 50 | shop.unlock.village_fittings | Brazier, construction sign, training dummy |
| 70 | shop.unlock.temple_masonry | Forgotten gateway, aqua brick |
Nodes are checked on join, on level-up and when an admin changes a level, and an XP reset or lowered level removes the nodes the new level no longer covers. Transcending Building keeps every set. LuckPerms is shared across a network, so servers sharing a LuckPerms database share the unlocks. You can hand a node out yourself (/lp user <name> permission set shop.unlock.temple_masonry true) and the plugin will not remove it. To change the sets, edit the unlock rows in rewards/building.json (id becomes the node name, where is the line shown in the tree, "enabled": false removes it for everyone on their next check) and reload. An unlock row can be added to any tier of any profession.
Gates (gates.json)
Level gates are enforced only while gates.enabled is true (or skills.<SKILL>.gatesEnabled for one profession). The shipped file gates the four high-tier metals, by ore for Mining and by bar for Smithing: Mithril at level 40, Adamantite at 55, Thorium at 70 and Onyxium at 85. Shape:
"MINING": [ { "level": 40, "ids": ["Ore_Mithril"], "message": "gate.mining.mithril" } ]
ids match by prefix (the broken block id for Mining, Woodcutting, Excavation and Farming, the placed block id for Building, the recipe id for Smithing and Alchemy). The highest matching level wins. A refused action is cancelled with a short message.
Capstones and recovery
capstones.json holds attuneFee and remakePrice per profession (25,000 each by default), announceDraw (true), and two power blocks:
| Key | Default | Meaning |
|---|---|---|
gatecaller.sRankChance | 0.005 | Chance the Gatecaller's Sigil opens an S gate with one player online |
gatecaller.sRankPlayerFalloff | 1.0 | The S chance is divided by the number of players online raised to this power (0 turns the scaling off, maximum 4) |
gatecaller.sRankFloor | 0.0001 | Lowest the S chance goes |
gatecaller.aRankShare | 0.55 | Of the gates that are not S, the share that are A; the rest are B |
gatecaller.announce | false | Let Endless Rifts announce the gate to the whole server and offer a free teleport to an S gate |
leviathan.despawnSeconds | 300 | How long a Leviathan stays before it slips back (30 to 3,600) |
leviathan.shoreRadius | 12 | How far from the bobber it looks for dry ground (4 to 32) |
leviathan.role | SP_Leviathan | NPC role it spawns as |
An S roll opens an A gate instead while an S gate or S-Gate event is already running. Each use is once per UTC day per server copy. On a server with no economy, attuning and remaking are free. capstone_world.json holds heartwood.regrowHours (6) and trinketsmith.cooldownDays (7), plus the trinket recipe list.
Capstone state is stored in capstone_ledger.json, capstone_placements.json, capstone_trades.json, capstone_stumps.json and related files, or in the shared backend when one is active. Do not delete player, purchase, artifact, capstone or delivery records to change balance.
Recovery workflow for a capstone loss, mistaken sale or wrong holder:
/professions admin capstonehistory <profession> <number>to read the custody history./professions admin capstonerepair <profession> <number> <recipient|revoke> "reason"for a preview and token./professions admin capstoneconfirm <token>within 60 seconds as the same admin. A changed ownership invalidates the preview, older copies on this server become void (a placed copy too, so inspect terrain), and a replacement waits durably for the recipient to join.- Use another recorded repair to compensate for a mistaken repair.
Other recovery tools:
admin diagnoseandadmin reconcilefor stuck deliveries,admin xp ... get/set/addfor wrong XP,admin perkandadmin claims resetfor tree repair.admin boost stopandadmin boost resolveorderfor wrong or uncertain boosts./professions artifactfor relics and revival incense,/professions admin vaporisationfor A/S Vaporiser destructions,/professions rejuvinatorfor an interrupted station purchase.- Cooking pots, forge sessions, economy receipts, remote terrain and provider-owned animal records need their own evidence. The tools do not invent a lost item, clear an unresolved payment or reset a cooldown based on a player's report alone.
Data & storage
- Player progression (XP, levels, tree choices, Transcend flags, collections, boosts and capstones) is stored in the Endless Leveling shared backend when it is active, so servers on the same
storage.namespaceshare levels, though not items or money. Otherwise it is stored locally inprofessions.dbunder the data folder. A server that previously used shared storage waits for it to return instead of starting a separate local count. - Reset credits live in the entity namespace
scuffedprofessions-tree-resetson shared storage, or intree-resetslocally. Switching from local reset wallets to shared storage is blocked until those wallets are migrated; there is no automatic merge. Keep profile and wallet backups together. - Server-local state files include
rejuvinator_claims.json,furnace_owners.json,forge_benches.json,vaporisation-history.json,purse_payments.json,coin_pouches.json,tablet_readings.json,boost_queue.json,boost_txns.txt,exploration-pending.jsonandxp_evidence.json. Amalgamation uses are recorded in shared storage when enabled, or locally inamalgamation_uses.json. Do not remove that ledger to recover a player's food, because a spent meal could become usable again. - Items, claims and rewards are per server. Each server pays a player the reward rows their levels earned once, even if they levelled elsewhere.
- Backup sets and the checkpoint audit hold private player data. Keep them out of Git and public downloads.
Backups
Professions registers as professions in the Endless Leveling suite backups. EL takes a startup checkpoint and then one each hour. Retention keeps 48 hourly, 14 daily, 10 startup, 20 manual and 20 safety sets. Each Professions checkpoint holds saved player progression, reset balances, local JSON settings and state, and language files, plus (on shared storage) capstones, server-local rewards, legacy claims, relics, revival incense, Amalgamation uses and boosts.
- Every payload has a SHA-256 checksum, verified before a checkpoint is listed as usable. Failed exports keep the previous good sets.
- If EL's suite API is unavailable, checkpoints go to
backups/checkpoints/under the data folder with the same retention. A delayed check runs three minutes after startup if no usable checkpoint exists. There is no shutdown backup. - These are local recovery points. Off-server backups stay the operator's job.
- EL's
/el backupincludes Professions, but EL's broad restore commands report Professions as unsupported and direct you to the selective commands below.
Selective restore: backup restore latest <player> <profession> xp,tree "reason" writes nothing and prints a token. backup confirm <token> first takes and verifies a safety checkpoint, checks for changes since the preview and then applies. Each result is recorded in checkpoint-audit/. XP restore recalculates levels with the current curve. Tree restore keeps the combined choice history. Reset restore keeps current grant receipts.
- Targets must be offline. With shared storage keep them offline on every network server and add
--network-offline true. The plugin cannot verify another server's live session. - Checkpoint namespace, server scope and storage lane must match. These commands do not migrate backups between networks.
- A restore keeps current item-delivery and reward-command receipts, inventories, money, boost purchases and timers, capstone numbers and custody, cooldowns, collections and recipe discoveries. It never replays reward commands or mints capstones.
- If a player's whole profile is missing, receipts, collections and discoveries are recovered and a recovery hold blocks XP, tree changes and reward delivery until an admin reviews post-checkpoint payouts and runs
backup releasehold.
XP reset campaign
/professions admin resetandcompensate lowers profession XP earned under looser settings to what the same play pays today. It does not cap a pace or a level. The window is set in xp-reset.json: campaign, since (start of the window), maxIntervalHours, keepXpBeforeSince (false by default) and historyDirs (relative folders holding backup sets copied from sister servers).
- XP logged in
xp_evidence.jsonis repriced per payout at today's row and multiplier. - Gains before the log, or seen on another server, are revalued at today's multiplier against the lowest multiplier any running server had.
- Nobody is raised above the XP they had at the cutoff, transcended rows are kept, and a gain above what the log paid stays as earned.
- The first run only previews and writes every row to a report. Confirm within 120 seconds with the printed token. Later runs move players only by the difference.
Excavation, Smithing and other tuning files
excavation.json:findChance0.005,maxExposedFinds32,restoreStrokes3,restoreXp150,firstFindXp250,highTierChance0.02,highTierTrinketShare0.5,highTierVoidstoneWeight1 (0 disables Voidstone),tabletLevelFraction0.05,abandonedJobHours24,keenEyeCap0.9,prospectorTin(min3,max5,ores),coinPouch(min150,max350),frostCache,siftOres(copper 3, iron 1) and per-terrainartifactsweights.vaporiser.json:rarityrows,hourlyXpCap(0 by default, no ceiling),bag.payoutShareandbag.xpShare(both 1). No weapon ever pays more than 100,000 lowest-tier cores. A/S destruction history is kept 30 days or 5,000 records.alchemy.json: recipes, costs, levels and grade durations. Hunter's Flare duration is capped at 60 seconds, and radius and enemy count have fixed ceilings. One flare per player, four per world and sixteen per server can be active.cooking.json: recipes, ingredients and theamalgamationobject (mastery level 95, duplicate scale 0.05, minimum quality 0.90, duration 3600 seconds, 24 attribute points, restored health 0.50, protection 3000 ms). The duplicate scale, duration and protection time cannot be raised above those defaults.- Vault keys: the six rank costs, Smithing levels and XP actions (
forge_vault_key_etoforge_vault_key_sinxp/SMITHING.json) are defined in this mod; the key items themselves come from Endless Rifts.
Integrations
| Plugin | Type | Use |
|---|---|---|
| EndlessLevelingCore | Required | Progression storage, attributes, menu navigation (the Professions tab), language selection, suite backups |
| LuckPerms | Required | Shop unlock nodes and master title permissions |
| AnglersAlmanac | Optional | Fishing XP, Quick Bite, fishing potions, Leviathan summons |
| FarmingPlus | Optional | Farming actions, the Sickle capstone, Growth Tonic |
| Tamework (Alec's Animal Husbandry) | Detected | Taming, feeding, breeding and produce XP; animal draughts; Golden Halter |
| Perfect Dodges | Optional | Dodge XP for Acrobatics |
| EndlessForged | Optional | Forged weapon upgrades, Vaporiser eligibility and currencies, trinket equipment, soulbound capstone trades |
| ScuffedNPCs | Optional | Mining sites, guild blessings, Rejuvinator worker supplies (capacities and worker travel are owned there) |
| EndlessGuilds / ScuffedProtection | Optional | Claim checks, guild supply access, claim flight, GAIA spawn filtering, Supply Network |
| EndlessMarriage | Optional | Recorded one-use NPC spouse revival. Profession XP is never spouse-shared |
| EndlessRifts / EndlessEvents | Optional | Exploration completions, Treasure Finder grants, Breach vault key items for the Forge Bench, Gatecaller's Sigil |
| EndlessFates | Optional | Fate Zone clear payouts |
| EndlessDurability | Optional | Death wear reduced by Equipment Care and Workshop Care |
| BetterLootBox | Optional | Mythos key claims with delivery confirmation |
| Condensed Crops pack | Detected | The Amalgamation recipe |
| EndlessQuests | Detected | Profession counters for external-counter quests (integrations.endlessQuests.enabled) |
| ZenShop or any shop that reads permissions | External | Lock listings behind shop.unlock.<set> with requiresPermission |
| PlaceholderAPI | Detected | %professions_*% placeholders (see below) |
Missing optional integrations disable their feature and never grant another player your XP. Third-party controls and configuration stay in the owning mod.
Placeholders
The professions expansion registers when PlaceholderAPI is present (see the PlaceholderAPI guide).
| Placeholder | Value |
|---|---|
%professions_total_level% · %professions_total_xp% · %professions_total_lifetime% | Sums across all professions |
%professions_rank_total% | Rank by total |
%professions_level_<id>% · xp_<id> · lifetime_<id> | Level, current XP, lifetime XP in a profession |
%professions_transcended_<id>% | Whether the profession is Transcended |
%professions_rank_<id>% | Leaderboard rank in a profession |
%professions_top_<id>_<n>% · %professions_top_total_<n>% | Name at rank n (1 to 10) |
%professions_first_<id>% | Name of the No. 1 capstone holder |
%professions_minted_<id>% | Numbered capstones that exist |
%professions_capstone_<id>% | The player's capstone number, or empty |
<id> is mining, woodcutting, excavation, farming, fishing, building, smithing, alchemy, exploration, cooking, acrobatics or husbandry.
Languages
English ships in the jar. For runtime overrides use mods/ScuffedProfessions/lang/<locale>.lang with underscores (for example lang/es_ES.lang); missing keys fall back to English. text.json is a flat language-independent override map that takes precedence. Keep keys, item ids, command tokens and {0} placeholders unchanged. Run /professions reload and reopen the page. Native item and UI changes in an asset pack may also need an asset reload or a restart. Custom recipe and ingredient names use the keys alchemy.brew.<item-id>, alchemy.reagent.<item-id> and cooking.ingredient.<item-id>.
API for other mods
Use com.zbeve.scuffedprofessions.api.ScuffedProfessionsAPI. All members are public static, so a call works without holding an instance.
| Area | Methods |
|---|---|
| Readiness | isReady(), hasData(uuid) |
| Read | getLevel, getXp, getLifetimeXp, getLevelProgress, xpIntoLevel, xpForNextLevel, isTranscended, getAllXp, getAllLevels, getTotalXp, getTotalLevel, xpForLevel, levelForXp, getProfessions |
| Capstones | hasCapstone, holdsCapstone, carriesCapstone, capstoneWorksFor, transcendedCount |
| Leaderboard | leaderboard(profession, limit) |
| Award XP | addXp(uuid, profession, amount, reason), award(...) (returns PAID, HELD_AT_CAP, BANKED or REFUSED), awardFinal for a displayed final amount |
| Edit | setXp, removeXp, setTranscended |
| Tree | claims, claim, resetClaims, bonus(uuid, skill, key) |
| Events | addXpListener, addLevelUpListener, addTranscendListener and matching remove methods (ProfessionXpEvent, ProfessionLevelUpEvent, ProfessionTranscendEvent) |
Rules for callers:
- Read-only consumers can query levels, XP, Transcend state and tree bonuses without issuing XP.
- Use
addXponly for a confirmed action by the supplied player. The source identity matters for anti-farming and audit. Do not award viewers, nearby players, spouses or unknown furnace owners. - It returns false and changes nothing when the profession or world is off, the amount is not positive, the player is in Creative (admin grants excepted) or the gain is under a whole point after the multiplier (the fraction is kept for the next gain).
- Resets spend one credit for that profession. Use the admin recovery tools for capstone and artifact replacements. Raw item creation does not produce a valid numbered copy.
- Configuration and reward records are not stable integration APIs. Register content through packs where possible, compile against the versions you deploy and test missing-provider behavior separately.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| The plugin does not load | LuckPerms or EndlessLevelingCore is missing or too old. Check the versions under Requirements |
/professions reload says to check the log | A JSON file is malformed. Nothing was applied. Fix the file and reload |
| A profession shows no XP | The profession is disabled in skills, the world lists it in disabledProfessions, or the player is in Creative |
| Players get no XP from placed blocks, cave spots or repeated actions | Working as designed: placed-block ledger (120 minutes), mining repeat window (30 minutes), animal credit windows and landing-spot window |
| A player's profile reads as missing after a restore | A recovery hold is set. Review payouts and custody, then backup releasehold |
| A capstone does nothing on another server | A copy works only on the server that made it. The player claims a copy on each server |
| A boost purchase did not start | Check [SP][AUDIT] lines. Recorded means it waits for the shared table; FAILED means rerun the corrected command by hand with the same --txn |
| Tame XP does not pay | Taming the same animal again pays once per antifarm.tameCooldownMinutes, and claiming an already-tamed animal is not a tame. Check the Tamework version |
| Config edits are overwritten on another server | storage.syncXpSettings shares xpMultiplier and antifarm.pace across servers on the same namespace. Edit the value on one server or turn the sync off |
| A reward claim shows Check | Use /professions rewardclaims list <uuid> -, verify the provider history, then retry or settle |