Compare commits
8 Commits
0.5.1
...
b6b30621f0
| Author | SHA1 | Date | |
|---|---|---|---|
| b6b30621f0 | |||
| efc39365c3 | |||
| a13f512be6 | |||
| 013dc6749c | |||
| 08d27ede40 | |||
| 8dbbdbac91 | |||
| 4ada53ba76 | |||
| 69cc0f8677 |
@@ -16,6 +16,7 @@ MINECRAFT_BACKUP_PATH=./backups
|
|||||||
# Release version is read from Gradle's Git-sensitive semantic version and checked against the jar's plugin.yml.
|
# Release version is read from Gradle's Git-sensitive semantic version and checked against the jar's plugin.yml.
|
||||||
MODRINTH_TOKEN=
|
MODRINTH_TOKEN=
|
||||||
MODRINTH_PROJECT_ID=metropolis-builder
|
MODRINTH_PROJECT_ID=metropolis-builder
|
||||||
|
# Optional Markdown override; empty generates notes from commits since the last tag.
|
||||||
MODRINTH_CHANGELOG=
|
MODRINTH_CHANGELOG=
|
||||||
MODRINTH_GAME_VERSIONS=26.2
|
MODRINTH_GAME_VERSIONS=26.2
|
||||||
MODRINTH_LOADERS=paper
|
MODRINTH_LOADERS=paper
|
||||||
|
|||||||
45
.github/workflows/gradle.yml
vendored
Normal file
45
.github/workflows/gradle.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Java CI with Gradle
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "develop" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "develop" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
|
- name: Set up JDK 25
|
||||||
|
uses: actions/setup-java@v6
|
||||||
|
with:
|
||||||
|
java-version: '25'
|
||||||
|
distribution: 'temurin'
|
||||||
|
|
||||||
|
- name: Setup Gradle 9.8.0
|
||||||
|
uses: gradle/actions/setup-gradle@v5
|
||||||
|
with:
|
||||||
|
gradle-version: '9.8.0'
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
|
||||||
|
- name: Build with Gradle Wrapper
|
||||||
|
run: ./tools/build-plugin.sh
|
||||||
|
|
||||||
|
- name: Extract Project Version
|
||||||
|
id: project_info
|
||||||
|
run: |
|
||||||
|
VERSION=$(./gradlew properties --no-daemon -q | awk -F ': ' '$1 == "version" {print $2}')
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Upload Plugin Artifact
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: Metropolis-${{ steps.project_info.outputs.version }}
|
||||||
|
path: build/libs/*.jar
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 14
|
||||||
83
Human-Tests.md
Normal file
83
Human-Tests.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Metropolis Human Testing
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Test Environment
|
||||||
|
|
||||||
|
- Use a disposable Paper 26.2 or 26.3 server with Java 25+, WorldGuard 7.0.19, WorldEdit 7.4.5, and Metropolis installed.
|
||||||
|
- Back up the server before testing. Home generation, reservations, and configuration can change world blocks and WorldGuard regions.
|
||||||
|
- Use at least two non-operator player accounts for ownership and protection checks. Operators can bypass protection and hide permission problems.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
### Startup and world setup
|
||||||
|
|
||||||
|
- Start with the required plugins enabled. Confirm Metropolis enables without errors and its commands are registered. Also confirm startup fails clearly if a required dependency or configured world is missing, then restore the valid setup.
|
||||||
|
- On a fresh test world, inspect the `City` and `Spawn` WorldGuard regions. Check their bounds, flags, and priority; verify the configured spawn generation and world-spawn location.
|
||||||
|
- Restart once with existing regions. Confirm Metropolis recognizes them instead of duplicating or resetting them, and that existing city bounds and player homes remain intact.
|
||||||
|
|
||||||
|
### Join and plot allocation
|
||||||
|
|
||||||
|
- Join as a new player. Confirm one home is allocated and the welcome message reports its actual bounds. Check the corresponding `h_1_<UUID>` region has the player as owner and its bounds match the configured plot size.
|
||||||
|
- Join with a second new player. Confirm the new home is distinct, does not overlap the first home or spawn, and the City region grows to include it.
|
||||||
|
- Join again as an existing player. Confirm the same home is selected and no duplicate region or plot is created.
|
||||||
|
- Reserve an area before allocating another home. Confirm future allocations skip it. Repeat with reservations near the city edge and near existing roads to look for overlaps or gaps.
|
||||||
|
- Test a user override that grants a different plot multiplier or home limit. Confirm the generated bounds and allowed number of homes match the override, and that the configured global defaults still apply to other players.
|
||||||
|
|
||||||
|
### Generated blocks and geometry
|
||||||
|
|
||||||
|
- Inspect a newly allocated home and adjoining roads. Check road width, level, material, clearance, plot floor, support blocks, and optional sign against the active config.
|
||||||
|
- Test generation over varied terrain, including water, caves, uneven ground, and existing structures. Confirm generated floors and roads do not leave unsafe gaps or erase blocks outside their intended area.
|
||||||
|
- Enable and disable optional floor, support, sign, spawn, world-spawn, and perimeter-wall settings one at a time on a disposable world. Confirm each setting changes only its intended behavior.
|
||||||
|
- Allocate plots in several directions and near the world origin. Check road joins, plot dimensions, City region expansion, and boundary coordinates for symmetry and off-by-one errors.
|
||||||
|
|
||||||
|
### Reservations and protection
|
||||||
|
|
||||||
|
- Reserve one plot with explicit coordinates. Then make a WorldEdit selection and reserve a second plot using `/metropolis-plot-reserve <name>`.
|
||||||
|
- Try invalid coordinates, a duplicate region name, and bounds that intersect a home or another reservation. Confirm the command reports a useful failure and does not silently overwrite an existing region.
|
||||||
|
- Check `/metropolis-home-list` and `/metropolis-plot-go <plotName>` for both occupied homes and reservations; confirm teleport destinations are safe and inside the requested plot.
|
||||||
|
- As the home owner, build and interact inside the home. As another non-op player, try the same actions. Verify ownership and protection behave as intended in homes, reservations, City, and Spawn.
|
||||||
|
- Verify representative protection flags in-game, including PvP, mob damage/spawning, explosions, and fire/lava behavior where applicable. Run `/metropolis-flag-reset` and confirm the expected flags are restored without changing region bounds or ownership.
|
||||||
|
- Restart the server and confirm reservations and their protection are still present in WorldGuard and remain excluded from home allocation.
|
||||||
|
|
||||||
|
### Commands, permissions, and player state
|
||||||
|
|
||||||
|
- For a new player with no overrides, join and confirm exactly one `h_1_<UUID>` home is created. Rejoin and confirm no additional home is created.
|
||||||
|
- Configure two `permissionOverrides` tiers in `plugins/Metropolis/config.yml`, then restart. Grant each permission node to a test user and to a test group through the server's permission manager. Confirm the player's effective `plotMultiplier` and `maxPlots` match the granted rule.
|
||||||
|
- Give one player multiple configured permission nodes with different priorities. Confirm the highest-priority rule controls both values; then give two matching rules the same priority and confirm the last matching YAML entry wins.
|
||||||
|
- Give a player both a permission tier and a matching `userOverrides` entry. Confirm the username override wins. Remove both overrides from another player and confirm `plot.multiplier` and `plot.maxPerPlayer` are used as defaults.
|
||||||
|
- Change or revoke a permission while the player is online, then acquire another home. Confirm the next acquisition uses the currently granted tier without requiring a restart.
|
||||||
|
- With plot multipliers of 1 and 2, acquire homes and inspect their WorldGuard bounds. Confirm size follows the tier, a larger footprint does not overlap an existing home, and the multiplier is applied to the X and Z footprint only once.
|
||||||
|
- Exercise `/metropolis-home-acquire` below and at each effective home limit. Confirm every successful request creates a distinct next-numbered home, creates none beyond the limit, and does not change other players' homes.
|
||||||
|
- After acquiring a second home, verify it becomes active: check the player's selected home in `plugins/Metropolis/currentHomes.yml` and use `/metropolis-home-go` to confirm travel to that home. Switch homes with `/metropolis-home-move` and verify the selection changes as expected.
|
||||||
|
- Run `/metropolis-home-move <homeNumber>` as a player with multiple homes. Verify the command confirms the selected home, updates `currentHomes.yml`, and `/metropolis-home-go` now travels to it.
|
||||||
|
- Run `/metropolis-home-move <homeNumber> <playerName>` as an authorized administrator, then repeat from console. Check an online target is notified and a cached offline target uses the selected home on their next join.
|
||||||
|
- Try zero, negative, non-numeric, nonexistent home numbers, unknown player names, and extra arguments. Confirm each request is rejected with useful feedback and does not change the stored active home.
|
||||||
|
- Restart after acquiring multiple homes. Confirm all home regions remain owned by the player, the active home selection persists, and joining does not allocate another first home.
|
||||||
|
- Generate a home for an offline player administratively. Confirm permission tiers are not assumed for offline players; the username override or global settings determine plot size and limit.
|
||||||
|
- Exercise `/metropolis-home-go` with a safe bed spawn inside the home and with no such bed spawn. Confirm teleportation chooses a valid location inside the home and reports a clear failure if no safe location exists.
|
||||||
|
- Exercise `/metropolis-home-move` for a player with multiple homes. Confirm the selected home persists across reconnect and restart; reject nonexistent home numbers.
|
||||||
|
- As an administrator, test `/metropolis-home-generate`, `/metropolis-home-evict`, and `/metropolis-home-list` with online and previously seen offline players. Confirm the intended region ownership changes, persistence, and subsequent allocation behavior.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
Run `./gradlew test` for the server-free JUnit suite. It has 20 tests covering:
|
||||||
|
|
||||||
|
- `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.
|
||||||
|
- `MetropolisPlotReserveCommandTest`: parsing six coordinates and rejecting malformed coordinates.
|
||||||
|
- `MetropolisHomeAcquireTest`: acquisition below the limit and refusal at the limit.
|
||||||
|
|
||||||
|
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.
|
||||||
47
Modrinth-Description.md
Normal file
47
Modrinth-Description.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
**Metropolis**
|
||||||
|
|
||||||
|
Metropolis grows a protected Minecraft city as players join. It assigns home plots connected by roads, expands the protected city region, and lets players and administrators manage homes and reserve plots.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Paper 26.2 or 26.3.
|
||||||
|
- Java 25 or newer.
|
||||||
|
- WorldGuard 7.0.19 and WorldEdit 7.4.5.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Automatically assigns a protected home plot when a player joins.
|
||||||
|
- Allows players to acquire additional homes up to their effective limit, configured globally, per user, or through permission-manager groups.
|
||||||
|
- Supports permission-based plot-size and home-limit tiers with configurable priorities; explicit per-user overrides take precedence.
|
||||||
|
- Lets players and authorized administrators select an existing home as active; selections persist by player UUID across restarts.
|
||||||
|
- Expands the protected city region as plots are occupied.
|
||||||
|
- Configures plot dimensions, roads, floors, supports, signs, spawn behavior, and perimeter walls.
|
||||||
|
- Reserves named plots by coordinates or a WorldEdit selection.
|
||||||
|
- Tracks home ownership and selected homes by player UUID.
|
||||||
|
- Supports home and plot teleportation, administration, and WorldGuard protection flags.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Metropolis creates `plugins/Metropolis/config.yml` on first startup. Configure plot limits and dimensions, roads, floors and supports, signs, spawn behavior, walls, world name, and per-player overrides. Use Bukkit material names; legacy numeric material IDs are also accepted for existing configurations.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
- `/metropolis` - Displays the plugin version.
|
||||||
|
- `/metropolis-home-acquire` - Acquires another available home plot.
|
||||||
|
- `/metropolis-home-generate <playerName>` - Generates a home for a known online or cached offline player.
|
||||||
|
- `/metropolis-home-list` - Lists occupied and reserved plots.
|
||||||
|
- `/metropolis-home-go [playerName]` - Teleports to a home.
|
||||||
|
- `/metropolis-home-move <homeNumber> [playerName]` - Selects an existing home as active. The player name defaults to the sender; authorized administrators and console can target online or cached offline players.
|
||||||
|
- `/metropolis-home-evict <playerName>` - Removes a player's ownership from their selected home region.
|
||||||
|
- `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` - Reserves a region by coordinates; players can use `/metropolis-plot-reserve <name>` with a WorldEdit selection.
|
||||||
|
- `/metropolis-plot-go <plotName> [playerName]` - Teleports to a named plot.
|
||||||
|
- `/metropolis-flag-reset` - Reapplies Metropolis protection flags.
|
||||||
|
- `/metropolis-debug-generatetesthomes <count>` - Generates test homes; intended for development servers.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Run `./gradlew build` from the project directory. The plugin jar is created in `build/libs/`.
|
||||||
13
Modrinth.json
Normal file
13
Modrinth.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "Metropolis",
|
||||||
|
"url": "https://modrinth.com/plugin/metropolis-builder",
|
||||||
|
"summary": "Grow a protected Minecraft city with automatic UUID-owned homes, configurable roads, WorldGuard protection, and reserved plots.",
|
||||||
|
"visibility": "public",
|
||||||
|
"links": {
|
||||||
|
"issueTracker": "https://github.com/headhunter45/Metropolis/issues",
|
||||||
|
"sourceCode": "https://github.com/headhunter45/Metropolis",
|
||||||
|
"wikiPage": null,
|
||||||
|
"discordInvite": null,
|
||||||
|
"donationLinks": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "metropolis",
|
"id": "metropolis",
|
||||||
"title": "Metropolis",
|
"title": "Metropolis",
|
||||||
"description": "Paper plugin that automatically creates protected home plots and connecting roads as players join a Minecraft server.",
|
"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",
|
"docId": "Metropolis",
|
||||||
"image": {
|
"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.",
|
"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.",
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
# Metropolis
|
# Metropolis
|
||||||
|
|
||||||
Metropolis is a Paper plugin that expands a protected Minecraft city as players join. It generates home plots and connecting roads, uses WorldGuard to protect the city and homes, and supports reserved plots and home teleportation.
|
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.
|
||||||
|
|
||||||
## Platform
|
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. 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.
|
||||||
|
|
||||||
- Paper 26.2, Java 25+
|
|
||||||
- WorldGuard 7.0.19 and WorldEdit 7.4.5
|
|
||||||
- Built with Gradle 9.8 and Git-sensitive semantic versioning
|
|
||||||
- Configuration: `plugins/Metropolis/config.yml`
|
|
||||||
- Unit tests run without a server; live integration tests use the separate Gradle `integrationTest` task.
|
|
||||||
- License: GNU General Public License v3
|
|
||||||
|
|||||||
56
README.md
56
README.md
@@ -2,9 +2,19 @@
|
|||||||
|
|
||||||
Metropolis expands a protected Minecraft city as players join. Each player can receive a home plot connected by generated roads; WorldGuard protects the city, homes, and reserved plots.
|
Metropolis expands a protected Minecraft city as players join. Each player can receive a home plot connected by generated roads; WorldGuard protects the city, homes, and reserved plots.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Assigns a protected home plot when a player joins and supports acquiring additional homes up to the configured player limit.
|
||||||
|
- Supports per-player plot sizes and home limits through `userOverrides` or configurable permission tiers; acquired homes can be selected as the active home.
|
||||||
|
- Expands the City region as plots are occupied, with optional spawn generation, world-spawn placement, floors, support blocks, signs, and perimeter walls.
|
||||||
|
- Generates roads around plots with configurable width, level, material, clearance, and supports.
|
||||||
|
- Creates named protected reservations from coordinates or a WorldEdit selection so reserved plots are not assigned as homes.
|
||||||
|
- Persists selected homes by player UUID and recognizes legacy name-based home data during migration.
|
||||||
|
- Supports online/offline player administration for home generation, movement, and eviction.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Paper 26.2, with Java 25 or newer
|
- Paper 26.2 or 26.3, with Java 25 or newer
|
||||||
- WorldGuard 7.0.19
|
- WorldGuard 7.0.19
|
||||||
- WorldEdit 7.4.5
|
- WorldEdit 7.4.5
|
||||||
|
|
||||||
@@ -41,26 +51,44 @@ Copy `.env.example` to `.env` and configure the Paper version/build and server p
|
|||||||
- `tools/start-server.sh` downloads the configured Paper build if needed and starts it.
|
- `tools/start-server.sh` downloads the configured Paper build if needed and starts it.
|
||||||
- `tools/backup-server.sh` and `tools/restore-server.sh` back up or restore the configured server.
|
- `tools/backup-server.sh` and `tools/restore-server.sh` back up or restore the configured server.
|
||||||
- `tools/publish-local.sh` publishes the artifact to the local Maven repository.
|
- `tools/publish-local.sh` publishes the artifact to the local Maven repository.
|
||||||
- `tools/publish-modrinth.sh` uploads a built jar after checking its version.
|
- `tools/publish-modrinth.sh` uploads a built jar after checking its version and generates a Markdown changelog from Git commits since the previous version tag. Set `MODRINTH_CHANGELOG` to override it with curated notes.
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The default configuration is in `src/main/resources/config.yml` and is copied to `plugins/Metropolis/config.yml` on first startup. Materials use Bukkit names; the previous numeric IDs for stone, grass, cobblestone, and bedrock are still accepted when loading a configuration.
|
`plugins/Metropolis/config.yml` controls plot dimensions and limits, floor and support generation, signs, road width/level/material/clearance, spawn behavior, wall generation, world name, and per-player overrides. `plot.multiplier` sets the default plot-size multiplier; `plot.maxPerPlayer` sets the default home limit.
|
||||||
|
|
||||||
Player home ownership and selected-home data use UUIDs. Existing name-keyed `currentHomes.yml` entries and name-based WorldGuard home regions are recognized during migration.
|
Use `permissionOverrides` to assign plot size and home limits through any permission manager. Each permission node maps to a `priority`, `plotMultiplier`, and `maxPlots`; the matching node with the highest priority wins, and the last matching entry in YAML order wins ties. An explicit username entry in `userOverrides` takes precedence over permission rules. If no override matches, the global `plot.*` defaults apply. Permission rules are checked for online players; offline home generation uses username overrides or global defaults. For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
permissionOverrides:
|
||||||
|
metropolis.plots.vip:
|
||||||
|
priority: 10
|
||||||
|
plotMultiplier: 2
|
||||||
|
maxPlots: 2
|
||||||
|
metropolis.plots.elite:
|
||||||
|
priority: 20
|
||||||
|
plotMultiplier: 3
|
||||||
|
maxPlots: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
Assign these permission nodes to groups or individual users in your permission plugin. Bukkit permissions are boolean, so the configured values determine the numeric limits. The bundled configuration provides the defaults. Metropolis targets Paper 26.2 and 26.3 only; Bukkit and Spigot servers are not supported.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
- `/metropolis` displays the plugin version.
|
| Command | Permission | Description |
|
||||||
- `/metropolis-home-acquire` acquires an available home plot.
|
| --- | --- | --- |
|
||||||
- `/metropolis-home-generate <player>` generates a home for a known online or cached offline player.
|
| `/metropolis` | None | Displays the plugin version. |
|
||||||
- `/metropolis-home-list` lists Metropolis plots.
|
| `/metropolis-home-acquire` | Player only | Acquires an available home if the player's home limit is not reached. |
|
||||||
- `/metropolis-home-go [player]` teleports to a home.
|
| `/metropolis-home-generate <playerName>` | `metropolis.home.generate` | Generates a home for an online or cached offline player. |
|
||||||
- `/metropolis-home-move <home-number> [player]` changes a player's selected home.
|
| `/metropolis-home-list` | `metropolis.home.list` | Lists the occupied and reserved Metropolis plots with their bounds. |
|
||||||
- `/metropolis-home-evict <player>` removes a player's home ownership.
|
| `/metropolis-home-go [playerName]` | `metropolis.home.go` | Teleports the sender, or a permitted target player, to their home. |
|
||||||
- `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` reserves coordinates; a player may instead provide a WorldEdit selection.
|
| `/metropolis-home-move <homeNumber> [playerName]` | `metropolis.home.move` | Selects one of a player's existing homes as active. The player argument defaults to the sender; console and authorized admins can target online or cached offline players. The selection persists across restarts. |
|
||||||
- `/metropolis-plot-go <plot-name> [player]` teleports to a plot.
|
| `/metropolis-home-evict <playerName>` | `metropolis.home.evict` | Removes the player's ownership from their selected home region. |
|
||||||
- `/metropolis-flag-reset` reapplies Metropolis protection flags.
|
| `/metropolis-plot-reserve <name> <minX> <minY> <minZ> <maxX> <maxY> <maxZ>` | `metropolis.plot.reserve` | Creates a named reservation from explicit bounds. A player can instead run `/metropolis-plot-reserve <name>` with a WorldEdit selection. |
|
||||||
|
| `/metropolis-plot-go <plotName> [playerName]` | `metropolis.plot.go` | Teleports the sender or target player to a named occupied or reserved plot. |
|
||||||
|
| `/metropolis-flag-reset` | `metropolis.flag.reset` | Reapplies Metropolis protection flags to the City and home regions. |
|
||||||
|
| `/metropolis-debug-generatetesthomes <count>` | `metropolis.debug` | Generates test homes; intended for development servers. |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
49
TODO.md
49
TODO.md
@@ -24,26 +24,30 @@
|
|||||||
| MET-020 | Done | Adopt the git-sensitive semantic versioning Gradle plugin used by MobScores and ScoreKeeper, using the existing 0.5-SNAPSHOT version as the migration baseline; verify version/tag behavior and enable the Gradle configuration cache when compatible. |
|
| MET-020 | Done | Adopt the git-sensitive semantic versioning Gradle plugin used by MobScores and ScoreKeeper, using the existing 0.5-SNAPSHOT version as the migration baseline; verify version/tag behavior and enable the Gradle configuration cache when compatible. |
|
||||||
| MET-021 | Done | Update README.md, CONTRIBUTING.md, other documentation, and project scripts with the Gradle build, test, versioning, and modern Paper server workflow. |
|
| MET-021 | Done | Update README.md, CONTRIBUTING.md, other documentation, and project scripts with the Gradle build, test, versioning, and modern Paper server workflow. |
|
||||||
| MET-022 | Planning | (Optional) Add new features, quality-of-life improvements, or CI configuration after the modernization and documentation tasks are complete. |
|
| MET-022 | Planning | (Optional) Add new features, quality-of-life improvements, or CI configuration after the modernization and documentation tasks are complete. |
|
||||||
|
| MET-023 | Planning | Add an optional home-allocation policy that grants all remaining homes up to a player's limit when they join. |
|
||||||
|
| MET-024 | Planning | Add an optional home-allocation policy that grants at most one additional home per login until the player's limit is reached. |
|
||||||
|
| MET-025 | Planning | Add a configuration option to choose the plot-allocation traversal algorithm: concentric rectangles/cuboids or concentric rings that prefer a free location near the center. |
|
||||||
|
| MET-026 | Planning | Research a world-conversion option for existing Metropolis worlds, including how to safely adapt existing regions and generated roads/plots. |
|
||||||
| GIT-009 | Planning | i have three reserve plots and one just got overwritten when a new player joined. |
|
| GIT-009 | Planning | i have three reserve plots and one just got overwritten when a new player joined. |
|
||||||
| GIT-008 | Ready | Implement multiple plot sizes by granting multiple plots around each other.
|
| GIT-008 | Ready | Implement multiple plot sizes by granting multiple plots around each other.
|
||||||
| GIT-007 | Ready | Allow buying and selling of homes via an ecnoomy plugin. |
|
| GIT-007 | Planning | Allow buying and selling of homes via an ecnoomy plugin. |
|
||||||
| GIT-006 | Ready | Add levels support. |
|
| GIT-006 | Ready | Add levels support. |
|
||||||
| GIT-005 | Planning | Add the possibility to create multiple plot homes in shapes. |
|
| GIT-005 | Planning | Add the possibility to create multiple plot homes in shapes. |
|
||||||
| GIT-004 | Ready | Add a command to request home allocation. |
|
| GIT-004 | Planning | Add a command to request home allocation. |
|
||||||
| GIT-003 | Ready | Add support for multiple homes. |
|
| GIT-003 | Ready | Add support for multiple homes. |
|
||||||
| GIT-002 | Ready | Add a command to teleport to a reservation you are part of. |
|
| GIT-002 | Planning | Add a command to teleport to a reservation you are part of. |
|
||||||
| GIT-001 | Ready | Add a command to move to a different home. |
|
| GIT-001 | Done | Add a command to move to a different home. |
|
||||||
|
|
||||||
# GIT-001 - Add a command to move to a different home.
|
# GIT-001 - Add a command to move to a different home.
|
||||||
**Status:** Ready
|
**Status:** Done
|
||||||
**Descriptioon:**
|
**Depends On:** [GIT-003](#git-003---add-support-for-multiple-homes)
|
||||||
|
**Description:**
|
||||||
|
|
||||||
/metropolis-home-move [playerName]
|
`/metropolis-home-move <homeNumber> [playerName]` selects one of a player's existing homes as active. Without a player name, the command acts on the player who ran it; console and authorized administrators can specify an online or cached offline player. Reject non-positive or malformed numbers, unknown players, nonexistent homes, and extra arguments with clear feedback. Persist the selection by player UUID and confirm the change to the sender and, when online, the target player.
|
||||||
The target player will be the callee or if specified [playerName].
|
|
||||||
This command should set the target player's home to the plot defined by .
|
|
||||||
|
|
||||||
# GIT-002 - Add a command to teleport to a reservation you are part of.
|
# GIT-002 - Add a command to teleport to a reservation you are part of.
|
||||||
**Status:** Ready
|
**Status:** Ready
|
||||||
|
**Depends On:** [GIT-003](#git-003---add-support-for-multiple-homes)
|
||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
/metropolis-plot-go [playerName]
|
/metropolis-plot-go [playerName]
|
||||||
@@ -56,20 +60,18 @@ Or better yet just use uhome or create your own, integrated that records the hom
|
|||||||
|
|
||||||
# GIT-003 - Add support for multiple homes
|
# GIT-003 - Add support for multiple homes
|
||||||
|
|
||||||
**Status:** Ready
|
**Status:** Done
|
||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
The max number of homes per player should be defined by a permission such as
|
Add a top-level `permissionOverrides` map keyed by permission node. Each rule defines `priority`, `plotMultiplier`, and `maxPlots`; any permission manager can grant the boolean nodes to groups or individual players. For online players, the matching rule with the highest priority wins, with the last matching entry in YAML order breaking ties. An explicit `userOverrides` entry takes precedence over permission rules. Without either override, use `plot.multiplier` and `plot.maxPerPlayer`. Offline-player generation uses username overrides or global defaults because permissions are only queried for online players.
|
||||||
metropolis.maxhomes: 2
|
|
||||||
|
|
||||||
A config option should be added to determine when the homes are added with at least the following options
|
On join, automatically allocate one home only when the player has no existing home, and restore a valid existing home as active if the saved selection is missing. Additional homes must be explicitly requested with `/metropolis-home-acquire`, up to the player's effective limit. Acquisition allocates the first unused positive home number and makes the new home active.
|
||||||
|
|
||||||
Allocate all homes that aren't allocated on login
|
The alternative login allocation policies are tracked separately in MET-023 and MET-024; they are not part of the default policy in this task.
|
||||||
Allocate at most 1 home per login
|
|
||||||
Only allocate the first home on login, and require a command to allocate additional homes.
|
|
||||||
|
|
||||||
# GIT-004 - Add a command to request home allocation.
|
# GIT-004 - Add a command to request home allocation.
|
||||||
**Status:** Ready
|
**Status:** Ready
|
||||||
|
**Depends On:** [GIT-003](#git-003---add-support-for-multiple-homes)
|
||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
Add a command that users can type to get their first or subsequent homes.
|
Add a command that users can type to get their first or subsequent homes.
|
||||||
@@ -88,10 +90,21 @@ Add the possibility to create multiple plot homes in shapes
|
|||||||
**Status:** Ready
|
**Status:** Ready
|
||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
Allow generating multilevel cities with stairs or interchanges to go between levels (streets are level but avenues are ramps.
|
Add multiple vertical levels to the city. Use the existing `road.level` as the base Y: the bottom of a ground-level plot is at that Y, and `plot.sizeY` defines the full plot height. For example, a five-block-high plot includes its floor at road level, three usable blocks, and a roof block; all five blocks belong to the plot region. Use the same plot-dimension-plus-road-spacing grid pitch vertically as horizontally; when road width is zero, adjacent plot volumes may touch. Do not allocate a plot if its full extent would exceed the world's buildable area. If the search cannot find any valid plot, log an allocation error and do not create the plot or region. The current config example is not intended for a multilevel world; request an updated `config.yml` before implementation. Existing `plot.offsetX`, `plot.offsetY`, and `plot.offsetZ` nudge the grid; `plot.multiplier`, `userOverrides[username].plotMultiplier`, and future `permissionOverrides[permission_name].plotMultiplier` affect plot size.
|
||||||
|
|
||||||
|
Add a maximum-level config value. If unset, default to 1; administrators can increase it to enable more levels. Allocate plots in X, Z, Y axis order: scan X from negative to positive, then increment Z, and only after scanning the X/Z area increment Y to the next level (Y outermost, Z middle, X innermost). For equal-distance candidates, use the same negative-to-positive X ordering. The selectable X/Z traversal shapes are tracked separately in MET-025.
|
||||||
|
|
||||||
|
Streets run along X and avenues run along Z. Streets remain level; avenues connect levels with stairs placed beside plots at a configurable cadence. Add `stairs.*`, `road.streets.*`, and `road.avenues.*` configuration. The street and avenue sections should each contain the current `road.*` settings plus `generateStairs`. Configure stair material, width, and `everyNBlocks`; this cadence is measured in plot-sized avenue blocks, so 3 means stairs beside every third plot along an avenue. Allow stairs to be configured independently for each direction, including different widths. Validate each enabled direction against its corresponding road width; if its stairs are not thinner than that road, log an error but continue plugin startup.
|
||||||
|
|
||||||
|
Keep spawn on its current level. Add independent X, Y, and Z spawn-size multipliers, each expressed as a multiple of the corresponding plot dimension and road spacing so roads line up with differently sized plots. The Y multiplier controls spawn's vertical height upward from `road.level`.
|
||||||
|
|
||||||
|
When allocating plots in an existing world, treat saved WorldGuard regions as occupied: never overwrite a region or create a new region that overlaps an existing one, even if avoiding overlaps leaves irregular gaps between plots and roads. Document this behavior so users know to expect it. Research a possible world-conversion option separately under MET-026; conversion requires further investigation.
|
||||||
|
|
||||||
|
This intentionally breaks the existing config schema: do not add a legacy `road.*` fallback or automatic migration. Document the config changes in release notes and make the breaking change in the 0.6.x release line.
|
||||||
|
|
||||||
# GIT-007 - Allow buying and selling of homes via an ecnoomy plugin.
|
# GIT-007 - Allow buying and selling of homes via an ecnoomy plugin.
|
||||||
**Status:** Ready
|
**Status:** Blocked
|
||||||
|
**Blockers:** Figure out how to integrate with economy plugins.
|
||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
Allow buying and selling of homes via an ecnoomy plugin. Include decent real estate support including wtb and wts listings as well as an auction facility.
|
Allow buying and selling of homes via an ecnoomy plugin. Include decent real estate support including wtb and wts listings as well as an auction facility.
|
||||||
|
|||||||
14
build.gradle
14
build.gradle
@@ -1,4 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
|
id 'com.diffplug.spotless' version '8.10.3'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'org.danilopianini.git-sensitive-semantic-versioning' version '7.0.24'
|
id 'org.danilopianini.git-sensitive-semantic-versioning' version '7.0.24'
|
||||||
@@ -9,7 +10,7 @@ description = 'Metropolis'
|
|||||||
|
|
||||||
gitSemVer {
|
gitSemVer {
|
||||||
minimumVersion.set('0.5.0')
|
minimumVersion.set('0.5.0')
|
||||||
versionPrefix.set('')
|
versionPrefix.set('v')
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -88,3 +89,14 @@ tasks.named('wrapper') {
|
|||||||
archiveBase = Wrapper.PathBase.PROJECT
|
archiveBase = Wrapper.PathBase.PROJECT
|
||||||
archivePath = '.gradle/wrapper/dists'
|
archivePath = '.gradle/wrapper/dists'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spotless {
|
||||||
|
java {
|
||||||
|
googleJavaFormat('1.36.1')
|
||||||
|
importOrder 'java', 'javax', 'com', 'net', 'org', ''
|
||||||
|
licenseHeaderFile 'config/license-header.txt'
|
||||||
|
target 'src/**/*.java'
|
||||||
|
removeUnusedImports()
|
||||||
|
toggleOffOn()
|
||||||
|
}
|
||||||
|
}
|
||||||
17
config/license-header.txt
Normal file
17
config/license-header.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@@ -28,18 +45,22 @@ class MetropolisServerIntegrationTest {
|
|||||||
void plotReservationIsPersistedByTheLoadedWorldGuardPlugin() throws IOException {
|
void plotReservationIsPersistedByTheLoadedWorldGuardPlugin() throws IOException {
|
||||||
String regionId = "metropolis-it-" + UUID.randomUUID().toString().substring(0, 8);
|
String regionId = "metropolis-it-" + UUID.randomUUID().toString().substring(0, 8);
|
||||||
try (RconClient rcon = connectToConfiguredServer()) {
|
try (RconClient rcon = connectToConfiguredServer()) {
|
||||||
String response = rcon.execute("metropolis-plot-reserve " + regionId + " 100 60 100 105 70 105");
|
String response =
|
||||||
|
rcon.execute("metropolis-plot-reserve " + regionId + " 100 60 100 105 70 105");
|
||||||
assertTrue(response.contains("Reserved plot region " + regionId), response);
|
assertTrue(response.contains("Reserved plot region " + regionId), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path serverDirectory = Path.of(requiredEnvironment("METROPOLIS_SERVER_DIR"));
|
Path serverDirectory = Path.of(requiredEnvironment("METROPOLIS_SERVER_DIR"));
|
||||||
String worldName = System.getenv().getOrDefault("METROPOLIS_WORLD", "world");
|
String worldName = System.getenv().getOrDefault("METROPOLIS_WORLD", "world");
|
||||||
Path regionsFile = serverDirectory.resolve("plugins/WorldGuard/worlds")
|
Path regionsFile =
|
||||||
|
serverDirectory
|
||||||
|
.resolve("plugins/WorldGuard/worlds")
|
||||||
.resolve(worldName)
|
.resolve(worldName)
|
||||||
.resolve("regions.yml");
|
.resolve("regions.yml");
|
||||||
YamlConfiguration regions = YamlConfiguration.loadConfiguration(regionsFile.toFile());
|
YamlConfiguration regions = YamlConfiguration.loadConfiguration(regionsFile.toFile());
|
||||||
|
|
||||||
assertTrue(regions.contains("regions." + regionId), "WorldGuard did not persist region " + regionId);
|
assertTrue(
|
||||||
|
regions.contains("regions." + regionId), "WorldGuard did not persist region " + regionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RconClient connectToConfiguredServer() throws IOException {
|
private static RconClient connectToConfiguredServer() throws IOException {
|
||||||
|
|||||||
@@ -1,11 +1,27 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
public class Cuboid implements Comparable<Cuboid> {
|
public class Cuboid implements Comparable<Cuboid> {
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
@@ -131,24 +147,61 @@ public class Cuboid implements Comparable<Cuboid> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Cuboid inset(int x, int y, int z) {
|
public Cuboid inset(int x, int y, int z) {
|
||||||
return new Cuboid(this.minX + x, this.minY, this.minZ + z, this.maxX - x, this.maxY, this.maxZ - z);
|
return new Cuboid(
|
||||||
|
this.minX + x, this.minY, this.minZ + z, this.maxX - x, this.maxY, this.maxZ - z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVolume() {
|
public int getVolume() {
|
||||||
return (this.maxX - this.minX) * (this.maxY - this.minY) * (this.maxZ - this.minZ);
|
return (this.maxX - this.minX) * (this.maxY - this.minY) * (this.maxZ - this.minZ);
|
||||||
}
|
}
|
||||||
public int getMinX(){return minX;}
|
|
||||||
public void setMinX(int minX){this.minX = minX;}
|
public int getMinX() {
|
||||||
public int getMinY(){return minY;}
|
return minX;
|
||||||
public void setMinY(int minY){this.minY = minY;}
|
}
|
||||||
public int getMinZ(){return minZ;}
|
|
||||||
public void setMinZ(int minZ){this.minZ = minZ;}
|
public void setMinX(int minX) {
|
||||||
public int getMaxX(){return maxX;}
|
this.minX = minX;
|
||||||
public void setMaxX(int maxX){this.maxX = maxX;}
|
}
|
||||||
public int getMaxY(){return maxY;}
|
|
||||||
public void setMaxY(int maxY){this.maxY = maxY;}
|
public int getMinY() {
|
||||||
public int getMaxZ(){return maxZ;}
|
return minY;
|
||||||
public void setMaxZ(int maxZ){this.maxZ = maxZ;}
|
}
|
||||||
|
|
||||||
|
public void setMinY(int minY) {
|
||||||
|
this.minY = minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinZ() {
|
||||||
|
return minZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinZ(int minZ) {
|
||||||
|
this.minZ = minZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxX() {
|
||||||
|
return maxX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxX(int maxX) {
|
||||||
|
this.maxX = maxX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxY() {
|
||||||
|
return maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxY(int maxY) {
|
||||||
|
this.maxY = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxZ() {
|
||||||
|
return maxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxZ(int maxZ) {
|
||||||
|
this.maxZ = maxZ;
|
||||||
|
}
|
||||||
|
|
||||||
public Cuboid outset(int amount) {
|
public Cuboid outset(int amount) {
|
||||||
return outset(amount, amount, amount);
|
return outset(amount, amount, amount);
|
||||||
@@ -159,7 +212,8 @@ public class Cuboid implements Comparable<Cuboid> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Cuboid outset(int x, int y, int z) {
|
public Cuboid outset(int x, int y, int z) {
|
||||||
return new Cuboid(this.minX - x, this.minY - y, this.minZ - z, this.maxX + x, this.maxY + y, this.maxZ + z);
|
return new Cuboid(
|
||||||
|
this.minX - x, this.minY - y, this.minZ - z, this.maxX + x, this.maxY + y, this.maxZ + z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCenterX() {
|
public int getCenterX() {
|
||||||
@@ -175,26 +229,17 @@ public class Cuboid implements Comparable<Cuboid> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean intersects(Cuboid other) {
|
public boolean intersects(Cuboid other) {
|
||||||
if (this.maxX >= other.minX && this.minX <= other.maxX)
|
if (this.maxX >= other.minX && this.minX <= other.maxX) {
|
||||||
{
|
if (this.maxZ >= other.minZ && this.minZ <= other.maxZ) {
|
||||||
if (this.maxZ >= other.minZ && this.minZ <= other.maxZ)
|
if (this.maxY >= other.minY && this.minY <= other.maxY) {
|
||||||
{
|
|
||||||
if (this.maxY >= other.minY && this.minY <= other.maxY)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,8 +258,8 @@ public class Cuboid implements Comparable<Cuboid> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("{Cuboid minX=%d, minY=%d, minZ=%d, maxX=%d, maxY=%d, maxZ=%d}", minX, minY, minZ, maxX, maxY, maxZ);
|
return String.format(
|
||||||
|
"{Cuboid minX=%d, minY=%d, minZ=%d, maxX=%d, maxY=%d, maxZ=%d}",
|
||||||
|
minX, minY, minZ, maxX, maxY, maxZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public final class HomeNumberAllocator {
|
||||||
|
private HomeNumberAllocator() {}
|
||||||
|
|
||||||
|
public static int nextHomeNumber(List<Plot> plots) {
|
||||||
|
Set<Integer> allocatedNumbers = new HashSet<>();
|
||||||
|
for (Plot plot : plots) {
|
||||||
|
if (plot instanceof PlayerHome home) {
|
||||||
|
allocatedNumbers.add(home.getNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextHomeNumber = 1;
|
||||||
|
while (allocatedNumbers.contains(nextHomeNumber)) {
|
||||||
|
nextHomeNumber++;
|
||||||
|
}
|
||||||
|
return nextHomeNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
|
public final class HomePermissionOverride {
|
||||||
|
private final String _permission;
|
||||||
|
private final int _priority;
|
||||||
|
private final int _plotMultiplier;
|
||||||
|
private final int _maxPlots;
|
||||||
|
|
||||||
|
private HomePermissionOverride(
|
||||||
|
String permission, int priority, int plotMultiplier, int maxPlots) {
|
||||||
|
_permission = permission;
|
||||||
|
_priority = priority;
|
||||||
|
_plotMultiplier = plotMultiplier;
|
||||||
|
_maxPlots = maxPlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPermission() {
|
||||||
|
return _permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return _priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlotMultiplier() {
|
||||||
|
return _plotMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPlots() {
|
||||||
|
return _maxPlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<HomePermissionOverride> load(
|
||||||
|
ConfigurationSection section, Consumer<String> warningLogger) {
|
||||||
|
if (section == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<HomePermissionOverride> overrides = new ArrayList<>();
|
||||||
|
collect(section, "", overrides, warningLogger);
|
||||||
|
return List.copyOf(overrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void collect(
|
||||||
|
ConfigurationSection section,
|
||||||
|
String permissionPrefix,
|
||||||
|
List<HomePermissionOverride> overrides,
|
||||||
|
Consumer<String> warningLogger) {
|
||||||
|
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||||
|
String permission =
|
||||||
|
permissionPrefix.isEmpty() ? entry.getKey() : permissionPrefix + "." + entry.getKey();
|
||||||
|
Map<?, ?> values = getValues(entry.getValue());
|
||||||
|
if (values != null && !hasRuleValues(values)) {
|
||||||
|
collect((ConfigurationSection) entry.getValue(), permission, overrides, warningLogger);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permission.isBlank()
|
||||||
|
|| values == null
|
||||||
|
|| !(values.get("priority") instanceof Number priority)
|
||||||
|
|| !(values.get("plotMultiplier") instanceof Number plotMultiplier)
|
||||||
|
|| !(values.get("maxPlots") instanceof Number maxPlots)
|
||||||
|
|| priority.intValue() != priority.doubleValue()
|
||||||
|
|| plotMultiplier.intValue() != plotMultiplier.doubleValue()
|
||||||
|
|| maxPlots.intValue() != maxPlots.doubleValue()
|
||||||
|
|| plotMultiplier.intValue() < 1
|
||||||
|
|| maxPlots.intValue() < 0) {
|
||||||
|
warningLogger.accept("Ignoring invalid permissionOverrides entry '" + permission + "'.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
overrides.add(
|
||||||
|
new HomePermissionOverride(
|
||||||
|
permission, priority.intValue(), plotMultiplier.intValue(), maxPlots.intValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasRuleValues(Map<?, ?> values) {
|
||||||
|
return values.containsKey("priority")
|
||||||
|
|| values.containsKey("plotMultiplier")
|
||||||
|
|| values.containsKey("maxPlots");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HomePermissionOverride findMatch(
|
||||||
|
List<HomePermissionOverride> overrides, Predicate<String> hasPermission) {
|
||||||
|
HomePermissionOverride match = null;
|
||||||
|
for (HomePermissionOverride override : overrides) {
|
||||||
|
if (hasPermission.test(override.getPermission())
|
||||||
|
&& (match == null || override.getPriority() >= match.getPriority())) {
|
||||||
|
match = override;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int resolveMaxPlots(
|
||||||
|
UserOverride userOverride,
|
||||||
|
List<HomePermissionOverride> overrides,
|
||||||
|
Predicate<String> hasPermission,
|
||||||
|
int fallback) {
|
||||||
|
if (userOverride != null) {
|
||||||
|
return userOverride.getMaxPlots();
|
||||||
|
}
|
||||||
|
HomePermissionOverride match = findMatch(overrides, hasPermission);
|
||||||
|
return match == null ? fallback : match.getMaxPlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int resolvePlotMultiplier(
|
||||||
|
UserOverride userOverride,
|
||||||
|
List<HomePermissionOverride> overrides,
|
||||||
|
Predicate<String> hasPermission,
|
||||||
|
int fallback) {
|
||||||
|
if (userOverride != null) {
|
||||||
|
return userOverride.getPlotMultiplier();
|
||||||
|
}
|
||||||
|
HomePermissionOverride match = findMatch(overrides, hasPermission);
|
||||||
|
return match == null ? fallback : match.getPlotMultiplier();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<?, ?> getValues(Object value) {
|
||||||
|
if (value instanceof ConfigurationSection section) {
|
||||||
|
return section.getValues(false);
|
||||||
|
}
|
||||||
|
if (value instanceof Map<?, ?> map) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -6,9 +23,32 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisDebugGenerateTestHomesCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisFlagResetCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeAcquire;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeEvictCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeGenerateCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeGoCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeListCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeMoveCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisPlotGoCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisPlotReserveCommand;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.eventlisteners.PlayerJoinListener;
|
||||||
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldguard.WorldGuard;
|
||||||
|
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||||
|
import com.sk89q.worldguard.domains.DefaultDomain;
|
||||||
|
import com.sk89q.worldguard.protection.flags.Flags;
|
||||||
|
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||||
|
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||||
|
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||||
|
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
@@ -27,30 +67,6 @@ import org.bukkit.plugin.PluginDescriptionFile;
|
|||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisDebugGenerateTestHomesCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisFlagResetCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeEvictCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeAcquire;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeGenerateCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeGoCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeListCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisHomeMoveCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisPlotGoCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.commands.MetropolisPlotReserveCommand;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.eventlisteners.PlayerJoinListener;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
|
||||||
import com.sk89q.worldguard.WorldGuard;
|
|
||||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
|
||||||
import com.sk89q.worldguard.domains.DefaultDomain;
|
|
||||||
import com.sk89q.worldguard.protection.flags.Flags;
|
|
||||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
|
||||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
|
||||||
|
|
||||||
public class MetropolisPlugin extends JavaPlugin {
|
public class MetropolisPlugin extends JavaPlugin {
|
||||||
public static final boolean DEBUG = false;
|
public static final boolean DEBUG = false;
|
||||||
private static final int version = 1;
|
private static final int version = 1;
|
||||||
@@ -69,6 +85,7 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
private List<Plot> _occupiedPlots;
|
private List<Plot> _occupiedPlots;
|
||||||
private HashMap<UUID, List<Plot>> _ownedPlots;
|
private HashMap<UUID, List<Plot>> _ownedPlots;
|
||||||
private HashMap<UUID, UserOverride> _userOverrides;
|
private HashMap<UUID, UserOverride> _userOverrides;
|
||||||
|
private List<HomePermissionOverride> _permissionOverrides;
|
||||||
private HashMap<UUID, Integer> _currentHomes;
|
private HashMap<UUID, Integer> _currentHomes;
|
||||||
|
|
||||||
private PlayerJoinListener _playerJoinListener = null;
|
private PlayerJoinListener _playerJoinListener = null;
|
||||||
@@ -108,7 +125,6 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
private ProtectedRegion _spawnRegion = null;
|
private ProtectedRegion _spawnRegion = null;
|
||||||
private ProtectedRegion _cityRegion = null;
|
private ProtectedRegion _cityRegion = null;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getLogger().info(String.format("%s disabled", pdf.getFullName()));
|
getLogger().info(String.format("%s disabled", pdf.getFullName()));
|
||||||
@@ -123,21 +139,32 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
_currentHomes = new HashMap<UUID, Integer>();
|
_currentHomes = new HashMap<UUID, Integer>();
|
||||||
loadCurrentHomes();
|
loadCurrentHomes();
|
||||||
|
|
||||||
if(DEBUG){getLogger().info("Checking config");}
|
if (DEBUG) {
|
||||||
|
getLogger().info("Checking config");
|
||||||
|
}
|
||||||
Configuration config = getConfig();
|
Configuration config = getConfig();
|
||||||
if (!config.contains("version")) {
|
if (!config.contains("version")) {
|
||||||
// new
|
// new
|
||||||
if(DEBUG){getLogger().info("No config exists. Assuming new installation.");}
|
if (DEBUG) {
|
||||||
|
getLogger().info("No config exists. Assuming new installation.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int configVersion = safeGetIntFromConfig(config, "version");
|
int configVersion = safeGetIntFromConfig(config, "version");
|
||||||
if (configVersion < version) {
|
if (configVersion < version) {
|
||||||
if(DEBUG){getLogger().info(String.format("Updating config from version v%s to v%s.", configVersion, version));}
|
if (DEBUG) {
|
||||||
|
getLogger()
|
||||||
|
.info(
|
||||||
|
String.format(
|
||||||
|
"Updating config from version v%s to v%s.", configVersion, version));
|
||||||
|
}
|
||||||
if (configVersion != version) {
|
if (configVersion != version) {
|
||||||
// upgrade config
|
// upgrade config
|
||||||
config.set("version", version);
|
config.set("version", version);
|
||||||
}
|
}
|
||||||
saveConfig();
|
saveConfig();
|
||||||
if(DEBUG){getLogger().info("Config updated");}
|
if (DEBUG) {
|
||||||
|
getLogger().info("Config updated");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +173,9 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
config.options().copyDefaults(true);
|
config.options().copyDefaults(true);
|
||||||
|
|
||||||
if(DEBUG){getLogger().info("Reading configuration from file.");}
|
if (DEBUG) {
|
||||||
|
getLogger().info("Reading configuration from file.");
|
||||||
|
}
|
||||||
plotSizeX = safeGetIntFromConfig(config, "plot.sizeX");
|
plotSizeX = safeGetIntFromConfig(config, "plot.sizeX");
|
||||||
plotSizeZ = safeGetIntFromConfig(config, "plot.sizeZ");
|
plotSizeZ = safeGetIntFromConfig(config, "plot.sizeZ");
|
||||||
generateFloor = safeGetBooleanFromConfig(config, "plot.floor.generate");
|
generateFloor = safeGetBooleanFromConfig(config, "plot.floor.generate");
|
||||||
@@ -168,13 +197,19 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
wallMaterial = safeGetMaterialFromConfig(config, "wall.material");
|
wallMaterial = safeGetMaterialFromConfig(config, "wall.material");
|
||||||
wallHeight = safeGetIntFromConfig(config, "wall.height");
|
wallHeight = safeGetIntFromConfig(config, "wall.height");
|
||||||
worldName = safeGetStringFromConfig(config, "worldname");
|
worldName = safeGetStringFromConfig(config, "worldname");
|
||||||
_maxPlots = safeGetIntFromConfig(config, "plot.multiplier");
|
_plotMultiplier = safeGetIntFromConfig(config, "plot.multiplier");
|
||||||
_plotMultiplier = safeGetIntFromConfig(config, "plot.maxPerPlayer");
|
_maxPlots = safeGetIntFromConfig(config, "plot.maxPerPlayer");
|
||||||
|
|
||||||
buildUserOverrides();
|
buildUserOverrides();
|
||||||
|
_permissionOverrides =
|
||||||
|
HomePermissionOverride.load(
|
||||||
|
config.getConfigurationSection("permissionOverrides"),
|
||||||
|
warning -> getLogger().warning(warning));
|
||||||
|
|
||||||
saveConfig();
|
saveConfig();
|
||||||
if(DEBUG){getLogger().info("Done reading config.");}
|
if (DEBUG) {
|
||||||
|
getLogger().info("Done reading config.");
|
||||||
|
}
|
||||||
|
|
||||||
getLogger().info(String.format("Metropolis: world name is %s", worldName));
|
getLogger().info(String.format("Metropolis: world name is %s", worldName));
|
||||||
|
|
||||||
@@ -209,14 +244,16 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
gridSizeY = world.getMaxHeight();
|
gridSizeY = world.getMaxHeight();
|
||||||
gridSizeZ = plotSizeZ + roadWidth;
|
gridSizeZ = plotSizeZ + roadWidth;
|
||||||
|
|
||||||
regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(world));
|
regionManager =
|
||||||
|
WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(world));
|
||||||
if (regionManager == null) {
|
if (regionManager == null) {
|
||||||
throw new RuntimeException("WorldGuard regions don't seem to be enabled.");
|
throw new RuntimeException("WorldGuard regions don't seem to be enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_cityRegion = regionManager.getRegion("City");
|
_cityRegion = regionManager.getRegion("City");
|
||||||
if (_cityRegion == null) {
|
if (_cityRegion == null) {
|
||||||
_cityRegion = new ProtectedCuboidRegion("City", getPlotMin(0, 0, 1), this.getPlotMax(0, 0, 1));
|
_cityRegion =
|
||||||
|
new ProtectedCuboidRegion("City", getPlotMin(0, 0, 1), this.getPlotMax(0, 0, 1));
|
||||||
_cityRegion.setPriority(0);
|
_cityRegion.setPriority(0);
|
||||||
_cityRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
_cityRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
||||||
_cityRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
_cityRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
||||||
@@ -283,7 +320,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
RegisterCommandHandler("metropolis", new MetropolisCommand(this));
|
RegisterCommandHandler("metropolis", new MetropolisCommand(this));
|
||||||
|
|
||||||
RegisterCommandHandler("metropolis-debug-generatetesthomes", new MetropolisDebugGenerateTestHomesCommand(this));
|
RegisterCommandHandler(
|
||||||
|
"metropolis-debug-generatetesthomes", new MetropolisDebugGenerateTestHomesCommand(this));
|
||||||
|
|
||||||
RegisterCommandHandler("metropolis-flag-reset", new MetropolisFlagResetCommand(this));
|
RegisterCommandHandler("metropolis-flag-reset", new MetropolisFlagResetCommand(this));
|
||||||
|
|
||||||
@@ -301,9 +339,9 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
private void loadCurrentHomes() {
|
private void loadCurrentHomes() {
|
||||||
File homesFile = new File(getDataFolder(), "currentHomes.yml");
|
File homesFile = new File(getDataFolder(), "currentHomes.yml");
|
||||||
try {
|
try {
|
||||||
_currentHomes.putAll(CurrentHomesStore.load(
|
_currentHomes.putAll(
|
||||||
homesFile,
|
CurrentHomesStore.load(
|
||||||
ownerName -> getServer().getOfflinePlayer(ownerName).getUniqueId()));
|
homesFile, ownerName -> getServer().getOfflinePlayer(ownerName).getUniqueId()));
|
||||||
saveCurrentHomes();
|
saveCurrentHomes();
|
||||||
} catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) {
|
} catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) {
|
||||||
getLogger().log(java.util.logging.Level.SEVERE, "Unable to load currentHomes.yml", e);
|
getLogger().log(java.util.logging.Level.SEVERE, "Unable to load currentHomes.yml", e);
|
||||||
@@ -359,7 +397,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
private void RegisterCommandHandler(String commandName, CommandExecutor executor) {
|
private void RegisterCommandHandler(String commandName, CommandExecutor executor) {
|
||||||
PluginCommand command = getCommand(commandName);
|
PluginCommand command = getCommand(commandName);
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
throw new RuntimeException(String.format("The command %s does not appear to exist", commandName));
|
throw new RuntimeException(
|
||||||
|
String.format("The command %s does not appear to exist", commandName));
|
||||||
} else {
|
} else {
|
||||||
command.setExecutor(executor);
|
command.setExecutor(executor);
|
||||||
}
|
}
|
||||||
@@ -395,7 +434,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
private Material safeGetMaterialFromConfig(Configuration config, String name) {
|
private Material safeGetMaterialFromConfig(Configuration config, String name) {
|
||||||
Material material = null;
|
Material material = null;
|
||||||
if (config.isInt(name)) {
|
if (config.isInt(name)) {
|
||||||
material = switch (config.getInt(name)) {
|
material =
|
||||||
|
switch (config.getInt(name)) {
|
||||||
case 1 -> Material.STONE;
|
case 1 -> Material.STONE;
|
||||||
case 2 -> Material.GRASS_BLOCK;
|
case 2 -> Material.GRASS_BLOCK;
|
||||||
case 4 -> Material.COBBLESTONE;
|
case 4 -> Material.COBBLESTONE;
|
||||||
@@ -413,7 +453,9 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void throwInvalidConfigException() {
|
private void throwInvalidConfigException() {
|
||||||
getLogger().info("Metropolis: ERROR config file is invalid. Please correct Metropolis/config.yml and restart the server.");
|
getLogger()
|
||||||
|
.info(
|
||||||
|
"Metropolis: ERROR config file is invalid. Please correct Metropolis/config.yml and restart the server.");
|
||||||
throw new RuntimeException("Config file is invalid.");
|
throw new RuntimeException("Config file is invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,10 +499,6 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
ProtectedCuboidRegion cuboidRegion = (ProtectedCuboidRegion) region;
|
ProtectedCuboidRegion cuboidRegion = (ProtectedCuboidRegion) region;
|
||||||
if (cuboidRegion.getId().startsWith("h_")) {
|
if (cuboidRegion.getId().startsWith("h_")) {
|
||||||
PlayerHome home = PlayerHome.get(region);
|
PlayerHome home = PlayerHome.get(region);
|
||||||
if(!_currentHomes.containsKey(home.getPlayerId()))
|
|
||||||
{
|
|
||||||
_currentHomes.put(home.getPlayerId(), home.getNumber());
|
|
||||||
}
|
|
||||||
_occupiedPlots.add(home);
|
_occupiedPlots.add(home);
|
||||||
addOwnedPlot(home.getPlayerId(), home);
|
addOwnedPlot(home.getPlayerId(), home);
|
||||||
} else if (cuboidRegion.getId().startsWith("r_")) {
|
} else if (cuboidRegion.getId().startsWith("r_")) {
|
||||||
@@ -469,7 +507,17 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (UUID playerId : _ownedPlots.keySet()) {
|
||||||
|
if (!_currentHomes.containsKey(playerId)) {
|
||||||
|
PlayerHome firstHome = getFirstOwnedHome(playerId);
|
||||||
|
if (firstHome != null) {
|
||||||
|
_currentHomes.put(playerId, firstHome.getNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size = calculateCitySize();
|
size = calculateCitySize();
|
||||||
|
saveCurrentHomes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addOwnedPlot(UUID playerId, Plot plot) {
|
private void addOwnedPlot(UUID playerId, Plot plot) {
|
||||||
@@ -491,20 +539,27 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
public PlayerHome getPlayerHome(Player player) {
|
public PlayerHome getPlayerHome(Player player) {
|
||||||
PlayerHome home = null;
|
PlayerHome home = null;
|
||||||
|
|
||||||
int homeNumber = _currentHomes.getOrDefault(player.getUniqueId(), 1);
|
UUID playerId = player.getUniqueId();
|
||||||
|
int homeNumber = _currentHomes.getOrDefault(playerId, 1);
|
||||||
String regionName = String.format("h_%d_%s", homeNumber, player.getUniqueId());
|
String regionName = String.format("h_%d_%s", homeNumber, player.getUniqueId());
|
||||||
ProtectedRegion homeRegion = regionManager.getRegion(regionName);
|
ProtectedRegion homeRegion = regionManager.getRegion(regionName);
|
||||||
|
|
||||||
if (homeRegion == null) {
|
if (homeRegion == null) {
|
||||||
PlayerHome existingHome = getOwnedHome(player.getUniqueId(), homeNumber);
|
PlayerHome existingHome = getOwnedHome(playerId, homeNumber);
|
||||||
if (existingHome != null) {
|
if (existingHome != null) {
|
||||||
existingHome.setPlayerName(player.getName());
|
existingHome.setPlayerName(player.getName());
|
||||||
return existingHome;
|
return existingHome;
|
||||||
}
|
}
|
||||||
|
existingHome = getFirstOwnedHome(playerId);
|
||||||
|
if (existingHome != null) {
|
||||||
|
existingHome.setPlayerName(player.getName());
|
||||||
|
setHome(playerId, existingHome.getNumber());
|
||||||
|
return existingHome;
|
||||||
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
getLogger().info(String.format("Creating home for player %s", player.getName()));
|
getLogger().info(String.format("Creating home for player %s", player.getName()));
|
||||||
}
|
}
|
||||||
home = generateHome(player);
|
home = generateHome(player, 1);
|
||||||
} else {
|
} else {
|
||||||
home = new PlayerHome(homeRegion);
|
home = new PlayerHome(homeRegion);
|
||||||
home.setPlayerName(player.getName());
|
home.setPlayerName(player.getName());
|
||||||
@@ -670,17 +725,16 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSolidMaterial(Material material) {
|
private boolean isSolidMaterial(Material material) {
|
||||||
return material.isBlock() &&
|
return material.isBlock()
|
||||||
material != Material.AIR &&
|
&& material != Material.AIR
|
||||||
material != Material.WATER &&
|
&& material != Material.WATER
|
||||||
material != Material.LAVA &&
|
&& material != Material.LAVA
|
||||||
material != Material.TORCH &&
|
&& material != Material.TORCH
|
||||||
material != Material.REDSTONE_TORCH;
|
&& material != Material.REDSTONE_TORCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPhysicsMaterial(Material material) {
|
private boolean isPhysicsMaterial(Material material) {
|
||||||
return material == Material.GRAVEL ||
|
return material == Material.GRAVEL || material == Material.SAND;
|
||||||
material == Material.SAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBlockOccupied(int row, int col) {
|
public boolean isBlockOccupied(int row, int col) {
|
||||||
@@ -725,8 +779,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
// Top
|
// Top
|
||||||
for (col = min; col <= max; col++) {
|
for (col = min; col <= max; col++) {
|
||||||
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
||||||
if(DEBUG){getLogger().info(String.format("row: %d, col: %d", row, col));}
|
if (DEBUG) {
|
||||||
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
getLogger().info(String.format("row: %d, col: %d", row, col));
|
||||||
|
}
|
||||||
|
return new Cuboid(
|
||||||
|
getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,8 +791,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
col = max;
|
col = max;
|
||||||
for (row = min + 1; row < max; row++) {
|
for (row = min + 1; row < max; row++) {
|
||||||
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
||||||
if(DEBUG){getLogger().info(String.format("row: %d, col: %d", row, col));}
|
if (DEBUG) {
|
||||||
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
getLogger().info(String.format("row: %d, col: %d", row, col));
|
||||||
|
}
|
||||||
|
return new Cuboid(
|
||||||
|
getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,8 +803,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
row = max;
|
row = max;
|
||||||
for (col = max; col >= min; col--) {
|
for (col = max; col >= min; col--) {
|
||||||
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
||||||
if(DEBUG){getLogger().info(String.format("row: %d, col: %d", row, col));}
|
if (DEBUG) {
|
||||||
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
getLogger().info(String.format("row: %d, col: %d", row, col));
|
||||||
|
}
|
||||||
|
return new Cuboid(
|
||||||
|
getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,8 +816,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
for (row = max; row > min; row--) {
|
for (row = max; row > min; row--) {
|
||||||
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
if (!areBlocksOccupied(row, col, plotMultiplier)) {
|
||||||
if (row != 0 || col != 0) {
|
if (row != 0 || col != 0) {
|
||||||
if(DEBUG){getLogger().info(String.format("row: %d, col: %d", row, col));}
|
if (DEBUG) {
|
||||||
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
getLogger().info(String.format("row: %d, col: %d", row, col));
|
||||||
|
}
|
||||||
|
return new Cuboid(
|
||||||
|
getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -764,7 +830,9 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
max = ring - (plotMultiplier - 1);
|
max = ring - (plotMultiplier - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEBUG){getLogger().info(String.format("row: %d, col: %d", row, col));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("row: %d, col: %d", row, col));
|
||||||
|
}
|
||||||
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
return new Cuboid(getPlotMin(row, col, plotMultiplier), getPlotMax(row, col, plotMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,18 +864,23 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
for (Plot home : _occupiedPlots) {
|
for (Plot home : _occupiedPlots) {
|
||||||
int plotCol = Math.abs(getPlotXFromMin(home.getCuboid()));
|
int plotCol = Math.abs(getPlotXFromMin(home.getCuboid()));
|
||||||
int plotRow = Math.abs(getPlotZFromMin(home.getCuboid()));
|
int plotRow = Math.abs(getPlotZFromMin(home.getCuboid()));
|
||||||
if(DEBUG){getLogger().info(String.format("col: %d, row: %d, iSize: %d", plotCol, plotRow, iSize));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("col: %d, row: %d, iSize: %d", plotCol, plotRow, iSize));
|
||||||
|
}
|
||||||
iSize = Math.max(Math.max(plotRow * 2 + 1, plotCol * 2 + 1), iSize);
|
iSize = Math.max(Math.max(plotRow * 2 + 1, plotCol * 2 + 1), iSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEBUG){getLogger().info(String.format("City size is %d", iSize));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("City size is %d", iSize));
|
||||||
|
}
|
||||||
return iSize;
|
return iSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockVector3 getPlotMin(int row, int col, int plotMultiplier) {
|
public BlockVector3 getPlotMin(int row, int col, int plotMultiplier) {
|
||||||
BlockVector3 gridMin = getGridMin(row, col, plotMultiplier);
|
BlockVector3 gridMin = getGridMin(row, col, plotMultiplier);
|
||||||
|
|
||||||
BlockVector3 bv = BlockVector3.at(gridMin.x() + roadWidth/2, gridMin.y(), gridMin.z() + roadWidth/2);
|
BlockVector3 bv =
|
||||||
|
BlockVector3.at(gridMin.x() + roadWidth / 2, gridMin.y(), gridMin.z() + roadWidth / 2);
|
||||||
getLogger().info(String.format("getPlotMin (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
getLogger().info(String.format("getPlotMin (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
@@ -815,7 +888,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
public BlockVector3 getPlotMax(int row, int col, int plotMultiplier) {
|
public BlockVector3 getPlotMax(int row, int col, int plotMultiplier) {
|
||||||
BlockVector3 gridMax = getGridMax(row, col, plotMultiplier);
|
BlockVector3 gridMax = getGridMax(row, col, plotMultiplier);
|
||||||
|
|
||||||
BlockVector3 bv = BlockVector3.at(gridMax.x() - (roadWidth - roadWidth/2), gridMax.y(), gridMax.z() - (roadWidth-roadWidth/2));
|
BlockVector3 bv =
|
||||||
|
BlockVector3.at(
|
||||||
|
gridMax.x() - (roadWidth - roadWidth / 2),
|
||||||
|
gridMax.y(),
|
||||||
|
gridMax.z() - (roadWidth - roadWidth / 2));
|
||||||
getLogger().info(String.format("getPlotMax (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
getLogger().info(String.format("getPlotMax (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
@@ -831,7 +908,11 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
public BlockVector3 getGridMax(int row, int col, int plotMultiplier) {
|
public BlockVector3 getGridMax(int row, int col, int plotMultiplier) {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
||||||
BlockVector3 bv = BlockVector3.at((col+plotMultiplier) * gridSizeX*plotMultiplier-1, (level+1/*plotMultiplier*/) * gridSizeY-1, (row+plotMultiplier) * gridSizeZ-1);
|
BlockVector3 bv =
|
||||||
|
BlockVector3.at(
|
||||||
|
(col + plotMultiplier) * gridSizeX - 1,
|
||||||
|
(level + 1 /*plotMultiplier*/) * gridSizeY - 1,
|
||||||
|
(row + plotMultiplier) * gridSizeZ - 1);
|
||||||
getLogger().info(String.format("getGridMax (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
getLogger().info(String.format("getGridMax (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
@@ -844,7 +925,12 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
return (cuboid.minZ - roadWidth / 2) / gridSizeZ;
|
return (cuboid.minZ - roadWidth / 2) / gridSizeZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHomeOccupied(UUID ownerId, String ownerName, int homeNumber, BlockVector3 minimumPoint, BlockVector3 maximumPoint) {
|
private void setHomeOccupied(
|
||||||
|
UUID ownerId,
|
||||||
|
String ownerName,
|
||||||
|
int homeNumber,
|
||||||
|
BlockVector3 minimumPoint,
|
||||||
|
BlockVector3 maximumPoint) {
|
||||||
PlayerHome home = new PlayerHome(ownerId, ownerName, homeNumber, minimumPoint, maximumPoint);
|
PlayerHome home = new PlayerHome(ownerId, ownerName, homeNumber, minimumPoint, maximumPoint);
|
||||||
if (!_occupiedPlots.contains(home)) {
|
if (!_occupiedPlots.contains(home)) {
|
||||||
_occupiedPlots.add(home);
|
_occupiedPlots.add(home);
|
||||||
@@ -857,12 +943,18 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PlayerHome generateHome(OfflinePlayer player) {
|
public PlayerHome generateHome(OfflinePlayer player) {
|
||||||
|
int homeNumber = _currentHomes.getOrDefault(player.getUniqueId(), 1);
|
||||||
|
return generateHome(player, homeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerHome generateHome(OfflinePlayer player, int homeNumber) {
|
||||||
UUID playerId = player.getUniqueId();
|
UUID playerId = player.getUniqueId();
|
||||||
String playerName = player.getName() == null ? playerId.toString() : player.getName();
|
String playerName = player.getName() == null ? playerId.toString() : player.getName();
|
||||||
int homeNumber = _currentHomes.getOrDefault(playerId, 1);
|
int multiplier = getPlotMultiplier(player);
|
||||||
int multiplier = getPlotMultiplier(playerId);
|
|
||||||
|
|
||||||
if(DEBUG){getLogger().info(String.format("Generating home for %s", playerName));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("Generating home for %s", playerName));
|
||||||
|
}
|
||||||
Cuboid homeCuboid = null;
|
Cuboid homeCuboid = null;
|
||||||
ProtectedRegion phomeRegion = null;
|
ProtectedRegion phomeRegion = null;
|
||||||
String regionName = getHomeRegionName(playerId, homeNumber);
|
String regionName = getHomeRegionName(playerId, homeNumber);
|
||||||
@@ -879,7 +971,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
getLogger().info("Metropolis Generating home in " + homeCuboid.toString());
|
getLogger().info("Metropolis Generating home in " + homeCuboid.toString());
|
||||||
|
|
||||||
ProtectedCuboidRegion newHomeRegion = new ProtectedCuboidRegion(regionName, homeCuboid.getMin(), homeCuboid.getMax());
|
ProtectedCuboidRegion newHomeRegion =
|
||||||
|
new ProtectedCuboidRegion(regionName, homeCuboid.getMin(), homeCuboid.getMax());
|
||||||
newHomeRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
newHomeRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
||||||
newHomeRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
newHomeRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
||||||
newHomeRegion.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY);
|
newHomeRegion.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY);
|
||||||
@@ -906,18 +999,24 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
getLogger().info("Metropolis: ERROR Problem saving region");
|
getLogger().info("Metropolis: ERROR Problem saving region");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
getLogger().info(String.format(
|
getLogger()
|
||||||
|
.info(
|
||||||
|
String.format(
|
||||||
"New home region (%d, %d, %d) (%d, %d, %d)",
|
"New home region (%d, %d, %d) (%d, %d, %d)",
|
||||||
newHomeRegion.getMinimumPoint().x(),
|
newHomeRegion.getMinimumPoint().x(),
|
||||||
newHomeRegion.getMinimumPoint().y(),
|
newHomeRegion.getMinimumPoint().y(),
|
||||||
newHomeRegion.getMinimumPoint().z(),
|
newHomeRegion.getMinimumPoint().z(),
|
||||||
newHomeRegion.getMaximumPoint().x(),
|
newHomeRegion.getMaximumPoint().x(),
|
||||||
newHomeRegion.getMaximumPoint().y(),
|
newHomeRegion.getMaximumPoint().y(),
|
||||||
newHomeRegion.getMaximumPoint().z()
|
newHomeRegion.getMaximumPoint().z()));
|
||||||
));
|
|
||||||
|
|
||||||
setHomeOccupied(playerId, playerName, homeNumber, newHomeRegion.getMinimumPoint(), newHomeRegion.getMaximumPoint());
|
setHomeOccupied(
|
||||||
_currentHomes.putIfAbsent(playerId, homeNumber);
|
playerId,
|
||||||
|
playerName,
|
||||||
|
homeNumber,
|
||||||
|
newHomeRegion.getMinimumPoint(),
|
||||||
|
newHomeRegion.getMaximumPoint());
|
||||||
|
_currentHomes.put(playerId, homeNumber);
|
||||||
saveCurrentHomes();
|
saveCurrentHomes();
|
||||||
|
|
||||||
createRoads(homeCuboid);
|
createRoads(homeCuboid);
|
||||||
@@ -926,12 +1025,16 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
generateFloor(homeCuboid);
|
generateFloor(homeCuboid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEBUG){getLogger().info(String.format("generateSign: %s", String.valueOf(generateSign)));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("generateSign: %s", String.valueOf(generateSign)));
|
||||||
|
}
|
||||||
if (generateSign) {
|
if (generateSign) {
|
||||||
generateSign(homeCuboid, playerName);
|
generateSign(homeCuboid, playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEBUG){getLogger().info(String.format("Done generating home for %s", playerName));}
|
if (DEBUG) {
|
||||||
|
getLogger().info(String.format("Done generating home for %s", playerName));
|
||||||
|
}
|
||||||
|
|
||||||
PlayerHome home = new PlayerHome(newHomeRegion);
|
PlayerHome home = new PlayerHome(newHomeRegion);
|
||||||
home.setPlayerName(playerName);
|
home.setPlayerName(playerName);
|
||||||
@@ -939,7 +1042,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateSign(Cuboid plotCuboid, String playerName) {
|
private void generateSign(Cuboid plotCuboid, String playerName) {
|
||||||
Block signBlock = world.getBlockAt(plotCuboid.getCenterX(), roadLevel+1, plotCuboid.getCenterZ());
|
Block signBlock =
|
||||||
|
world.getBlockAt(plotCuboid.getCenterX(), roadLevel + 1, plotCuboid.getCenterZ());
|
||||||
signBlock.setType(Material.OAK_SIGN);
|
signBlock.setType(Material.OAK_SIGN);
|
||||||
Sign sign = (Sign) signBlock.getState();
|
Sign sign = (Sign) signBlock.getState();
|
||||||
sign.setLine(0, "Home of");
|
sign.setLine(0, "Home of");
|
||||||
@@ -964,7 +1068,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reserveCuboid(String regionName, Cuboid cuboid) {
|
public void reserveCuboid(String regionName, Cuboid cuboid) {
|
||||||
ProtectedCuboidRegion reservedRegion = new ProtectedCuboidRegion(regionName, cuboid.getMin(), cuboid.getMax());
|
ProtectedCuboidRegion reservedRegion =
|
||||||
|
new ProtectedCuboidRegion(regionName, cuboid.getMin(), cuboid.getMax());
|
||||||
reservedRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
reservedRegion.setFlag(Flags.PVP, StateFlag.State.DENY);
|
||||||
reservedRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
reservedRegion.setFlag(Flags.MOB_DAMAGE, StateFlag.State.DENY);
|
||||||
reservedRegion.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY);
|
reservedRegion.setFlag(Flags.MOB_SPAWNING, StateFlag.State.DENY);
|
||||||
@@ -991,6 +1096,7 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
public Material getWallMaterial() {
|
public Material getWallMaterial() {
|
||||||
return wallMaterial;
|
return wallMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWallheight() {
|
public int getWallheight() {
|
||||||
return wallHeight;
|
return wallHeight;
|
||||||
}
|
}
|
||||||
@@ -1011,7 +1117,8 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
try {
|
try {
|
||||||
regionManager.removeRegion(regionId);
|
regionManager.removeRegion(regionId);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
getLogger().info(String.format("[ERROR] Metropolis: Unable to remove region {%s}.", regionId));
|
getLogger()
|
||||||
|
.info(String.format("[ERROR] Metropolis: Unable to remove region {%s}.", regionId));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1046,10 +1153,28 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxPlots(Player player) {
|
||||||
|
return HomePermissionOverride.resolveMaxPlots(
|
||||||
|
_userOverrides.get(player.getUniqueId()),
|
||||||
|
_permissionOverrides,
|
||||||
|
player::hasPermission,
|
||||||
|
_maxPlots);
|
||||||
|
}
|
||||||
|
|
||||||
public void assignPlot(OfflinePlayer player) {
|
public void assignPlot(OfflinePlayer player) {
|
||||||
generateHome(player);
|
generateHome(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PlayerHome acquireHome(OfflinePlayer player) {
|
||||||
|
List<Plot> ownedPlots = _ownedPlots.getOrDefault(player.getUniqueId(), List.of());
|
||||||
|
int nextHomeNumber = HomeNumberAllocator.nextHomeNumber(ownedPlots);
|
||||||
|
PlayerHome home = generateHome(player, nextHomeNumber);
|
||||||
|
if (home != null) {
|
||||||
|
setHome(player.getUniqueId(), home.getNumber());
|
||||||
|
}
|
||||||
|
return home;
|
||||||
|
}
|
||||||
|
|
||||||
private int getPlotMultiplier(UUID playerId) {
|
private int getPlotMultiplier(UUID playerId) {
|
||||||
if (_userOverrides.containsKey(playerId)) {
|
if (_userOverrides.containsKey(playerId)) {
|
||||||
return _userOverrides.get(playerId).getPlotMultiplier();
|
return _userOverrides.get(playerId).getPlotMultiplier();
|
||||||
@@ -1058,11 +1183,26 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPlotMultiplier(OfflinePlayer player) {
|
||||||
|
if (player instanceof Player onlinePlayer) {
|
||||||
|
return HomePermissionOverride.resolvePlotMultiplier(
|
||||||
|
_userOverrides.get(player.getUniqueId()),
|
||||||
|
_permissionOverrides,
|
||||||
|
onlinePlayer::hasPermission,
|
||||||
|
_plotMultiplier);
|
||||||
|
}
|
||||||
|
return HomePermissionOverride.resolvePlotMultiplier(
|
||||||
|
_userOverrides.get(player.getUniqueId()),
|
||||||
|
_permissionOverrides,
|
||||||
|
ignored -> false,
|
||||||
|
_plotMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
public Plot getPlot(String string) {
|
public Plot getPlot(String string) {
|
||||||
/**
|
/**
|
||||||
* string is the name of the region to get a plot for
|
* string is the name of the region to get a plot for
|
||||||
*
|
*
|
||||||
* loop through all regions and find one with the specified name return null if there is none
|
* <p>loop through all regions and find one with the specified name return null if there is none
|
||||||
*/
|
*/
|
||||||
for (Plot plot : _occupiedPlots) {
|
for (Plot plot : _occupiedPlots) {
|
||||||
if (plot.getRegionName().equals(string)) {
|
if (plot.getRegionName().equals(string)) {
|
||||||
@@ -1106,7 +1246,9 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
public boolean homeExists(UUID playerId, int homeNumber) {
|
public boolean homeExists(UUID playerId, int homeNumber) {
|
||||||
for (Plot plot : _occupiedPlots) {
|
for (Plot plot : _occupiedPlots) {
|
||||||
if(plot instanceof PlayerHome home && home.getPlayerId().equals(playerId) && home.getNumber() == homeNumber){
|
if (plot instanceof PlayerHome home
|
||||||
|
&& home.getPlayerId().equals(playerId)
|
||||||
|
&& home.getNumber() == homeNumber) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1143,6 +1285,18 @@ public class MetropolisPlugin extends JavaPlugin {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PlayerHome getFirstOwnedHome(UUID playerId) {
|
||||||
|
List<Plot> plots = _ownedPlots.get(playerId);
|
||||||
|
if (plots == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return plots.stream()
|
||||||
|
.filter(PlayerHome.class::isInstance)
|
||||||
|
.map(PlayerHome.class::cast)
|
||||||
|
.min(java.util.Comparator.comparingInt(PlayerHome::getNumber))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
private void saveCurrentHomes() {
|
private void saveCurrentHomes() {
|
||||||
File homesFile = new File(getDataFolder(), "currentHomes.yml");
|
File homesFile = new File(getDataFolder(), "currentHomes.yml");
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,25 +1,52 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
|
||||||
public class PlayerHome extends Plot {
|
public class PlayerHome extends Plot {
|
||||||
private UUID playerId;
|
private UUID playerId;
|
||||||
private String playerName;
|
private String playerName;
|
||||||
public UUID getPlayerId(){return this.playerId;}
|
|
||||||
public String getPlayerName(){return this.playerName;}
|
public UUID getPlayerId() {
|
||||||
public void setPlayerName(String playerName){this.playerName = playerName;}
|
return this.playerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName() {
|
||||||
|
return this.playerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayerName(String playerName) {
|
||||||
|
this.playerName = playerName;
|
||||||
|
}
|
||||||
|
|
||||||
private int number;
|
private int number;
|
||||||
|
|
||||||
public PlayerHome(UUID ownerId, String ownerName, int homeNumber, BlockVector3 min, BlockVector3 max) {
|
public PlayerHome(
|
||||||
|
UUID ownerId, String ownerName, int homeNumber, BlockVector3 min, BlockVector3 max) {
|
||||||
super(String.format("h_%d_%s", homeNumber, ownerId), min, max);
|
super(String.format("h_%d_%s", homeNumber, ownerId), min, max);
|
||||||
this.playerId = ownerId;
|
this.playerId = ownerId;
|
||||||
this.playerName = ownerName;
|
this.playerName = ownerName;
|
||||||
@@ -54,7 +81,8 @@ public class PlayerHome extends Plot{
|
|||||||
this.playerName = offlinePlayer.getName() == null ? regionOwner : offlinePlayer.getName();
|
this.playerName = offlinePlayer.getName() == null ? regionOwner : offlinePlayer.getName();
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
Set<UUID> ownerIds = homeRegion.getOwners().getUniqueIds();
|
Set<UUID> ownerIds = homeRegion.getOwners().getUniqueIds();
|
||||||
this.playerId = ownerIds.isEmpty()
|
this.playerId =
|
||||||
|
ownerIds.isEmpty()
|
||||||
? Bukkit.getOfflinePlayer(regionOwner).getUniqueId()
|
? Bukkit.getOfflinePlayer(regionOwner).getUniqueId()
|
||||||
: ownerIds.iterator().next();
|
: ownerIds.iterator().next();
|
||||||
this.playerName = regionOwner;
|
this.playerName = regionOwner;
|
||||||
@@ -84,7 +112,16 @@ public class PlayerHome extends Plot{
|
|||||||
public String toFriendlyString() {
|
public String toFriendlyString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append(String.format("Metropolis Home {Owner: %s min: (%d, %d, %d) max: (%d, %d, %d)}", getPlayerName(), getCuboid().getMinX(), getCuboid().getMinY(), getCuboid().getMinZ(), getCuboid().getMaxX(), getCuboid().getMaxY(), getCuboid().getMaxZ()));
|
sb.append(
|
||||||
|
String.format(
|
||||||
|
"Metropolis Home {Owner: %s min: (%d, %d, %d) max: (%d, %d, %d)}",
|
||||||
|
getPlayerName(),
|
||||||
|
getCuboid().getMinX(),
|
||||||
|
getCuboid().getMinY(),
|
||||||
|
getCuboid().getMinZ(),
|
||||||
|
getCuboid().getMaxX(),
|
||||||
|
getCuboid().getMaxY(),
|
||||||
|
getCuboid().getMaxZ()));
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|||||||
@@ -1,26 +1,61 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||||
|
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
|
||||||
|
|
||||||
public class Plot implements Comparable<Plot> {
|
public class Plot implements Comparable<Plot> {
|
||||||
private int _id;
|
private int _id;
|
||||||
public int getId(){return _id;}
|
|
||||||
public void setId(int id){_id = id;}
|
public int getId() {
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
private Cuboid _cuboid;
|
private Cuboid _cuboid;
|
||||||
public Cuboid getCuboid(){return _cuboid;}
|
|
||||||
public void setCuboid(Cuboid cuboid){_cuboid = cuboid;}
|
public Cuboid getCuboid() {
|
||||||
|
return _cuboid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCuboid(Cuboid cuboid) {
|
||||||
|
_cuboid = cuboid;
|
||||||
|
}
|
||||||
|
|
||||||
private String _regionName;
|
private String _regionName;
|
||||||
public String getRegionName(){return _regionName;}
|
|
||||||
public void setRegionName(String regionName){_regionName = regionName;}
|
public String getRegionName() {
|
||||||
|
return _regionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegionName(String regionName) {
|
||||||
|
_regionName = regionName;
|
||||||
|
}
|
||||||
|
|
||||||
public Plot(String regionName, BlockVector3 min, BlockVector3 max) {
|
public Plot(String regionName, BlockVector3 min, BlockVector3 max) {
|
||||||
_cuboid = new Cuboid(min, max);
|
_cuboid = new Cuboid(min, max);
|
||||||
@@ -38,7 +73,8 @@ public class Plot implements Comparable<Plot>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BlockVector3 getPlotMin(int roadWidth) {
|
public BlockVector3 getPlotMin(int roadWidth) {
|
||||||
return BlockVector3.at(_cuboid.minX - roadWidth/2, _cuboid.minY, _cuboid.minZ - roadWidth/2);
|
return BlockVector3.at(
|
||||||
|
_cuboid.minX - roadWidth / 2, _cuboid.minY, _cuboid.minZ - roadWidth / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRow(int roadWidth, int plotSizeZ) {
|
public int getRow(int roadWidth, int plotSizeZ) {
|
||||||
@@ -90,7 +126,15 @@ public class Plot implements Comparable<Plot>{
|
|||||||
public String toFriendlyString() {
|
public String toFriendlyString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append(String.format("Metropolis Reserved Plot {min: (%d, %d, %d) max: (%d, %d, %d)}", getCuboid().getMinX(), getCuboid().getMinY(), getCuboid().getMinZ(), getCuboid().getMaxX(), getCuboid().getMaxY(), getCuboid().getMaxZ()));
|
sb.append(
|
||||||
|
String.format(
|
||||||
|
"Metropolis Reserved Plot {min: (%d, %d, %d) max: (%d, %d, %d)}",
|
||||||
|
getCuboid().getMinX(),
|
||||||
|
getCuboid().getMinY(),
|
||||||
|
getCuboid().getMinZ(),
|
||||||
|
getCuboid().getMaxX(),
|
||||||
|
getCuboid().getMaxY(),
|
||||||
|
getCuboid().getMaxZ()));
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
@@ -107,7 +151,8 @@ public class Plot implements Comparable<Plot>{
|
|||||||
Block block = world.getBlockAt(x, y, z);
|
Block block = world.getBlockAt(x, y, z);
|
||||||
Block blockAbove = world.getBlockAt(x, y + 1, z);
|
Block blockAbove = world.getBlockAt(x, y + 1, z);
|
||||||
Block blockUnder = world.getBlockAt(x, y - 1, z);
|
Block blockUnder = world.getBlockAt(x, y - 1, z);
|
||||||
if(block.getType() == Material.AIR & blockAbove.getType() == Material.AIR && blockUnder.getType() != Material.AIR){
|
if (block.getType() == Material.AIR & blockAbove.getType() == Material.AIR
|
||||||
|
&& blockUnder.getType() != Material.AIR) {
|
||||||
return new Location(world, x, y, z);
|
return new Location(world, x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
public class UserOverride {
|
public class UserOverride {
|
||||||
@@ -5,9 +22,17 @@ public class UserOverride {
|
|||||||
private int _plotMultiplier;
|
private int _plotMultiplier;
|
||||||
private int _maxPlots;
|
private int _maxPlots;
|
||||||
|
|
||||||
public String getUsername(){return _username;}
|
public String getUsername() {
|
||||||
public int getPlotMultiplier(){return _plotMultiplier;}
|
return _username;
|
||||||
public int getMaxPlots(){return _maxPlots;}
|
}
|
||||||
|
|
||||||
|
public int getPlotMultiplier() {
|
||||||
|
return _plotMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPlots() {
|
||||||
|
return _maxPlots;
|
||||||
|
}
|
||||||
|
|
||||||
public UserOverride(String username, int plotMultiplier, int maxPlots) {
|
public UserOverride(String username, int plotMultiplier, int maxPlots) {
|
||||||
_username = username;
|
_username = username;
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class MetropolisCommand implements CommandExecutor {
|
public class MetropolisCommand implements CommandExecutor {
|
||||||
private MetropolisPlugin _plugin;
|
private MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -20,5 +37,4 @@ public class MetropolisCommand implements CommandExecutor {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,34 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class MetropolisDebugGenerateTestHomesCommand implements CommandExecutor {
|
public class MetropolisDebugGenerateTestHomesCommand implements CommandExecutor {
|
||||||
|
|
||||||
private MetropolisPlugin _plugin;
|
private MetropolisPlugin _plugin;
|
||||||
|
|
||||||
public MetropolisDebugGenerateTestHomesCommand(MetropolisPlugin plugin) {
|
public MetropolisDebugGenerateTestHomesCommand(MetropolisPlugin plugin) {
|
||||||
_plugin = plugin;
|
_plugin = plugin;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -28,5 +44,4 @@ public class MetropolisDebugGenerateTestHomesCommand implements CommandExecutor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
import org.bukkit.command.CommandExecutor;
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
import org.bukkit.command.CommandSender;
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
import com.sk89q.worldguard.protection.flags.Flags;
|
import com.sk89q.worldguard.protection.flags.Flags;
|
||||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||||
|
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
public class MetropolisFlagResetCommand implements CommandExecutor {
|
public class MetropolisFlagResetCommand implements CommandExecutor {
|
||||||
private MetropolisPlugin _plugin;
|
private MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -38,16 +55,11 @@ public class MetropolisFlagResetCommand implements CommandExecutor {
|
|||||||
homeRegion.setFlag(Flags.ENDER_BUILD, StateFlag.State.DENY);
|
homeRegion.setFlag(Flags.ENDER_BUILD, StateFlag.State.DENY);
|
||||||
homeRegion.setFlag(Flags.GHAST_FIREBALL, StateFlag.State.DENY);
|
homeRegion.setFlag(Flags.GHAST_FIREBALL, StateFlag.State.DENY);
|
||||||
homeRegion.setFlag(Flags.TNT, StateFlag.State.DENY);
|
homeRegion.setFlag(Flags.TNT, StateFlag.State.DENY);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sender.sendMessage("Metropolis: flags have been reset");
|
sender.sendMessage("Metropolis: flags have been reset");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,29 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class MetropolisHomeAcquire implements CommandExecutor {
|
public class MetropolisHomeAcquire implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -23,13 +40,11 @@ public class MetropolisHomeAcquire implements CommandExecutor {
|
|||||||
|
|
||||||
Player player = (Player) sender;
|
Player player = (Player) sender;
|
||||||
|
|
||||||
if(_plugin.getNumPlots(player.getUniqueId()) >= _plugin.getMaxPlots(player.getUniqueId())){
|
if (_plugin.getNumPlots(player.getUniqueId()) >= _plugin.getMaxPlots(player)) {
|
||||||
sender.sendMessage("You cannot have any more plots");
|
sender.sendMessage("You cannot have any more plots");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugin.assignPlot(player);
|
return _plugin.acquireHome(player) != null;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||||
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
|
||||||
|
|
||||||
public class MetropolisHomeEvictCommand implements CommandExecutor {
|
public class MetropolisHomeEvictCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin = null;
|
MetropolisPlugin _plugin = null;
|
||||||
|
|
||||||
@@ -30,11 +47,13 @@ public class MetropolisHomeEvictCommand implements CommandExecutor {
|
|||||||
|
|
||||||
OfflinePlayer player = _plugin.getOfflinePlayer(playerName);
|
OfflinePlayer player = _plugin.getOfflinePlayer(playerName);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
sender.sendMessage(String.format("The requested player {%s}does not appear to exist.", playerName));
|
sender.sendMessage(
|
||||||
|
String.format("The requested player {%s}does not appear to exist.", playerName));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtectedRegion region = _plugin.getRegion(_plugin.getCurrentHomeRegionName(player.getUniqueId()));
|
ProtectedRegion region =
|
||||||
|
_plugin.getRegion(_plugin.getCurrentHomeRegionName(player.getUniqueId()));
|
||||||
if (region == null) {
|
if (region == null) {
|
||||||
sender.sendMessage(String.format("The player {%s} has no home to be evicted from."));
|
sender.sendMessage(String.format("The player {%s} has no home to be evicted from."));
|
||||||
return false;
|
return false;
|
||||||
@@ -52,9 +71,9 @@ public class MetropolisHomeEvictCommand implements CommandExecutor {
|
|||||||
_plugin.saveRegions();
|
_plugin.saveRegions();
|
||||||
|
|
||||||
// ?optionally regen the region
|
// ?optionally regen the region
|
||||||
//_plugin.worldEdit.getCommand("regen").execute(_plugin.getServer().getConsoleSender(), "regen", new String[]{});
|
// _plugin.worldEdit.getCommand("regen").execute(_plugin.getServer().getConsoleSender(),
|
||||||
|
// "regen", new String[]{});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class MetropolisHomeGenerateCommand implements CommandExecutor {
|
public class MetropolisHomeGenerateCommand implements CommandExecutor {
|
||||||
|
|
||||||
@@ -32,5 +49,4 @@ public class MetropolisHomeGenerateCommand implements CommandExecutor {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
|
||||||
|
|
||||||
public class MetropolisHomeGoCommand implements CommandExecutor {
|
public class MetropolisHomeGoCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin = null;
|
MetropolisPlugin _plugin = null;
|
||||||
|
|
||||||
@@ -66,7 +83,8 @@ public class MetropolisHomeGoCommand implements CommandExecutor {
|
|||||||
if (sender == player) {
|
if (sender == player) {
|
||||||
sender.sendMessage("There is no valid spawn location in your home");
|
sender.sendMessage("There is no valid spawn location in your home");
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(String.format("There is no valid spawn location in %s's home", player.getName()));
|
sender.sendMessage(
|
||||||
|
String.format("There is no valid spawn location in %s's home", player.getName()));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,29 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.Plot;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.Plot;
|
|
||||||
|
|
||||||
public class MetropolisHomeListCommand implements CommandExecutor {
|
public class MetropolisHomeListCommand implements CommandExecutor {
|
||||||
private MetropolisPlugin _plugin;
|
private MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -21,5 +38,4 @@ public class MetropolisHomeListCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,29 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class MetropolisHomeMoveCommand implements CommandExecutor {
|
public class MetropolisHomeMoveCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
@@ -16,38 +34,53 @@ public class MetropolisHomeMoveCommand implements CommandExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
OfflinePlayer player = null;
|
if (args.length < 1 || args.length > 2) {
|
||||||
int newHomeNumber = 0;
|
sender.sendMessage("Usage: /metropolis-home-move <homeNumber> [playerName]");
|
||||||
|
return false;
|
||||||
if(sender instanceof OfflinePlayer){
|
|
||||||
player = (OfflinePlayer)sender;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int homeNumber;
|
||||||
|
try {
|
||||||
|
homeNumber = Integer.parseInt(args[0]);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
sender.sendMessage("Home number must be a positive integer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (homeNumber < 1) {
|
||||||
|
sender.sendMessage("Home number must be a positive integer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OfflinePlayer target;
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
try{
|
if (!(sender instanceof Player player)) {
|
||||||
newHomeNumber = Integer.parseInt(args[0]);
|
sender.sendMessage("Console must specify a player name.");
|
||||||
}catch(NumberFormatException ex){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}else if(args.length >= 2){
|
target = player;
|
||||||
try{
|
|
||||||
newHomeNumber = Integer.parseInt(args[0]);
|
|
||||||
}catch(NumberFormatException ex){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
player = _plugin.getOfflinePlayer(args[1]);
|
|
||||||
} else {
|
} else {
|
||||||
|
target = _plugin.getOfflinePlayer(args[1]);
|
||||||
|
if (target == null) {
|
||||||
|
sender.sendMessage("No known player named " + args[1] + ".");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_plugin.homeExists(target.getUniqueId(), homeNumber)) {
|
||||||
|
String targetName =
|
||||||
|
target.getName() == null ? target.getUniqueId().toString() : target.getName();
|
||||||
|
sender.sendMessage(targetName + " does not have home " + homeNumber + ".");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(player == null || !_plugin.homeExists(player.getUniqueId(), newHomeNumber)){
|
_plugin.setHome(target.getUniqueId(), homeNumber);
|
||||||
return false;
|
String targetName =
|
||||||
|
target.getName() == null ? target.getUniqueId().toString() : target.getName();
|
||||||
|
sender.sendMessage("Home " + homeNumber + " is now active for " + targetName + ".");
|
||||||
|
if (target instanceof Player targetPlayer && targetPlayer != sender) {
|
||||||
|
targetPlayer.sendMessage("Your active Metropolis home is now home " + homeNumber + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugin.setHome(player.getUniqueId(), newHomeNumber);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.Plot;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.Plot;
|
|
||||||
|
|
||||||
public class MetropolisPlotGoCommand implements CommandExecutor {
|
public class MetropolisPlotGoCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -45,5 +62,4 @@ public class MetropolisPlotGoCommand implements CommandExecutor {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
import org.bukkit.command.CommandExecutor;
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
import org.bukkit.command.CommandSender;
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
import org.bukkit.entity.Player;
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
@@ -11,6 +23,11 @@ import com.sk89q.worldedit.IncompleteRegionException;
|
|||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class MetropolisPlotReserveCommand implements CommandExecutor {
|
public class MetropolisPlotReserveCommand implements CommandExecutor {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
|
|
||||||
@@ -30,7 +47,10 @@ public class MetropolisPlotReserveCommand implements CommandExecutor {
|
|||||||
|
|
||||||
if (sender instanceof Player && args.length == 1) {
|
if (sender instanceof Player && args.length == 1) {
|
||||||
try {
|
try {
|
||||||
Region selection = _plugin.worldEdit.getSession((Player) sender)
|
Region selection =
|
||||||
|
_plugin
|
||||||
|
.worldEdit
|
||||||
|
.getSession((Player) sender)
|
||||||
.getSelection(BukkitAdapter.adapt(_plugin.getWorld()));
|
.getSelection(BukkitAdapter.adapt(_plugin.getWorld()));
|
||||||
cuboid = new Cuboid(selection);
|
cuboid = new Cuboid(selection);
|
||||||
} catch (IncompleteRegionException ex) {
|
} catch (IncompleteRegionException ex) {
|
||||||
@@ -72,5 +92,4 @@ public class MetropolisPlotReserveCommand implements CommandExecutor {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,29 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
public class DebugListener implements Listener {
|
public class DebugListener implements Listener {
|
||||||
MetropolisPlugin _plugin;
|
MetropolisPlugin _plugin;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,32 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
|
||||||
|
|
||||||
public class PlayerJoinListener implements Listener {
|
public class PlayerJoinListener implements Listener {
|
||||||
private MetropolisPlugin _plugin = null;
|
private MetropolisPlugin _plugin = null;
|
||||||
|
|
||||||
@@ -25,15 +42,32 @@ public class PlayerJoinListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerHome home = _plugin.getPlayerHome(player);
|
PlayerHome home = _plugin.getPlayerHome(player);
|
||||||
if(home==null){_plugin.getLogger().info("home is null");}
|
if (home == null) {
|
||||||
else if(home.getCuboid() == null){_plugin.getLogger().info("home.getCuboid() is null");}
|
_plugin.getLogger().info("home is null");
|
||||||
else if(home.getCuboid().getVolume() == 0){_plugin.getLogger().info("home.getCuboid().getVolume() is 0");}
|
} else if (home.getCuboid() == null) {
|
||||||
|
_plugin.getLogger().info("home.getCuboid() is null");
|
||||||
|
} else if (home.getCuboid().getVolume() == 0) {
|
||||||
|
_plugin.getLogger().info("home.getCuboid().getVolume() is 0");
|
||||||
|
}
|
||||||
|
|
||||||
if (home == null || home.getCuboid() == null || home.getCuboid().getVolume() == 0) {
|
if (home == null || home.getCuboid() == null || home.getCuboid().getVolume() == 0) {
|
||||||
_plugin.getLogger().info(String.format("Metropolis: Unable to get or create home for player %s", player.getName()));
|
_plugin
|
||||||
|
.getLogger()
|
||||||
|
.info(
|
||||||
|
String.format(
|
||||||
|
"Metropolis: Unable to get or create home for player %s", player.getName()));
|
||||||
} else {
|
} else {
|
||||||
Cuboid cuboid = home.getCuboid();
|
Cuboid cuboid = home.getCuboid();
|
||||||
player.sendMessage(String.format("Metropolis: Welcome %s your home is between (%d, %d, %d) and (%d, %d, %d)", player.getName(), cuboid.getMinX(), cuboid.getMinY(), cuboid.getMinZ(), cuboid.getMaxX(), cuboid.getMaxY(), cuboid.getMaxZ()));
|
player.sendMessage(
|
||||||
|
String.format(
|
||||||
|
"Metropolis: Welcome %s your home is between (%d, %d, %d) and (%d, %d, %d)",
|
||||||
|
player.getName(),
|
||||||
|
cuboid.getMinX(),
|
||||||
|
cuboid.getMinY(),
|
||||||
|
cuboid.getMinZ(),
|
||||||
|
cuboid.getMaxX(),
|
||||||
|
cuboid.getMaxY(),
|
||||||
|
cuboid.getMaxZ()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.util;
|
package com.majinnaibu.bukkitplugins.metropolis.util;
|
||||||
|
|
||||||
public class Material {
|
public class Material {
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
Goal: Have 1 plot size for mods and 1 plot size for normals.
|
|
||||||
Implementation:
|
|
||||||
1. Set the plotSize in the config to the larger plot size there are other possible sizes but powers of 2 work really well so lets give mods a 64x64 plot. Roads are recomended but will eat into the plot on all sides so the roadsize can be ignored for this example.
|
|
||||||
2. Start the server and run /metropolis-home-generate <username> for each mod.
|
|
||||||
3. If you have not completed a full ring then run /metropolis-home-generate <test n> where n starts at 1 and increases until you have filled a full ring. This will reserve those plots for later or anyone who happens to have that username, but that can be dealth with later.
|
|
||||||
4. Stop the server and change the plotSize to a smaller number like 32.
|
|
||||||
5. Restart the server and let your users log in.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
All users will be assigned a small plot when they first connect. When you make them a mod just delete their current region and change the name of one of the reserved home regions to h_<their username>.
|
|
||||||
/region remove h_jonnynewadmin
|
|
||||||
/region select test_1
|
|
||||||
/region remove test_1
|
|
||||||
/region define h_johnnynewadmin
|
|
||||||
JohnnyNewAdmin's old home will become available for resettlement. If you want to copy johnny's old blocks into his new home region I'd suggest WorldEdit.
|
|
||||||
This process including optionally copying the blocks will be an upcoming feature. Probably in 0.5.x and maybe in 0.6.
|
|
||||||
|
|
||||||
If you later run out of larger plots you can just set the size back to the larger number and let more generate. Moving and evictions will be coming soon and make this easier.
|
|
||||||
You can manually just create a region for a user before they login named like h_<username> if you want a specific user to have a really big space as well.
|
|
||||||
@@ -22,7 +22,6 @@ commands:
|
|||||||
permission: metropolis.home.evict
|
permission: metropolis.home.evict
|
||||||
usage: /metropolis-home-evict <playerName>
|
usage: /metropolis-home-evict <playerName>
|
||||||
metropolis-home-move:
|
metropolis-home-move:
|
||||||
description: This command swaps a player's current home with a reserved plot.
|
|
||||||
permission: metropolis.home.move
|
permission: metropolis.home.move
|
||||||
usage: /metropolis-home-move <newHomeNumber> [player]
|
usage: /metropolis-home-move <newHomeNumber> [player]
|
||||||
metropolis-home-go:
|
metropolis-home-go:
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
|
|
||||||
class CuboidTest {
|
class CuboidTest {
|
||||||
@Test
|
@Test
|
||||||
void convertsWorldEditBoundsToCuboidCoordinates() {
|
void convertsWorldEditBoundsToCuboidCoordinates() {
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -11,8 +28,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
class CurrentHomesStoreTest {
|
class CurrentHomesStoreTest {
|
||||||
@TempDir
|
@TempDir File temporaryDirectory;
|
||||||
File temporaryDirectory;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void roundTripsHomesByUuid() throws Exception {
|
void roundTripsHomesByUuid() throws Exception {
|
||||||
@@ -33,7 +49,11 @@ class CurrentHomesStoreTest {
|
|||||||
yaml.set("OldPlayerName", 2);
|
yaml.set("OldPlayerName", 2);
|
||||||
yaml.save(file);
|
yaml.save(file);
|
||||||
|
|
||||||
assertEquals(Map.of(playerId, 2), CurrentHomesStore.load(file, name -> {
|
assertEquals(
|
||||||
|
Map.of(playerId, 2),
|
||||||
|
CurrentHomesStore.load(
|
||||||
|
file,
|
||||||
|
name -> {
|
||||||
assertEquals("OldPlayerName", name);
|
assertEquals("OldPlayerName", name);
|
||||||
return playerId;
|
return playerId;
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class HomeNumberAllocatorTest {
|
||||||
|
@Test
|
||||||
|
void choosesTheFirstUnusedPositiveHomeNumber() {
|
||||||
|
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
|
PlayerHome first =
|
||||||
|
new PlayerHome(playerId, "PlayerName", 1, BlockVector3.ZERO, BlockVector3.ZERO);
|
||||||
|
PlayerHome third =
|
||||||
|
new PlayerHome(playerId, "PlayerName", 3, BlockVector3.ZERO, BlockVector3.ZERO);
|
||||||
|
|
||||||
|
assertEquals(1, HomeNumberAllocator.nextHomeNumber(List.of()));
|
||||||
|
assertEquals(2, HomeNumberAllocator.nextHomeNumber(List.of(first, third)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class HomePermissionOverrideTest {
|
||||||
|
@Test
|
||||||
|
void selectsTheHighestPriorityAndUsesLastEntryForTies() throws InvalidConfigurationException {
|
||||||
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
|
config.loadFromString(
|
||||||
|
"""
|
||||||
|
permissionOverrides:
|
||||||
|
metropolis.plots.vip:
|
||||||
|
priority: 10
|
||||||
|
plotMultiplier: 2
|
||||||
|
maxPlots: 2
|
||||||
|
metropolis.plots.elite:
|
||||||
|
priority: 20
|
||||||
|
plotMultiplier: 3
|
||||||
|
maxPlots: 5
|
||||||
|
metropolis.plots.staff:
|
||||||
|
priority: 20
|
||||||
|
plotMultiplier: 4
|
||||||
|
maxPlots: 8
|
||||||
|
""");
|
||||||
|
List<String> warnings = new ArrayList<>();
|
||||||
|
|
||||||
|
List<HomePermissionOverride> overrides =
|
||||||
|
HomePermissionOverride.load(
|
||||||
|
config.getConfigurationSection("permissionOverrides"), warnings::add);
|
||||||
|
HomePermissionOverride match =
|
||||||
|
HomePermissionOverride.findMatch(
|
||||||
|
overrides,
|
||||||
|
Set.of("metropolis.plots.vip", "metropolis.plots.elite", "metropolis.plots.staff")
|
||||||
|
::contains);
|
||||||
|
|
||||||
|
assertEquals(3, overrides.size());
|
||||||
|
assertEquals("metropolis.plots.staff", match.getPermission());
|
||||||
|
assertEquals(4, match.getPlotMultiplier());
|
||||||
|
assertEquals(8, match.getMaxPlots());
|
||||||
|
assertEquals(List.of(), warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void preservesDottedPermissionNamesAndSkipsInvalidEntries() throws InvalidConfigurationException {
|
||||||
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
|
config.loadFromString(
|
||||||
|
"""
|
||||||
|
permissionOverrides:
|
||||||
|
metropolis.plots.vip:
|
||||||
|
priority: 3
|
||||||
|
plotMultiplier: 2
|
||||||
|
maxPlots: 4
|
||||||
|
metropolis.plots.invalid:
|
||||||
|
plotMultiplier: 2
|
||||||
|
maxPlots: 4
|
||||||
|
""");
|
||||||
|
List<String> warnings = new ArrayList<>();
|
||||||
|
|
||||||
|
List<HomePermissionOverride> overrides =
|
||||||
|
HomePermissionOverride.load(
|
||||||
|
config.getConfigurationSection("permissionOverrides"), warnings::add);
|
||||||
|
HomePermissionOverride match =
|
||||||
|
HomePermissionOverride.findMatch(overrides, "metropolis.plots.vip"::equals);
|
||||||
|
|
||||||
|
assertEquals(1, overrides.size());
|
||||||
|
assertEquals("metropolis.plots.vip", overrides.get(0).getPermission());
|
||||||
|
assertSame(overrides.get(0), match);
|
||||||
|
assertNull(HomePermissionOverride.findMatch(overrides, ignored -> false));
|
||||||
|
assertEquals(1, warnings.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resolvesUserOverrideBeforePermissionAndGlobalFallback()
|
||||||
|
throws InvalidConfigurationException {
|
||||||
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
|
config.set("permissionOverrides.metropolis.plots.vip.priority", 10);
|
||||||
|
config.set("permissionOverrides.metropolis.plots.vip.plotMultiplier", 2);
|
||||||
|
config.set("permissionOverrides.metropolis.plots.vip.maxPlots", 4);
|
||||||
|
List<HomePermissionOverride> overrides =
|
||||||
|
HomePermissionOverride.load(
|
||||||
|
config.getConfigurationSection("permissionOverrides"), ignored -> {});
|
||||||
|
UserOverride userOverride = new UserOverride("PlayerName", 3, 6);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
6,
|
||||||
|
HomePermissionOverride.resolveMaxPlots(
|
||||||
|
userOverride, overrides, "metropolis.plots.vip"::equals, 1));
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
HomePermissionOverride.resolvePlotMultiplier(
|
||||||
|
userOverride, overrides, "metropolis.plots.vip"::equals, 1));
|
||||||
|
assertEquals(
|
||||||
|
4,
|
||||||
|
HomePermissionOverride.resolveMaxPlots(null, overrides, "metropolis.plots.vip"::equals, 1));
|
||||||
|
assertEquals(
|
||||||
|
2,
|
||||||
|
HomePermissionOverride.resolvePlotMultiplier(
|
||||||
|
null, overrides, "metropolis.plots.vip"::equals, 1));
|
||||||
|
assertEquals(1, HomePermissionOverride.resolveMaxPlots(null, overrides, ignored -> false, 1));
|
||||||
|
assertEquals(
|
||||||
|
1, HomePermissionOverride.resolvePlotMultiplier(null, overrides, ignored -> false, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,37 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class PlayerHomeTest {
|
class PlayerHomeTest {
|
||||||
@Test
|
@Test
|
||||||
void buildsUuidBasedRegionIdentityAndPreservesDisplayName() {
|
void buildsUuidBasedRegionIdentityAndPreservesDisplayName() {
|
||||||
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
PlayerHome home = new PlayerHome(
|
PlayerHome home =
|
||||||
playerId,
|
new PlayerHome(
|
||||||
"PlayerName",
|
playerId, "PlayerName", 2, BlockVector3.at(1, 2, 3), BlockVector3.at(4, 5, 6));
|
||||||
2,
|
|
||||||
BlockVector3.at(1, 2, 3),
|
|
||||||
BlockVector3.at(4, 5, 6));
|
|
||||||
|
|
||||||
assertEquals(playerId, home.getPlayerId());
|
assertEquals(playerId, home.getPlayerId());
|
||||||
assertEquals("PlayerName", home.getPlayerName());
|
assertEquals("PlayerName", home.getPlayerName());
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis;
|
package com.majinnaibu.bukkitplugins.metropolis;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -9,12 +26,13 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
class MetropolisHomeAcquireTest {
|
class MetropolisHomeAcquireTest {
|
||||||
@Test
|
@Test
|
||||||
void assignsAPlotWhenThePlayerIsBelowTheirLimit() {
|
void assignsAPlotWhenThePlayerIsBelowTheirLimit() {
|
||||||
@@ -23,12 +41,13 @@ class MetropolisHomeAcquireTest {
|
|||||||
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
when(player.getUniqueId()).thenReturn(playerId);
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
when(plugin.getNumPlots(playerId)).thenReturn(0);
|
when(plugin.getNumPlots(playerId)).thenReturn(0);
|
||||||
when(plugin.getMaxPlots(playerId)).thenReturn(1);
|
when(plugin.getMaxPlots(player)).thenReturn(1);
|
||||||
|
when(plugin.acquireHome(player)).thenReturn(mock(PlayerHome.class));
|
||||||
MetropolisHomeAcquire executor = new MetropolisHomeAcquire(plugin);
|
MetropolisHomeAcquire executor = new MetropolisHomeAcquire(plugin);
|
||||||
|
|
||||||
assertTrue(executor.onCommand(player, mock(Command.class), "acquire", new String[0]));
|
assertTrue(executor.onCommand(player, mock(Command.class), "acquire", new String[0]));
|
||||||
|
|
||||||
verify(plugin).assignPlot(player);
|
verify(plugin).acquireHome(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -38,11 +57,11 @@ class MetropolisHomeAcquireTest {
|
|||||||
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
UUID playerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
when(player.getUniqueId()).thenReturn(playerId);
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
when(plugin.getNumPlots(playerId)).thenReturn(1);
|
when(plugin.getNumPlots(playerId)).thenReturn(1);
|
||||||
when(plugin.getMaxPlots(playerId)).thenReturn(1);
|
when(plugin.getMaxPlots(player)).thenReturn(1);
|
||||||
MetropolisHomeAcquire executor = new MetropolisHomeAcquire(plugin);
|
MetropolisHomeAcquire executor = new MetropolisHomeAcquire(plugin);
|
||||||
|
|
||||||
assertFalse(executor.onCommand(player, mock(Command.class), "acquire", new String[0]));
|
assertFalse(executor.onCommand(player, mock(Command.class), "acquire", new String[0]));
|
||||||
|
|
||||||
verify(plugin, never()).assignPlot(player);
|
verify(plugin, never()).acquireHome(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.contains;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class MetropolisHomeMoveCommandTest {
|
||||||
|
private static final UUID PLAYER_ID = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void selectsTheSendersExistingHome() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
Player sender = mock(Player.class);
|
||||||
|
when(sender.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
when(sender.getName()).thenReturn("PlayerName");
|
||||||
|
when(plugin.homeExists(PLAYER_ID, 2)).thenReturn(true);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertTrue(command.onCommand(sender, mock(Command.class), "move", new String[] {"2"}));
|
||||||
|
|
||||||
|
verify(plugin).setHome(PLAYER_ID, 2);
|
||||||
|
verify(sender).sendMessage(contains("Home 2 is now active for PlayerName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void selectsAnOfflineTargetsExistingHome() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
CommandSender sender = mock(CommandSender.class);
|
||||||
|
OfflinePlayer target = mock(OfflinePlayer.class);
|
||||||
|
when(plugin.getOfflinePlayer("OfflineName")).thenReturn(target);
|
||||||
|
when(target.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
when(target.getName()).thenReturn("OfflineName");
|
||||||
|
when(plugin.homeExists(PLAYER_ID, 3)).thenReturn(true);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"3", "OfflineName"}));
|
||||||
|
|
||||||
|
verify(plugin).setHome(PLAYER_ID, 3);
|
||||||
|
verify(sender).sendMessage(contains("Home 3 is now active for OfflineName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsInvalidNumbersMissingPlayersAndNonexistentHomes() {
|
||||||
|
MetropolisPlugin plugin = mock(MetropolisPlugin.class);
|
||||||
|
Player sender = mock(Player.class);
|
||||||
|
when(sender.getUniqueId()).thenReturn(PLAYER_ID);
|
||||||
|
MetropolisHomeMoveCommand command = new MetropolisHomeMoveCommand(plugin);
|
||||||
|
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"0"}));
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"nope"}));
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "unknown"}));
|
||||||
|
when(plugin.getOfflinePlayer("unknown")).thenReturn(null);
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "unknown"}));
|
||||||
|
assertFalse(
|
||||||
|
command.onCommand(sender, mock(Command.class), "move", new String[] {"1", "2", "extra"}));
|
||||||
|
assertFalse(command.onCommand(sender, mock(Command.class), "move", new String[] {"1"}));
|
||||||
|
|
||||||
|
verify(plugin, never()).setHome(PLAYER_ID, 0);
|
||||||
|
verify(sender, times(2)).sendMessage(contains("positive integer"));
|
||||||
|
verify(sender).sendMessage(contains("does not have home 1"));
|
||||||
|
verify(sender).sendMessage(contains("Usage:"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
package com.majinnaibu.bukkitplugins.metropolis.commands;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -8,14 +25,14 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
||||||
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.Cuboid;
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
|
||||||
|
|
||||||
class MetropolisPlotReserveCommandTest {
|
class MetropolisPlotReserveCommandTest {
|
||||||
@Test
|
@Test
|
||||||
void reservesCoordinatesFromAllSixArguments() {
|
void reservesCoordinatesFromAllSixArguments() {
|
||||||
@@ -24,7 +41,9 @@ class MetropolisPlotReserveCommandTest {
|
|||||||
Command command = mock(Command.class);
|
Command command = mock(Command.class);
|
||||||
MetropolisPlotReserveCommand executor = new MetropolisPlotReserveCommand(plugin);
|
MetropolisPlotReserveCommand executor = new MetropolisPlotReserveCommand(plugin);
|
||||||
|
|
||||||
assertTrue(executor.onCommand(sender, command, "reserve", new String[] {"north", "1", "2", "3", "4", "5", "6"}));
|
assertTrue(
|
||||||
|
executor.onCommand(
|
||||||
|
sender, command, "reserve", new String[] {"north", "1", "2", "3", "4", "5", "6"}));
|
||||||
|
|
||||||
ArgumentCaptor<Cuboid> cuboid = ArgumentCaptor.forClass(Cuboid.class);
|
ArgumentCaptor<Cuboid> cuboid = ArgumentCaptor.forClass(Cuboid.class);
|
||||||
verify(plugin).reserveCuboid(eq("north"), cuboid.capture());
|
verify(plugin).reserveCuboid(eq("north"), cuboid.capture());
|
||||||
@@ -43,7 +62,9 @@ class MetropolisPlotReserveCommandTest {
|
|||||||
Command command = mock(Command.class);
|
Command command = mock(Command.class);
|
||||||
MetropolisPlotReserveCommand executor = new MetropolisPlotReserveCommand(plugin);
|
MetropolisPlotReserveCommand executor = new MetropolisPlotReserveCommand(plugin);
|
||||||
|
|
||||||
assertFalse(executor.onCommand(sender, command, "reserve", new String[] {"north", "1", "two", "3", "4", "5", "6"}));
|
assertFalse(
|
||||||
|
executor.onCommand(
|
||||||
|
sender, command, "reserve", new String[] {"north", "1", "two", "3", "4", "5", "6"}));
|
||||||
verifyNoInteractions(plugin);
|
verifyNoInteractions(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Metropolis.
|
||||||
|
|
||||||
|
Metropolis is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Metropolis is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
package com.majinnaibu.bukkitplugins.metropolis.eventlisteners;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.contains;
|
import static org.mockito.ArgumentMatchers.contains;
|
||||||
@@ -7,14 +24,14 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
import com.majinnaibu.bukkitplugins.metropolis.MetropolisPlugin;
|
||||||
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
import com.majinnaibu.bukkitplugins.metropolis.PlayerHome;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class PlayerJoinListenerTest {
|
class PlayerJoinListenerTest {
|
||||||
@Test
|
@Test
|
||||||
void tellsJoiningPlayerTheirHomeBounds() {
|
void tellsJoiningPlayerTheirHomeBounds() {
|
||||||
@@ -23,7 +40,9 @@ class PlayerJoinListenerTest {
|
|||||||
PlayerJoinEvent event = mock(PlayerJoinEvent.class);
|
PlayerJoinEvent event = mock(PlayerJoinEvent.class);
|
||||||
when(event.getPlayer()).thenReturn(player);
|
when(event.getPlayer()).thenReturn(player);
|
||||||
when(player.getName()).thenReturn("PlayerName");
|
when(player.getName()).thenReturn("PlayerName");
|
||||||
when(plugin.getPlayerHome(player)).thenReturn(new PlayerHome(
|
when(plugin.getPlayerHome(player))
|
||||||
|
.thenReturn(
|
||||||
|
new PlayerHome(
|
||||||
UUID.fromString("123e4567-e89b-12d3-a456-426614174000"),
|
UUID.fromString("123e4567-e89b-12d3-a456-426614174000"),
|
||||||
"PlayerName",
|
"PlayerName",
|
||||||
1,
|
1,
|
||||||
|
|||||||
@@ -44,8 +44,24 @@ MODRINTH_VERSION="${MODRINTH_VERSION:-${VERSION:-}}"
|
|||||||
if [[ -z "$MODRINTH_VERSION" ]]; then
|
if [[ -z "$MODRINTH_VERSION" ]]; then
|
||||||
MODRINTH_VERSION=$(cd "$PROJECT_ROOT" && ./gradlew -q properties --property version | sed -n 's/^version: //p' | head -n1)
|
MODRINTH_VERSION=$(cd "$PROJECT_ROOT" && ./gradlew -q properties --property version | sed -n 's/^version: //p' | head -n1)
|
||||||
fi
|
fi
|
||||||
MODRINTH_CHANGELOG="${MODRINTH_CHANGELOG:-Auto release via publish-modrinth.sh}"
|
generate_changelog() {
|
||||||
MODRINTH_GAME_VERSIONS="${MODRINTH_GAME_VERSIONS:-26.2}"
|
local current_tag previous_tag range commits
|
||||||
|
current_tag=$(git -C "$PROJECT_ROOT" describe --tags --exact-match HEAD 2>/dev/null || true)
|
||||||
|
if [[ -n "$current_tag" ]]; then
|
||||||
|
previous_tag=$(git -C "$PROJECT_ROOT" describe --tags --abbrev=0 "${current_tag}^" 2>/dev/null || true)
|
||||||
|
range="${previous_tag:+$previous_tag..}$current_tag"
|
||||||
|
else
|
||||||
|
previous_tag=$(git -C "$PROJECT_ROOT" describe --tags --abbrev=0 2>/dev/null || true)
|
||||||
|
range="${previous_tag:+$previous_tag..}HEAD"
|
||||||
|
fi
|
||||||
|
commits=$(git -C "$PROJECT_ROOT" log --no-merges --format='- %s (%h)' "$range" 2>/dev/null || true)
|
||||||
|
if [[ -z "$commits" ]]; then
|
||||||
|
commits='- No commit messages found for this release.'
|
||||||
|
fi
|
||||||
|
printf '%s\n\n%s\n' "## What's Changed" "$commits"
|
||||||
|
}
|
||||||
|
MODRINTH_CHANGELOG="${MODRINTH_CHANGELOG:-$(generate_changelog)}"
|
||||||
|
MODRINTH_GAME_VERSIONS="${MODRINTH_GAME_VERSIONS:-26.2,26.3}"
|
||||||
MODRINTH_LOADERS="${MODRINTH_LOADERS:-paper}"
|
MODRINTH_LOADERS="${MODRINTH_LOADERS:-paper}"
|
||||||
MODRINTH_VERSION_TYPE="${MODRINTH_VERSION_TYPE:-}"
|
MODRINTH_VERSION_TYPE="${MODRINTH_VERSION_TYPE:-}"
|
||||||
MODRINTH_FILE="${MODRINTH_FILE:-}"
|
MODRINTH_FILE="${MODRINTH_FILE:-}"
|
||||||
|
|||||||
Reference in New Issue
Block a user