Skip to content

Commit 0ccb341

Browse files
committed
Refresh EndCrystals for modern Paper, Java 25, and config-driven protection
1 parent ad5acbe commit 0ccb341

11 files changed

Lines changed: 687 additions & 95 deletions

README.md

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@ The produced jar is named:
1111

1212
`1MB-EndCrystals-v2.0.1-021-v25-26.1.2.jar`
1313

14-
## What It Does
14+
## Feature List
1515

1616
- Clears end crystal block damage without cancelling the whole explosion event
17+
- Prevents item and decorative entity destruction from crystal explosions
18+
- Protects minecart variants, boat or raft variants, display entities, paintings, frames, armor stands, leash knots, and dropped items
1719
- Optionally blocks players from breaking protected crystals
1820
- Optionally blocks player projectiles from breaking protected crystals
1921
- Keeps The End configurable so dragon-fight style gameplay can stay intact if desired
20-
- Stores config in a shared home-folder location: `~/plugins/1MB-EndCrystals/config.yml`
22+
- Uses the normal Paper plugin data folder: `plugins/1MB-EndCrystals/config.yml`
23+
- Migrates the misplaced legacy home-folder config into the correct server-local folder on first startup
2124
- Supports `/_endcrystals reload`
22-
- Supports `/_endcrystals toggle <setting> [true|false]` for live boolean config toggles
25+
- Supports `/_endcrystals toggle [setting] [true|false]` for live boolean config toggles
2326
- Supports `/_endcrystals debug` for runtime/build/config diagnostics
27+
- Supports configurable command aliases from `config.yml`
28+
- Uses MiniMessage formatting for plugin output
29+
- Uses strict permission nodes with op not automatically bypassing protection
30+
- Targets Java `25` and modern Paper builds
31+
- Builds with Gradle from a fresh clone without requiring any private `/servers/` test setup
2432

2533
## Commands
2634

@@ -30,42 +38,73 @@ The produced jar is named:
3038
- `/_endcrystals toggle protection.prevent-block-damage`
3139
- `/_endcrystals toggle debug.log-block-protection true`
3240

33-
Aliases:
41+
Configurable aliases:
3442

3543
- `/endcrystals`
3644
- `/ec`
3745

46+
Those aliases are controlled by `commands.aliases` in `plugins/1MB-EndCrystals/config.yml`. Set `commands.aliases: []` if you want no extra aliases. Changes apply after `/_endcrystals reload`.
47+
If another plugin or the server already owns one of those names, 1MB-EndCrystals skips that alias and logs a warning while keeping `/_endcrystals` available.
48+
3849
## Permissions
3950

40-
- `1mb.endcrystals.admin`
41-
- `1mb.endcrystals.debug`
42-
- `1mb.endcrystals.reload`
43-
- `1mb.endcrystals.toggle`
44-
- `1mb.endcrystals.bypass`
51+
- `onembendcrystals.admin`
52+
- `onembendcrystals.debug`
53+
- `onembendcrystals.reload`
54+
- `onembendcrystals.toggle`
55+
- `onembendcrystals.break`
4556

46-
`1mb.endcrystals.admin` grants the command permissions. `1mb.endcrystals.bypass` allows a player to break otherwise protected crystals.
57+
All of these permissions default to `false`, so being op alone does not grant them. `onembendcrystals.admin` grants the command permissions. `onembendcrystals.break` allows a player to break otherwise protected crystals.
4758

4859
## Config
4960

5061
The plugin reads and writes its main config here:
5162

52-
`~/plugins/1MB-EndCrystals/config.yml`
63+
`plugins/1MB-EndCrystals/config.yml`
64+
65+
Each Paper server gets its own local config folder, which is the normal Bukkit/Paper behavior.
5366

54-
That makes it easy to share one config across multiple local servers started by the same user account.
67+
If you are upgrading from an older build that wrote to `~/plugins/1MB-EndCrystals/config.yml`, the plugin will copy that legacy file into the server-local plugin folder on first startup if the new server-local config does not already exist.
5568

5669
Important defaults:
5770

71+
- `commands.aliases: [endcrystals, ec]`
5872
- `protection.prevent-block-damage: true`
5973
- `protection.prevent-player-break: true`
6074
- `protection.prevent-projectile-break: true`
61-
- `protection.allow-player-break-in-the-end: true`
75+
- `protection.prevent-protected-entity-damage: true`
76+
- `protection.allow-player-break-in-the-end: false`
6277
- `protection.clear-explosion-yield: true`
6378

