papermc-skill 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +12 -12
- package/assets/banner-animated.svg +360 -0
- package/assets/banner.svg +360 -0
- package/bin/cli.js +107 -2
- package/docs/01-modern-paper-architecture.md +48 -51
- package/docs/02-adventure-and-minimessage.md +48 -52
- package/docs/03-persistent-data-container.md +39 -39
- package/docs/04-commands-and-brigadier.md +32 -35
- package/docs/05-concurrency-and-folia.md +44 -44
- package/docs/06-events-and-listeners.md +30 -31
- package/docs/07-best-practices-and-perf.md +39 -40
- package/docs/08-gui-and-menus.md +34 -37
- package/docs/09-custom-items-and-combat.md +25 -33
- package/docs/10-database-and-storage.md +27 -27
- package/docs/11-security-and-exploit-prevention.md +233 -0
- package/package.json +2 -1
- package/skills/paper-plugin-dev/SKILL.md +391 -114
- package/templates/paper-modern-template/.gradle/9.7.1/checksums/checksums.lock +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/checksums/md5-checksums.bin +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/checksums/sha1-checksums.bin +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/executionHistory/executionHistory.bin +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/executionHistory/executionHistory.lock +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/fileHashes/fileHashes.bin +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/fileHashes/fileHashes.lock +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/fileHashes/resourceHashesCache.bin +0 -0
- package/templates/paper-modern-template/.gradle/9.7.1/kotlin-dsl-plugin-entries/kotlin-dsl-plugin-entries.lock +0 -0
- package/templates/paper-modern-template/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/templates/paper-modern-template/.gradle/buildOutputCleanup/cache.properties +1 -1
- package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/ExamplePaperPlugin.class +0 -0
- package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/PaperPluginBootstrap.class +0 -0
- package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/command/HelloCommand.class +0 -0
- package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/listener/PlayerEventListener.class +0 -0
- package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/util/SchedulerAdapter.class +0 -0
- package/templates/paper-modern-template/build/tmp/compileJava/previous-compilation-data.bin +0 -0
- package/templates/paper-modern-template/build.gradle.kts +7 -7
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/ExamplePaperPlugin.java +6 -6
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/PaperPluginBootstrap.java +2 -2
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/command/HelloCommand.java +2 -4
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/data/PluginDataKeys.java +2 -2
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/listener/PlayerEventListener.java +6 -7
- package/templates/paper-modern-template/src/main/java/com/example/paperplugin/util/SchedulerAdapter.java +6 -6
- package/templates/paper-modern-template/src/main/resources/config.yml +5 -5
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
plugins {
|
|
2
2
|
`java-library`
|
|
3
|
-
//
|
|
3
|
+
// The run-paper plugin for instant Paper/Folia local test server execution
|
|
4
4
|
id("xyz.jpenilla.run-paper") version "3.1.0"
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// Enable paperweight.userdev if direct Mojang NMS internals access is needed
|
|
7
7
|
// id("io.papermc.paperweight.userdev") version "2.0.0-beta.21"
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
group = "com.example"
|
|
11
11
|
version = "1.0.0-SNAPSHOT"
|
|
12
|
-
description = "
|
|
12
|
+
description = "Modern Paper & Folia Minecraft Plugin Starter Template"
|
|
13
13
|
|
|
14
14
|
repositories {
|
|
15
15
|
mavenCentral()
|
|
@@ -24,13 +24,13 @@ java {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
dependencies {
|
|
27
|
-
//
|
|
27
|
+
// Primary Standard: Paper API (Kyori Adventure, Folia Schedulers, Brigadier, PDC)
|
|
28
28
|
compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
|
|
29
29
|
|
|
30
|
-
//
|
|
30
|
+
// Optional: For NMS / internal Mojang mappings (enable paperweight plugin above if using this):
|
|
31
31
|
// paperweight.paperDevBundle("1.21.4.build.+")
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// Modern Nullability Annotations
|
|
34
34
|
compileOnly("org.jspecify:jspecify:1.0.1")
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -50,5 +50,5 @@ tasks {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// Registers the './gradlew runFoliaServer' task for multi-threaded Folia local testing
|
|
54
54
|
runPaper.folia.registerTask()
|
|
@@ -11,25 +11,25 @@ public final class ExamplePaperPlugin extends JavaPlugin {
|
|
|
11
11
|
|
|
12
12
|
@Override
|
|
13
13
|
public void onEnable() {
|
|
14
|
-
//
|
|
14
|
+
// Save default configuration if missing
|
|
15
15
|
saveDefaultConfig();
|
|
16
16
|
|
|
17
|
-
//
|
|
17
|
+
// Initialize PersistentDataContainer keys
|
|
18
18
|
PluginDataKeys.init(this);
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// Register Event Listeners
|
|
21
21
|
getServer().getPluginManager().registerEvents(new PlayerEventListener(this), this);
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Log startup using Paper's native ComponentLogger
|
|
24
24
|
getComponentLogger().info(
|
|
25
|
-
Component.text("ExamplePaperPlugin
|
|
25
|
+
Component.text("ExamplePaperPlugin enabled! Running on Folia: " + SchedulerAdapter.isFolia(), NamedTextColor.GREEN)
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
@Override
|
|
30
30
|
public void onDisable() {
|
|
31
31
|
getComponentLogger().info(
|
|
32
|
-
Component.text("ExamplePaperPlugin
|
|
32
|
+
Component.text("ExamplePaperPlugin disabled.", NamedTextColor.YELLOW)
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -14,14 +14,14 @@ public final class PaperPluginBootstrap implements PluginBootstrap {
|
|
|
14
14
|
|
|
15
15
|
@Override
|
|
16
16
|
public void bootstrap(final BootstrapContext context) {
|
|
17
|
-
//
|
|
17
|
+
// Register Paper Brigadier Commands via LifecycleEvents
|
|
18
18
|
context.getLifecycleManager().registerEventHandler(
|
|
19
19
|
LifecycleEvents.COMMANDS,
|
|
20
20
|
event -> {
|
|
21
21
|
final var registrar = event.registrar();
|
|
22
22
|
registrar.register(
|
|
23
23
|
HelloCommand.create(),
|
|
24
|
-
"
|
|
24
|
+
"Example modern Paper command powered by Mojang Brigadier",
|
|
25
25
|
List.of("phello")
|
|
26
26
|
);
|
|
27
27
|
}
|
|
@@ -11,8 +11,6 @@ import org.bukkit.Bukkit;
|
|
|
11
11
|
import org.bukkit.command.CommandSender;
|
|
12
12
|
import org.bukkit.entity.Player;
|
|
13
13
|
|
|
14
|
-
import java.util.List;
|
|
15
|
-
|
|
16
14
|
public final class HelloCommand {
|
|
17
15
|
|
|
18
16
|
private HelloCommand() {
|
|
@@ -24,7 +22,7 @@ public final class HelloCommand {
|
|
|
24
22
|
.executes(context -> {
|
|
25
23
|
final CommandSender sender = context.getSource().getSender();
|
|
26
24
|
sender.sendMessage(
|
|
27
|
-
MiniMessage.miniMessage().deserialize("<green>
|
|
25
|
+
MiniMessage.miniMessage().deserialize("<green>Hello, <yellow><name></yellow>! Welcome to modern Paper Brigadier.</green>",
|
|
28
26
|
Placeholder.unparsed("name", sender.getName())
|
|
29
27
|
)
|
|
30
28
|
);
|
|
@@ -42,7 +40,7 @@ public final class HelloCommand {
|
|
|
42
40
|
final String target = StringArgumentType.getString(context, "target");
|
|
43
41
|
|
|
44
42
|
sender.sendMessage(
|
|
45
|
-
MiniMessage.miniMessage().deserialize("<green>
|
|
43
|
+
MiniMessage.miniMessage().deserialize("<green>Greetings sent to <gold><target></gold> on behalf of <yellow><sender></yellow>!</green>",
|
|
46
44
|
Placeholder.unparsed("target", target),
|
|
47
45
|
Placeholder.unparsed("sender", sender.getName())
|
|
48
46
|
)
|
|
@@ -4,8 +4,8 @@ import org.bukkit.NamespacedKey;
|
|
|
4
4
|
import org.bukkit.plugin.Plugin;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Stores static NamespacedKey identifiers for PersistentDataContainer (PDC).
|
|
8
|
+
* Always initialized once on plugin startup to eliminate repeated heap allocations.
|
|
9
9
|
*/
|
|
10
10
|
public final class PluginDataKeys {
|
|
11
11
|
|
|
@@ -2,7 +2,6 @@ package com.example.paperplugin.listener;
|
|
|
2
2
|
|
|
3
3
|
import com.example.paperplugin.ExamplePaperPlugin;
|
|
4
4
|
import com.example.paperplugin.data.PluginDataKeys;
|
|
5
|
-
import net.kyori.adventure.text.Component;
|
|
6
5
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
7
6
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
|
8
7
|
import org.bukkit.entity.Player;
|
|
@@ -32,28 +31,28 @@ public final class PlayerEventListener implements Listener {
|
|
|
32
31
|
pdc.set(PluginDataKeys.LAST_LOGIN_TIMESTAMP, PersistentDataType.LONG, System.currentTimeMillis());
|
|
33
32
|
|
|
34
33
|
if (currentJoins == 1) {
|
|
35
|
-
//
|
|
34
|
+
// First time player join
|
|
36
35
|
final String firstJoinFormat = plugin.getConfig().getString(
|
|
37
36
|
"messages.first_join",
|
|
38
|
-
"<rainbow>MEMBER
|
|
37
|
+
"<rainbow>NEW MEMBER!</rainbow> Give a warm welcome to <yellow><player></yellow>!"
|
|
39
38
|
);
|
|
40
39
|
event.joinMessage(
|
|
41
40
|
MiniMessage.miniMessage().deserialize(firstJoinFormat, Placeholder.unparsed("player", player.getName()))
|
|
42
41
|
);
|
|
43
42
|
} else {
|
|
44
|
-
//
|
|
43
|
+
// Returning player join
|
|
45
44
|
final String welcomeFormat = plugin.getConfig().getString(
|
|
46
45
|
"messages.welcome",
|
|
47
|
-
"<green>
|
|
46
|
+
"<green>Welcome back, <yellow><player></yellow>!</green>"
|
|
48
47
|
);
|
|
49
48
|
event.joinMessage(
|
|
50
49
|
MiniMessage.miniMessage().deserialize(welcomeFormat, Placeholder.unparsed("player", player.getName()))
|
|
51
50
|
);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
//
|
|
53
|
+
// Send personalized action bar
|
|
55
54
|
player.sendActionBar(
|
|
56
|
-
MiniMessage.miniMessage().deserialize("<gray>
|
|
55
|
+
MiniMessage.miniMessage().deserialize("<gray>Visit #<gold><count></gold></gray>",
|
|
57
56
|
Placeholder.unparsed("count", String.valueOf(currentJoins))
|
|
58
57
|
)
|
|
59
58
|
);
|
|
@@ -8,7 +8,7 @@ import org.bukkit.plugin.Plugin;
|
|
|
8
8
|
import java.util.concurrent.TimeUnit;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Universal Scheduler Adapter providing transparent concurrency across standard Paper and Folia (Threaded Regions).
|
|
12
12
|
*/
|
|
13
13
|
public final class SchedulerAdapter {
|
|
14
14
|
|
|
@@ -31,7 +31,7 @@ public final class SchedulerAdapter {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Executes a runnable on the region thread owning the specified location.
|
|
35
35
|
*/
|
|
36
36
|
public static void runAtLocation(final Plugin plugin, final Location location, final Runnable runnable) {
|
|
37
37
|
if (IS_FOLIA) {
|
|
@@ -42,7 +42,7 @@ public final class SchedulerAdapter {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* Executes a runnable on the region thread currently owning the specified entity.
|
|
46
46
|
*/
|
|
47
47
|
public static void runAtEntity(final Plugin plugin, final Entity entity, final Runnable runnable) {
|
|
48
48
|
if (IS_FOLIA) {
|
|
@@ -53,7 +53,7 @@ public final class SchedulerAdapter {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* Executes a runnable asynchronously (off-main-thread).
|
|
57
57
|
*/
|
|
58
58
|
public static void runAsync(final Plugin plugin, final Runnable runnable) {
|
|
59
59
|
if (IS_FOLIA) {
|
|
@@ -64,13 +64,13 @@ public final class SchedulerAdapter {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* Executes a delayed task asynchronously.
|
|
68
68
|
*/
|
|
69
69
|
public static void runAsyncDelayed(final Plugin plugin, final Runnable runnable, final long delay, final TimeUnit timeUnit) {
|
|
70
70
|
if (IS_FOLIA) {
|
|
71
71
|
Bukkit.getAsyncScheduler().runDelayed(plugin, task -> runnable.run(), delay, timeUnit);
|
|
72
72
|
} else {
|
|
73
|
-
final long ticks = delay
|
|
73
|
+
final long ticks = Math.max(1L, timeUnit.toMillis(delay) / 50L);
|
|
74
74
|
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, ticks);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
# Modern Paper Plugin Template Configuration
|
|
2
|
+
# Formatted using Kyori MiniMessage syntax
|
|
3
3
|
|
|
4
4
|
messages:
|
|
5
|
-
welcome: "<gradient:#00c6ff:#0072ff><bold>
|
|
6
|
-
first_join: "<rainbow><bold>MEMBER
|
|
7
|
-
command_hello: "<green>
|
|
5
|
+
welcome: "<gradient:#00c6ff:#0072ff><bold>Welcome back to the server!</bold></gradient> Great to see you again, <yellow><player></yellow>."
|
|
6
|
+
first_join: "<rainbow><bold>NEW MEMBER!</bold></rainbow> Give a warm welcome to <yellow><player></yellow> for joining the server!"
|
|
7
|
+
command_hello: "<green>Hello, <aqua><target></aqua>! Greetings from modern PaperMC.</green>"
|
|
8
8
|
|
|
9
9
|
settings:
|
|
10
10
|
track_join_count: true
|