Skip to main content

Configuration

DistrictWarden has two files in plugins/DistrictWarden/: config.yml for behaviour and storage.yml for the database. /dw reload re-reads config.yml; storage.yml changes need a restart.

config.yml​

plugin:
locale: en
timezone: UTC
debug: false

providers:
property: GRIEFDEFENDER
shop: QUICKSHOP_HIKARI
archive: WORLDEDIT

worlds:
enabled: []
disabled: []

properties:
default-size: STANDARD
areas: {}

lifecycle:
stale-shop-days: 30
warning-interval-days: 7

notifications:
discord:
enabled: false
webhook-url: ""
minemail:
enabled: true
KeyDefaultMeaning
plugin.localeenMessage language
plugin.timezoneUTCTimezone for timestamps
plugin.debugfalseVerbose logging
providers.propertyGRIEFDEFENDERLand provider
providers.shopQUICKSHOP_HIKARIShop provider
providers.archiveWORLDEDITArchive provider (property-block archive not yet used)
worlds.enabled[]Worlds DistrictWarden manages
worlds.disabled[]Worlds explicitly excluded
worlds.regions.<world>(none)Optional circular region (center-x, center-z, radius) limiting a world to part of itself
properties.default-sizeSTANDARDSize for an area with no mapping
properties.areas{}Per-world size overrides
lifecycle.stale-shop-days30Days a shop must be unable to trade before the first notice
lifecycle.warning-interval-days7Days between repeat notices until the shop recovers
notifications.discord.enabledfalseSend notices to a Discord webhook
notifications.discord.webhook-url""HTTPS Discord webhook URL
notifications.minemail.enabledtrueSend notices through MineMail when it is installed

Choosing worlds​

DistrictWarden manages a claim only if its world is listed in worlds.enabled and not listed in worlds.disabled. List as many worlds as you like; names are matched without regard to case.

worlds:
enabled: [shopping, market2]
disabled: []

Claims in any other world are invisible to DistrictWarden — not tracked, not monitored, and never acted on even with staff approval. With worlds.enabled empty, nothing is managed.

A dedicated shopping world pairs well with this: keep GriefDefender and your logging plugin focused on that world in their own configs, and enable only that world here.

Removing a world from worlds.enabled does not delete records already stored for it. They stay in the database but receive no further updates.

Managing a radius instead of a whole world​

When the district is only part of a world — a market square inside your main survival world, say — give that world a circular region under worlds.regions. DistrictWarden then manages only the claims whose centre falls inside the circle; claims elsewhere in that world are left alone, exactly as claims in an unmanaged world are.

worlds:
enabled: [world]
regions:
world:
center-x: 100
center-z: -200
radius: 300

A world listed in worlds.enabled with no region entry is still managed in full. A region needs center-x, center-z and a radius of at least one block; a half-written region (a missing centre, or a radius of zero) stops the plugin from loading with a message naming the world, on the same principle as a mis-typed property size. World names are matched without regard to case.

The easiest way to set a region is in game: stand at the centre and run /dw setcenter <radius>. That writes the three keys for you and reloads; follow it with /dw reconcile to drop any properties now outside the circle. Use /dw test border to see the boundary drawn in particles.

A region narrows shop monitoring too

A shop is only tracked if it sits inside a managed claim. So a region also narrows shops: a shop in a claim whose centre is outside the circle is no longer tracked, and a shop in unclaimed land is never tracked at all.

What counts as a property​

Each top-level, player-owned GriefDefender claim (basic or town) is one property. Admin claims belong to the server and are ignored. Subclaims (subdivisions) are part of their parent claim's property, so a shop inside a subdivision counts towards the parent claim.

Property sizing​

Sizes are never hardcoded — you map each world to a size. Future lifecycle rules will use the size, so getting it right matters.

properties:
default-size: STANDARD
areas:
shopping: STANDARD
small_market: SMALL

The keys under areas are world names. Valid sizes are SMALL, STANDARD, LARGE, CUSTOM and COMBINED (case-insensitive). An area with no entry uses default-size.

A misspelled size stops the plugin from loading

MEDUIM will not silently become STANDARD. The log names the offending key and the legal values. Because the size will drive the removal lifecycle, refusing to start is safer than quietly mis-sizing an entire area. If a reload hits a bad size, the previous configuration stays in force and the server keeps running — fix the typo and reload again.

Lifecycle timing​

lifecycle:
stale-shop-days: 30
warning-interval-days: 7

A shop that cannot trade for stale-shop-days days gets its first warning. After that, the owner is reminded every warning-interval-days days until the shop can trade again. Warnings never remove a shop — see Shop Lifecycle.

Notifications​

notifications:
discord:
enabled: false
webhook-url: ""
minemail:
enabled: true
  • Discord requires an HTTPS webhook URL. Set enabled: true and paste the URL into webhook-url.
  • MineMail must be installed and the recipient must have a primary mailbox. See MineMail.

Notices always go to the server log as well, and to the player in game when they are online. /dw reload applies notification changes.

Underground mob spawning​

This protection is automatic — there is no command or extra permission to switch it on. It applies when GriefDefender is installed and DistrictWarden is managing both the world and the player-owned claim.

DistrictWarden cancels a creature spawn when the spawn point is inside a managed claim and below the highest non-air block in that X/Z column. It covers every creature spawn reason — natural, spawner, breeding and spawn-egg — while above-ground spawns are allowed. It only prevents new spawns; mobs already underground are not removed. Unclaimed areas and worlds outside DistrictWarden's scope are unaffected.

To confirm it works, stand in a player-owned claim in a managed world: a spawn below the surface should be cancelled, while a spawn on the surface should still work. No /dw reconcile is needed for this rule — just make sure the world is enabled and reload if you changed the config.

storage.yml​

storage:
type: SQLITE
sqlite:
file: districtwarden.db
mysql:
host: localhost
port: 3306
database: districtwarden
username: districtwarden
password: ""
pool-size: 10

type is SQLITE or MYSQL. SQLite is the default and needs no setup — the file is created inside the plugin folder. MySQL/MariaDB is supported for multi-server setups. Connections are pooled with HikariCP, and schema migrations run automatically at startup.

Tables created: dw_schema_version, dw_properties, dw_property_regions, dw_shops, dw_shop_warnings, dw_shop_archives, dw_audit_log. Migrations are listed in db/migrations/<dialect>/migrations.txt and applied in order, once each, tracked in dw_schema_version.

dw_audit_log records property and shop archive/restore actions. It is append-only — no code path edits or deletes an audit row.

storage.yml is not reloaded

/dw reload does not re-read storage.yml. Swapping the database under a running server would strand open connections and in-flight work, so storage changes need a full restart.