64-
Live toggle keys are listed in the config under `live-toggles`. Those settings can be changed immediately with `/_endcrystals toggle ...` and also refresh when you run `/_endcrystals reload`.
79+
By default the protected entity list includes armor stands, dropped items, item frames, glow item frames, paintings, display entities, leash knots, minecart variants, and boat or raft variants. Live toggle keys are listed in the config under `live-toggles`. Those settings can be changed immediately with `/_endcrystals toggle [setting] [true|false]` and also refresh when you run `/_endcrystals reload`.
80+
81+
## Changelog
82+
83+
### Legacy -> `v2.0.1` Refresh
84+
85+
This section summarizes the modernization work completed for the current refresh.
86+
87+
- Migrated the plugin to a Gradle build for Java `25`
88+
- Retargeted the plugin for modern Paper, validated against `1.21.11` and `26.1.2`
89+
- Standardized the shipped jar name to `1MB-EndCrystals-v2.0.1-021-v25-26.1.2.jar`
90+
- Reworked config storage to use the active server's `plugins/1MB-EndCrystals/config.yml`
91+
- Added one-time migration support for the old misplaced `~/plugins/1MB-EndCrystals/config.yml`
92+
- Added `/_endcrystals reload`
93+
- Added `/_endcrystals debug`
94+
- Added live config toggles through `/_endcrystals toggle [setting] [true|false]`
95+
- Moved command aliases into `config.yml` so they can be added or removed without editing `plugin.yml`
96+
- Kept `/_endcrystals` as the permanent primary command
97+
- Switched to explicit `onembendcrystals.*` permission nodes with `default: false`
98+
- Made crystal breaking permission-driven instead of implicitly allowing ops
99+
- Expanded protection beyond blocks to cover decorative and item entities
100+
- Added protection for minecart and boat-style entities that were still vulnerable on the legacy path
101+
- Improved debug output to show build/runtime info, config path, permissions, live toggles, and active commands
102+
- Moved plugin messages into config and formatted output with MiniMessage
103+
- Updated docs so public builds do not depend on any private local `/servers/` test directory
65104

66105
## Build
67106

68-
If the local Paper `1.21.11` API jar is available in `servers/Server-One-Paper-1.21.11`, Gradle uses that directly for offline local builds. Otherwise it falls back to the Paper Maven repository.
107+
The public build does not depend on any local `servers/` directory. A normal checkout builds against the Paper API from the Paper Maven repository, and any repo-local test servers are strictly optional private development tooling.
69108

70109
Build with:
71110

@@ -81,10 +120,10 @@ Output jar:
81120

82121
1. Build the jar.
83122
2. Copy it into a Paper server's `plugins/` folder.
84-
3. Start the server once so the shared config is created under `~/plugins/1MB-EndCrystals/`.
123+
3. Start the server once so the plugin creates `plugins/1MB-EndCrystals/config.yml`.
85124
4. Use `/_endcrystals debug` to verify runtime information.
86125
5. Use `/_endcrystals reload` after editing the config.
87126

88127
## Testing Notes
89128

90-
The plugin is meant to be testable without WorldGuard present. If an end crystal explodes near normal blocks, the explosion should still happen but the blocks should remain intact while the plugin is enabled.
129+
The plugin is meant to be testable without WorldGuard present. If an end crystal explodes near normal blocks, the explosion should still happen but the blocks should remain intact while the plugin is enabled. Any `/servers/` directory used in development is for private local testing only and is not part of the public build flow.

build.gradle.kts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ description = "1MB helper plugin that prevents end crystals from damaging blocks
88
val pluginVersion = providers.gradleProperty("pluginVersion").get()
99
val buildNumber = providers.gradleProperty("buildNumber").get()
1010
val javaTarget = providers.gradleProperty("javaTarget").get()
11+
val paperApiVersion = providers.gradleProperty("paperApiVersion").get()
1112
val targetPaperVersion = providers.gradleProperty("targetPaperVersion").get()
1213
val targetMinecraftVersion = providers.gradleProperty("targetMinecraftVersion").get()
1314

@@ -18,20 +19,8 @@ repositories {
1819
maven("https://repo.papermc.io/repository/maven-public/")
1920
}
2021

21-
val localPaperApi = layout.projectDirectory.file(
22-
"servers/Server-One-Paper-1.21.11/libraries/io/papermc/paper/paper-api/1.21.11-R0.1-SNAPSHOT/paper-api-1.21.11-R0.1-SNAPSHOT.jar"
23-
).asFile
24-
val localPaperLibraries = layout.projectDirectory.dir("servers/Server-One-Paper-1.21.11/libraries").asFile
25-
2622
dependencies {
27-
if (localPaperApi.exists() && localPaperLibraries.isDirectory) {
28-
compileOnly(files(localPaperApi))
29-
compileOnly(fileTree(localPaperLibraries) {
30-
include("**/*.jar")
31-
})
32-
} else {
33-
compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
34-
}
23+
compileOnly("io.papermc.paper:paper-api:$paperApiVersion")
3524
}
3625

3726
java {

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pluginVersion=2.0.1
22
buildNumber=021
33
javaTarget=25
4+
paperApiVersion=1.21.11-R0.1-SNAPSHOT
45
targetPaperVersion=26.1.2
56
targetMinecraftVersion=1.21.11+
67
org.gradle.jvmargs=-Xmx1G -Dfile.encoding=UTF-8
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.mrfloris.endcrystals;
2+
3+
import java.util.List;
4+
import net.kyori.adventure.text.Component;
5+
import org.bukkit.command.Command;
6+
import org.bukkit.command.CommandSender;
7+
import org.bukkit.command.PluginCommand;
8+
9+
final class ConfiguredAliasCommand extends Command {
10+
11+
private final PluginCommand delegate;
12+
13+
ConfiguredAliasCommand(String alias, PluginCommand delegate) {
14+
super(alias, delegate.getDescription(), delegate.getUsage(), List.of());
15+
this.delegate = delegate;
16+
setPermission(delegate.getPermission());
17+
18+
Component permissionMessage = delegate.permissionMessage();
19+
if (permissionMessage != null) {
20+
permissionMessage(permissionMessage);
21+
}
22+
}
23+
24+
@Override
25+
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
26+
return delegate.execute(sender, commandLabel, args);
27+
}
28+
29+
@Override
30+
public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
31+
return delegate.tabComplete(sender, alias, args);
32+
}
33+
}

0 commit comments

Comments
 (0)