papermc-skill 1.0.0 → 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.
Files changed (56) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +90 -110
  3. package/assets/banner-animated.svg +360 -0
  4. package/assets/banner.svg +360 -0
  5. package/bin/cli.js +199 -0
  6. package/docs/01-modern-paper-architecture.md +48 -51
  7. package/docs/02-adventure-and-minimessage.md +48 -52
  8. package/docs/03-persistent-data-container.md +39 -39
  9. package/docs/04-commands-and-brigadier.md +32 -35
  10. package/docs/05-concurrency-and-folia.md +44 -44
  11. package/docs/06-events-and-listeners.md +30 -31
  12. package/docs/07-best-practices-and-perf.md +39 -40
  13. package/docs/08-gui-and-menus.md +34 -37
  14. package/docs/09-custom-items-and-combat.md +25 -33
  15. package/docs/10-database-and-storage.md +27 -27
  16. package/docs/11-security-and-exploit-prevention.md +233 -0
  17. package/package.json +2 -1
  18. package/skills/paper-plugin-dev/SKILL.md +391 -111
  19. package/templates/paper-modern-template/.gradle/9.7.1/checksums/checksums.lock +0 -0
  20. package/templates/paper-modern-template/.gradle/9.7.1/checksums/md5-checksums.bin +0 -0
  21. package/templates/paper-modern-template/.gradle/9.7.1/checksums/sha1-checksums.bin +0 -0
  22. package/templates/paper-modern-template/.gradle/{9.4.1 → 9.7.1}/executionHistory/executionHistory.bin +0 -0
  23. package/templates/paper-modern-template/.gradle/9.7.1/executionHistory/executionHistory.lock +0 -0
  24. package/templates/paper-modern-template/.gradle/{9.4.1 → 9.7.1}/fileHashes/fileHashes.bin +0 -0
  25. package/templates/paper-modern-template/.gradle/9.7.1/fileHashes/fileHashes.lock +0 -0
  26. package/templates/paper-modern-template/.gradle/{9.4.1 → 9.7.1}/fileHashes/resourceHashesCache.bin +0 -0
  27. package/templates/paper-modern-template/.gradle/{9.4.1/checksums/md5-checksums.bin → 9.7.1/kotlin-dsl-plugin-entries/jar-entries.bin} +0 -0
  28. package/templates/paper-modern-template/.gradle/9.7.1/kotlin-dsl-plugin-entries/kotlin-dsl-plugin-entries.lock +0 -0
  29. package/templates/paper-modern-template/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  30. package/templates/paper-modern-template/.gradle/buildOutputCleanup/cache.properties +2 -2
  31. package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/ExamplePaperPlugin.class +0 -0
  32. package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/PaperPluginBootstrap.class +0 -0
  33. package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/command/HelloCommand.class +0 -0
  34. package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/listener/PlayerEventListener.class +0 -0
  35. package/templates/paper-modern-template/build/classes/java/main/com/example/paperplugin/util/SchedulerAdapter.class +0 -0
  36. package/templates/paper-modern-template/build/tmp/compileJava/previous-compilation-data.bin +0 -0
  37. package/templates/paper-modern-template/build.gradle.kts +10 -10
  38. package/templates/paper-modern-template/gradle/wrapper/gradle-wrapper.jar +0 -0
  39. package/templates/paper-modern-template/gradle/wrapper/gradle-wrapper.properties +1 -1
  40. package/templates/paper-modern-template/gradlew +3 -3
  41. package/templates/paper-modern-template/gradlew.bat +12 -23
  42. package/templates/paper-modern-template/settings.gradle.kts +7 -0
  43. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/ExamplePaperPlugin.java +6 -6
  44. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/PaperPluginBootstrap.java +2 -2
  45. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/command/HelloCommand.java +2 -4
  46. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/data/PluginDataKeys.java +2 -2
  47. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/listener/PlayerEventListener.java +6 -7
  48. package/templates/paper-modern-template/src/main/java/com/example/paperplugin/util/SchedulerAdapter.java +6 -6
  49. package/templates/paper-modern-template/src/main/resources/config.yml +5 -5
  50. package/templates/paper-modern-template/.gradle/9.4.1/checksums/checksums.lock +0 -0
  51. package/templates/paper-modern-template/.gradle/9.4.1/checksums/sha1-checksums.bin +0 -0
  52. package/templates/paper-modern-template/.gradle/9.4.1/executionHistory/executionHistory.lock +0 -0
  53. package/templates/paper-modern-template/.gradle/9.4.1/fileHashes/fileHashes.lock +0 -0
  54. package/templates/paper-modern-template/.gradle/file-system.probe +0 -0
  55. /package/templates/paper-modern-template/.gradle/{9.4.1 → 9.7.1}/fileChanges/last-build.bin +0 -0
  56. /package/templates/paper-modern-template/.gradle/{9.4.1 → 9.7.1}/gc.properties +0 -0
