MCME Wiki

MCME-Architect is the builder's toolkit of the MCME build server: one large Paper plugin that changes how blocks behave and gives builders their tools. It holds about twenty mostly independent features: resource-pack "special blocks" with their own placing rules, build inventories, kits, item blocks, the per-world no-physics list, editors for armor stands, banners, signs and paintings, its own copy and paste, resource-pack switching and releases, live biome tuning, and map layers on the dynmap web map. Its build tools ask TheGaffer whether a player may build at a spot, so they respect job areas. The code is on GitHub at MCME/MCME-Architect; this page describes release 3.3.1 on master.

The repository's own Developer Manual is the detailed reference (startup order, every subsystem, threading rules, pitfalls). This page is the overview; read the manual before changing code.

At a glance

Repository MCME/MCME-Architect (GPL-3.0)
Release branch master (releases); new work goes to development
Version described 3.3.1 (tag v3.3.1)
Platform Paper 26.2 (api-version: 26.2), plugin name MCME-Architect, load: STARTUP
Build Maven 3.9, JDK 25 (<release>25</release>), no Maven wrapper
Depends on Hard: PluginUtils (depend). Needed but not declared: WorldEdit 7.4. Soft: ProtocolLib, dynmap, ViaVersion, MCME-Connect, Essentials (softdepend). Optional and not declared: TheGaffer
Maven coordinate com.mcmiddleearth:MCME-Architect, on the MCME Maven repository

How the code is organised

There is one main class, com.mcmiddleearth.architect.ArchitectPlugin. Each feature lives in its own package under com.mcmiddleearth.architect, usually as a manager or data class with static state, one or more listeners, and commands whose executors extend AbstractArchitectCommand. Shared helpers sit in com.mcmiddleearth.util.

Package Feature
(root) Core: ArchitectPlugin, PluginData (per-world data, permission checks), WorldConfig, Modules (the per-world switches), Permission (the node enum), ConfigFile (all config writes), Log and LogFileManager
specialBlockHandling Special blocks, the build inventory (/inv), /get kits, item blocks, the stick and the flint, doors. More than a third of the source files
serverResoucePack (sic) Resource packs: /rp, pack regions, player pack settings, /rp release (RpManager, RpListener, RpReleaseUtil)
biomeTuning Live biome tuning (/biometune) and its Dialog editor; the only code that reaches Minecraft internals, through ReflectionNmsBridge
mapLayers, mapLayers.customBiomes Architect's layers on the dynmap web map; DynmapBackend is the only class here that names dynmap types
noPhysicsEditor The no-physics list, exception areas and the redstone freeze (/nophy)
copyPaste Architect's own clipboard (/copy, /cut, /paste, /undo, /redo, /flip, /rot)
gamemodeSwitcher The F3+F4 game-mode switcher for builders without op, and the invisible-blocks gate
armorStand, bannerEditor, signEditor, paintingEditor The editors
customHeadManager, randomiser, viewDistance, chunkUpdate, entityLogging, voxelStencilEditor, weSchematicsViewer, WorldGeneration Smaller tools
com.mcmiddleearth.util Shared helpers, including TheGafferUtil (the TheGaffer link) and PathSafety

Things to know before you read the code:

Building and testing

mvn -B -ntp clean verify                     # build, run every test, make the jar (what CI runs)
mvn -B package -DskipTests                   # the jar only
mvn -B package -Dbuild.type=RELEASE          # a jar named as a release build
mvn -B test -Dtest=FbtCommandTest            # one test class

Configuration

Architect's data folder is plugins/MCME-Architect/. The files a developer meets most:

