DuelForge 2.1.1

A duel plugin for Paper 26.3 with:


Requirements

Server Paper 26.3 (tested against build 26.3-169)
Java 25 (Paper 26.3 requires it; the plugin itself is compiled for Java 21 bytecode)
Optional Multiverse-Core 5.8.1+ for /mv managed arena worlds (without it the plugin falls back to plain Bukkit world creation)

Build

mvn package          # produces target/DuelForge-2.1.1.jar

The build compiles against io.papermc.paper:paper-api:26.3.build.169-beta and org.mvplugins.multiverse.core:multiverse-core:5.8.1 — change the paper.version / multiverse.version properties in pom.xml if you target another build.

Optionally validate the shipped YAML with the same parser Bukkit uses:

java -cp ~/.m2/repository/org/yaml/snakeyaml/2.2/snakeyaml-2.2.jar \
     tools/YamlCheck.java src/main/resources/*.yml

Install

  1. Drop DuelForge-2.1.1.jar (and optionally multiverse-core-5.8.1.jar) into plugins/.
  2. Start the server once — plugins/DuelForge/{config.yml,messages.yml,kits.yml,shop.yml} are created. Any world folder named duelsPaperSpigot-* is registered as an arena automatically.

Quick start

1. Build the arena

Three ways, easiest first.

Template worlds — one command. Drop a ready-made map into the server folder as a world whose name starts with arenas.template-prefix (default duelsPaperSpigot-, e.g. duelsPaperSpigot-1, duelsPaperSpigot-2, …). DuelForge loads/imports such a world itself and — because a prefix is a wildcard — one arena entry accepts any matching world, so you add maps by dropping in folders:

/duelarena quick classic duelsPaperSpigot-           # whole-world clone arena, spawns + beds auto-set
/duelarena quick bedfight duelsPaperSpigot- bedwars  # BedWars variant

(Pass an exact name such as duelsPaperSpigot-1 to pin one specific map. In a normal world /duelarena quick <name> instead cuts a arenas.default-box-radius cube around you.)

The region becomes the whole world (arenas.world-radius, which also becomes the world border), spawn 1 is the world spawn, spawn 2 a safe spot alongside it, spectator 8 blocks above, and for bedwars two beds are placed two blocks behind the spawns. Review it any time with /duelarena info classic / /duelarena check classic.

Boxes / whole worlds — also one command.

/duelarena quick classic 40      # cube of radius 40 around you, spawns + beds auto-set
/duelarena box 40 classic        # just re-cut the region to a cube around you
/duelarena world classic         # make the arena the whole world you are standing in
/duelarena autospawn classic     # (re)derive spawn 1/2 + spectator from the region
/duelarena autobeds classic      # (re)derive the bed anchors

Fully manual (full control; a dedicated template world such as duel_template is recommended so the clone only contains arena content):

/mv create duel_template normal            # optional, only when using Multiverse
/duelarena create classic                  # remembers you are editing "classic"
/duelarena wand                            # left click = position 1, right click = position 2
/duelarena pos1     /duelarena pos2        # alternative: mark your current position
/duelarena region classic                  # store the two corners as the arena region
/duelarena setspawn 1 classic              # stand where player 1 should spawn
/duelarena setspawn 2 classic
/duelarena setspawn spectator classic      # optional spectator spot
/duelarena setbed 1 classic                # optional: exact bed anchor for team 1
/duelarena save classic
/duelarena check classic                   # generates the world once and reports the result
/duelarena preview classic                 # fly through the generated arena, "/duelarena preview stop" to leave

The spawns must be inside the region; the region is what gets cloned/copied into the temporary world, and it also becomes the world border (world.world-border) so players cannot run away.

Repeat for every map you want — /duelarena list shows all of them, weight controls how often a map is picked, and kit add <kit> <arena> restricts which kits may be played on a map.

2. Build a kit

/duelkit create sword        # copies your current inventory, then opens the editor
/duelkit edit sword          # visual editor: slots 0-35 inventory, 36-39 armour, 40 offhand
/duelkit set sword health 20
/duelkit set sword cooldown 60
/duelkit set sword permission duelforge.kit.sword
/duelkit add-effect sword SPEED:1:-1        # type:amplifier:durationTicks (-1 = infinite)
/duelkit info sword

Kits can also be hand-written in kits.yml with a plain items: list — see the comments in that file.

3. Duel

/duel <player> [kit] [arena] [ranked]     # send a request (clickable in chat)
/duel accept | deny [player]
/duel queue [kit] [arena] [ranked]        # matchmaking against another waiting player
/duel menu                                # full menu: opponents, kits, arenas, ranked, stats, top
/duel spectate <player>
/duel leave                               # forfeits the duel (or stops spectating)

4. BedWars duels

An arena created with the bedwars keyword (/duelarena quick bedfight duelsPaperSpigot- bedwars) or switched later with /duelarena mode bedfight bedwars is played with respawns. Players can also ask for the mode per request:

/duel <player> bedwars              # or `bedwars` as the arena / kit argument, mode keywords win

Rules (all tunable under bedwars: in config.yml):

/duelarena check <arena> reports the beds it placed in the generated world (4 bed(s), 8/8 bed blocks verified), so you can confirm a map works without starting a duel.

5. Team duels and the random queue

A duel is a set of teams. Team shapes are written 2v2, 3v3, 4v4, or AxB for A teams of B players:

Shape Teams Players Modes
1v1 2 2 regular + BedWars
2v2 2 4 regular + BedWars
3v3 2 6 regular + BedWars
4v4 (= 2x4) 2 8 regular + BedWars
4x4 4 16 BedWars only

2x4 and 4v4 are the same two teams of four, so the spellings share one queue. Every team needs its own spawn, and in BedWars its own bed — /duelarena autospawn derives up to four of them, and the shape you queue for picks the teams automatically:

/duel queue 2v2 bedwars        # wait for four players, teams of two
/duel queue 4x4 bedwars        # BedWars-only four teams of four (16 players)
/duel random 3v3               # random queue: matched with anyone waiting
/duel random                   # random 1v1

Which shapes are allowed is configurable (teams.formats, teams.bedwars-formats) and per arena with /duelarena teams <arena> 2v2 3v3 4x4. The menu (/duel menu) has a team-shape button and a random-duel button.

6. Shops and resource generators (BedWars)

Every BedWars island gets a shop villager and iron + gold generators; the middle of the map also produces iron, gold and emeralds. Right click the villager to open the shop — categories, prices and items come from shop.yml and purchases cost the iron / gold / emerald in your inventory:

/duelarena shop <arena> on|off|default        # per arena switch
/duelarena generators <arena> on|off|default

Timings and the safety cap live under bedwars.generators in config.yml (iron-interval, gold-interval, emerald-interval, max-nearby-items, …).

7. Using a whole world as it is (LIVE)

Each arena can pick how its world is produced — the global world.content-mode or a per-map override (/duelarena content <arena> CLONE|COPY|LIVE|DEFAULT):

8. The world settings screen

/duelarena menu (aliases /da worlds, /da settings) opens a clickable screen listing every arena. Click one to configure it per gamemode:

9. Template maps are discovered automatically

Any world folder whose name starts with arenas.template-prefix (duelsPaperSpigot- by default) is registered as a whole-world BedWars arena on startup — drop a map folder into the server and it works. The spawns, beds and playable region are derived from the map the first time it is generated. /duelarena scan does the same on demand and is safe to run repeatedly.


Console output after this was verified on a real server

[DuelForge] Enabling DuelForge v1.0.0
[DuelForge] Loaded 3 kits and 1 arenas.
[DuelForge] World mode: MULTIVERSE / content mode: CLONE
[DuelForge] Ranking: WINS
DuelForge » Generating arena <aqua>Test Arena...
[DuelForge] [debug] Copied 867 blocks into duelforge_test_1
[DuelForge] [debug] region copy verification: 8/8 sampled blocks match
DuelForge » Arena <aqua>Test Arena generated successfully (duelforge_test_1, 867 blocks copied, spawn duelforge_test_1 3/70/8)
[DuelForge] [debug] Deleted temporary world duelforge_test_1 through Multiverse.

Commands

Command Permission Description
/duel [menu] duelforge.duel Open the duel menu (defaults to it when run without arguments)
/duel <player> [kit] [arena] [ranked] duelforge.duel Send a duel request
/duel accept|deny [player] duelforge.duel Answer a request
/duel queue [kit] [arena] [2v2|3v3|4v4|4x4] [ranked] [bedwars] duelforge.duel Join the match queue for a team shape
/duel random [1v1|2v2|3v3|4v4|4x4] [ranked] [bedwars] duelforge.duel Random queue: matched with anyone, random kit and map
/duel spectate <player> duelforge.spectate Watch a duel (spectator mode)
/duel leave duelforge.duel Forfeit / stop spectating / leave the queue
/duel stats [player] duelforge.duel Statistics menu
/duel top [page] duelforge.duel Leaderboard
/duel stop <player> duelforge.admin.duel Abort a running duel
/duel reload duelforge.admin.reload Reload config, messages, kits and arenas
/duelkit create|edit|delete|list|info|give|icon|set|add-effect|clear-effects duelforge.command.kit Kit management
/duelarena quick <name> [world|prefix] [radius] [bedwars] duelforge.admin.arena Create a playable arena in one command — whole-world for a template prefix, otherwise a box around you — with spawns (and beds for bedwars) derived automatically
/duelarena create|pos1|pos2|wand|region|box|world|autospawn|autobeds|setspawn|setbed|mode|save|list|info|enable|disable|delete|kit|tp|weight|icon|check|preview|reload duelforge.admin.arena Arena management (check/preview generate a world once so you can test a map)
/duelarena menu|worlds|settings duelforge.admin.arena Clickable world settings screen per gamemode
/duelarena scan duelforge.admin.arena Register one arena per template map found
/duelarena content <arena> <DEFAULT|CLONE|COPY|LIVE> duelforge.admin.arena How the arena’s world is produced
/duelarena teams <arena> [2v2 3v3 4v4 4x4] duelforge.admin.arena Allowed team shapes (no shapes = all)
/duelarena generators|shop <arena> [on|off|default] duelforge.admin.arena Per-arena BedWars extras
/duelrank top|stats|reset <player|all> duelforge.rank (duelforge.admin.rank for reset) Ranking

Aliases: /duels, /df, /da, /arenas, /dk, /kits, /dr, /rank. Console can use list, info, check, enable/disable, delete, kit, weight, icon, save, reload and duelrank; anything that needs a location or inventory (region, spawns, preview, kits) requires a player.

Permissions

Node Default Purpose
duelforge.duel true Use /duel
duelforge.spectate true Spectate duels
duelforge.rank true Use /duelrank and the leaderboard
duelforge.kit.list true List kits
duelforge.command.kit op Manage kits
duelforge.admin.arena op Manage arenas
duelforge.admin.reload op /duel reload
duelforge.admin.duel op /duel stop
duelforge.admin.rank op /duelrank reset
per-kit — Optional node you set with /duelkit set <kit> permission <node>

How the temporary arena world works

world.content-mode (a per-arena override wins) picks one of three strategies:

CLONE (default, needs Multiverse)

COPY

LIVE

CLONE and COPY then apply world.settings: time, weather, difficulty, the game-rules map (modern names such as advance_time and classic names such as doDaylightCycle both resolve), PvP on, auto-save off, a world border around the region and the spawn set to spawn 1.

Lifecycle: world.reuse-worlds keeps generated worlds loaded for the next duel (fast replays, world.max-cached-per-arena), otherwise they are deleted world.delete-delay seconds after the duel ends. Unused cached worlds are purged after 10 minutes. On shutdown every temporary world is removed.

Without Multiverse the plugin logs a warning and falls back to plain Bukkit world creation (COPY mode only), and cleans up with Bukkit.unloadWorld + folder deletion.

Configuration highlights

All options documented inline in config.yml. The most useful ones:

Message texts live in messages.yml and use MiniMessage, e.g. '<gold>{winner}</gold> <gray>defeated</gray> <gold>{loser}</gold>'. {placeholders} are escaped before parsing, so a player name can never inject formatting.

Storage

File Content
plugins/DuelForge/config.yml settings
plugins/DuelForge/messages.yml all texts
plugins/DuelForge/kits.yml kits (items as Base64 NBT, or the readable items: shorthand)
plugins/DuelForge/arenas.yml arenas: region, team spawns, beds, content/duel mode, generators, shop, formats, weight, icon, kit whitelist
plugins/DuelForge/shop.yml BedWars shop categories, items and prices
plugins/DuelForge/playerdata/<uuid>.yml wins, losses, ranked results, Elo points, streaks

For developers

Verified on Paper 26.3 build 169 (DuelForge 2.1.1)

Not verified automatically: the interactive player flows (request/accept, GUI clicks — including the world settings screen, the shop and team-shape buttons — kit editor, death/respawn restore, the BedWars life/bed-break cycle, generator item drops and NPC right-clicks during a live duel, team matchmaking with real players, spectator handling, Elo writes) need a real client. Everything reachable without one is verified by /duelarena check, /duelarena scan, the console commands and the startup log.