@@ -0,0 +1,360 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 320" width="100%" height="100%">
2
+ <defs>
3
+ <!-- Background Gradient -->
4
+ <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#0a0d17" />
6
+ <stop offset="45%" stop-color="#101524" />
7
+ <stop offset="75%" stop-color="#141a2e" />
8
+ <stop offset="100%" stop-color="#090c15" />
9
+ </linearGradient>
10
+
11
+ <!-- Title Cyan Gradients -->
12
+ <linearGradient id="titleCyan" x1="0%" y1="0%" x2="0%" y2="100%">
13
+ <stop offset="0%" stop-color="#affaff" />
14
+ <stop offset="30%" stop-color="#38d9ff" />
15
+ <stop offset="70%" stop-color="#00a3ff" />
16
+ <stop offset="100%" stop-color="#0055b3" />
17
+ </linearGradient>
18
+
19
+ <linearGradient id="titleCyanGlow" x1="0%" y1="0%" x2="0%" y2="100%">
20
+ <stop offset="0%" stop-color="#e0ffff" />
21
+ <stop offset="100%" stop-color="#00bfff" />
22
+ </linearGradient>
23
+
24
+ <!-- Portal & Beacon Radial Glow -->
25
+ <radialGradient id="portalCenterGlow" cx="50%" cy="40%" r="60%">
26
+ <stop offset="0%" stop-color="#9d4edd" stop-opacity="0.25" />
27
+ <stop offset="40%" stop-color="#38d9ff" stop-opacity="0.15" />
28
+ <stop offset="75%" stop-color="#101524" stop-opacity="0.05" />
29
+ <stop offset="100%" stop-color="#101524" stop-opacity="0" />
30
+ </radialGradient>
31
+
32
+ <linearGradient id="beaconBeam" x1="0%" y1="0%" x2="100%" y2="0%">
33
+ <stop offset="0%" stop-color="#38d9ff" stop-opacity="0" />
34
+ <stop offset="50%" stop-color="#38d9ff" stop-opacity="0.18" />
35
+ <stop offset="100%" stop-color="#9d4edd" stop-opacity="0" />
36
+ </linearGradient>
37
+
38
+ <!-- Drop Shadow / Glow Filters -->
39
+ <filter id="textGlow" x="-20%" y="-20%" width="140%" height="140%">
40
+ <feGaussianBlur stdDeviation="5" result="blur" />
41
+ <feComposite in="SourceGraphic" in2="blur" operator="over" />
42
+ </filter>
43
+
44
+ <filter id="softAura" x="-40%" y="-40%" width="180%" height="180%">
45
+ <feGaussianBlur stdDeviation="10" result="blur" />
46
+ <feComposite in="SourceGraphic" in2="blur" operator="over" />
47
+ </filter>
48
+
49
+ <filter id="pixelShadow">
50
+ <feDropShadow dx="3" dy="4" stdDeviation="0" flood-color="#020408" flood-opacity="0.95" />
51
+ </filter>
52
+
53
+ <!-- Minecraft Grid Texture Pattern -->
54
+ <pattern id="mcGrid" width="24" height="24" patternUnits="userSpaceOnUse">
55
+ <rect width="24" height="24" fill="none" />
56
+ <path d="M 24 0 L 0 0 0 24" fill="none" stroke="#ffffff" stroke-width="0.75" stroke-opacity="0.03" />
57
+ <rect x="11" y="11" width="2" height="2" fill="#ffffff" fill-opacity="0.035" />
58
+ </pattern>
59
+ </defs>
60
+
61
+ <style>
62
+ <![CDATA[
63
+ /* CSS Animations */
64
+ @keyframes float-sword {
65
+ 0%, 100% { transform: translateY(0px) rotate(-16deg); }
66
+ 50% { transform: translateY(-14px) rotate(-12deg); }
67
+ }
68
+ @keyframes float-apple {
69
+ 0%, 100% { transform: translateY(0px) rotate(10deg); }
70
+ 50% { transform: translateY(-12px) rotate(14deg); }
71
+ }
72
+ @keyframes xp-drift {
73
+ 0% { transform: translateY(0px); opacity: 0; }
74
+ 25% { opacity: 0.9; }
75
+ 80% { opacity: 0.8; }
76
+ 100% { transform: translateY(-80px); opacity: 0; }
77
+ }
78
+ @keyframes star-flicker {
79
+ 0%, 100% { opacity: 0.2; transform: scale(0.7); }
80
+ 50% { opacity: 1; transform: scale(1.3); }
81
+ }
82
+ @keyframes radar-pulse {
83
+ 0% { r: 4; opacity: 1; stroke-width: 2; }
84
+ 100% { r: 13; opacity: 0; stroke-width: 0.5; }
85
+ }
86
+
87
+ .sword-group {
88
+ transform-box: fill-box;
89
+ transform-origin: center;
90
+ animation: float-sword 4.5s ease-in-out infinite;
91
+ }
92
+ .apple-group {
93
+ transform-box: fill-box;
94
+ transform-origin: center;
95
+ animation: float-apple 5s ease-in-out infinite;
96
+ }
97
+ .xp-drift-1 { animation: xp-drift 3.6s ease-in-out infinite; }
98
+ .xp-drift-2 { animation: xp-drift 4.4s ease-in-out infinite 1.2s; }
99
+ .xp-drift-3 { animation: xp-drift 5.0s ease-in-out infinite 2.2s; }
100
+ .xp-drift-4 { animation: xp-drift 3.8s ease-in-out infinite 0.7s; }
101
+
102
+ .star-1 { transform-origin: center; animation: star-flicker 2.2s ease-in-out infinite; }
103
+ .star-2 { transform-origin: center; animation: star-flicker 3.0s ease-in-out infinite 0.8s; }
104
+ .star-3 { transform-origin: center; animation: star-flicker 2.6s ease-in-out infinite 1.5s; }
105
+
106
+ .radar-pulse-anim { animation: radar-pulse 1.8s cubic-bezier(0, 0.2, 0.8, 1) infinite; }
107
+
108
+ .mc-header-font {
109
+ font-family: 'Courier New', Courier, monospace;
110
+ font-weight: 900;
111
+ letter-spacing: 2px;
112
+ }
113
+ ]]>
114
+ </style>
115
+
116
+ <!-- Frame Background & Border -->
117
+ <rect x="2" y="2" width="996" height="316" rx="14" fill="url(#bgGrad)" stroke="#222b40" stroke-width="3" />
118
+ <rect x="6" y="6" width="988" height="308" rx="10" fill="none" stroke="#141a29" stroke-width="2" />
119
+
120
+ <!-- Subtle Minecraft Grid -->
121
+ <rect x="8" y="8" width="984" height="304" rx="8" fill="url(#mcGrid)" />
122
+
123
+ <!-- Center Ambient Beacon Aura -->
124
+ <ellipse cx="500" cy="140" rx="380" ry="130" fill="url(#portalCenterGlow)" />
125
+ <rect x="410" y="8" width="180" height="304" fill="url(#beaconBeam)" opacity="0.6">
126
+ <animate attributeName="opacity" values="0.3;0.7;0.3" dur="4s" repeatCount="indefinite" />
127
+ </rect>
128
+
129
+ <!-- Minecraft Bedrock / Obsidian Corner Accents -->
130
+ <!-- Top Left -->
131
+ <path d="M 8 36 L 36 8 L 60 8 L 8 60 Z" fill="#2d344d" opacity="0.6" />
132
+ <rect x="14" y="14" width="7" height="7" fill="#00f0ff" opacity="0.85" />
133
+ <rect x="23" y="14" width="5" height="5" fill="#55ff55" opacity="0.75" />
134
+ <!-- Top Right -->
135
+ <path d="M 992 36 L 964 8 L 940 8 L 992 60 Z" fill="#2d344d" opacity="0.6" />
136
+ <rect x="979" y="14" width="7" height="7" fill="#00f0ff" opacity="0.85" />
137
+ <rect x="972" y="14" width="5" height="5" fill="#ffaa00" opacity="0.75" />
138
+ <!-- Bottom Left -->
139
+ <path d="M 8 284 L 36 312 L 60 312 L 8 260 Z" fill="#2d344d" opacity="0.6" />
140
+ <!-- Bottom Right -->
141
+ <path d="M 992 284 L 964 312 L 940 312 L 992 260 Z" fill="#2d344d" opacity="0.6" />
142
+
143
+ <!-- Twinkling Critical Hit Stars / Sparkles -->
144
+ <g transform="translate(180, 52)" class="star-1">
145
+ <path d="M 0 -8 L 2.5 -2.5 L 8 0 L 2.5 2.5 L 0 8 L -2.5 2.5 L -8 0 L -2.5 -2.5 Z" fill="#55ffff" />
146
+ <animateTransform attributeName="transform" type="scale" values="0.7;1.3;0.7" dur="2.2s" repeatCount="indefinite" />
147
+ </g>
148
+ <g transform="translate(830, 58)" class="star-2">
149
+ <path d="M 0 -7 L 2 -2 L 7 0 L 2 2 L 0 7 L -2 2 L -7 0 L -2 -2 Z" fill="#ffff55" />
150
+ <animateTransform attributeName="transform" type="scale" values="0.8;1.4;0.8" dur="3.0s" repeatCount="indefinite" begin="0.8s" />
151
+ </g>
152
+ <g transform="translate(310, 36)" class="star-3">
153
+ <path d="M 0 -5 L 1.5 -1.5 L 5 0 L 1.5 1.5 L 0 5 L -1.5 1.5 L -5 0 L -1.5 -1.5 Z" fill="#ff55ff" />
154
+ <animateTransform attributeName="transform" type="scale" values="0.6;1.2;0.6" dur="2.6s" repeatCount="indefinite" begin="1.5s" />
155
+ </g>
156
+ <g transform="translate(690, 44)" class="star-1">
157
+ <path d="M 0 -5 L 1.5 -1.5 L 5 0 L 1.5 1.5 L 0 5 L -1.5 1.5 L -5 0 L -1.5 -1.5 Z" fill="#55ff55" />
158
+ </g>
159
+
160
+ <!-- Drifting Minecraft XP Orbs & Redstone Dust with SMIL Fallback -->
161
+ <g transform="translate(250, 240)" class="xp-drift-1">
162
+ <rect x="-4" y="-4" width="8" height="8" rx="2" fill="#55ff55" stroke="#00aa00" stroke-width="1.5" />
163
+ <rect x="-1" y="-1" width="3" height="3" fill="#ffffff" />
164
+ <animateTransform attributeName="transform" type="translate" values="250,240; 250,165" dur="3.6s" repeatCount="indefinite" />
165
+ <animate attributeName="opacity" values="0;0.9;0.8;0" dur="3.6s" repeatCount="indefinite" />
166
+ </g>
167
+ <g transform="translate(740, 230)" class="xp-drift-2">
168
+ <rect x="-3" y="-3" width="6" height="6" rx="1.5" fill="#55ffff" stroke="#00aaaa" stroke-width="1.5" />
169
+ <rect x="-1" y="-1" width="2" height="2" fill="#ffffff" />
170
+ <animateTransform attributeName="transform" type="translate" values="740,230; 740,150" dur="4.4s" repeatCount="indefinite" begin="1.2s" />
171
+ <animate attributeName="opacity" values="0;0.9;0.7;0" dur="4.4s" repeatCount="indefinite" begin="1.2s" />
172
+ </g>
173
+ <g transform="translate(200, 210)" class="xp-drift-3">
174
+ <rect x="-3" y="-3" width="6" height="6" fill="#ff4d4d" stroke="#990000" stroke-width="1" />
175
+ <animateTransform attributeName="transform" type="translate" values="200,210; 200,135" dur="5.0s" repeatCount="indefinite" begin="2.2s" />
176
+ <animate attributeName="opacity" values="0;0.85;0.6;0" dur="5.0s" repeatCount="indefinite" begin="2.2s" />
177
+ </g>
178
+ <g transform="translate(790, 250)" class="xp-drift-4">
179
+ <rect x="-4" y="-4" width="8" height="8" rx="2" fill="#ffea55" stroke="#d48800" stroke-width="1.5" />
180
+ <animateTransform attributeName="transform" type="translate" values="790,250; 790,175" dur="3.8s" repeatCount="indefinite" begin="0.7s" />
181
+ <animate attributeName="opacity" values="0;0.9;0.7;0" dur="3.8s" repeatCount="indefinite" begin="0.7s" />
182
+ </g>
183
+
184
+ <!-- ================= LEFT: PIXEL ART DIAMOND SWORD (ANIMATED) ================= -->
185
+ <g transform="translate(95, 140)">
186
+ <g class="sword-group">
187
+ <animateTransform attributeName="transform" type="translate" values="0,0; 0,-14; 0,0" dur="4.5s" repeatCount="indefinite" />
188
+
189
+ <!-- Aura Glow -->
190
+ <circle cx="0" cy="0" r="48" fill="#00f0ff" opacity="0.08" filter="url(#softAura)" />
191
+ <circle cx="0" cy="0" r="44" fill="none" stroke="#00f0ff" stroke-width="1.5" stroke-dasharray="6,6" opacity="0.35" />
192
+
193
+ <!-- Pixel Art Sword Body (Centered and Scaled) -->
194
+ <g transform="scale(3.4) translate(-10, -10)" filter="url(#pixelShadow)">
195
+ <!-- Blade Outer Edge / Highlights -->
196
+ <rect x="18" y="2" width="2" height="2" fill="#ffffff" />
197
+ <rect x="17" y="3" width="2" height="2" fill="#7bf5ff" />
198
+ <rect x="16" y="4" width="2" height="2" fill="#2de2e6" />
199
+ <rect x="15" y="5" width="2" height="2" fill="#ffffff" />
200
+ <rect x="14" y="6" width="2" height="2" fill="#7bf5ff" />
201
+ <rect x="13" y="7" width="2" height="2" fill="#2de2e6" />
202
+ <rect x="12" y="8" width="2" height="2" fill="#ffffff" />
203
+ <rect x="11" y="9" width="2" height="2" fill="#7bf5ff" />
204
+ <rect x="10" y="10" width="2" height="2" fill="#2de2e6" />
205
+ <rect x="9" y="11" width="2" height="2" fill="#ffffff" />
206
+ <rect x="8" y="12" width="2" height="2" fill="#7bf5ff" />
207
+ <rect x="7" y="13" width="2" height="2" fill="#2de2e6" />
208
+
209
+ <!-- Inner Blade Shading (Diamond Core) -->
210
+ <rect x="18" y="3" width="2" height="2" fill="#2de2e6" />
211
+ <rect x="17" y="4" width="2" height="2" fill="#0099bb" />
212
+ <rect x="15" y="6" width="2" height="2" fill="#0099bb" />
213
+ <rect x="14" y="7" width="2" height="2" fill="#006688" />
214
+ <rect x="12" y="9" width="2" height="2" fill="#0099bb" />
215
+ <rect x="11" y="10" width="2" height="2" fill="#006688" />
216
+ <rect x="9" y="12" width="2" height="2" fill="#0099bb" />
217
+ <rect x="8" y="13" width="2" height="2" fill="#006688" />
218
+
219
+ <!-- Sword Guard / Crossguard (Obsidian & Gold) -->
220
+ <rect x="6" y="13" width="2" height="2" fill="#3c3f41" />
221
+ <rect x="7" y="14" width="2" height="2" fill="#ffaa00" />
222
+ <rect x="8" y="14" width="2" height="2" fill="#3c3f41" />
223
+ <rect x="9" y="15" width="2" height="2" fill="#ffaa00" />
224
+ <rect x="5" y="14" width="2" height="2" fill="#27292a" />
225
+ <rect x="6" y="15" width="2" height="2" fill="#3c3f41" />
226
+ <rect x="9" y="13" width="2" height="2" fill="#27292a" />
227
+ <rect x="10" y="14" width="2" height="2" fill="#3c3f41" />
228
+
229
+ <!-- Sword Handle (Wood Oak) -->
230
+ <rect x="5" y="16" width="2" height="2" fill="#8b5a2b" />
231
+ <rect x="4" y="17" width="2" height="2" fill="#6d421e" />
232
+
233
+ <!-- Pommel (Obsidian) -->
234
+ <rect x="3" y="18" width="2" height="2" fill="#27292a" />
235
+ <rect x="2" y="19" width="2" height="2" fill="#3c3f41" />
236
+ </g>
237
+ </g>
238
+ </g>
239
+
240
+ <!-- ================= RIGHT: PIXEL ART ENCHANTED APPLE / ORB (ANIMATED) ================= -->
241
+ <g transform="translate(895, 140)">
242
+ <g class="apple-group">
243
+ <animateTransform attributeName="transform" type="translate" values="0,0; 0,-12; 0,0" dur="5s" repeatCount="indefinite" />
244
+
245
+ <!-- Enchantment Halo -->
246
+ <ellipse cx="0" cy="0" rx="46" ry="20" fill="none" stroke="#c77dff" stroke-width="2" stroke-dasharray="8,4" opacity="0.65" />
247
+ <circle cx="0" cy="0" r="38" fill="#c77dff" opacity="0.1" filter="url(#softAura)" />
248
+
249
+ <!-- Apple Pixel Art -->
250
+ <g transform="scale(3.2) translate(-11, -10)" filter="url(#pixelShadow)">
251
+ <!-- Stem & Leaf -->
252
+ <rect x="11" y="3" width="2" height="3" fill="#8b5a2b" />
253
+ <rect x="13" y="2" width="2" height="2" fill="#55ff55" />
254
+
255
+ <!-- Apple Body -->
256
+ <rect x="8" y="6" width="8" height="10" rx="1" fill="#ffaa00" />
257
+ <rect x="6" y="8" width="12" height="7" rx="1" fill="#ffaa00" />
258
+ <!-- Shiny Highlights -->
259
+ <rect x="7" y="7" width="4" height="4" fill="#ffff55" />
260
+ <rect x="7" y="7" width="2" height="2" fill="#ffffff" />
261
+
262
+ <!-- Shading & Outline -->
263
+ <rect x="7" y="14" width="10" height="2" fill="#cc7700" />
264
+ <rect x="8" y="15" width="8" height="1" fill="#884400" />
265
+ <rect x="5" y="9" width="1" height="5" fill="#884400" />
266
+ <rect x="18" y="9" width="1" height="5" fill="#884400" />
267
+ </g>
268
+ </g>
269
+ </g>
270
+
271
+ <!-- ================= CENTER: BRAND & TYPOGRAPHY ================= -->
272
+ <!-- Top Category Pill -->
273
+ <g transform="translate(500, 48)">
274
+ <rect x="-165" y="-14" width="330" height="28" rx="14" fill="#131929" stroke="#2b3754" stroke-width="1.5" />
275
+ <text x="0" y="5" text-anchor="middle" fill="#00d2ff" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="800" letter-spacing="2.5">
276
+ MINECRAFT JAVA ARCHITECTURE
277
+ </text>
278
+ </g>
279
+
280
+ <!-- Main 3D Title: PAPERMC SKILL -->
281
+ <!-- Bevel Shadow 1 -->
282
+ <text x="502" y="127" text-anchor="middle" class="mc-header-font" font-size="56" fill="#040b17" opacity="0.95">
283
+ PAPERMC SKILL
284
+ </text>
285
+ <!-- Bevel Shadow 2 -->
286
+ <text x="500" y="125" text-anchor="middle" class="mc-header-font" font-size="56" fill="#0a3150">
287
+ PAPERMC SKILL
288
+ </text>
289
+ <!-- Main Glowing Gradient Text -->
290
+ <text x="500" y="122" text-anchor="middle" class="mc-header-font" font-size="56" fill="url(#titleCyan)" filter="url(#textGlow)">
291
+ PAPERMC SKILL
292
+ </text>
293
+ <text x="500" y="122" text-anchor="middle" class="mc-header-font" font-size="56" fill="url(#titleCyan)">
294
+ PAPERMC SKILL
295
+ </text>
296
+
297
+ <!-- High-Energy Tagline -->
298
+ <text x="500" y="165" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Minecraft', sans-serif" font-size="16" font-weight="700" fill="#e2e8f0" letter-spacing="1.2">
299
+ ⚔️ NEXT-GEN MINECRAFT PLUGIN ARSENAL • FOLIA READY • JAVA 21+ ⚔️
300
+ </text>
301
+
302
+ <!-- Feature Pills -->
303
+ <g transform="translate(500, 206)">
304
+ <!-- Pill 1: Paper 1.21.11 -->
305
+ <g transform="translate(-235, 0)">
306
+ <rect x="-65" y="-12" width="130" height="24" rx="6" fill="#0c1d2e" stroke="#00aaff" stroke-width="1" />
307
+ <text x="0" y="4" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="11" font-weight="700" fill="#7bf5ff">
308
+ ⚡ PAPER 1.21+
309
+ </text>
310
+ </g>
311
+
312
+ <!-- Pill 2: Folia Multithreaded -->
313
+ <g transform="translate(-80, 0)">
314
+ <rect x="-70" y="-12" width="140" height="24" rx="6" fill="#1b1233" stroke="#9d4edd" stroke-width="1" />
315
+ <text x="0" y="4" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="11" font-weight="700" fill="#d8b4fe">
316
+ 🌌 FOLIA NATIVE
317
+ </text>
318
+ </g>
319
+
320
+ <!-- Pill 3: Fill v3 Auto-Updater -->
321
+ <g transform="translate(80, 0)">
322
+ <rect x="-70" y="-12" width="140" height="24" rx="6" fill="#1c1f10" stroke="#55ff55" stroke-width="1" />
323
+ <text x="0" y="4" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="11" font-weight="700" fill="#86efac">
324
+ 🔄 FILL V3 TRACKER
325
+ </text>
326
+ </g>
327
+
328
+ <!-- Pill 4: Zero Tech-Debt -->
329
+ <g transform="translate(235, 0)">
330
+ <rect x="-65" y="-12" width="130" height="24" rx="6" fill="#241708" stroke="#ffaa00" stroke-width="1" />
331
+ <text x="0" y="4" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="11" font-weight="700" fill="#fde047">
332
+ 🛡️ ZERO TECH-DEBT
333
+ </text>
334
+ </g>
335
+ </g>
336
+
337
+ <!-- Bottom Terminal Status Bar -->
338
+ <g transform="translate(500, 274)">
339
+ <rect x="-310" y="-17" width="620" height="34" rx="8" fill="#080a10" stroke="#1c2336" stroke-width="1.5" />
340
+
341
+ <!-- Radar Live Ping Circle (CSS + SMIL) -->
342
+ <g transform="translate(-280, 0)">
343
+ <circle class="radar-pulse-anim" cx="0" cy="0" r="4" fill="none" stroke="#22c55e">
344
+ <animate attributeName="r" values="4;13" dur="1.8s" repeatCount="indefinite" />
345
+ <animate attributeName="opacity" values="1;0" dur="1.8s" repeatCount="indefinite" />
346
+ </circle>
347
+ <circle cx="0" cy="0" r="4" fill="#22c55e" />
348
+ </g>
349
+
350
+ <text x="-260" y="4" font-family="'Courier New', Courier, monospace" font-size="13" font-weight="700" fill="#22c55e">
351
+ SYS_READY:
352
+ </text>
353
+ <text x="-165" y="4" font-family="'Courier New', Courier, monospace" font-size="12" font-weight="600" fill="#94a3b8">
354
+ LATEST ENGINE <tspan fill="#38d9ff">v1.1.0</tspan> | BUILD <tspan fill="#f59e0b">GRADLE 9.7.1</tspan> | JAVA <tspan fill="#e2e8f0">21 LTS</tspan>
355
+ </text>
356
+ <text x="275" y="4" text-anchor="end" font-family="'Courier New', Courier, monospace" font-size="12" font-weight="700" fill="#00d2ff">
357
+ [LIVE]
358
+ </text>
359
+ </g>
360
+ </svg>
package/bin/cli.js CHANGED
@@ -237,6 +237,191 @@ function handleDocs(topic) {
237
237
  console.log(content);
238
238
  }