File What it holds
config.yml Server-wide settings (below). Several servers may share one file
WorldConfig/defaultWorldConfig.yml, WorldConfig/<world>.yml The per-world module switches and lists (no-physics list, inventory access, item-block limit, and more)
WorldConfig/server.yml A pseudo-world; only its modules.command.fullBrightness is read, to decide whether /fbt exists
protocolVersions.yml Version keys mapped to protocol numbers, used to pick a resource-pack slot
inventories/block/<pack>/*.yml Special-block definitions, one folder per resource pack

Two rules shape all config.yml code:

Sections of the bundled config.yml:

Key Default Meaning
ServerResourcePacks.<pack>.<client>.<resolution>.<variant>.'<versionKey>' one example Human slot Pack slots, each with url and sha. Client is vanilla, sodium or lite; version keys come from protocolVersions.yml and must be quoted. /rp server and /rp calcsha write these
rpSettingsDatabase.user / password / dbName / ip / port xxx / xxx / xxx / localhost / 3306 MySQL database for players' pack settings, shared by all servers (table architect_rp). xxx as user or database name means "no database"
dynmap.enabled true Legacy switch for the RP-region and item-block-limit layers
mapLayers.rpRegions, itemBlockLimit, noPhysics, itemBlockBudget, customBiomes commented out (every layer on, hidden by default) Per-layer enabled, hidden, colours, border and area opacity; customBiomes.scanMegabytesPerSecond (20) paces the region-file scan
entityLogger.enabled true The entity-count layer (/architect eLog)
EntityLimit.number / radius 500 / 80 Read, but nothing uses the values
headGalleryLocation a location Where /chead warp sends players; written by /chead setCollection
gitHubRpReleases.<pack>.owner / repo / script / path / timeoutMinutes example entries; timeoutMinutes 30 What /rp release runs for a pack. separateSodium appears in the example but nothing reads it
inventoryDownload.script / path example entry The script /inv download runs
logging.file.enabled / alsoServerLog / maxSizeMB / maxFiles / retentionDays true / false / 10 / 5 / 14 Architect's rotating log files
biomeTuning.undoDepth / backupsPerBiome 20 / 20 Undo steps per biome; backups kept per biome file
biomeTuning.sparePattern / targetPack 'mcme:custom_###' / bukkit Ids of spare biomes builders can claim; the datapack folder that holds new spares and mcme-biometune.json
biomeTuning.refresh.cooldownSeconds / timeoutSeconds / publishPlayersPerSecond / publishCooldownSeconds 5 / 15 / 5 / 30 Pacing of the client refreshes that show tuned biomes

Three keys are read but not in the bundled file: CopyPasteUndoLimit, CustomHeadUploadPath (written when missing) and inventoryUpload (/inv upload fails until it is set).

/architect reload runs loadData() only. Changes to logging.*, biomeTuning.*, rpSettingsDatabase, and anything that onEnable registers need a server restart. The User Manual's Running Architect chapter explains every per-world switch.

Commands and permissions

Every command also answers to the mcme-architect: prefix (for example /mcme-architect:undo when WorldEdit owns /undo). Most commands also need their per-world switch to be on.

Command Aliases What it does Permission
/architect [help] Lists the commands you may use architect.help (everyone)
/architect version, reload, reloaddata, world, blockdata, dev, checkNBT, weather, eLog, placeAllBlockStates Admin and debug tools architect.info, architect.reload, architect.checknbt or architect.weather
/architect maplayers refresh, scan [<world> [off]] Redraws the map layers; picks the worlds of the Custom biomes layer architect.maplayers
/inv Opens the build inventory of your pack (the F key does too); saved inventories; admin reload, download, upload architect.inventory, plus .save, .other, .reload, .download, .upload
/get Hotbar kits, dyed leather armor, heads architect.getCommand, plus architect.get.* per part
/itemblock Item-block counts, glow, clean-up and limit regions architect.itemBlock, plus .remove, .region.create, .region.limit
/nophy The no-physics list and its exception areas architect.noPhysicsList.view, .edit, .exception
/chunkupdate Automatic block resends (auto); the radius form does nothing in 3.3.1 architect.chunkupdate, .auto
/switchstick /swst, /ss Turns block-state editing with the stick on or off architect.switchstick
/weselect /wes Sets the command a flint click puts in chat architect.weselect
/sign, /banner, /armor Sign, banner and armor-stand editors architect.signEditor, architect.bannerEditor[.save\|.delete], architect.armorStandEditor[.trusted\|.delete]
/copy, /cut /cp, /ct Copies (and clears) a cuboid WorldEdit selection to Architect's clipboard architect.copypaste plus architect.copypaste.limit.<n> or architect.copypaste.unlimited
/paste, /undo, /redo, /flip, /rot /pst /ps, /un /ud, /re /rd, /flp /fl, /rt Clipboard operations architect.copypaste
/random Randomises one block state around you architect.randomiser.user, .allowMaterials
/vv, /sl, /schlist VoxelSniper stencils; WorldEdit schematic list architect.voxel.viewer, .delete, .stencilListEditor; architect.weSchemViewer
/chead Custom heads, their review and the gallery architect.customHeadManager.user, .manager
/fbt /fullbright, /nightvision Endless night vision architect.fullBrightness
/viewdistance /viewdist Sets the view distance Architect tells your client architect.viewdistance
/parrot Removes parrots from your shoulders none
/rp Switches your pack and pack settings; check needs no permission architect.resourcePackSwitcher
/rp server, calcsha, release, dropdb, list, create, edit, remove Pack slots, hashing, releases, the settings table, pack regions architect.resourcePackAdmin
/biometune Live biome tuning: the editor and its commands architect.biomeTune, plus .save, .publish, .admin

Permission structure. Nodes follow architect.<feature>[.<sub>] in camelCase and are listed in the Permission enum. Four rank bundles nest, each including the one below: architect.ranks.headDesigner → designer → artist → adventurer; architect.* grants headDesigner. Notable nodes outside the bundles:

Permission Default Grants
architect.help true /architect help
architect.gamemodeSwitcher false Every mode on the F3+F4 switcher without op (children .creative, .survival, .adventure, .spectator, each default false). Give .spectator only with another mode, or a spectator cannot switch back
architect.invisibleBlocks op Placing barrier, light and structure-void blocks
architect.interactDragonEgg false Interacting with dragon eggs (in the adventurer bundle)
architect.inventory.ignoreProtection op Changing container contents without build permission where chest protection is on
architect.copypaste.limit.<n> not declared Copy size limit of n blocks, read from the player's effective permissions
architect.biomeTune.save / .publish / .admin op Writing tuned biomes to the datapack; refreshing other players; spares, self-test and debug

The full tree, with every description, is in plugin.yml and the User Manual's Permissions chapter.

APIs and extension points

Architect has no formal API module, but other plugins rely on a few public static methods. Keep them stable:

API Used by What it gives
RpManager.getPlayerData(Player) → RpPlayerData MCME-Introduction A player's resource-pack settings and status (RpPlayerStatus, with the SENT and last-status pair kept for it)
RpManager.isSodiumClient(Player) MCME-Introduction Whether the client announced MCME's modpack marker
RpManager.getCurrentRpName(Player) Architect itself (special blocks, inventories) The name of the pack last sent to the player
BiomeTuning.isRefreshing(UUID) any listener true while a player is being sent through the configuration phase, which looks like a quit and a rejoin; skip quit and join work then

To compile against Architect, depend on com.mcmiddleearth:MCME-Architect (scope provided) from the Maven repository.

Inside the plugin, the extension points are:

How it talks to other plugins and systems

flowchart LR
  A[MCME-Architect]
  A -- "reflection: hasBuildPermission,<br/>getBuildProtectionMessage,<br/>recordExternalBuild" --> G[TheGaffer]
  A -- "depend (Maven + plugin.yml)" --> PU[PluginUtils]
  A -- "selections, regions" --> WE[WorldEdit]
  A -- "marker API via DynmapBackend" --> D[dynmap / LiveAtlas]
  C[MCME-Connect] -- "PlayerConnectEvent" --> A
  I[MCME-Introduction] -- "RpManager API" --> A
  A -- "runs release script,<br/>reads its output" --> R[ResourcePackScripts]
  A -- "JDBC, table architect_rp" --> DB[(Pack settings DB)]
System Direction How Notes
TheGaffer calls Reflection, in com.mcmiddleearth.util.TheGafferUtil Before a build or interact action Architect calls TheGaffer's public static hasBuildPermission(Player, Location) and, on a refusal, getBuildProtectionMessage(Player, Location) to tell the player why. After it sets blocks in code, which vanilla events would not report (special blocks, doors it places itself, half doors and similar, but not sneak edits), it calls recordExternalBuild(Player, Location, true) for each block so they count in TheGaffer's job statistics. Breaks need no call: they go through the vanilla break event, which TheGaffer counts itself. No Maven dependency and no plugin.yml entry. The checks fail open: without TheGaffer, or if the reflective call fails, the build is allowed (and the failure logged). A TheGaffer older than 3.0.0, which lacks recordExternalBuild, gets one warning and no counting. TheGaffer pins the three signatures with ProtectionApiContractTest; change both repos together
PluginUtils depends on Maven provided (2.0.4) and depend Messages with the [Architect] prefix, paged and clickable lists (FancyMessage), WorldEdit selections, plotStoring for the clipboard, the second debug channel
WorldEdit 7.4 depends on Maven provided (7.4.5); not declared in plugin.yml Selections for /copy, /cut, /nophy exception, /rp create, /itemblock create; pack and item-block regions are WorldEdit regions. Guarded by WorldEditGuard
dynmap (shown in LiveAtlas) writes Marker API behind MapBackend Map layers (RP regions, item-block limits and budget, no-physics exception areas, custom biomes) and the entity-log layer. Marker sets are non-persistent and redrawn at every start
MCME-Connect listens PlayerConnectEvent (Maven provided 3.0.1, softdepend) Sends a player's pack when they join the network. Without MCME-Connect none of RpListener's handlers register
MCME-Introduction is read by RpManager static methods See the API table above
ProtocolLib uses Packet listeners /viewdistance and the game-mode switcher. Compiled against 5.3.0; 26.x servers need a 5.5.0+ dev build
ViaVersion reads viaversion-api The client's real protocol version, to choose a pack slot; falls back to Paper's
ResourcePackScripts starts /rp release runs the pack's release script with sh (Linux only) Architect reads the script's output lines to report progress and the result in chat. That output format is a contract with the release pipeline; change both sides together
MCME modpack clients receives Plugin channel mcme-modpack-marker:hello Marks the player as a Sodium client for the choice of pack
MySQL reads/writes JDBC (jdbc:mysql:), driver supplied by the server Players' pack settings, one table shared by all servers. The connection is made on the main thread at start-up
Datapacks writes Files in the primary world's datapacks/ folder Biome tuning saves biome JSON, spare biomes and mcme-biometune.json

Further reading