342 lines
12 KiB
Markdown
342 lines
12 KiB
Markdown
# Soul Steal Project Documentation
|
||
|
||
## Overview
|
||
|
||
Soul Steal is a server-side Fabric mod that implements a soul economy, player bounties, tracker compasses, a vanilla-style shop GUI, optional HUD elements, and permission-backed admin controls.
|
||
|
||
The mod is built to run entirely on the server. Players do not need a client mod to use the commands or the shop.
|
||
|
||
## Runtime Architecture
|
||
|
||
The entry point is [`SoulStealMod`](../src/main/java/com/g2806/soulsteal/SoulStealMod.java), which performs four jobs:
|
||
|
||
1. Loads configuration from `config/soulsteal/config.yml`.
|
||
2. Loads persistent player data from `config/soulsteal/soulsteal-data.json`.
|
||
3. Instantiates the feature services.
|
||
4. Registers command, tick, join, death, and disconnect handlers.
|
||
|
||
The main services are:
|
||
|
||
- [`SoulService`](../src/main/java/com/g2806/soulsteal/service/SoulService.java): balance reads and mutations.
|
||
- [`BountyService`](../src/main/java/com/g2806/soulsteal/service/BountyService.java): bounty placement, expiry, and kill claims.
|
||
- [`TrackerCompassService`](../src/main/java/com/g2806/soulsteal/service/TrackerCompassService.java): temporary tracking compasses for player kills.
|
||
- [`ShopService`](../src/main/java/com/g2806/soulsteal/service/ShopService.java): server-side shop GUI and purchases.
|
||
- [`RewardService`](../src/main/java/com/g2806/soulsteal/service/RewardService.java): validates and grants rewards from shop entries.
|
||
- [`PermissionService`](../src/main/java/com/g2806/soulsteal/service/PermissionService.java): permission lookups and fallback storage.
|
||
- [`HudService`](../src/main/java/com/g2806/soulsteal/service/HudService.java): scoreboard sidebar, leaderboard, and bounty bossbar.
|
||
|
||
Shared utilities:
|
||
|
||
- [`SoulTexts`](../src/main/java/com/g2806/soulsteal/util/SoulTexts.java): formatted feedback, success, warning, and error messages.
|
||
- [`DurationFormatter`](../src/main/java/com/g2806/soulsteal/util/DurationFormatter.java): human-readable duration strings.
|
||
|
||
## Feature Summary
|
||
|
||
### Soul Economy
|
||
|
||
Players have a soul balance stored per UUID.
|
||
|
||
- Killing another player can grant souls.
|
||
- Dying can remove souls using configurable flat and percentage penalties.
|
||
- Transfers between players can be enabled or disabled in config.
|
||
- Admin commands can set, add, or remove balances directly.
|
||
|
||
Implemented by:
|
||
|
||
- [`SoulService`](../src/main/java/com/g2806/soulsteal/service/SoulService.java)
|
||
- [`SoulCommandRegistrar`](../src/main/java/com/g2806/soulsteal/command/SoulCommandRegistrar.java)
|
||
|
||
### Bounties
|
||
|
||
Players can place timed bounties on other players using their souls as the payment source.
|
||
|
||
Behavior:
|
||
|
||
- Placement is bounded by min/max value, min/max duration, cooldowns, and active bounty limits.
|
||
- Killing the target claims all active bounties on that target.
|
||
- If a bounty expires, the target receives a configured survivor payout.
|
||
- Bounties are cleared if the target dies to non-player damage and no killer claims them.
|
||
|
||
Implemented by:
|
||
|
||
- [`BountyService`](../src/main/java/com/g2806/soulsteal/service/BountyService.java)
|
||
- [`SoulStealMod`](../src/main/java/com/g2806/soulsteal/SoulStealMod.java)
|
||
|
||
### Tracker Compasses
|
||
|
||
When enabled, killing a player grants a temporary tracker compass.
|
||
|
||
Behavior:
|
||
|
||
- The compass tracks the killed player using lodestone-tracker data.
|
||
- The item stores target UUID, target name, and expiration time in custom NBT.
|
||
- Expired compasses are removed during server ticks.
|
||
- Optional behavior can remove the compass if the target is offline.
|
||
|
||
Admins can also grant a tracker compass directly with `/souls tracker give <player> <target>`. This uses the same tracker data and duration as the kill-granted version.
|
||
|
||
### Contracts
|
||
|
||
Contracts let players earn souls without PvP by completing mining and hunting goals.
|
||
|
||
Behavior:
|
||
|
||
- Players pick one active contract at a time.
|
||
- Mining contracts track block breaks against a configured block id.
|
||
- Hunting contracts track kills against a configured entity id.
|
||
- The selected contract and its progress appear in the HUD sidebar.
|
||
- Completing a contract pays souls automatically.
|
||
- One-time contracts disappear from the browser after completion and cannot be selected again.
|
||
- The contract browser uses `catalog.yml`, where the YAML key is the internal contract id and `name` is the player-facing label.
|
||
- Contract entries are organized under `contracts: mining:` and `contracts: hunting:` sections for readability, while still using per-entry ids.
|
||
- The contract browser uses a bottom control row like the shop, including page navigation anchored to the bottom of the inventory.
|
||
- The contract browser includes a clear-selection action on the home page and inside contract categories so players can remove their active contract from the GUI.
|
||
|
||
Implemented by:
|
||
|
||
- [`ContractService`](../src/main/java/com/g2806/soulsteal/service/ContractService.java)
|
||
- [`ContractGuiService`](../src/main/java/com/g2806/soulsteal/contract/ContractGuiService.java)
|
||
- [`ContractCatalog`](../src/main/java/com/g2806/soulsteal/contract/ContractCatalog.java)
|
||
- [`ContractDefinition`](../src/main/java/com/g2806/soulsteal/contract/ContractDefinition.java)
|
||
|
||
### Shop
|
||
|
||
The shop is a chest-based GUI rendered entirely with vanilla screen handler APIs.
|
||
|
||
Behavior:
|
||
|
||
- The home view lists categories with pagination.
|
||
- Category views list entries with pagination.
|
||
- Item entries can be direct purchases or quantity-select purchases.
|
||
- Purchases can be repeatable or single-unlock.
|
||
- Cooldowns can be stored per entry per player.
|
||
- Rewards can include items, effects, commands, and permissions.
|
||
|
||
Implemented by:
|
||
|
||
- [`ShopService`](../src/main/java/com/g2806/soulsteal/service/ShopService.java)
|
||
- [`RewardService`](../src/main/java/com/g2806/soulsteal/service/RewardService.java)
|
||
- [`SoulShopScreenHandler`](../src/main/java/com/g2806/soulsteal/shop/SoulShopScreenHandler.java)
|
||
- [`ShopCatalog`](../src/main/java/com/g2806/soulsteal/shop/ShopCatalog.java)
|
||
|
||
### HUD
|
||
|
||
The HUD layer is optional and configurable per player.
|
||
|
||
Behavior:
|
||
|
||
- Scoreboard sidebar can be enabled globally and toggled per player.
|
||
- The sidebar title uses the same dark aqua styling as the mod's chat prefix.
|
||
- Contract and bounty rows only appear while the player has an active selected contract or active bounties.
|
||
- Balance, contract, and bounty rows use color to make the sidebar easier to scan.
|
||
- Leaderboard pages are built from stored player names and balance values.
|
||
- Wanted-player bossbars show bounty value and remaining time.
|
||
|
||
Implemented by:
|
||
|
||
- [`HudService`](../src/main/java/com/g2806/soulsteal/service/HudService.java)
|
||
|
||
### Permissions
|
||
|
||
The mod checks permissions in two layers:
|
||
|
||
1. External permission backends through the Fabric permissions API and optional LuckPerms integration.
|
||
2. Internal fallback storage persisted in `soulsteal-data.json`.
|
||
|
||
This allows reward-granted permissions and admin nodes to keep working even without an external permission mod.
|
||
|
||
Implemented by:
|
||
|
||
- [`PermissionService`](../src/main/java/com/g2806/soulsteal/service/PermissionService.java)
|
||
|
||
## Command Reference
|
||
|
||
The root command has two aliases:
|
||
|
||
- `/souls`
|
||
- `/soul`
|
||
|
||
### Player Commands
|
||
|
||
- `/souls`
|
||
- Shows your current balance.
|
||
- `/souls balance`
|
||
- Same as `/souls`.
|
||
- `/souls balance <player>`
|
||
- Shows another player’s balance.
|
||
- `/souls pay <player> <amount>`
|
||
- Transfers souls to another player.
|
||
- `/souls shop [category]`
|
||
- Opens the shop GUI.
|
||
- `/souls bounty place <player> <amount> [durationSeconds]`
|
||
- Places a bounty.
|
||
- `/souls bounty list [player]`
|
||
- Lists active bounties.
|
||
- `/souls scoreboard`
|
||
- Shows scoreboard visibility state.
|
||
- `/souls scoreboard toggle`
|
||
- Toggles the player’s scoreboard preference.
|
||
- `/souls scoreboard on`
|
||
- Forces scoreboard visibility on.
|
||
- `/souls scoreboard off`
|
||
- Forces scoreboard visibility off.
|
||
- `/souls top [page]`
|
||
- Shows leaderboard pages.
|
||
- `/souls tracker give <player> <target>`
|
||
- Gives a tracker compass to one player that points at another player.
|
||
- `/souls contracts`
|
||
- Opens the contract browser GUI.
|
||
- `/souls contracts selected`
|
||
- Shows the currently selected contract and progress.
|
||
- `/souls contracts clear`
|
||
- Clears your selected contract.
|
||
|
||
### Admin Commands
|
||
|
||
- `/souls reload`
|
||
- Reloads config and shop definitions.
|
||
- `/souls set <player> <amount>`
|
||
- Sets a balance directly.
|
||
- `/souls add <player> <amount>`
|
||
- Adds souls to a balance.
|
||
- `/souls take <player> <amount>`
|
||
- Removes souls from a balance.
|
||
|
||
Permission defaults and node names are configured in `config.yml`.
|
||
|
||
## Configuration Files
|
||
|
||
### `config/soulsteal/config.yml`
|
||
|
||
Primary configuration file. It controls:
|
||
|
||
- Economy values
|
||
- Death penalties
|
||
- Transfer rules
|
||
- Bounty limits and payouts
|
||
- Tracker compass behavior
|
||
- Shop UI defaults
|
||
- HUD toggles and titles
|
||
- Permission node names
|
||
|
||
The schema is defined in [`SoulStealConfig`](../src/main/java/com/g2806/soulsteal/config/SoulStealConfig.java).
|
||
|
||
### `config/soulsteal/shop.yml`
|
||
|
||
Shop catalog definition. It controls:
|
||
|
||
- Shop title and layout
|
||
- Category list
|
||
- Entry pricing
|
||
- Entry cooldowns
|
||
- Reward definitions
|
||
- Optional custom quantity selector behavior
|
||
|
||
The catalog is loaded through [`ConfigBundle`](../src/main/java/com/g2806/soulsteal/config/ConfigBundle.java).
|
||
|
||
### `config/soulsteal/catalog.yml`
|
||
|
||
Contract catalog definition. It controls:
|
||
|
||
- Grouped contract lists under `mining` and `hunting`
|
||
- Internal contract ids from each entry `id`
|
||
- Player-facing contract names
|
||
- Icon item ids
|
||
- Target block or mob ids
|
||
- Required amounts and rewards
|
||
- Repeatable behavior
|
||
|
||
The catalog is loaded through [`ConfigBundle`](../src/main/java/com/g2806/soulsteal/config/ConfigBundle.java).
|
||
|
||
### `config/soulsteal/soulsteal-data.json`
|
||
|
||
Persistent runtime data. It stores:
|
||
|
||
- Player soul balances
|
||
- Active bounties
|
||
- Bounty placement cooldowns
|
||
- Shop unlocks
|
||
- Shop purchase cooldowns
|
||
- Permission fallback grants
|
||
- Player name history
|
||
- Scoreboard visibility preferences
|
||
- Selected contracts
|
||
- Contract progress
|
||
|
||
Loaded and saved by [`SoulStealDataStore`](../src/main/java/com/g2806/soulsteal/data/SoulStealDataStore.java).
|
||
|
||
## Data Flow
|
||
|
||
### Player Join
|
||
|
||
When a player joins:
|
||
|
||
1. Their name is recorded in persistent data.
|
||
2. Their HUD state is refreshed.
|
||
3. Any configured scoreboard or bossbar state is pushed to them.
|
||
|
||
### HUD Sidebar
|
||
|
||
When the sidebar is visible:
|
||
|
||
1. The title is rendered in dark aqua.
|
||
2. The soul balance row is always shown.
|
||
3. Contract rows are only shown if the player has an active selected contract.
|
||
4. Bounty rows are only shown if the player currently has active bounties.
|
||
5. The visible rows use color to distinguish balance, contract, and bounty information.
|
||
|
||
### Player Kill
|
||
|
||
When one player kills another player:
|
||
|
||
1. The killer receives kill reward souls if enabled.
|
||
2. Any matching bounties on the victim are claimed.
|
||
3. The killer receives a tracker compass if the tracker feature is enabled.
|
||
4. Any matching hunting contract progresses if the killer has one selected.
|
||
|
||
### Block Break
|
||
|
||
When a player breaks a block:
|
||
|
||
1. Any matching mining contract progresses if the player has one selected.
|
||
|
||
### Player Death
|
||
|
||
When a player dies:
|
||
|
||
1. The configured death penalty is applied.
|
||
2. If the death was not caused by another player, unclaimed bounties on the victim can be cleared.
|
||
|
||
### Server Tick
|
||
|
||
On server tick:
|
||
|
||
1. Tracker compasses are updated and expired compasses are removed.
|
||
2. Bounty expirations are processed once per second.
|
||
3. HUD elements are refreshed.
|
||
|
||
### Server Shutdown
|
||
|
||
On shutdown:
|
||
|
||
- Persistent data is saved to disk.
|
||
|
||
## Project Structure
|
||
|
||
- `src/main/java/com/g2806/soulsteal/`
|
||
- Bootstrap, commands, services, config, data, shop, and utilities.
|
||
- `src/main/java/com/g2806/soulsteal/contract/`
|
||
- Contract catalog, GUI, and screen handling classes.
|
||
- `src/main/resources/`
|
||
- Fabric metadata and resource files.
|
||
- `build.gradle`
|
||
- Fabric Loom build configuration.
|
||
|
||
## Development Notes
|
||
|
||
- The mod targets Java 21.
|
||
- It is structured as a server-only feature set, so most behavior is driven by server lifecycle events.
|
||
- Persistence is intentionally simple: one JSON data file and YAML-driven configuration.
|
||
- External integrations are reflected through reflection-based checks so the mod can run without hard dependencies on permission backends.
|
||
- Contract configuration is separated into `catalog.yml` so contract entries can be expanded without changing the main economy config.
|