239
239
 
240
+ async function handleCheckUpdate(options = []) {
241
+ printBanner();
242
+ console.log(`${c.bold}Checking PaperMC Fill API for the latest versions...${c.reset}\n`);
243
+
244
+ try {
245
+ const res = await fetch('https://fill.papermc.io/v3/projects/paper', {
246
+ headers: {
247
+ 'User-Agent': 'papermc-skill/1.1.0 (https://github.com/ardianryan/papermc-skill)'
248
+ }
249
+ });
250
+
251
+ if (!res.ok) {
252
+ throw new Error(`PaperMC API returned status ${res.status}`);
253
+ }
254
+
255
+ const data = await res.json();
256
+ const versionGroups = Object.keys(data.versions || {});
257
+
258
+ if (versionGroups.length === 0) {
259
+ console.log(`${c.yellow}No version groups returned by PaperMC API.${c.reset}`);
260
+ return;
261
+ }
262
+
263
+ console.log(`${c.green}${c.bold}✔ Successfully queried PaperMC Fill v3 API${c.reset}\n`);
264
+ console.log(`${c.bold}Available Major Version Groups:${c.reset} ${versionGroups.slice(0, 5).join(', ')}`);
265
+
266
+ // Candidate group (latest supported group)
267
+ const candidateGroup = versionGroups[0];
268
+ const latestVersions = data.versions[candidateGroup] || [];
269
+ const latestVersionId = latestVersions[0] || candidateGroup;
270
+
271
+ // Fetch details for candidate version
272
+ const verRes = await fetch(`https://fill.papermc.io/v3/projects/paper/versions/${latestVersionId}`, {
273
+ headers: {
274
+ 'User-Agent': 'papermc-skill/1.1.0 (https://github.com/ardianryan/papermc-skill)'
275
+ }
276
+ });
277
+
278
+ let verData = null;
279
+ if (verRes.ok) {
280
+ verData = await verRes.json();
281
+ }
282
+
283
+ const latestBuild = verData?.builds?.[0] || 'latest';
284
+ const status = verData?.version?.support?.status || 'UNKNOWN';
285
+ const minJava = verData?.version?.java?.version?.minimum || 21;
286
+
287
+ console.log(`\n${c.cyan}${c.bold}Latest PaperMC Release Info:${c.reset}`);
288
+ console.log(` Version: ${c.green}${c.bold}${latestVersionId}${c.reset}`);
289
+ console.log(` Latest Build: ${c.yellow}#${latestBuild}${c.reset}`);
290
+ console.log(` Support: ${status === 'SUPPORTED' ? c.green : c.gray}${status}${c.reset}`);
291
+ console.log(` Minimum Java: ${c.bold}Java ${minJava}+${c.reset}\n`);
292
+
293
+ // Check template version
294
+ const templateBuildGradle = path.join(ROOT_DIR, 'templates', 'paper-modern-template', 'build.gradle.kts');
295
+ if (fs.existsSync(templateBuildGradle)) {
296
+ const content = fs.readFileSync(templateBuildGradle, 'utf-8');
297
+ const match = content.match(/paper-api:([0-9.]+)-R0\.1-SNAPSHOT/);
298
+ const currentConfigured = match ? match[1] : 'unknown';
299
+ console.log(`Starter Template Current Version: ${c.bold}${currentConfigured}${c.reset}`);
300
+
301
+ if (currentConfigured !== latestVersionId && options.includes('--apply')) {
302
+ console.log(`\n${c.yellow}Applying update to templates/paper-modern-template...${c.reset}`);
303
+ let updated = content.replaceAll(currentConfigured, latestVersionId);
304
+ fs.writeFileSync(templateBuildGradle, updated, 'utf-8');
305
+
306
+ // Update paper-plugin.yml
307
+ const pluginYamlPath = path.join(ROOT_DIR, 'templates', 'paper-modern-template', 'src', 'main', 'resources', 'paper-plugin.yml');
308
+ if (fs.existsSync(pluginYamlPath)) {
309
+ let yml = fs.readFileSync(pluginYamlPath, 'utf-8');
310
+ const major = latestVersionId.split('.').slice(0, 2).join('.');
311
+ yml = yml.replace(/api-version:\s*['"][^'"]+['"]/, `api-version: '${major}'`);
312
+ fs.writeFileSync(pluginYamlPath, yml, 'utf-8');
313
+ }
314
+ console.log(`${c.green}${c.bold}✔ Updated starter template to ${latestVersionId}!${c.reset}`);
315
+ } else if (currentConfigured !== latestVersionId) {
316
+ console.log(`${c.dim}Run 'npx papermc-skill check-update --apply' to update template automatically.${c.reset}`);
317
+ } else {
318
+ console.log(`${c.green}Starter template is already up to date!${c.reset}`);
319
+ }
320
+ }
321
+ } catch (err) {
322
+ console.error(`${c.red}Failed to check PaperMC update:${c.reset}`, err.message);
323
+ }
324
+ }
325
+
326
+ async function handleAudit(targetDirInput) {
327
+ printBanner();
328
+ const targetDir = path.resolve(process.cwd(), targetDirInput || '.');
329
+ console.log(`${c.cyan}${c.bold}Running PaperMC Security & Exploit Audit on:${c.reset} ${c.dim}${targetDir}${c.reset}\n`);
330
+
331
+ if (!fs.existsSync(targetDir)) {
332
+ console.error(`${c.red}Directory does not exist:${c.reset} ${targetDir}`);
333
+ return;
334
+ }
335
+
336
+ const javaFiles = [];
337
+ function scan(dir) {
338
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
339
+ for (const entry of entries) {
340
+ if (entry.name === '.git' || entry.name === 'node_modules' || entry.name === 'build' || entry.name === '.gradle') continue;
341
+ const full = path.join(dir, entry.name);
342
+ if (entry.isDirectory()) {
343
+ scan(full);
344
+ } else if (entry.name.endsWith('.java')) {
345
+ javaFiles.push(full);
346
+ }
347
+ }
348
+ }
349
+
350
+ scan(targetDir);
351
+
352
+ if (javaFiles.length === 0) {
353
+ console.log(`${c.yellow}No .java files found to audit in this directory.${c.reset}`);
354
+ return;
355
+ }
356
+
357
+ console.log(`Auditing ${c.bold}${javaFiles.length}${c.reset} Java source files for exploit vectors & anti-patterns...\n`);
358
+
359
+ const checks = [
360
+ {
361
+ id: 'CHATCOLOR_LEGACY',
362
+ regex: /ChatColor\.[A-Z_]+/,
363
+ level: 'HIGH',
364
+ msg: 'Legacy ChatColor usage detected. Migrate to Adventure Component & MiniMessage to prevent console formatting corruption.'
365
+ },
366
+ {
367
+ id: 'SECTION_SIGN_COLOR',
368
+ regex: /["'].*?§[0-9a-fk-or].*?["']/,
369
+ level: 'HIGH',
370
+ msg: 'Hardcoded legacy section sign (§) detected. Use MiniMessage.miniMessage().deserialize(...) instead.'
371
+ },
372
+ {
373
+ id: 'PLAYER_STATIC_LEAK',
374
+ regex: /public\s+static\s+(?:final\s+)?(?:List|Set|Map|Collection)<(?:[^,>]+,\s*)?Player>/,
375
+ level: 'CRITICAL',
376
+ msg: 'Static collection holding Player instances detected! This causes massive Memory Leaks. Store UUID instead.'
377
+ },
378
+ {
379
+ id: 'SYNC_CHUNK_LOAD',
380
+ regex: /world\s*\.\s*getChunkAt\s*\(/,
381
+ level: 'HIGH',
382
+ msg: 'Synchronous chunk loading (world.getChunkAt) freezes the main server tick thread. Use getChunkAtAsync instead.'
383
+ },
384
+ {
385
+ id: 'INSECURE_SQL_CONCAT',
386
+ regex: /(?:executeQuery|executeUpdate|execute)\s*\(\s*["'].*?\+/i,
387
+ level: 'CRITICAL',
388
+ msg: 'Potential SQL Injection via string concatenation detected in query. Use PreparedStatement with ? placeholders.'
389
+ },
390
+ {
391
+ id: 'RAW_DOUBLE_NAN_CHECK',
392
+ regex: /DoubleArgumentType\.doubleArg\s*\(/,
393
+ level: 'INFO',
394
+ msg: 'Double argument registered. Ensure execution validates !Double.isFinite(val) and checks for positive numbers.'
395
+ }
396
+ ];
397
+
398
+ let issueCount = 0;
399
+ for (const file of javaFiles) {
400
+ const content = fs.readFileSync(file, 'utf-8');
401
+ const lines = content.split('\n');
402
+ const relPath = path.relative(targetDir, file);
403
+
404
+ lines.forEach((line, idx) => {
405
+ for (const check of checks) {
406
+ if (check.regex.test(line)) {
407
+ issueCount++;
408
+ const color = check.level === 'CRITICAL' ? c.red : (check.level === 'HIGH' ? c.yellow : c.cyan);
409
+ console.log(`[${color}${check.level}${c.reset}] ${c.bold}${relPath}:${idx + 1}${c.reset}`);
410
+ console.log(` ${c.dim}${line.trim()}${c.reset}`);
411
+ console.log(` ↳ ${check.msg}\n`);
412
+ }
413
+ }
414
+ });
415
+ }
416
+
417
+ if (issueCount === 0) {
418
+ console.log(`${c.green}${c.bold}✔ 0 Vulnerabilities or Anti-Patterns Found!${c.reset}`);
419
+ console.log(`${c.green}Codebase adheres to modern Paper & Folia exploit-proof security standards.${c.reset}\n`);
420
+ } else {
421
+ console.log(`${c.yellow}${c.bold}Found ${issueCount} potential issue(s).${c.reset} Review docs/11-security-and-exploit-prevention.md for guidelines.\n`);
422
+ }
423
+ }
424
+
240
425
  function printHelp() {
241
426
  printBanner();
242
427
  console.log(`${c.bold}Usage:${c.reset}
@@ -244,6 +429,8 @@ function printHelp() {
244
429
 
245
430
  ${c.bold}Commands:${c.reset}
246
431
  ${c.cyan}create [name]${c.reset} / ${c.cyan}init [name]${c.reset} Scaffold a modern Paper & Folia plugin project
432
+ ${c.cyan}check-update [--apply]${c.reset} Query PaperMC Fill API for new Minecraft & Paper releases
433
+ ${c.cyan}audit [path]${c.reset} Audit Java plugin codebase for security exploits & anti-patterns
247
434
  ${c.cyan}install-skill [--global]${c.reset} Install the AI skill into workspace (.agents) or global (~/.gemini)
248
435
  ${c.cyan}docs [number|keyword]${c.reset} Browse or print documentation guides
249
436
  ${c.cyan}help${c.reset} / ${c.cyan}--help${c.reset} Display this help screen
@@ -253,6 +440,9 @@ ${c.bold}Examples:${c.reset}
253
440
  ${c.dim}# Create a new Paper plugin in current directory${c.reset}
254
441
  npx papermc-skill create MyAwesomePlugin
255
442
 
443
+ ${c.dim}# Check if there is a new Minecraft/Paper update from PaperMC API${c.reset}
444
+ npx papermc-skill check-update
445
+
256
446
  ${c.dim}# Install AI skill globally for your coding agent${c.reset}
257
447
  npx papermc-skill install-skill --global
258
448
 
@@ -272,6 +462,10 @@ async function main() {
272
462
  case 'new':
273
463
  await handleCreate(args[1]);
274
464
  break;
465
+ case 'check-update':
466
+ case 'update':
467
+ await handleCheckUpdate(args.slice(1));
468
+ break;
275
469
  case 'install-skill':
276
470
  case 'install':
277
471
  case 'skill':
@@ -282,6 +476,11 @@ async function main() {
282
476
  case 'guide':
283
477
  handleDocs(args[1]);
284
478
  break;
479
+ case 'audit':
480
+ case 'scan':
481
+ case 'security':
482
+ await handleAudit(args[1]);
483
+ break;
285
484
  case '--version':
286
485
  case '-v': {
287
486
  const pkg = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, 'package.json'), 'utf-8'));