Updates documentation.
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
# Modernize Metropolis Plugin: Implementation Tasks
|
||||
# Historical Modernization Backlog
|
||||
|
||||
This file preserves the earlier task list for context. Its status labels and
|
||||
acceptance text are historical and are not the current implementation report.
|
||||
Use the maintained [modernization plan](modernization-plan.md) for current
|
||||
implementation status, pending work, and completion criteria.
|
||||
|
||||
| ID | Status | Title |
|
||||
|:-------:|:--------:|:------|
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Metropolis Human Testing
|
||||
# Metropolis Manual Pre-release Checklist
|
||||
|
||||
Use this checklist for behavior that depends on a real Paper world, player interactions, or the installed WorldGuard and WorldEdit plugins. Automated tests cover some isolated logic, but they do not establish that the complete in-game workflows behave correctly.
|
||||
This is a manual checklist of expected behavior that needs a real Paper world,
|
||||
player interaction, or installed WorldGuard/WorldEdit plugins. Checklist items
|
||||
are scenarios to run, not test results; no item is considered passed until a
|
||||
person performs it and records the outcome. Automated coverage is summarized
|
||||
separately below.
|
||||
|
||||
## Test Environment
|
||||
|
||||
@@ -10,7 +14,7 @@ Use this checklist for behavior that depends on a real Paper world, player inter
|
||||
- Keep a server console open and check it for errors after startup, commands, joins, and restarts.
|
||||
- Record the Metropolis config, world name, test player UUIDs, command output, and any unexpected region bounds or block changes.
|
||||
|
||||
## Human Checklist
|
||||
## Manual Scenarios
|
||||
|
||||
### Startup and world setup
|
||||
|
||||
@@ -78,34 +82,20 @@ Use this checklist for behavior that depends on a real Paper world, player inter
|
||||
- Test commands as console, permitted player, and player without the relevant permission. Check player-only commands, target-player arguments, unknown names, malformed arguments, and permission denials for useful feedback and no unintended changes.
|
||||
- If upgrading an existing server, verify a legacy name-keyed `currentHomes.yml` entry resolves to the right UUID and the player's selected home is retained.
|
||||
|
||||
## Existing Automated Coverage
|
||||
## Automated Coverage (Separate from This Checklist)
|
||||
|
||||
Run `./gradlew test` for the server-free JUnit suite. It has 62 tests covering:
|
||||
Run `./gradlew test` for the server-free JUnit suite. It covers isolated plot
|
||||
geometry/allocation rules, road and stair layouts/build plans, WorldGuard
|
||||
region occupancy and reservation lookup, spawn/city bounds, home identity and
|
||||
selection persistence, permission overrides, player lookup, and selected
|
||||
command/event behavior. These unit tests do not load a real Paper server.
|
||||
|
||||
- `AvenueStairwayLayoutTest`: centered per-segment street and avenue flights, both border directions, independent cadence, top-tread alignment, inverted backing plan, exact-width openings, and invalid-fit rejection.
|
||||
- `PlotLevelSupportTest`: rejection of upper plots with missing logical support cells and complete coverage requirements across all lower levels.
|
||||
- `CityRegionBoundsTest`: City bounds expand to include elevated plots and Spawn without shrinking existing protection bounds.
|
||||
- `PlotGridLayoutTest`: zero-offset compatibility, offsets on X/Y/Z, axis-specific spacing, and negative logical-index recovery.
|
||||
- `WorldGuardRegionOccupancyTest`: arbitrary saved-region bounds are excluded while City/global regions are treated as non-occupying envelopes.
|
||||
- `PlotWorldBorderBoundsTest`: search bounds follow WorldBorder size/center and require the full candidate footprint inside it.
|
||||
- `SpawnLayoutTest`: default one-cell bounds, independent multipliers, and build-height validation.
|
||||
- `AvenueStairwayBuilderTest`: configured stair material and facing/half data for avenue and street directions, upside-down backing stairs, exact upper-road AIR placements, and no block writes at lower-road Y.
|
||||
- `RoadLayoutTest`: independently sized street/avenue bands, correct road-type tagging, non-overlapping corners, and disabled roads at zero width.
|
||||
- `RoadBlockWriterTest`: no-op writes for existing roads, filling missing road blocks, and preserving stair treads.
|
||||
- `CuboidTest`: WorldEdit bound conversion, vector ordering/null handling, touching intersections, and point containment.
|
||||
- `CurrentHomesStoreTest`: UUID-based persistence and resolving a legacy player-name key.
|
||||
- `PlayerJoinListenerTest`: the welcome bounds message when a home is supplied by a mock.
|
||||
- `PlayerLookupTest`: case-insensitive full-name matching and rejection of prefix matching.
|
||||
- `PlayerHomeTest`: UUID-based region identity and display-name retention.
|
||||
- `HomePermissionOverrideTest`: dotted permission-node parsing, priority and tie resolution, invalid entries, and username/permission/default precedence.
|
||||
- `HomeNumberAllocatorTest`: choosing the first unused positive home number.
|
||||
- `MetropolisHomeMoveCommandTest`: selecting a sender's home, selecting an offline target's home, and rejecting invalid requests.
|
||||
- `PlotReservationLookupTest`: owner/member matching, exclusion of homes/City/Spawn, legacy reservation markers, and region-name aliases.
|
||||
- `MetropolisPlotGoCommandTest`: self and target teleportation, ambiguous memberships, absent membership, and unsafe-destination feedback.
|
||||
- `MetropolisPlotReserveCommandTest`: parsing six coordinates and rejecting malformed coordinates.
|
||||
- `MetropolisHomeAcquireTest`: acquisition below the limit and refusal at the limit.
|
||||
- `MetropolisDebugGenerateTestHomesCommandTest`: asynchronous tick-queued generation, one home per interval, no overlapping batches, and continuing test-player names across repeated runs.
|
||||
|
||||
The two opt-in tests in `src/integrationTest` require a running Paper server and RCON. They check that Metropolis appears in `/plugins` and that a coordinate reservation is persisted by WorldGuard. They do not currently verify restart persistence, join allocation, WorldEdit-selection reservations, permissions, teleports, generated blocks, protection behavior, or the other command workflows above. Run them with the environment variables documented in `README.md`; use a disposable server because the reservation test changes its WorldGuard data.
|
||||
|
||||
The integration scope described in `TODO.md` is broader than the tests currently present. Treat the scenarios in this guide as unverified until a human has run them on the target Paper and plugin versions.
|
||||
The separate `src/integrationTest` source set currently contains two live
|
||||
checks: Metropolis appears in `/plugins`, and a coordinate reservation is
|
||||
persisted in WorldGuard's `regions.yml`. It does not verify restart behavior,
|
||||
join allocation, WorldEdit-selection reservations, permissions, teleport
|
||||
workflows, generated blocks, or protection behavior. See
|
||||
[CONTRIBUTING.md](../CONTRIBUTING.md) for prerequisites and safe invocation.
|
||||
Those integration checks have not been run as part of this documentation
|
||||
update. The manual scenarios above remain unverified until individually run
|
||||
and recorded against the target server/plugins.
|
||||
|
||||
59
docs/modernization-plan.md
Normal file
59
docs/modernization-plan.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Metropolis Modernization Plan
|
||||
|
||||
This is the maintained status and follow-up plan. Implemented behavior is
|
||||
described in [README.md](../README.md); automated and manual coverage are
|
||||
separated in [human-tests.md](human-tests.md). A feature is not considered
|
||||
runtime-verified merely because its code or an isolated unit test exists.
|
||||
|
||||
## Completed
|
||||
|
||||
- **Build and CI modernization.** Gradle 9.8 builds the Java 25 plugin and
|
||||
expands the version into `plugin.yml`. CI runs `test` and the plugin build
|
||||
for pushes and pull requests to `develop`. Completion check: running
|
||||
`./gradlew test build` succeeds; CI provides the corresponding hosted check.
|
||||
- **Paper/WorldGuard/WorldEdit integration.** The plugin declares Paper API
|
||||
26.2, WorldGuard 7.0.19, and WorldEdit 7.4.5, and uses WorldGuard regions
|
||||
for city, home, and reservation geometry. Paper 26.2/26.3 are project
|
||||
targets; the current build and CI do not perform live server compatibility
|
||||
checks. Completion check for runtime claims: run the applicable manual
|
||||
scenarios in `human-tests.md` on a disposable server.
|
||||
- **Plot, home, and command features.** The implementation includes join-time
|
||||
initial home allocation, explicit additional-home acquisition, UUID-based
|
||||
active-home persistence with legacy name-key loading, user/permission plot
|
||||
overrides, reservations, multi-level support checks, and configured
|
||||
road/stair generation. Isolated tests cover parts of these rules; see
|
||||
`src/test/` and `human-tests.md` for their boundaries.
|
||||
|
||||
## Pending
|
||||
|
||||
- **Expand live-server integration coverage.** The current `integrationTest`
|
||||
suite only checks plugin visibility and persistence of one coordinate-based
|
||||
WorldGuard reservation. Add focused disposable-server checks for join-time
|
||||
home allocation/ownership and selected-home restart persistence. Completion
|
||||
criteria: tests assert the expected region/UUID state before and after a
|
||||
restart, clean up their own test regions, and remain excluded from `build`.
|
||||
- **Choose optional login allocation policies (MET-023/MET-024).** Current
|
||||
behavior allocates the configured initial home count (default one) when a
|
||||
player has no home; later homes require `/metropolis-home-acquire`. Decide
|
||||
whether to offer grant-all-to-limit or one-more-per-login policies before
|
||||
implementing them. Completion criteria: documented config semantics,
|
||||
compatibility defaults, and unit tests for limits, reconnects, and existing
|
||||
home selections.
|
||||
- **Choose an allocation traversal option (MET-025).** The proposal to select
|
||||
a rectangle/cuboid or ring-based traversal remains unimplemented. First
|
||||
document deterministic ordering and how each policy treats occupied regions,
|
||||
levels, and WorldBorder bounds. Completion criteria: configuration and
|
||||
focused allocation tests establish repeatable ordering without overlaps.
|
||||
- **Research conversion of existing worlds (MET-026).** There is no automatic
|
||||
world/config conversion workflow. Document the legacy data/config formats,
|
||||
backups and rollback requirements, and a safe migration strategy before
|
||||
proposing implementation. Completion criteria: a reviewed conversion
|
||||
specification plus disposable-world validation; do not claim migration
|
||||
support before that work is complete.
|
||||
|
||||
## Deferred Ideas
|
||||
|
||||
Economy-based home sales, arbitrary connected plot shapes, and alternate
|
||||
multi-plot footprints remain product ideas, not committed work. Reconsider them
|
||||
only after requirements, compatibility constraints, and acceptance criteria
|
||||
are defined.
|
||||
@@ -11,6 +11,8 @@ Metropolis grows a protected Minecraft city as players join. It assigns home plo
|
||||
WorldGuard and WorldEdit are required dependencies. Install all three plugins in the server's `plugins` directory.
|
||||
|
||||
Metropolis targets Paper only; Bukkit and Spigot servers are not supported.
|
||||
The project targets Paper 26.2 and 26.3, while its build/CI compile against the
|
||||
Paper 26.2 API and do not run a live server compatibility check.
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
{
|
||||
"id": "metropolis",
|
||||
"title": "Metropolis",
|
||||
"description": "A Paper 26.2/26.3 city-planning plugin that turns player onboarding into procedural urban growth with protected UUID-owned homes, roads, reservations, and configurable infrastructure.",
|
||||
"docId": "Metropolis",
|
||||
"image": {
|
||||
"url": "Pixel-art aerial view of a growing Minecraft city planned in a square grid, small player home plots connected by pale roads, a protected central spawn, blocky green landscape, subtle WorldGuard-inspired boundary lines, warm daylight, clean game-plugin thumbnail composition, no words or logos.",
|
||||
"alt": "Pixel-art aerial view of a Minecraft city with player home plots and connecting roads",
|
||||
"prompt": "Pixel-art aerial view of a growing Minecraft city planned in a square grid, small player home plots connected by pale roads, a protected central spawn, blocky green landscape, subtle WorldGuard-inspired boundary lines, warm daylight, clean game-plugin thumbnail composition, no words or logos.",
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"backgroundClassName": "bg-surface"
|
||||
},
|
||||
"url": "/projects/metropolis",
|
||||
"tags": ["open-source"],
|
||||
"source": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/headhunter45/Metropolis"
|
||||
},
|
||||
"feedback": {
|
||||
"url": "https://github.com/headhunter45/Metropolis/issues"
|
||||
"metropolis": {
|
||||
"id": "metropolis",
|
||||
"title": "Metropolis",
|
||||
"description": "City manager that automatically creates protected home plots and roads as players join a Minecraft server.",
|
||||
"docId": "Metropolis",
|
||||
"headerImage": null,
|
||||
"platforms": [
|
||||
{ "name": "Minecraft", "info": "Paper server plugin" }
|
||||
],
|
||||
"image": {
|
||||
"url": "/projects/metropolis/logo.png",
|
||||
"alt": "Metropolis Minecraft plugin logo",
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"backgroundClassName": "bg-surface"
|
||||
},
|
||||
"url": "/projects/metropolis",
|
||||
"tags": ["Open-Source", "Game", "Minecraft"],
|
||||
"source": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/headhunter45/Metropolis"
|
||||
},
|
||||
"feedback": {
|
||||
"type": "github-issues",
|
||||
"url": "https://github.com/headhunter45/Metropolis/issues"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Metropolis
|
||||
|
||||
The project targets Paper 26.2 and 26.3; Gradle and CI compile against Paper
|
||||
API 26.2, and CI does not run a live server compatibility check.
|
||||
|
||||
Metropolis turns player onboarding into city planning. As players arrive, the Paper plugin finds the next available plot, builds the surrounding roads and infrastructure, and extends a WorldGuard-protected city that feels designed rather than randomly generated.
|
||||
|
||||
The project combines procedural spatial logic, persistent UUID-based ownership, configurable construction rules, WorldEdit-assisted reservations, and a command suite for acquiring and selecting multiple homes. Home limits and plot sizes can be assigned per user or through permission-manager groups using configurable permission tiers. Reservation owners and members can teleport to their reserved plots, with explicit selection when they belong to multiple reservations. Active-home selections persist across reconnects and server restarts. It is also a modernization case study: a legacy plugin brought forward to Paper 26.2 and 26.3 with Gradle, focused unit tests, and opt-in live-server integration tests. Bukkit and Spigot servers are outside the support target.
|
||||
|
||||
114
docs/projects.schema.json
Normal file
114
docs/projects.schema.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Projects",
|
||||
"description": "Project metadata keyed by the project route slug.",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z0-9]+(?:-[a-z0-9]+)*$": { "$ref": "#/definitions/project" }
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"image": {
|
||||
"type": "object",
|
||||
"required": ["url", "width", "height"],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "Public asset path or remote image URL. A blank header image URL falls back to image.",
|
||||
"pattern": "^(\\s*|/[^/].*|https?://.+)$"
|
||||
},
|
||||
"alt": { "type": "string" },
|
||||
"prompt": { "type": "string" },
|
||||
"name": { "type": "string" },
|
||||
"width": { "type": "integer", "minimum": 1 },
|
||||
"height": { "type": "integer", "minimum": 1 },
|
||||
"backgroundClassName": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"projectLink": {
|
||||
"type": "object",
|
||||
"required": ["url"],
|
||||
"properties": {
|
||||
"type": { "type": "string" },
|
||||
"url": { "type": "string", "pattern": "^(\\s*|https?://.+)$" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"platform": {
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": { "type": "string", "pattern": "\\S" },
|
||||
"info": { "type": "string" },
|
||||
"links": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["label", "url"],
|
||||
"properties": {
|
||||
"label": { "type": "string", "pattern": "\\S" },
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"pattern": "^https?://.+"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"project": {
|
||||
"type": "object",
|
||||
"required": ["id", "title", "description", "tags"],
|
||||
"properties": {
|
||||
"id": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
||||
"title": { "type": "string", "pattern": "\\S" },
|
||||
"description": { "type": "string", "pattern": "\\S" },
|
||||
"docId": { "type": "string", "minLength": 1 },
|
||||
"image": { "$ref": "#/definitions/image" },
|
||||
"headerImage": {
|
||||
"description": "Optional detail-page logo override. Omit, set to null, or use a blank URL to fall back to image. Listing cards continue to use image.",
|
||||
"anyOf": [{ "$ref": "#/definitions/image" }, { "type": "null" }]
|
||||
},
|
||||
"status": { "type": "string" },
|
||||
"platforms": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/platform" }
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^/projects/[a-z0-9]+(?:-[a-z0-9]+)*$"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": { "type": "string", "minLength": 1 },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"source": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/projectLink" },
|
||||
{ "required": ["type"] }
|
||||
]
|
||||
},
|
||||
"feedback": { "$ref": "#/definitions/projectLink" },
|
||||
"repository": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"pattern": "^https?://.+"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": { "type": "string", "minLength": 1 }
|
||||
},
|
||||
"technology": {
|
||||
"type": "array",
|
||||
"items": { "type": "string", "minLength": 1 }
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user