Skip to content

Commit 221e404

Browse files
committed
- more commands, permissions,
- placeholders, updated readme, - further testing done. - pre-release beta. Dont use in live yet
1 parent 559cc2e commit 221e404

6 files changed

Lines changed: 162 additions & 31 deletions

File tree

README.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The Gradle build creates the legacy reference jar and the current Paper 26.1.2 t
1313
| Jar | Purpose |
1414
| --- | --- |
1515
| `1MB-XMas-2026-v2.0.0-004-v21-1.21.8.jar` | Legacy reference jar copied from the deployed 2025 server jar. |
16-
| `1MB-XMas-2026-v2.0.1-010-v25-26.1.2.jar` | Modern Paper 26.1.2 build, Java 25 bytecode. |
16+
| `1MB-XMas-2026-v2.0.1-011-v25-26.1.2.jar` | Modern Paper 26.1.2 build, Java 25 bytecode. |
1717

1818
The checked-in source targets Paper 26.1.2. The legacy jar is preserved so the deployed working 2025 behavior can be compared or rolled back during testing.
1919

@@ -44,17 +44,17 @@ The checked-in source targets Paper 26.1.2. The legacy jar is preserved so the d
4444

4545
For the 2026 target, use the modern Paper 26.1.2 jar:
4646

47-
- Paper 26.1.2: `1MB-XMas-2026-v2.0.1-010-v25-26.1.2.jar`
47+
- Paper 26.1.2: `1MB-XMas-2026-v2.0.1-011-v25-26.1.2.jar`
4848

4949
## Building
5050

5151
Requirements:
5252

5353
- JDK 25
5454
- Gradle
55-
- The local Paper server folder in `servers/Server-Two-Paper-26.1.2`
56-
- The local PlaceholderAPI jar in `servers/Server-Two-Paper-26.1.2/plugins`
57-
- The deployed legacy jar in `servers/Server-One-Paper-1.21.11/plugins` if you want `legacyJar`
55+
- The current local dev/test setup in this repo uses `servers/Server-Two-Paper-26.1.2` for Paper API jars and local smoke testing
56+
- The current local dev/test setup in this repo uses `servers/Server-Two-Paper-26.1.2/plugins/PlaceholderAPI-2.12.3-DEV-265.jar` for the optional PlaceholderAPI compile-time classpath
57+
- The deployed legacy jar in `servers/Server-One-Paper-1.21.11/plugins` is only needed if you want the `legacyJar` copy task
5858

5959
Build the current Paper 26.1.2 jar and the legacy reference jar:
6060

@@ -80,7 +80,9 @@ Copy the deployed legacy jar into the requested legacy filename:
8080
gradle legacyJar
8181
```
8282

83-
The build compiles against the Paper 26.1.2 API jars found in `servers/Server-Two-Paper-26.1.2`. If that folder is missing or has not been started far enough for Paper to download its libraries, Gradle will not have the Paper API classpath it needs.
83+
End users do not need the `servers/` folder. The build output jars are written to `build/libs/`, and those are the files you install on a Paper server.
84+
85+
In this workspace, the current Gradle setup compiles against the Paper 26.1.2 API jars found in `servers/Server-Two-Paper-26.1.2`. If that folder is missing or has not been started far enough for Paper to download its libraries, Gradle will not have the local Paper API classpath it currently expects.
8486

8587
## Commands
8688

@@ -104,7 +106,17 @@ If `core.commands.legacy-command-enabled` is `true`, the legacy `/xmas` alias is
104106

105107
| Permission | Default | Description |
106108
| --- | --- | --- |
107-
| `xmas.admin` | `op` | Allows use of the `/xmastree` command and all XMas Tree admin subcommands. |
109+
| `onembxmastree.admin` | `op` | Umbrella permission for all XMas Tree commands and override actions. |
110+
| `onembxmastree.command.status` | `true` | Allows viewing `/xmastree` status output. |
111+
| `onembxmastree.command.help` | `true` | Allows viewing `/xmastree help`. |
112+
| `onembxmastree.command.give` | `op` | Allows `/xmastree give <player>`. |
113+
| `onembxmastree.command.gifts` | `op` | Allows `/xmastree gifts`. |
114+
| `onembxmastree.command.addhand` | `op` | Allows `/xmastree addhand`. |
115+
| `onembxmastree.command.reload` | `op` | Allows `/xmastree reload`. |
116+
| `onembxmastree.command.debug` | `op` | Allows `/xmastree debug [page]`. |
117+
| `onembxmastree.command.debug.toggle` | `op` | Allows `/xmastree debug toggle <key> true\|false`. |
118+
| `onembxmastree.command.end` | `op` | Allows `/xmastree end`. |
119+
| `onembxmastree.tree.override` | `op` | Allows managing other players' trees. |
108120

109121
## Player flow
110122

@@ -199,7 +211,7 @@ The dotted key after `onembxmastree_` is supported to keep the placeholders read
199211
| `%onembxmastree_trees.total%` | `14` | Total loaded X-Mas trees. |
200212
| `%onembxmastree_trees.owners%` | `6` | Number of unique loaded tree owners. |
201213
| `%onembxmastree_player.trees%` | `2` | Number of loaded trees owned by the placeholder player. |
202-
| `%onembxmastree_version%` | `2.0.1-010` | Loaded plugin version. |
214+
| `%onembxmastree_version%` | `2.0.1-011` | Loaded plugin version. |
203215

204216
CMI hologram example:
205217

@@ -229,7 +241,7 @@ ajLeaderboards placeholder examples:
229241

230242
## Security notes
231243

232-
- Admin commands are gated by `xmas.admin`.
244+
- Admin and staff access is gated by `onembxmastree.*` permissions.
233245
- Present texture URLs are restricted to `textures.minecraft.net`.
234246
- Gift item Base64 entries are capped before deserialization.
235247
- Config material names are resolved with modern `Material.matchMaterial` and invalid or legacy values are skipped.
@@ -247,7 +259,7 @@ Please report bugs, compatibility problems, and upgrade questions in the GitHub
247259
- **Ghost_chu** - NMS fixes - [Ghost-chu](https://github.com/Ghost-chu)
248260
- **LoneDev6** - Optimization patches - [LoneDev6](https://github.com/LoneDev6)
249261
- **montlikadani** - Hungarian translation - [montlikadani](https://github.com/montlikadani)
250-
- **1MB / mrfdev** - 2026 Paper modernization, Java 25 builds, and XMasTree maintenance
262+
- **mrfloris** - 2026 Paper modernization, Java 25 builds, and XMasTree maintenance - [mrfloris](https://github.com/mrfloris)
251263

252264
Original SpigotMC listing:
253265

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ plugins {
33
}
44

55
group = 'com.onemb.xmas'
6-
version = '2.0.1-010'
6+
version = '2.0.1-011'
77

88
def legacyArchiveName = '1MB-XMas-2026-v2.0.0-004-v21-1.21.8.jar'
9-
def paper2612ArchiveName = '1MB-XMas-2026-v2.0.1-010-v25-26.1.2.jar'
9+
def paper2612ArchiveName = '1MB-XMas-2026-v2.0.1-011-v25-26.1.2.jar'
1010

1111
def serverOne = layout.projectDirectory.dir('servers/Server-One-Paper-1.21.11')
1212
def serverTwo = layout.projectDirectory.dir('servers/Server-Two-Paper-26.1.2')

src/main/java/ru/meloncode/xmas/Events.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ public void onPlayerBreakBlock(BlockBreakEvent event) {
217217
MagicTree tree = MagicTree.getTreeByBlock(block);
218218
switch (block.getType()) {
219219
case SPRUCE_LOG:
220-
if (player.getUniqueId().equals(tree.getOwner()) || player.hasPermission("xmas.admin")) {
220+
if (player.getUniqueId().equals(tree.getOwner()) || XMasCommand.canOverrideTree(player)) {
221221
if (Main.inProgress)
222222
if (destroyers.containsKey(player.getUniqueId()) && System.currentTimeMillis() - destroyers.get(player.getUniqueId()) <= 10000) {
223223
if (Main.resourceBack) {
@@ -247,14 +247,14 @@ public void onPlayerBreakBlock(BlockBreakEvent event) {
247247
case GLOWSTONE:
248248
if (Main.inProgress)
249249
TextUtils.sendMessage(player, "<dark_green>" + LocaleManager.DESTROY_LEAVES_SANTA);
250-
if (player.getUniqueId().equals(tree.getOwner()) || player.hasPermission("xmas.admin")) {
250+
if (player.getUniqueId().equals(tree.getOwner()) || XMasCommand.canOverrideTree(player)) {
251251
TextUtils.sendMessage(player, "<red>" + LocaleManager.DESTROY_LEAVES_TUT);
252252
} else {
253253
TextUtils.sendMessage(player, LocaleManager.DESTROY_FAIL_OWNER);
254254
}
255255
break;
256256
case SPRUCE_SAPLING:
257-
if (player.getUniqueId().equals(tree.getOwner()) || player.hasPermission("xmas.admin")) {
257+
if (player.getUniqueId().equals(tree.getOwner()) || XMasCommand.canOverrideTree(player)) {
258258
if (Main.inProgress) {
259259
if (destroyers.containsKey(player.getUniqueId()) && System.currentTimeMillis() - destroyers.get(player.getUniqueId()) <= 10000) {
260260
if (Main.resourceBack) {

src/main/java/ru/meloncode/xmas/XMasCommand.java

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@
2020
public class XMasCommand implements CommandExecutor, TabCompleter {
2121
public static final String PRIMARY_COMMAND = "xmastree";
2222
public static final String LEGACY_COMMAND = "xmas";
23+
public static final String PERMISSION_ADMIN = "onembxmastree.admin";
24+
public static final String PERMISSION_STATUS = "onembxmastree.command.status";
25+
public static final String PERMISSION_HELP = "onembxmastree.command.help";
26+
public static final String PERMISSION_GIVE = "onembxmastree.command.give";
27+
public static final String PERMISSION_GIFTS = "onembxmastree.command.gifts";
28+
public static final String PERMISSION_ADDHAND = "onembxmastree.command.addhand";
29+
public static final String PERMISSION_RELOAD = "onembxmastree.command.reload";
30+
public static final String PERMISSION_DEBUG = "onembxmastree.command.debug";
31+
public static final String PERMISSION_DEBUG_TOGGLE = "onembxmastree.command.debug.toggle";
32+
public static final String PERMISSION_END = "onembxmastree.command.end";
33+
public static final String PERMISSION_TREE_OVERRIDE = "onembxmastree.tree.override";
2334
private static final List<String> COMMANDS = Arrays.asList("help", "give", "end", "gifts", "reload", "addhand", "debug");
2435
private static final Set<String> DEBUG_TOGGLE_KEYS = new LinkedHashSet<>(Arrays.asList(
2536
"core.commands.legacy-command-enabled",
@@ -29,6 +40,7 @@ public class XMasCommand implements CommandExecutor, TabCompleter {
2940
"core.particles-enabled",
3041
"xmas.luck.enabled"
3142
));
43+
private static final Map<String, String> PERMISSIONS = createPermissionDescriptions();
3244
private static final int DEBUG_PAGE_SIZE = 8;
3345
private static XMasCommand registeredExecutor;
3446
private static PluginCommand legacyAliasCommand;
@@ -65,12 +77,20 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
6577
String action = args[0].toLowerCase(Locale.ENGLISH);
6678
switch (action) {
6779
case "help": {
80+
if (!hasPermission(sender, PERMISSION_HELP)) {
81+
sendNoPermission(sender);
82+
break;
83+
}
6884
for (String line : getHelpLines()) {
6985
TextUtils.sendRawMessage(sender, line);
7086
}
7187
break;
7288
}
7389
case "give": {
90+
if (!hasPermission(sender, PERMISSION_GIVE)) {
91+
sendNoPermission(sender);
92+
break;
93+
}
7494
if (args.length > 1) {
7595
String name = args[1];
7696
Player player = Bukkit.getPlayer(name);
@@ -85,10 +105,18 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
85105
break;
86106
}
87107
case "end": {
108+
if (!hasPermission(sender, PERMISSION_END)) {
109+
sendNoPermission(sender);
110+
break;
111+
}
88112
plugin.end();
89113
break;
90114
}
91115
case "gifts": {
116+
if (!hasPermission(sender, PERMISSION_GIFTS)) {
117+
sendNoPermission(sender);
118+
break;
119+
}
92120
Random random = new Random();
93121
for (MagicTree magicTree : XMas.getAllTrees()) {
94122
for (int i = 0; i < 3 + random.nextInt(4); i++) {
@@ -99,8 +127,8 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
99127
break;
100128
}
101129
case "reload": {
102-
if (!sender.hasPermission("xmas.admin")) {
103-
TextUtils.sendRawMessage(sender, "<red>You do not have permission to use this command.");
130+
if (!hasPermission(sender, PERMISSION_RELOAD)) {
131+
sendNoPermission(sender);
104132
break;
105133
}
106134
plugin.reloadPluginConfig();
@@ -112,8 +140,8 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
112140
TextUtils.sendRawMessage(sender, "<red>Only players can use this command.");
113141
break;
114142
}
115-
if (!sender.hasPermission("xmas.admin")) {
116-
TextUtils.sendRawMessage(sender, "<red>You do not have permission to use this command.");
143+
if (!hasPermission(sender, PERMISSION_ADDHAND)) {
144+
sendNoPermission(sender);
117145
break;
118146
}
119147
ItemStack item = player.getInventory().getItemInMainHand();
@@ -134,7 +162,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
134162
return false;
135163
}
136164
} else {
137-
sendStatus(sender);
165+
if (!hasPermission(sender, PERMISSION_STATUS)) {
166+
sendNoPermission(sender);
167+
} else {
168+
sendStatus(sender);
169+
}
138170
}
139171
return true;
140172
}
@@ -145,7 +177,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
145177
if (args.length == 1) {
146178
String typed = args[0].toLowerCase(Locale.ENGLISH);
147179
for (String subCommand : COMMANDS) {
148-
if (subCommand.startsWith(typed)) {
180+
if (subCommand.startsWith(typed) && canUseSubCommand(sender, subCommand)) {
149181
suggestions.add(subCommand);
150182
}
151183
}
@@ -199,13 +231,17 @@ private List<String> getStatusLines() {
199231
}
200232

201233
private void handleDebug(CommandSender sender, String[] args) {
202-
if (!sender.hasPermission("xmas.admin")) {
203-
TextUtils.sendRawMessage(sender, "<red>You do not have permission to use this command.");
234+
if (args.length >= 2 && args[1].equalsIgnoreCase("toggle")) {
235+
if (!hasPermission(sender, PERMISSION_DEBUG_TOGGLE)) {
236+
sendNoPermission(sender);
237+
return;
238+
}
239+
handleDebugToggle(sender, args);
204240
return;
205241
}
206242

207-
if (args.length >= 2 && args[1].equalsIgnoreCase("toggle")) {
208-
handleDebugToggle(sender, args);
243+
if (!hasPermission(sender, PERMISSION_DEBUG)) {
244+
sendNoPermission(sender);
209245
return;
210246
}
211247

@@ -263,7 +299,9 @@ private void sendDebugPage(CommandSender sender, int requestedPage) {
263299
}
264300
lines.add("");
265301
lines.add("<gold>Permissions");
266-
lines.add("<gray>xmas.admin - allows all " + TextUtils.DISPLAY_NAME + " admin commands");
302+
for (Map.Entry<String, String> permission : PERMISSIONS.entrySet()) {
303+
lines.add("<gray>" + permission.getKey() + " - " + permission.getValue());
304+
}
267305
lines.add("");
268306
lines.add("<gold>Placeholders");
269307
lines.add("<gray>Requires PlaceholderAPI. Use '_' after prefix, then dotted keys.");
@@ -312,6 +350,10 @@ private boolean isLegacyAliasEnabled() {
312350
return plugin.getConfig().getBoolean("core.commands.legacy-command-enabled", true);
313351
}
314352

353+
public static boolean canOverrideTree(CommandSender sender) {
354+
return hasPermission(sender, PERMISSION_TREE_OVERRIDE);
355+
}
356+
315357
private static void syncLegacyAlias(Main plugin, XMasCommand executor) {
316358
CommandMap commandMap = getCommandMap();
317359
if (commandMap == null) {
@@ -346,7 +388,7 @@ private static void syncLegacyAlias(Main plugin, XMasCommand executor) {
346388
}
347389
aliasCommand.setDescription("Legacy alias for /" + PRIMARY_COMMAND);
348390
aliasCommand.setUsage("/" + LEGACY_COMMAND + " [help|give|gifts|addhand|reload|debug|end]");
349-
aliasCommand.setPermission("xmas.admin");
391+
aliasCommand.setPermission(null);
350392
aliasCommand.setExecutor(executor);
351393
aliasCommand.setTabCompleter(executor);
352394
commandMap.register(plugin.getDescription().getName().toLowerCase(Locale.ENGLISH), aliasCommand);
@@ -420,4 +462,41 @@ private List<String> filterStartingWith(List<String> values, String typed) {
420462
return matches;
421463
}
422464

465+
private boolean canUseSubCommand(CommandSender sender, String subCommand) {
466+
return switch (subCommand.toLowerCase(Locale.ENGLISH)) {
467+
case "help" -> hasPermission(sender, PERMISSION_HELP);
468+
case "give" -> hasPermission(sender, PERMISSION_GIVE);
469+
case "end" -> hasPermission(sender, PERMISSION_END);
470+
case "gifts" -> hasPermission(sender, PERMISSION_GIFTS);
471+
case "reload" -> hasPermission(sender, PERMISSION_RELOAD);
472+
case "addhand" -> hasPermission(sender, PERMISSION_ADDHAND);
473+
case "debug" -> hasPermission(sender, PERMISSION_DEBUG) || hasPermission(sender, PERMISSION_DEBUG_TOGGLE);
474+
default -> false;
475+
};
476+
}
477+
478+
private static boolean hasPermission(CommandSender sender, String permission) {
479+
return sender.hasPermission(PERMISSION_ADMIN) || sender.hasPermission(permission);
480+
}
481+
482+
private void sendNoPermission(CommandSender sender) {
483+
TextUtils.sendRawMessage(sender, "<red>You do not have permission to use this command.");
484+
}
485+
486+
private static Map<String, String> createPermissionDescriptions() {
487+
Map<String, String> permissions = new LinkedHashMap<>();
488+
permissions.put(PERMISSION_ADMIN, "allows all " + TextUtils.DISPLAY_NAME + " commands and overrides");
489+
permissions.put(PERMISSION_STATUS, "shows /" + PRIMARY_COMMAND + " status output");
490+
permissions.put(PERMISSION_HELP, "shows /" + PRIMARY_COMMAND + " help output");
491+
permissions.put(PERMISSION_GIVE, "allows /" + PRIMARY_COMMAND + " give");
492+
permissions.put(PERMISSION_GIFTS, "allows /" + PRIMARY_COMMAND + " gifts");
493+
permissions.put(PERMISSION_ADDHAND, "allows /" + PRIMARY_COMMAND + " addhand");
494+
permissions.put(PERMISSION_RELOAD, "allows /" + PRIMARY_COMMAND + " reload");
495+
permissions.put(PERMISSION_DEBUG, "allows /" + PRIMARY_COMMAND + " debug");
496+
permissions.put(PERMISSION_DEBUG_TOGGLE, "allows /" + PRIMARY_COMMAND + " debug toggle");
497+
permissions.put(PERMISSION_END, "allows /" + PRIMARY_COMMAND + " end");
498+
permissions.put(PERMISSION_TREE_OVERRIDE, "allows managing other players' trees");
499+
return permissions;
500+
}
501+
423502
}

src/main/java/ru/meloncode/xmas/XMasPlaceholderExpansion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public String getIdentifier() {
1919

2020
@Override
2121
public String getAuthor() {
22-
return "1MB / mrfdev";
22+
return "mrfloris";
2323
}
2424

2525
@Override

src/main/resources/plugin.yml

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,48 @@ commands:
88
xmastree:
99
description: Manage the 1MB XMas Tree event
1010
usage: /<command> [help|give|gifts|addhand|reload|debug|end]
11-
permission: xmas.admin
1211
permissions:
13-
xmas.admin:
14-
description: Allows all XMas Tree admin commands
12+
onembxmastree.admin:
13+
description: Allows all XMas Tree commands and overrides
14+
default: op
15+
children:
16+
onembxmastree.command.status: true
17+
onembxmastree.command.help: true
18+
onembxmastree.command.give: true
19+
onembxmastree.command.gifts: true
20+
onembxmastree.command.addhand: true
21+
onembxmastree.command.reload: true
22+
onembxmastree.command.debug: true
23+
onembxmastree.command.debug.toggle: true
24+
onembxmastree.command.end: true
25+
onembxmastree.tree.override: true
26+
onembxmastree.command.status:
27+
description: Allows viewing /xmastree status
28+
default: true
29+
onembxmastree.command.help:
30+
description: Allows viewing /xmastree help
31+
default: true
32+
onembxmastree.command.give:
33+
description: Allows /xmastree give
34+
default: op
35+
onembxmastree.command.gifts:
36+
description: Allows /xmastree gifts
37+
default: op
38+
onembxmastree.command.addhand:
39+
description: Allows /xmastree addhand
40+
default: op
41+
onembxmastree.command.reload:
42+
description: Allows /xmastree reload
43+
default: op
44+
onembxmastree.command.debug:
45+
description: Allows /xmastree debug
46+
default: op
47+
onembxmastree.command.debug.toggle:
48+
description: Allows /xmastree debug toggle
49+
default: op
50+
onembxmastree.command.end:
51+
description: Allows /xmastree end
52+
default: op
53+
onembxmastree.tree.override:
54+
description: Allows managing other players' trees
1555
default: op

0 commit comments

Comments
 (0)