Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21f07b6994 | ||
|
|
a30a3e33d1 | ||
|
|
7ad7386dcb | ||
|
|
bced1b15d0 | ||
|
|
ecf2b7290f | ||
|
|
8ecedfa7fc | ||
|
|
84920b1499 | ||
|
|
885d91a491 | ||
|
|
cb39d6cce7 | ||
|
|
c426672f6d | ||
|
|
12935d9584 | ||
|
|
013f6bdf62 | ||
|
|
763a4c4a8c | ||
|
|
b30f89a254 | ||
|
|
797f97080b | ||
|
|
6709f021ca | ||
|
|
ea339fffb3 | ||
|
|
600f5c4381 | ||
|
|
8a3b80de09 | ||
|
|
2100f66d73 | ||
|
|
7591a25f03 | ||
|
|
7003a4e077 | ||
|
|
b99b34f70d | ||
|
|
a390ec1f18 | ||
|
|
52e546420d | ||
|
|
633f46c13d | ||
|
|
cfe2a04b5c | ||
|
|
dc157f44ff | ||
|
|
721b41b1bd | ||
|
|
b0c0fdb8c7 | ||
|
|
845c57bf66 | ||
|
|
5cf03e3553 | ||
|
|
2e0a4492d3 | ||
|
|
275941f96b | ||
|
|
43cc9813e2 | ||
|
|
7083f3ac4a | ||
|
|
dab6d1aeb6 | ||
|
|
82640a8adc | ||
|
|
3dec1a56ac | ||
|
|
bfafcc8e4e | ||
|
|
22f4981296 | ||
|
|
59bf4d12f3 | ||
|
|
f7a09a627f | ||
|
|
bfddcebda7 | ||
|
|
55b43aa268 | ||
|
|
8d9643bd31 | ||
|
|
3ffb2706f5 | ||
|
|
26d3857628 | ||
|
|
2f5393f91f | ||
|
|
4dd08d7fe4 | ||
|
|
3c6f7c3369 | ||
|
|
0b2e0206d5 | ||
|
|
66aba20ac2 | ||
|
|
323d89dc97 | ||
|
|
e6a1093cc0 | ||
|
|
9778d6fed3 | ||
|
|
4411d1bcdc | ||
|
|
cf74ae9392 | ||
|
|
207d79f5c2 | ||
|
|
57d91ed5e9 | ||
|
|
2416cdae68 | ||
|
|
38cb9dd9d9 | ||
|
|
d2ce5c0931 | ||
|
|
1441177841 | ||
|
|
f03a9e17fb | ||
|
|
80da7b3c11 | ||
|
|
938e6b1abb | ||
|
|
c3cf3ec4e3 | ||
|
|
5e08e0bc2c | ||
|
|
8fd72d5e2b | ||
|
|
d4492cec47 | ||
|
|
6dcc96955c | ||
|
|
0b9b261ce0 | ||
|
|
f6705b9ee6 | ||
|
|
e4cdd6feae | ||
|
|
879fa06672 | ||
|
|
518659b8d3 | ||
|
|
85141b6fa6 | ||
|
|
976a05f458 | ||
|
|
998828138b | ||
|
|
638acd9e88 | ||
|
|
5c0850dbdd | ||
|
|
8a5415c37d | ||
|
|
b5c6afa368 | ||
|
|
4bcf85d718 | ||
|
|
548187238e | ||
|
|
c7845cec0b | ||
|
|
ab3316bcf1 | ||
|
|
33b09e85d7 | ||
|
|
4b6110aa2b | ||
|
|
e404a158e7 | ||
|
|
981901271c | ||
|
|
3f93840e5a | ||
|
|
4d5e45e9eb | ||
|
|
be8e6d268e | ||
|
|
b89799ff75 | ||
|
|
10cb91ac56 | ||
|
|
b7d190ce7f | ||
|
|
e028a3bada | ||
|
|
f339248ad3 | ||
|
|
b8a6f9b746 | ||
|
|
3d45362241 | ||
|
|
859047762c | ||
|
|
63a95961f8 | ||
|
|
f3c5540d15 | ||
|
|
fcbf2e9454 | ||
|
|
ae993a34e0 | ||
|
|
eba9aa8e0e | ||
|
|
04b86d4a56 | ||
|
|
53402d3c1d | ||
|
|
7634c37ad4 | ||
|
|
26125abef2 | ||
|
|
93182688e2 | ||
|
|
a67b23079d | ||
|
|
79bffc2522 | ||
|
|
7e9aa41fdd | ||
|
|
cc30f56c76 | ||
|
|
b24ddb12cc | ||
|
|
2df52bf858 | ||
|
|
dd64837958 | ||
|
|
ccf3045cb3 | ||
|
|
34cab56b2c | ||
|
|
7090497684 | ||
|
|
4fefeda34d | ||
|
|
9ec693ae16 | ||
|
|
36039dd0f6 | ||
|
|
7295ce2b6c | ||
|
|
82987e54f1 | ||
|
|
19da3e8050 | ||
|
|
440efc5d8a | ||
|
|
b8e9cf3b07 | ||
|
|
eb34c410e0 | ||
|
|
866767f08f | ||
|
|
9c175b8ffd | ||
|
|
f3460dbc51 | ||
|
|
a8671bbcd2 | ||
|
|
47f17eb199 | ||
|
|
f92df0f0dd | ||
|
|
1ccf5ce3ec | ||
|
|
9dad10c46a | ||
|
|
b87e7bc50f | ||
|
|
103bdf9a78 | ||
|
|
58391bd263 | ||
|
|
1405925a43 | ||
|
|
bc6d51e07c | ||
|
|
0048eb1186 | ||
|
|
3f00242d1a | ||
|
|
89573967fd | ||
|
|
18d8538144 | ||
|
|
c6a2739162 | ||
|
|
42049dc7d7 | ||
|
|
94bd9180f7 | ||
|
|
3ea331f00a | ||
|
|
98e27c85d2 | ||
|
|
c48e42c21d | ||
|
|
18901c887c | ||
|
|
218bfc0bab | ||
|
|
dba1bbe0d5 | ||
|
|
6be0f99a85 | ||
|
|
b65c83eb69 | ||
|
|
96836270d6 | ||
|
|
d94c3c5bba | ||
|
|
c780a1bb8f | ||
|
|
9954cf36db | ||
|
|
15aa2779c8 | ||
|
|
b1fa65d335 | ||
|
|
dd4af51264 | ||
|
|
ac138706b7 | ||
|
|
888df22b1f | ||
|
|
98048622c6 | ||
|
|
6ba68553c6 | ||
|
|
6aa65a6a95 | ||
|
|
37a7ece2d3 | ||
|
|
4d5f6a2928 | ||
|
|
65f7a9652c | ||
|
|
373d15a115 | ||
|
|
67e1de9334 | ||
|
|
07c780411f | ||
|
|
c678931a31 | ||
|
|
2511a0f2df | ||
|
|
27ff27caf6 | ||
|
|
547f9a1788 | ||
|
|
12a407585b | ||
|
|
60796df402 | ||
|
|
56fd8557c6 | ||
|
|
fa4305682a | ||
|
|
08f0c8871b | ||
|
|
8dfaa35b16 | ||
|
|
3137a87095 | ||
|
|
423275e11d | ||
|
|
21b876c13a | ||
|
|
3fedc67356 | ||
|
|
63a8ef9e02 | ||
|
|
4666531bb8 | ||
|
|
abf476c368 | ||
|
|
d213a20df6 | ||
|
|
8f5a81c17e | ||
|
|
dd0e895513 | ||
|
|
8f42950ef3 | ||
|
|
4043a578e1 | ||
|
|
1c06b1bee4 | ||
|
|
5c6b3f4e43 | ||
|
|
8df4e70032 | ||
|
|
432267b567 | ||
|
|
28090463b8 | ||
|
|
fff437a60b | ||
|
|
00e0bdcaf3 | ||
|
|
1c9ff78b4c | ||
|
|
0aa037d1af | ||
|
|
1440d19663 | ||
|
|
20daf60534 | ||
|
|
dd36c10a0f | ||
|
|
0caddf5b44 | ||
|
|
7ca4536dc5 | ||
|
|
e9ecd3aebf | ||
|
|
5adadcbbcb | ||
|
|
4c1739f3b0 | ||
|
|
dcfd2a6fe1 | ||
|
|
b7a56198f4 | ||
|
|
2d9fdaccc2 | ||
|
|
4f63f55d11 | ||
|
|
5495f5f57a | ||
|
|
d33e98714a | ||
|
|
e6e98c9852 | ||
|
|
6f9abbefc9 | ||
|
|
7ee6dcb1b7 | ||
|
|
db37d4ae66 | ||
|
|
38b707d091 | ||
|
|
6737e63232 | ||
|
|
5f9c42c5d7 | ||
|
|
f97665fe47 | ||
|
|
202782e053 | ||
|
|
20da844129 | ||
|
|
e98b222250 | ||
|
|
430c483f39 | ||
|
|
92798a38c7 | ||
|
|
5f491e9553 | ||
|
|
1a862fce44 | ||
|
|
da965a7b4a | ||
|
|
d3cd42c076 | ||
|
|
4a3572d39c | ||
|
|
8f5baf7757 | ||
|
|
5a98d82c49 | ||
|
|
984ef05ffb | ||
|
|
db2a723c57 | ||
|
|
5187a74a06 | ||
|
|
4b7a003c27 | ||
|
|
1a673997e0 | ||
|
|
2364f306a8 | ||
|
|
23b21eb921 | ||
|
|
6e71e33bf8 | ||
|
|
1164d4551f | ||
|
|
de562d1bae | ||
|
|
9c117b156b | ||
|
|
4a9b90ed95 | ||
|
|
de095dd900 |
No files matched your search
+2
-13
@@ -1,13 +1,2 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: https://paypal.me/4drian3d # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
github: 4drian3d
|
||||
custom: https://paypal.me/4drian3d
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- name: Build with Gradle
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 4
|
||||
timeout_minutes: 10
|
||||
max_attempts: 2
|
||||
command: gradle build
|
||||
|
||||
@@ -28,4 +28,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: MiniPlaceholders
|
||||
path: build/libs/MiniPlaceholders-*.jar
|
||||
path: jar/MiniPlaceholders-*.jar
|
||||
@@ -2,6 +2,7 @@
|
||||
/.idea/
|
||||
build/
|
||||
bin/
|
||||
jar/
|
||||
|
||||
# Visual Studio Code
|
||||
|
||||
|
||||
@@ -1,41 +1,66 @@
|
||||
# MiniPlaceholders  [](https://discord.gg/5NMMzK5mAn)
|
||||
MiniMessage Component-based Placeholders for PaperMC and Velocity platforms
|
||||
# MiniPlaceholders
|
||||
[](https://github.com/MiniPlaceholders/MiniPlaceholders/actions)
|
||||

|
||||
[](https://discord.gg/5NMMzK5mAn)
|
||||

|
||||

|
||||
|
||||
MiniMessage Component-based Placeholders for Paper, Fabric, Sponge, Folia and Velocity platforms
|
||||
|
||||
## Compatibility
|
||||
- Paper 1.19.3+
|
||||
- Paper 1.19.3, 1.19.4+
|
||||
- Folia 1.19.4+
|
||||
- Velocity 3.1.2+
|
||||
- Krypton
|
||||
- Fabric 1.19.4+
|
||||
- Sponge API 8+
|
||||
|
||||
## Commands
|
||||
|
||||
## Commands:
|
||||
### Velocity
|
||||
`/vminiplaceholders <parse|help> <me|player> <player-to-parse>`
|
||||
### Paper
|
||||
`/miniplaceholders <parse|help> <me|player> <player-to-parse>`
|
||||
|
||||
## Usage
|
||||
- `/vminiplaceholders parse me "[message with placeholders]"`
|
||||
- `/vminiplaceholders parse player [some-player] "[message with placeholders]"`
|
||||
|
||||
Check our usage wiki [here](https://github.com/MiniPlaceholders/MiniPlaceholders/wiki/User-Getting-Started)
|
||||
### Paper | Folia | Fabric | Krypton
|
||||
|
||||
- `/miniplaceholders <parse|help> player [some-player] "[message with placeholders]`
|
||||
- `/miniplaceholders parse player [some-player] "[message with placeholders]"`
|
||||
|
||||
#### Example:
|
||||
|
||||
- `/miniplaceholders parse me "<player_xp>"`
|
||||
- `/vminiplaceholders parse player 4drian3d "<player_name>"`
|
||||
|
||||
## User Usage
|
||||
|
||||
Check our user usage wiki [here](https://github.com/MiniPlaceholders/MiniPlaceholders/wiki/User-Getting-Started)
|
||||
|
||||
## API
|
||||
|
||||
Check the available [Javadocs](https://javadoc.io/doc/io.github.miniplaceholders/miniplaceholders-api)
|
||||
|
||||
Or check the [Developer Wiki](https://github.com/MiniPlaceholders/MiniPlaceholders/wiki/Developer-Getting-Started)
|
||||
|
||||
### Java
|
||||
```java
|
||||
|
||||
class Main {
|
||||
public static void registerExpansion() {
|
||||
Expansion expansion = Expansion.builder("my-expansion")
|
||||
final Expansion expansion = Expansion.builder("my-expansion")
|
||||
.filter(Player.class)
|
||||
.audiencePlaceholder("name", (aud, ctx, queue) -> {
|
||||
return Tag.selfClosingInserting(aud.getName());
|
||||
.audiencePlaceholder("name", (audience, ctx, queue) -> {
|
||||
final Player player = (player) audience;
|
||||
return Tag.selfClosingInserting(player.getName());
|
||||
})
|
||||
.globalPlaceholder("tps", (ctx, queue) -> {
|
||||
return Tag.inserting(Component.text(Bukkit.getTps()[0]));
|
||||
}).build;
|
||||
.globalPlaceholder("tps", (ctx, queue) ->
|
||||
Tag.selfClosingInserting(Component.text(Bukkit.getTps()[0]))
|
||||
).build;
|
||||
|
||||
expansion.register();
|
||||
|
||||
Player player;
|
||||
player.sendMessage(miniMessage().deserialize("Player Name: <my-expansion_name>", MiniPlaceholders.getAudiencePlaceholders(player)));
|
||||
final TagResolver playerResolver = MiniPlaceholders.getAudiencePlaceholders(player);
|
||||
player.sendMessage(miniMessage().deserialize("Player Name: <my-expansion_name>", playerResolver));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,24 +69,19 @@ class Main {
|
||||
### Kotlin
|
||||
```kotlin
|
||||
fun register() {
|
||||
val expansion = expansion("my-expansion") {
|
||||
audiencePlaceholder("name") { aud, _, _ ->
|
||||
aud.getName().asClosingTag()
|
||||
val expansion = expansion("my-expansion") {
|
||||
audiencePlaceholder("name") { aud, _, _ ->
|
||||
aud.getName().asClosingTag()
|
||||
}
|
||||
globalPlaceholder("tps") { _, _ ->
|
||||
Component.text(Bukkit.getTps()[0]).asInsertingTag()
|
||||
}
|
||||
}
|
||||
globalPlaceholder("tps") { _, _ ->
|
||||
Component.text(Bukkit.getTps()[0]).asInsertingTag()
|
||||
}
|
||||
}
|
||||
|
||||
expansion.register()
|
||||
|
||||
val player: Player
|
||||
player.sendMessage(miniMessage().deserialize("Player Name: <my-expansion_name>", MiniPlaceholders.getAudiencePlaceholders(player)))
|
||||
val playerResolver = MiniPlaceholders.getAudiencePlaceholders(player)
|
||||
player.sendMessage(miniMessage().deserialize("Player Name: <my-expansion_name>", playerResolver))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Check the available javadocs [here](https://javadoc.jitpack.io/com/github/4drian3d/MiniPlaceholders/latest/javadoc/index.html)
|
||||
|
||||
Or check the developer wiki [here](https://github.com/MiniPlaceholders/MiniPlaceholders/wiki/Developer-Getting-Started)
|
||||
|
||||
+16
-23
@@ -1,28 +1,22 @@
|
||||
plugins {
|
||||
id("miniplaceholders.base")
|
||||
alias(libs.plugins.jmh)
|
||||
id("miniplaceholders.publish")
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.adventure.api)
|
||||
compileOnly(libs.adventure.minimesssage)
|
||||
compileOnly("net.kyori:adventure-text-serializer-legacy:4.12.0")
|
||||
compileOnly(libs.adventure.serializer.legacy)
|
||||
compileOnly(projects.miniplaceholdersConnect)
|
||||
testImplementation(platform("org.junit:junit-bom:5.9.2"))
|
||||
|
||||
testImplementation(platform(libs.junit.bom))
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testImplementation(libs.adventure.api)
|
||||
testImplementation(libs.adventure.minimesssage)
|
||||
testImplementation("net.kyori:adventure-text-serializer-plain:4.12.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("passed", "failed")
|
||||
}
|
||||
}
|
||||
testImplementation(libs.adventure.serializer.plain)
|
||||
testImplementation(libs.adventure.serializer.legacy)
|
||||
}
|
||||
|
||||
jmh {
|
||||
@@ -33,19 +27,9 @@ jmh {
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
||||
options.release.set(11)
|
||||
}
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
@@ -56,4 +40,13 @@ tasks {
|
||||
"https://jd.advntr.dev/text-minimessage/${libs.versions.adventure.get()}/"
|
||||
)
|
||||
}
|
||||
compileTestJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("passed", "failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface Expansion {
|
||||
public sealed interface Expansion permits ExpansionImpl {
|
||||
/**
|
||||
* Get the expansion name
|
||||
* @return the expansion name
|
||||
@@ -74,9 +74,26 @@ public interface Expansion {
|
||||
/**
|
||||
* Register this expansion
|
||||
* @since 1.0.0
|
||||
* @throws IllegalStateException if the expansion you are trying to register is already registered
|
||||
* @see Expansion#registered()
|
||||
*/
|
||||
void register();
|
||||
|
||||
/**
|
||||
* Unregisters this expansion
|
||||
* @since 2.1.0
|
||||
* @throws IllegalStateException if the expansion you are trying to unregister is not registered
|
||||
* @see Expansion#registered()
|
||||
*/
|
||||
void unregister();
|
||||
|
||||
/**
|
||||
* Get the registration status of this expansion
|
||||
* @return true if the expansion is registered, otherwise false
|
||||
* @since 2.1.0
|
||||
*/
|
||||
boolean registered();
|
||||
|
||||
/**
|
||||
* Creates a new Expansion Builder
|
||||
* @param name the expansion name
|
||||
@@ -117,6 +134,7 @@ public interface Expansion {
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param audiencePlaceholder the single placeholder
|
||||
* @return the {@link Builder} itself
|
||||
@@ -125,7 +143,7 @@ public interface Expansion {
|
||||
@NotNull Builder audiencePlaceholder(final @NotNull String key, final @NotNull AudiencePlaceholder audiencePlaceholder);
|
||||
|
||||
/**
|
||||
* Adds an Relational Placeholder based on two audiences
|
||||
* Adds a Relational Placeholder based on two audiences
|
||||
*
|
||||
* <p>This type of placeholder allows you to create
|
||||
* components based on a 2-audiences relationship,
|
||||
@@ -135,6 +153,7 @@ public interface Expansion {
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param relationalPlaceholder the relational placeholder
|
||||
* @return the {@link Builder} itself
|
||||
@@ -157,7 +176,7 @@ public interface Expansion {
|
||||
/**
|
||||
* Adds a global placeholder
|
||||
*
|
||||
* <p>This placeholder is not cached and is inmutable</p>
|
||||
* <p>This placeholder is not cached and is immutable</p>
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param tag the tag of this placeholder
|
||||
* @return the {@link Builder} itself
|
||||
@@ -174,6 +193,7 @@ public interface Expansion {
|
||||
*
|
||||
* <p>This eliminates the need to perform a manual
|
||||
* <pre>if(!(audience instanceof Player)) return TagResolver.empty();</pre>
|
||||
*
|
||||
* @param clazz the class to filter
|
||||
* @return the {@link Builder} itself
|
||||
* @since 1.0.0
|
||||
@@ -185,15 +205,17 @@ public interface Expansion {
|
||||
* Filters the audiences that this expansion can receive through a Predicate
|
||||
* <p>Example:</p>
|
||||
* <pre>
|
||||
* Expansion.builder("example").filter(Player.class).filter(aud -> isInProtectedServer((Player)aud))
|
||||
* Expansion.builder("example")
|
||||
* .filter(aud -> aud instanceof Player player{@literal &&} isInProtectedServer(player)
|
||||
* .audiencePlaceholder("hello", (aud, queue, ctx) -> Tag.selfInsertingClosing(Component.text("you are in protected server")))
|
||||
* .build();
|
||||
* </pre>
|
||||
*
|
||||
* @param predicate the check to realize
|
||||
* @return the {@link Builder} itself
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
@NotNull Builder filter(final @Nullable Predicate<Audience> predicate);
|
||||
@NotNull Builder filter(final @Nullable Predicate<@NotNull Audience> predicate);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
package io.github.miniplaceholders.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import io.github.miniplaceholders.api.placeholder.AudiencePlaceholder;
|
||||
import io.github.miniplaceholders.api.placeholder.RelationalPlaceholder;
|
||||
import io.github.miniplaceholders.api.utils.Conditions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static io.github.miniplaceholders.api.utils.Conditions.nonNullOrEmptyString;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
final class ExpansionImpl implements Expansion {
|
||||
private static final Tags.Single[] EMPTY_SINGLE_AUDIENCE = new Tags.Single[0];
|
||||
private static final Tags.Relational[] EMPTY_RELATIONAL_AUDIENCE = new Tags.Relational[0];
|
||||
private final String name;
|
||||
private final Tags.Single[] audiencePlaceholders;
|
||||
private final Tags.Relational[] relationalPlaceholders;
|
||||
@@ -38,14 +37,12 @@ final class ExpansionImpl implements Expansion {
|
||||
@Nullable final Predicate<Audience> predicateFilter){
|
||||
this.name = expansionName+"-";
|
||||
this.audiencePlaceholders = audiencePlaceholders != null
|
||||
? audiencePlaceholders.toArray(Tags.Single[]::new)
|
||||
: new Tags.Single[0];
|
||||
? audiencePlaceholders.toArray(EMPTY_SINGLE_AUDIENCE)
|
||||
: EMPTY_SINGLE_AUDIENCE;
|
||||
this.relationalPlaceholders = relationalPlaceholders != null
|
||||
? relationalPlaceholders.toArray(Tags.Relational[]::new)
|
||||
: new Tags.Relational[0];
|
||||
this.globalPlaceholders = globalPlaceholders == null
|
||||
? TagResolver.empty()
|
||||
: globalPlaceholders;
|
||||
? relationalPlaceholders.toArray(EMPTY_RELATIONAL_AUDIENCE)
|
||||
: EMPTY_RELATIONAL_AUDIENCE;
|
||||
this.globalPlaceholders = globalPlaceholders;
|
||||
this.filterClass = filterClass;
|
||||
this.predicateFilter = predicateFilter;
|
||||
}
|
||||
@@ -56,56 +53,82 @@ final class ExpansionImpl implements Expansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TagResolver audiencePlaceholders(@NotNull final Audience audience){
|
||||
if(audiencePlaceholders.length == 0) return TagResolver.empty();
|
||||
public @NotNull TagResolver audiencePlaceholders(@NotNull Audience audience) {
|
||||
if (audiencePlaceholders.length == 0) return TagResolver.empty();
|
||||
|
||||
Objects.requireNonNull(audience, "the audience cannot be null");
|
||||
requireNonNull(audience, "the audience cannot be null");
|
||||
|
||||
if(this.singleFilter(audience)) return TagResolver.empty();
|
||||
if ((audience = expansionFilter(audience)) == null) return TagResolver.empty();
|
||||
|
||||
final TagResolver.Builder placeholders = TagResolver.builder();
|
||||
for(final Tags.Single pl : this.audiencePlaceholders){
|
||||
for (final Tags.Single pl : this.audiencePlaceholders) {
|
||||
placeholders.resolver(pl.of(audience));
|
||||
}
|
||||
return placeholders.build();
|
||||
}
|
||||
|
||||
private boolean singleFilter(final Audience audience){
|
||||
return filterClass != null && !filterClass.isInstance(audience)
|
||||
|| predicateFilter != null && predicateFilter.test(audience);
|
||||
@SuppressWarnings("OverrideOnly")
|
||||
private Audience expansionFilter(final Audience audience) {
|
||||
if (audience == null || filterClass == null && predicateFilter == null) {
|
||||
return audience;
|
||||
}
|
||||
final boolean eligible = filterClass != null && filterClass.isInstance(audience)
|
||||
|| predicateFilter != null && predicateFilter.test(audience);
|
||||
if (eligible) {
|
||||
return audience;
|
||||
}
|
||||
if (audience instanceof final ForwardingAudience.Single forward) {
|
||||
return expansionFilter(forward.audience());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TagResolver relationalPlaceholders(@NotNull final Audience audience, @NotNull final Audience otherAudience){
|
||||
if(relationalPlaceholders.length == 0) return TagResolver.empty();
|
||||
public @NotNull TagResolver relationalPlaceholders(@NotNull Audience audience, @NotNull Audience otherAudience){
|
||||
if (relationalPlaceholders.length == 0) return TagResolver.empty();
|
||||
|
||||
Objects.requireNonNull(audience, "the audience cannot be null");
|
||||
Objects.requireNonNull(otherAudience, "the other audience cannot be null");
|
||||
requireNonNull(audience, "the audience cannot be null");
|
||||
requireNonNull(otherAudience, "the other audience cannot be null");
|
||||
|
||||
if (this.relationalFilter(audience, otherAudience)) return TagResolver.empty();
|
||||
audience = expansionFilter(audience);
|
||||
otherAudience = expansionFilter(otherAudience);
|
||||
if (audience == null || otherAudience == null) {
|
||||
return TagResolver.empty();
|
||||
}
|
||||
|
||||
final TagResolver.Builder placeholders = TagResolver.builder();
|
||||
for (final Tags.Relational pl : this.relationalPlaceholders){
|
||||
for (final Tags.Relational pl : this.relationalPlaceholders) {
|
||||
placeholders.resolver(pl.of(audience, otherAudience));
|
||||
}
|
||||
return placeholders.build();
|
||||
}
|
||||
|
||||
private boolean relationalFilter(final Audience audience, final Audience otherAudience){
|
||||
return filterClass != null && (!filterClass.isInstance(audience) || !filterClass.isInstance(otherAudience))
|
||||
|| predicateFilter != null && (!predicateFilter.test(audience) || !predicateFilter.test(otherAudience));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TagResolver globalPlaceholders(){
|
||||
return this.globalPlaceholders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(){
|
||||
public void register() {
|
||||
if (this.registered()) {
|
||||
throw new IllegalStateException("Expansion" + this.name + "is already registered");
|
||||
}
|
||||
MiniPlaceholders.expansions.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
if (!this.registered()) {
|
||||
throw new IllegalStateException("Expansion " + this.name + " is not registered");
|
||||
}
|
||||
MiniPlaceholders.expansions.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registered() {
|
||||
return MiniPlaceholders.expansions.contains(this);
|
||||
}
|
||||
|
||||
static final class Builder implements Expansion.Builder {
|
||||
private final String expansionName;
|
||||
private Set<Tags.Single> audiencePlaceholders;
|
||||
@@ -115,16 +138,16 @@ final class ExpansionImpl implements Expansion {
|
||||
private Predicate<Audience> predicateFilter;
|
||||
|
||||
Builder(@NotNull final String name){
|
||||
this.expansionName = Conditions.nonNullOrEmptyString(name, () -> "expansion name")
|
||||
this.expansionName = nonNullOrEmptyString(name, "Expansion name")
|
||||
.toLowerCase(Locale.ROOT).concat("_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Builder audiencePlaceholder(@NotNull final String key, @NotNull final AudiencePlaceholder audiencePlaceholder){
|
||||
Conditions.nonNullOrEmptyString(key, () -> "placeholder key");
|
||||
Objects.requireNonNull(audiencePlaceholder, "the audience placeholder cannot be null");
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(audiencePlaceholder, "the audience placeholder cannot be null");
|
||||
|
||||
if (this.audiencePlaceholders == null) this.audiencePlaceholders = new HashSet<>(5);
|
||||
if (this.audiencePlaceholders == null) this.audiencePlaceholders = new HashSet<>();
|
||||
|
||||
this.audiencePlaceholders.add(Tags.single(expansionName+key, audiencePlaceholder));
|
||||
return this;
|
||||
@@ -132,10 +155,10 @@ final class ExpansionImpl implements Expansion {
|
||||
|
||||
@Override
|
||||
public @NotNull Builder relationalPlaceholder(@NotNull final String key, @NotNull final RelationalPlaceholder relationalPlaceholder){
|
||||
Conditions.nonNullOrEmptyString(key, () -> "placeholder key");
|
||||
Objects.requireNonNull(relationalPlaceholder, "the relational placeholder cannot be null");
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(relationalPlaceholder, "the relational placeholder cannot be null");
|
||||
|
||||
if (this.relationalPlaceholders == null) this.relationalPlaceholders = new HashSet<>(4);
|
||||
if (this.relationalPlaceholders == null) this.relationalPlaceholders = new HashSet<>();
|
||||
|
||||
this.relationalPlaceholders.add(Tags.relational(expansionName+"rel_"+key, relationalPlaceholder));
|
||||
return this;
|
||||
@@ -143,10 +166,10 @@ final class ExpansionImpl implements Expansion {
|
||||
|
||||
@Override
|
||||
public @NotNull Builder globalPlaceholder(@NotNull final String key, @NotNull final BiFunction<ArgumentQueue, Context, Tag> function){
|
||||
Conditions.nonNullOrEmptyString(key, () -> "placeholder key");
|
||||
Objects.requireNonNull(function, "the global placeholder cannot be null");
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(function, "the global placeholder cannot be null");
|
||||
|
||||
if(this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
|
||||
if (this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
|
||||
|
||||
this.globalPlaceholders.tag(expansionName+key, function);
|
||||
return this;
|
||||
@@ -154,10 +177,10 @@ final class ExpansionImpl implements Expansion {
|
||||
|
||||
@Override
|
||||
public @NotNull Builder globalPlaceholder(@NotNull final String key, @NotNull final Tag tag){
|
||||
Conditions.nonNullOrEmptyString(key, () -> "placeholder key");
|
||||
Objects.requireNonNull(tag, "the tag cannot be null");
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(tag, "the tag cannot be null");
|
||||
|
||||
if(this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
|
||||
if (this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
|
||||
|
||||
this.globalPlaceholders.tag(expansionName+key, tag);
|
||||
return this;
|
||||
@@ -181,7 +204,7 @@ final class ExpansionImpl implements Expansion {
|
||||
this.expansionName,
|
||||
this.audiencePlaceholders,
|
||||
this.relationalPlaceholders,
|
||||
this.globalPlaceholders != null ? this.globalPlaceholders.build() : null,
|
||||
this.globalPlaceholders != null ? this.globalPlaceholders.build() : TagResolver.empty(),
|
||||
this.filterClass,
|
||||
this.predicateFilter
|
||||
);
|
||||
@@ -189,10 +212,11 @@ final class ExpansionImpl implements Expansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if (this==o) return true;
|
||||
if (o == null || o.getClass() != ExpansionImpl.class) return false;
|
||||
return ((ExpansionImpl)o).name.equals(this.name);
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Expansion that)) return false;
|
||||
|
||||
return that.name().equalsIgnoreCase(this.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package io.github.miniplaceholders.api;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import io.github.miniplaceholders.api.enums.Platform;
|
||||
import io.github.miniplaceholders.api.utils.Resolvers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static io.github.miniplaceholders.api.utils.Resolvers.applyIfNotEmpty;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
@@ -27,8 +27,8 @@ import static java.util.Objects.requireNonNull;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class MiniPlaceholders {
|
||||
private MiniPlaceholders(){}
|
||||
static final Set<Expansion> expansions = Collections.synchronizedSet(new HashSet<>());
|
||||
private MiniPlaceholders() {}
|
||||
static final Set<Expansion> expansions = ConcurrentHashMap.newKeySet();
|
||||
|
||||
/**
|
||||
* Get the platform
|
||||
@@ -36,11 +36,13 @@ public final class MiniPlaceholders {
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static @NotNull Platform getPlatform() {
|
||||
switch (InternalPlatform.platform()) {
|
||||
case PAPER: return Platform.PAPER;
|
||||
case VELOCITY: return Platform.VELOCITY;
|
||||
default: return Platform.KRYPTON;
|
||||
}
|
||||
return switch (InternalPlatform.platform()) {
|
||||
case PAPER -> Platform.PAPER;
|
||||
case VELOCITY -> Platform.VELOCITY;
|
||||
case KRYPTON -> Platform.KRYPTON;
|
||||
case FABRIC -> Platform.FABRIC;
|
||||
case SPONGE -> Platform.SPONGE;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +51,7 @@ public final class MiniPlaceholders {
|
||||
* <pre>TagResolver resolver = MiniPlaceholders.getGlobalPlaceholders();
|
||||
* Component messageParsed = MiniMessage.miniMessage().deserialize({@link String}, resolver);</pre>
|
||||
*
|
||||
* @return global placeholders independient of any audience
|
||||
* @return global placeholders independent of any audience
|
||||
* @see TagResolver
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@@ -79,8 +81,7 @@ public final class MiniPlaceholders {
|
||||
final TagResolver.Builder resolvers = TagResolver.builder();
|
||||
for (Expansion expansion : expansions) {
|
||||
final TagResolver resolver = expansion.audiencePlaceholders(audience);
|
||||
if (resolver != TagResolver.empty())
|
||||
resolvers.resolver(resolver);
|
||||
applyIfNotEmpty(resolver, resolvers);
|
||||
}
|
||||
return resolvers.build();
|
||||
}
|
||||
@@ -102,7 +103,7 @@ public final class MiniPlaceholders {
|
||||
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
Resolvers.applyIfNotEmpty(
|
||||
applyIfNotEmpty(
|
||||
expansion.relationalPlaceholders(audience, otherAudience),
|
||||
builder
|
||||
);
|
||||
@@ -134,8 +135,8 @@ public final class MiniPlaceholders {
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
|
||||
for (final Expansion expansion : expansions) {
|
||||
Resolvers.applyIfNotEmpty(expansion.audiencePlaceholders(audience), builder);
|
||||
Resolvers.applyIfNotEmpty(expansion.globalPlaceholders(), builder);
|
||||
applyIfNotEmpty(expansion.audiencePlaceholders(audience), builder);
|
||||
applyIfNotEmpty(expansion.globalPlaceholders(), builder);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
@@ -168,9 +169,9 @@ public final class MiniPlaceholders {
|
||||
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
Resolvers.applyIfNotEmpty(expansion.audiencePlaceholders(audience), builder);
|
||||
Resolvers.applyIfNotEmpty(expansion.relationalPlaceholders(audience, otherAudience), builder);
|
||||
Resolvers.applyIfNotEmpty(expansion.globalPlaceholders(), builder);
|
||||
applyIfNotEmpty(expansion.audiencePlaceholders(audience), builder);
|
||||
applyIfNotEmpty(expansion.relationalPlaceholders(audience, otherAudience), builder);
|
||||
applyIfNotEmpty(expansion.globalPlaceholders(), builder);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
@@ -184,4 +185,27 @@ public final class MiniPlaceholders {
|
||||
public static int getExpansionCount(){
|
||||
return expansions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific expansion by name
|
||||
* <p>The name of each expansion is set when the expansion is created</p>
|
||||
* <pre>
|
||||
* Expansion expansion = Expansion.builder("example").build();
|
||||
* expansion.register();
|
||||
*
|
||||
* assertThat(MiniPlaceholders.getExpansionByName("example")).isNotNull();
|
||||
* </pre>
|
||||
* @param name the name of the required expansion
|
||||
* @return the required expansion, if not present, will return null
|
||||
* @see Expansion#builder(String)
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public static @Nullable Expansion getExpansionByName(final @NotNull String name) {
|
||||
for (final Expansion expansion : expansions) {
|
||||
if (Objects.equals(expansion.name(), name)) {
|
||||
return expansion;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
|
||||
final class Tags {
|
||||
private Tags(){}
|
||||
private Tags() {}
|
||||
|
||||
static Relational relational(@NotNull final String name, @NotNull final RelationalPlaceholder relationalPlaceholder){
|
||||
return new Tags.Relational(name, relationalPlaceholder);
|
||||
@@ -35,7 +35,7 @@ final class Tags {
|
||||
}
|
||||
|
||||
TagResolver of(@NotNull final Audience audience, @NotNull final Audience otherAudience){
|
||||
return new TagResolver(){
|
||||
return new TagResolver() {
|
||||
@Override
|
||||
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments,
|
||||
@NotNull Context ctx) throws ParsingException {
|
||||
@@ -53,10 +53,10 @@ final class Tags {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if(o == this) return true;
|
||||
if(!(o instanceof Relational)) return false;
|
||||
return ((Relational)o).key.equals(this.key);
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof final Relational that)) return false;
|
||||
return that.key.equalsIgnoreCase(this.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,10 +93,10 @@ final class Tags {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if(o == this) return true;
|
||||
if(!(o instanceof Single)) return false;
|
||||
return ((Single)o).key.equals(this.key);
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof final Single that)) return false;
|
||||
return that.key.equalsIgnoreCase(this.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,5 +7,9 @@ public enum Platform {
|
||||
/**Velocity Platform */
|
||||
VELOCITY,
|
||||
/**Krypton Platform */
|
||||
KRYPTON
|
||||
KRYPTON,
|
||||
/**Fabric Platform */
|
||||
FABRIC,
|
||||
/**Sponge Platform */
|
||||
SPONGE
|
||||
}
|
||||
@@ -1,36 +1,73 @@
|
||||
package io.github.miniplaceholders.api.utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Checks required for the correct operation of the expansions*/
|
||||
public final class Conditions {
|
||||
private Conditions(){}
|
||||
private Conditions() {}
|
||||
|
||||
/**
|
||||
* Checks if a string is null or empty or consists of whitespace characters only
|
||||
* Checks if a string is null or empty or consists of whitespace characters only.
|
||||
*
|
||||
* @param string the string
|
||||
* @param name the name supplier
|
||||
* @return the string if it is not null or empty
|
||||
* @since 1.0.0
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
*/
|
||||
public static String nonNullOrEmptyString(String string, Supplier<String> name){
|
||||
public static String nonNullOrEmptyString(@Nullable String string, @NotNull Supplier<@NotNull String> name){
|
||||
if (string == null)
|
||||
throw new NullPointerException("the " + name.get() + " cannot be null");
|
||||
throw new NullPointerException(name.get() + " cannot be null");
|
||||
if (string.isBlank())
|
||||
throw new IllegalStateException("the " + name.get() + "cannot be an empty string");
|
||||
throw new IllegalStateException(name.get() + "cannot be an empty string");
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is empty or consists of whitespace characters only
|
||||
* Checks if a string is null or empty or consists of whitespace characters only.
|
||||
*
|
||||
* @param string the string
|
||||
* @param name the name
|
||||
* @return the string if it is not null or empty
|
||||
* @since 2.2.0
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
*/
|
||||
public static String nonNullOrEmptyString(@Nullable String string, @NotNull String name){
|
||||
if (string == null)
|
||||
throw new NullPointerException(name + " cannot be null");
|
||||
if (string.isBlank())
|
||||
throw new IllegalStateException(name + "cannot be an empty string");
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is empty or consists of whitespace characters only.
|
||||
*
|
||||
* @param string the string
|
||||
* @param reason the reason supplier
|
||||
* @return the string if it not empty
|
||||
* @since 1.0.0
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
*/
|
||||
public static String nonEmptyString(String string, Supplier<String> reason){
|
||||
if (string.isBlank())
|
||||
throw new IllegalStateException(reason.get());
|
||||
public static String nonEmptyString(@NotNull String string, @NotNull Supplier<@NotNull String> reason){
|
||||
if (string.isBlank()) throw new IllegalStateException(reason.get());
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is empty or consists of whitespace characters only.
|
||||
*
|
||||
* @param string the string
|
||||
* @param reason the reason
|
||||
* @return the string if it not empty
|
||||
* @since 2.2.0
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
*/
|
||||
public static String nonEmptyString(@NotNull String string, @NotNull String reason){
|
||||
if (string.isBlank()) throw new IllegalStateException(reason);
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.github.miniplaceholders.api.utils;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -25,20 +27,89 @@ public final class LegacyUtils {
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Parse a string with possible legacy symbols
|
||||
* Parse a string with possible legacy Ampersand/Section symbols
|
||||
* <br>
|
||||
* <p><b>
|
||||
* This method should only be used in case a String is provided from a legacy plugin/mod
|
||||
* or legacy source, where it is very likely to get a legacy string.
|
||||
* It is not recommended to use this method regularly in any sense
|
||||
* </b></p>
|
||||
*
|
||||
* @param string the string
|
||||
* @return a parsed string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static @NotNull Component parsePossibleLegacy(@Nullable String string) {
|
||||
if (string == null || string.isBlank()) return Component.empty();
|
||||
if (string.indexOf('&') != 0) {
|
||||
return miniMessage().deserialize(
|
||||
miniMessage().serialize(LEGACY_HEX_SERIALIZER.deserialize(string))
|
||||
);
|
||||
} else {
|
||||
if (string == null || string.isEmpty()) return Component.empty();
|
||||
if (string.indexOf(LegacyComponentSerializer.SECTION_CHAR) != -1) {
|
||||
string = string.replace(LegacyComponentSerializer.SECTION_CHAR, LegacyComponentSerializer.AMPERSAND_CHAR);
|
||||
}
|
||||
if (string.indexOf(LegacyComponentSerializer.AMPERSAND_CHAR) == -1) {
|
||||
return miniMessage().deserialize(string);
|
||||
}
|
||||
return miniMessage().deserialize(
|
||||
miniMessage().serialize(LEGACY_HEX_SERIALIZER.deserialize(string))
|
||||
.replace("\\<", "<")
|
||||
.replace("\\>", ">")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string with possible legacy Ampersand/Section symbols
|
||||
* using a parsing Context
|
||||
* <p><b>
|
||||
* This method should only be used in case a String is provided from a legacy plugin/mod
|
||||
* or legacy source, where it is very likely to get a legacy string.
|
||||
* It is not recommended to use this method regularly in any sense
|
||||
* </b></p>
|
||||
*
|
||||
* @param string the string
|
||||
* @param context the provided parsing context
|
||||
* @return a parsed string
|
||||
* @since 2.2.1
|
||||
*/
|
||||
public static @NotNull Component parsePossibleLegacy(@Nullable String string, @NotNull final Context context) {
|
||||
if (string == null || string.isEmpty()) return Component.empty();
|
||||
if (string.indexOf(LegacyComponentSerializer.SECTION_CHAR) != -1) {
|
||||
string = string.replace(LegacyComponentSerializer.SECTION_CHAR, LegacyComponentSerializer.AMPERSAND_CHAR);
|
||||
}
|
||||
if (string.indexOf(LegacyComponentSerializer.AMPERSAND_CHAR) == -1) {
|
||||
return context.deserialize(string);
|
||||
}
|
||||
return context.deserialize(
|
||||
miniMessage().serialize(LEGACY_HEX_SERIALIZER.deserialize(string))
|
||||
.replace("\\<", "<")
|
||||
.replace("\\>", ">")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string with possible legacy Ampersand/Section symbols
|
||||
* using the provided resolver
|
||||
* <p><b>
|
||||
* This method should only be used in case a String is provided from a legacy plugin/mod
|
||||
* or legacy source, where it is very likely to get a legacy string.
|
||||
* It is not recommended to use this method regularly in any sense
|
||||
* </b></p>
|
||||
*
|
||||
* @param string the string
|
||||
* @param resolver a resolver
|
||||
* @return a parsed string
|
||||
* @since 2.2.1
|
||||
*/
|
||||
public static @NotNull Component parsePossibleLegacy(@Nullable String string, @NotNull final TagResolver resolver) {
|
||||
if (string == null || string.isEmpty()) return Component.empty();
|
||||
if (string.indexOf(LegacyComponentSerializer.SECTION_CHAR) != -1) {
|
||||
string = string.replace(LegacyComponentSerializer.SECTION_CHAR, LegacyComponentSerializer.AMPERSAND_CHAR);
|
||||
}
|
||||
if (string.indexOf(LegacyComponentSerializer.AMPERSAND_CHAR) == -1) {
|
||||
return miniMessage().deserialize(string, resolver);
|
||||
}
|
||||
return miniMessage().deserialize(
|
||||
miniMessage().serialize(LEGACY_HEX_SERIALIZER.deserialize(string))
|
||||
.replace("\\<", "<")
|
||||
.replace("\\>", ">"),
|
||||
resolver
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
/** MiniPlaceholders API Module */
|
||||
open module io.github.miniplaceholders.api {
|
||||
requires io.github.miniplaceholders.connect;
|
||||
|
||||
requires net.kyori.adventure;
|
||||
requires net.kyori.adventure.text.minimessage;
|
||||
requires net.kyori.examination.api;
|
||||
requires static org.jetbrains.annotations;
|
||||
requires io.github.miniplaceholders.connect;
|
||||
requires net.kyori.adventure.text.serializer.legacy;
|
||||
requires net.kyori.examination.api;
|
||||
|
||||
requires static org.jetbrains.annotations;
|
||||
|
||||
exports io.github.miniplaceholders.api;
|
||||
exports io.github.miniplaceholders.api.enums;
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
import io.github.miniplaceholders.test.testobjects.TestAudienceHolder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static io.github.miniplaceholders.test.PlaceholderTest.assertContentEquals;
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ExpansionsTest {
|
||||
@Test
|
||||
@@ -21,4 +26,20 @@ class ExpansionsTest {
|
||||
|
||||
assertEquals(firstExpansion, secondExpansion);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullForwardedAudience() {
|
||||
TestAudienceHolder audience = new TestAudienceHolder(null);
|
||||
|
||||
final Expansion expansion = Expansion.builder("test")
|
||||
.filter(aud -> aud.toString().isBlank())
|
||||
.audiencePlaceholder("testing", (aud, queue, ctx) -> Tag.selfClosingInserting(Component.text(aud.toString())))
|
||||
.build();
|
||||
|
||||
Component result = assertDoesNotThrow(
|
||||
() -> miniMessage().deserialize("<test_testing>", expansion.audiencePlaceholders(audience))
|
||||
);
|
||||
|
||||
assertContentEquals(result, Component.text("<test_testing>"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import io.github.miniplaceholders.api.utils.LegacyUtils;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class LegacyTest {
|
||||
@Test
|
||||
void testLegacyParsing() {
|
||||
final String string = "<rainbow>hello... i &8hate legacy format §bso much";
|
||||
final Component parsed = LegacyUtils.parsePossibleLegacy(string);
|
||||
final String result = PlainTextComponentSerializer.plainText().serialize(parsed);
|
||||
final String expected = "hello... i hate legacy format so much";
|
||||
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -11,6 +9,8 @@ import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MiniPlaceholdersTest {
|
||||
@Test
|
||||
@Disabled("Cannot correctly calculate the equity of 2 TagResolvers obtained in different ways")
|
||||
@@ -30,4 +30,16 @@ class MiniPlaceholdersTest {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registrationTest() {
|
||||
Expansion expansion = Expansion.builder("testregistration")
|
||||
.build();
|
||||
expansion.register();
|
||||
|
||||
assertTrue(expansion.registered());
|
||||
assertThrows(IllegalStateException.class, expansion::register);
|
||||
|
||||
assertDoesNotThrow(expansion::unregister);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import io.github.miniplaceholders.test.testobjects.TestAudience;
|
||||
import io.github.miniplaceholders.test.testobjects.TestAudienceHolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
@@ -23,12 +25,15 @@ class PlaceholderTest {
|
||||
TestAudience player = new TestAudience("4drian3d");
|
||||
|
||||
Expansion expansion = Expansion.builder("example")
|
||||
.audiencePlaceholder("name", (aud, queue, ctx) -> Tag.selfClosingInserting(Component.text(((TestAudience)aud).name()))).build();
|
||||
.audiencePlaceholder("name", (aud, queue, ctx) -> {
|
||||
TestAudience audience = (TestAudience) aud;
|
||||
return Tag.selfClosingInserting(Component.text(audience.name()));
|
||||
}).build();
|
||||
|
||||
final Component expected = Component.text("Player Name: 4drian3d");
|
||||
final Component result = MiniMessage.miniMessage().deserialize("Player Name: <example_name>", expansion.audiencePlaceholders(player));
|
||||
final Component result = miniMessage().deserialize("Player Name: <example_name>", expansion.audiencePlaceholders(player));
|
||||
|
||||
assertEquals(expected, result);
|
||||
assertContentEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -59,7 +64,7 @@ class PlaceholderTest {
|
||||
final Component expected = Component.text("Online players: 1305 | Servers: 7");
|
||||
final Component actual = MiniMessage.miniMessage().deserialize("Online players: <global_players> | Servers: <global_servers>", expansion.globalPlaceholders());
|
||||
|
||||
assertEquals(expected, actual);
|
||||
assertContentEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,13 +97,50 @@ class PlaceholderTest {
|
||||
Component playerExpected = Component.text("Player Name: TestPlayer04");
|
||||
Component emptyExpected = Component.text("Player Name: <filter_name>");
|
||||
|
||||
assertEquals(playerExpected, MiniMessage.miniMessage().deserialize(string, expansion.audiencePlaceholders(player)));
|
||||
assertEquals(emptyExpected, MiniMessage.miniMessage().deserialize(string, expansion.audiencePlaceholders(emptyAudience)));
|
||||
|
||||
|
||||
assertContentEquals(playerExpected, MiniMessage.miniMessage().deserialize(string, expansion.audiencePlaceholders(player)));
|
||||
assertContentEquals(emptyExpected, MiniMessage.miniMessage().deserialize(string, expansion.audiencePlaceholders(emptyAudience)));
|
||||
}
|
||||
|
||||
void assertContentEquals(Component first, Component second){
|
||||
@Test
|
||||
@DisplayName("Empty Arguments")
|
||||
void testEmptyArguments() {
|
||||
final Expansion expansion = Expansion.builder("test")
|
||||
.globalPlaceholder("testing", (queue, ctx) -> {
|
||||
int arguments = 0;
|
||||
while (queue.hasNext()) {
|
||||
arguments++;
|
||||
Tag.Argument argument = queue.pop();
|
||||
assertTrue(argument.value().isBlank());
|
||||
}
|
||||
return Tag.selfClosingInserting(Component.text("Arguments: "+arguments));
|
||||
})
|
||||
.build();
|
||||
|
||||
Component parsed = miniMessage().deserialize("<test_testing::>", expansion.globalPlaceholders());
|
||||
|
||||
assertContentEquals(parsed, Component.text("Arguments: 2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Forwarding Audience Parsing Test")
|
||||
void forwardingAudienceTest() {
|
||||
Expansion expansion = Expansion.builder("test")
|
||||
.filter(TestAudience.class)
|
||||
.audiencePlaceholder("testing", (audience, queue, ctx) -> {
|
||||
TestAudience testAudience = (TestAudience) audience;
|
||||
return Tag.selfClosingInserting(Component.text("Name: "+testAudience.name()));
|
||||
}).build();
|
||||
|
||||
TestAudience testAudience = new TestAudience("4drian3d");
|
||||
Audience forward = new TestAudienceHolder(testAudience);
|
||||
|
||||
Component parsed = miniMessage().deserialize("<test_testing>.", expansion.audiencePlaceholders(forward));
|
||||
Component expected = Component.text("Name: 4drian3d.");
|
||||
|
||||
assertContentEquals(parsed, expected);
|
||||
}
|
||||
|
||||
static void assertContentEquals(Component first, Component second){
|
||||
String firstSerialized = PlainTextComponentSerializer.plainText().serialize(first);
|
||||
String secondSerialized = PlainTextComponentSerializer.plainText().serialize(second);
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.github.miniplaceholders.test.testobjects;
|
||||
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record TestAudienceHolder(TestAudience audience) implements ForwardingAudience.Single {
|
||||
@Override
|
||||
public @NotNull TestAudience audience() {
|
||||
return audience;
|
||||
}
|
||||
}
|
||||
@@ -12,4 +12,8 @@ dependencyResolutionManagement {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.configurationcache.extensions.capitalized
|
||||
|
||||
val Project.capitalizeName: String
|
||||
get() = this.name.substring(17).capitalized()
|
||||
|
||||
fun Project.simpleName(): String = this.name.substring(17)
|
||||
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id("miniplaceholders.base")
|
||||
}
|
||||
|
||||
tasks {
|
||||
jar {
|
||||
manifest {
|
||||
attributes("Automatic-Module-Name" to "io.github.miniplaceholders.${project.simpleName()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import java.util.Date
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
"Specification-Version" to project.version,
|
||||
"Specification-Vendor" to "MiniPlaceholders",
|
||||
"Implementation-Build-Date" to Date()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java{
|
||||
toolchain{
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
vendor.set(JvmVendorSpec.ADOPTIUM)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id("miniplaceholders.base")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveBaseName.set("MiniPlaceholders-${project.capitalizeName}")
|
||||
archiveClassifier.set("")
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
relocate("net.william278.desertwell", "io.github.miniplaceholders.libs.desertwell")
|
||||
relocate("cloud.commandframework", "io.github.miniplaceholders.libs.cloud")
|
||||
if (project.simpleName() != "sponge") {
|
||||
relocate("io.leangen.geantyref", "io.github.miniplaceholders.libs.geantyref")
|
||||
}
|
||||
destinationDirectory.set(file("${project.rootDir}/jar"))
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
+3
-27
@@ -1,33 +1,9 @@
|
||||
plugins {
|
||||
java
|
||||
alias(libs.plugins.shadow)
|
||||
kotlin("jvm") version "1.8.10" apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply<JavaPlugin>()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.miniplaceholdersVelocity)
|
||||
implementation(project(":miniplaceholders-paper", "reobf"))
|
||||
implementation(projects.miniplaceholdersKrypton)
|
||||
}
|
||||
|
||||
subprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://papermc.io/repo/repository/maven-public/")
|
||||
maven("https://repo.maven.apache.org/maven2/")
|
||||
}
|
||||
kotlin("jvm") version "1.9.20" apply false
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveFileName.set("MiniPlaceholders-${project.version}.jar")
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
delete {
|
||||
delete("jar")
|
||||
}
|
||||
}
|
||||
+15
-24
@@ -1,37 +1,28 @@
|
||||
plugins {
|
||||
id("miniplaceholders.auto.module")
|
||||
alias(libs.plugins.idea.ext)
|
||||
alias(libs.plugins.blossom)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://libraries.minecraft.net") {
|
||||
mavenContent {
|
||||
includeGroup("com.mojang")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(libs.desertwell) {
|
||||
exclude("org.json")
|
||||
}
|
||||
implementation(libs.cloud.core)
|
||||
implementation(libs.cloud.extras) {
|
||||
isTransitive = false
|
||||
}
|
||||
compileOnly(libs.adventure.api)
|
||||
compileOnly(libs.adventure.minimesssage)
|
||||
compileOnly(libs.brigadier)
|
||||
}
|
||||
|
||||
blossom{
|
||||
replaceToken("{version}", project.version)
|
||||
replaceTokenIn("src/main/java/io/github/miniplaceholders/common/PluginConstants.java")
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes("Automatic-Module-Name" to "io.github.miniplaceholders.common")
|
||||
sourceSets {
|
||||
main {
|
||||
blossom {
|
||||
javaSources {
|
||||
property("version", project.version.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package io.github.miniplaceholders.common;
|
||||
|
||||
public final class PluginConstants {
|
||||
public static final String VERSION = "{{ version }}";
|
||||
|
||||
private PluginConstants() {}
|
||||
}
|
||||
@@ -1,175 +1,198 @@
|
||||
package io.github.miniplaceholders.common;
|
||||
|
||||
import java.util.Collection;
|
||||
import cloud.commandframework.ArgumentDescription;
|
||||
import cloud.commandframework.Command;
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.standard.StringArgument;
|
||||
import cloud.commandframework.minecraft.extras.AudienceProvider;
|
||||
import cloud.commandframework.minecraft.extras.MinecraftExceptionHandler;
|
||||
import io.github.miniplaceholders.api.MiniPlaceholders;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.builder.AbstractBuilder;
|
||||
import net.kyori.adventure.permission.PermissionChecker;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import net.kyori.adventure.util.TriState;
|
||||
import net.william278.desertwell.about.AboutMenu;
|
||||
import net.william278.desertwell.util.Version;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.MiniPlaceholders;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.permission.PermissionChecker;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static net.kyori.adventure.text.Component.newline;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
|
||||
public class PlaceholdersCommand<A> {
|
||||
private final @NotNull Supplier<@NotNull Collection<@NotNull String>> playersSuggestions;
|
||||
private final @NotNull Function<@NotNull String, @Nullable Audience> toAudience;
|
||||
private Function<A, Audience> fromAToAudience = a -> Audience.empty();
|
||||
private BiPredicate<A, String> hasPermission = null;
|
||||
private final Expansion commandExpansion = Expansion.builder("placeholders")
|
||||
.globalPlaceholder("count", (queue, ctx) -> Tag.selfClosingInserting(Component.text(MiniPlaceholders.getExpansionCount())))
|
||||
.globalPlaceholder("version", (queue, ctx) -> Tag.selfClosingInserting(Component.text(PluginConstants.VERSION)))
|
||||
.build();
|
||||
public final class PlaceholdersCommand<A extends Audience> {
|
||||
private final Supplier<ArrayList<String>> playersSuggestions;
|
||||
private final Function<String, Audience> toAudience;
|
||||
private final BiPredicate<A, String> hasPermission;
|
||||
private final String command;
|
||||
private final CommandManager<A> commandManager;
|
||||
|
||||
public PlaceholdersCommand(
|
||||
@NotNull Supplier<Collection<String>> playersSuggestions,
|
||||
@NotNull Function<@NotNull String,
|
||||
@Nullable Audience> toAudience
|
||||
private PlaceholdersCommand(
|
||||
final Supplier<ArrayList<String>> playersSuggestions,
|
||||
final Function<String, Audience> toAudience,
|
||||
final BiPredicate<A, String> hasPermission,
|
||||
final String command,
|
||||
final CommandManager<A> commandManager
|
||||
) {
|
||||
this.playersSuggestions = playersSuggestions;
|
||||
this.toAudience = toAudience;
|
||||
}
|
||||
|
||||
public PlaceholdersCommand(
|
||||
Supplier<Collection<String>> playersSuggestions,
|
||||
Function<@NotNull String, @Nullable Audience> toAudience,
|
||||
Function<A, Audience> fromAToAudience
|
||||
) {
|
||||
this(playersSuggestions, toAudience);
|
||||
this.fromAToAudience = fromAToAudience;
|
||||
}
|
||||
|
||||
public PlaceholdersCommand(
|
||||
Supplier<Collection<String>> playersSuggestions,
|
||||
Function<@NotNull String, @Nullable Audience> toAudience,
|
||||
Function<A, Audience> fromAToAudience,
|
||||
BiPredicate<A, String> hasPermission
|
||||
) {
|
||||
this(playersSuggestions, toAudience, fromAToAudience);
|
||||
this.hasPermission = hasPermission;
|
||||
this.command = command;
|
||||
this.commandManager = commandManager;
|
||||
}
|
||||
|
||||
private static final Component HEADER = miniMessage().deserialize("<gradient:aqua:white:aqua>---------- <gradient:#4d8bff:#a4ff96>MiniPlaceholders</gradient> -----------</gradient>");
|
||||
private static final Component FOOTER = miniMessage().deserialize("<gradient:aqua:white:aqua> --------------- ---------------</gradient>");
|
||||
private static final Component TITLE = miniMessage().deserialize("<gradient:#4d8bff:#a4ff96>MiniPlaceholders</gradient>");
|
||||
private static final Component HELP = text()
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:aqua:white:aqua><st><b> </st> <title> <st><b> </st>", Placeholder.component("title", TITLE)))
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:#9694ff:#5269ff>Commands:</gradient>"))
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:aqua:#94d1ff>/miniplaceholders</gradient> <aqua>help</aqua>"))
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:aqua:#94d1ff>/miniplaceholders</gradient> <aqua>parse</aqua> <#8fadff><player | me></#8fadff> <#99ffb6><player></#99ffb6>"))
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:aqua:white:aqua><st><b> "))
|
||||
.build();
|
||||
|
||||
public LiteralArgumentBuilder<A> placeholderTestBuilder(String commandName){
|
||||
return LiteralArgumentBuilder.<A>literal(commandName)
|
||||
.requires(a -> getAudience(a).pointers().supports(PermissionChecker.POINTER))
|
||||
.executes(cmd -> {
|
||||
Audience source = getAudience(cmd.getSource());
|
||||
if (hasPermission(cmd.getSource(), "miniplaceholders.command")) {
|
||||
source.sendMessage(
|
||||
Component.text()
|
||||
.append(HEADER).append(Component.newline())
|
||||
.append(miniMessage().deserialize("<gradient:aqua:#918fff>Placeholders Available:</gradient> <aqua><placeholders_count></aqua>", commandExpansion.globalPlaceholders())).append(Component.newline())
|
||||
.append(FOOTER)
|
||||
.build()
|
||||
);
|
||||
} else {
|
||||
source.sendMessage(
|
||||
Component.text()
|
||||
.append(HEADER).append(Component.newline())
|
||||
.append(miniMessage().deserialize("<gradient:red:dark_red>Version: <placeholders_version>", commandExpansion.globalPlaceholders())).append(Component.newline())
|
||||
.append(FOOTER)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
})
|
||||
.then(LiteralArgumentBuilder.<A>literal("help")
|
||||
.requires(src -> hasPermission(src, "miniplaceholders.command.help"))
|
||||
.executes(cmd -> {
|
||||
getAudience(cmd.getSource()).sendMessage(
|
||||
Component.text()
|
||||
.append(HEADER).append(Component.newline())
|
||||
.append(miniMessage().deserialize("<gradient:#9694ff:#5269ff>Commands:</gradient>")).append(Component.newline())
|
||||
.append(miniMessage().deserialize("<gradient:aqua:#94d1ff>/miniplaceholders</gradient> <aqua>help</aqua>")).append(Component.newline())
|
||||
.append(miniMessage().deserialize("<gradient:aqua:#94d1ff>/miniplaceholders</gradient> <aqua>parse</aqua> <color:#8fadff><player:me></color> <color:#99ffb6><player></color>")).append(Component.newline())
|
||||
.append(FOOTER)
|
||||
.build()
|
||||
);
|
||||
return 1;
|
||||
private static final Component INFO = AboutMenu.builder()
|
||||
.title(TITLE)
|
||||
.description(text("MiniMessage Component-based Placeholders for Paper, Folia, Fabric, Velocity, Sponge and Krypton platforms"))
|
||||
.credits("Author", AboutMenu.Credit.of("4drian3d").url("https://github.com/4drian3d"))
|
||||
.credits("Contributors", AboutMenu.Credit.of("Sliman4"))
|
||||
.buttons(
|
||||
AboutMenu.Link.of("https://github.com/MiniPlaceholders/MiniPlaceholders/wiki/User-Getting-Started").text("Documentation").icon("⛏"),
|
||||
AboutMenu.Link.of("https://discord.gg/5NMMzK5mAn").text("Discord").color(TextColor.color(0x7289da)).icon("⭐"),
|
||||
AboutMenu.Link.of("https://modrinth.com/plugin/miniplaceholders").text("Downloads").color(TextColor.color(0xff496e)).icon("↓")
|
||||
).version(Version.fromString(PluginConstants.VERSION))
|
||||
.build()
|
||||
.toComponent();
|
||||
|
||||
private Command.Builder<A> rootBuilder() {
|
||||
return commandManager.commandBuilder(command);
|
||||
}
|
||||
|
||||
public void register() {
|
||||
new MinecraftExceptionHandler<A>()
|
||||
.withDefaultHandlers()
|
||||
.withDecorator(component -> Component.text().append(TITLE).appendSpace().append(component).build())
|
||||
.apply(commandManager, AudienceProvider.nativeAudience());
|
||||
|
||||
commandManager.command(rootBuilder()
|
||||
.permission(src -> {
|
||||
if (hasPermission != null) {
|
||||
return hasPermission.test(src, "miniplaceholders.command");
|
||||
}
|
||||
return src
|
||||
.get(PermissionChecker.POINTER)
|
||||
.map(checker -> checker.value("miniplaceholders.command"))
|
||||
.orElse(TriState.FALSE) != TriState.FALSE;
|
||||
})
|
||||
)
|
||||
.then(LiteralArgumentBuilder.<A>literal("parse")
|
||||
.requires(cmd -> hasPermission(cmd, "miniplaceholders.command.parse"))
|
||||
.then(LiteralArgumentBuilder.<A>literal("me")
|
||||
.then(RequiredArgumentBuilder.<A, String>argument("string", StringArgumentType.string())
|
||||
.executes(cmd -> {
|
||||
String stringToParse = cmd.getArgument("string", String.class);
|
||||
Component parsed = this.parseGlobal(stringToParse, getAudience(cmd.getSource()));
|
||||
getAudience(cmd.getSource()).sendMessage(parsed);
|
||||
return 1;
|
||||
.handler(handler -> handler.getSender().sendMessage(INFO)));
|
||||
final CommandArgument<A, String> sourceArgument = StringArgument.<A>builder("source")
|
||||
.single()
|
||||
.withDefaultDescription(ArgumentDescription.of("The source from which the message will be parsed"))
|
||||
.withSuggestionsProvider((ctx, st) -> {
|
||||
final List<String> suggestions = playersSuggestions.get();
|
||||
suggestions.add("me");
|
||||
return suggestions;
|
||||
})
|
||||
.build();
|
||||
final CommandArgument<A, String> stringArgument = StringArgument.<A>builder("message")
|
||||
.greedy()
|
||||
.withDefaultDescription(ArgumentDescription.of("Message to be parsed"))
|
||||
.build();
|
||||
|
||||
commandManager.command(
|
||||
rootBuilder().literal("parse")
|
||||
.argument(sourceArgument)
|
||||
.argument(stringArgument)
|
||||
.permission("miniplaceholders.command.parse")
|
||||
.handler(handler -> {
|
||||
final String source = handler.get(sourceArgument);
|
||||
|
||||
final Audience objective = "me".equals(source)
|
||||
? handler.getSender()
|
||||
: toAudience.apply(source);
|
||||
if (objective == null){
|
||||
handler.getSender().sendMessage(text("You must specify a valid player", RED));
|
||||
return;
|
||||
}
|
||||
final String toParse = handler.get(stringArgument);
|
||||
|
||||
final Component parsed = miniMessage().deserialize(
|
||||
toParse,
|
||||
MiniPlaceholders.getAudienceGlobalPlaceholders(objective)
|
||||
);
|
||||
handler.getSender().sendMessage(parsed);
|
||||
})
|
||||
)
|
||||
)
|
||||
.then(LiteralArgumentBuilder.<A>literal("player")
|
||||
.then(RequiredArgumentBuilder.<A, String>argument("source", StringArgumentType.word())
|
||||
.suggests((argument, builder) -> {
|
||||
playersSuggestions.get().forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
})
|
||||
.then(RequiredArgumentBuilder.<A, String>argument("string", StringArgumentType.string())
|
||||
.executes(cmd -> {
|
||||
Audience objetive = toAudience.apply(cmd.getArgument("source", String.class));
|
||||
if(objetive == null){
|
||||
getAudience(cmd.getSource()).sendMessage(Component.text("You must specify a valid player", NamedTextColor.RED));
|
||||
return 1;
|
||||
}
|
||||
String stringToParse = cmd.getArgument("playerStringToParse", String.class);
|
||||
|
||||
Component parsed = this.parseGlobal(stringToParse, objetive);
|
||||
getAudience(cmd.getSource()).sendMessage(parsed);
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public LiteralCommandNode<A> placeholderTestCommand(String command){
|
||||
return this.placeholderTestBuilder(command).build();
|
||||
}
|
||||
|
||||
private Component parseGlobal(String string, Audience audience){
|
||||
return miniMessage().deserialize(
|
||||
string,
|
||||
TagResolver.resolver(
|
||||
MiniPlaceholders.getGlobalPlaceholders(),
|
||||
MiniPlaceholders.getAudiencePlaceholders(audience)
|
||||
)
|
||||
);
|
||||
commandManager.command(
|
||||
rootBuilder().literal("help")
|
||||
.permission("miniplaceholders.command.help")
|
||||
.handler(handler -> handler.getSender().sendMessage(HELP))
|
||||
);
|
||||
}
|
||||
|
||||
private Audience getAudience(A possibleAudience){
|
||||
if (possibleAudience instanceof Audience audience){
|
||||
return audience;
|
||||
}
|
||||
Audience audience = fromAToAudience.apply(possibleAudience);
|
||||
return audience != null ? audience : Audience.empty();
|
||||
public static <A extends Audience> Builder<A> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
private boolean hasPermission(A source, String permission) {
|
||||
if (hasPermission != null) {
|
||||
return hasPermission.test(source, permission);
|
||||
public final static class Builder<A extends Audience> implements AbstractBuilder<PlaceholdersCommand<A>> {
|
||||
private Supplier<ArrayList<String>> playersSuggestions;
|
||||
private Function<String, Audience> toAudience;
|
||||
private BiPredicate<A, String> hasPermission;
|
||||
private String command;
|
||||
private CommandManager<A> commandManager;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder<A> playerSuggestions(final Supplier<@NotNull ArrayList<@NotNull String>> playersSuggestions) {
|
||||
this.playersSuggestions = playersSuggestions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> toAudience(final @NotNull Function<@NotNull String, @Nullable Audience> argumentToAudience) {
|
||||
this.toAudience = argumentToAudience;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> hasPermissionCheck(final @NotNull BiPredicate<@NotNull A, @NotNull String> hasPermission) {
|
||||
this.hasPermission = hasPermission;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> command(final String command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> manager(CommandManager<A> commandManager) {
|
||||
this.commandManager = commandManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlaceholdersCommand<A> build() {
|
||||
return new PlaceholdersCommand<>(
|
||||
requireNonNull(playersSuggestions),
|
||||
requireNonNull(toAudience),
|
||||
hasPermission,
|
||||
command,
|
||||
commandManager
|
||||
);
|
||||
}
|
||||
return getAudience(source)
|
||||
.get(PermissionChecker.POINTER)
|
||||
.map(checker -> checker.test(permission))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package io.github.miniplaceholders.common;
|
||||
|
||||
public final class PluginConstants {
|
||||
public static final String VERSION = "{version}";
|
||||
|
||||
private PluginConstants(){}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
java.toolchain.languageVersion.set(JavaLanguageVersion.of(11))
|
||||
|
||||
tasks.compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
||||
options.release.set(11)
|
||||
plugins {
|
||||
id("miniplaceholders.base")
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package io.github.miniplaceholders.connect;
|
||||
|
||||
public enum InternalPlatform {
|
||||
|
||||
PAPER, VELOCITY, KRYPTON;
|
||||
PAPER, VELOCITY, KRYPTON, FABRIC, SPONGE;
|
||||
|
||||
private static InternalPlatform actualPlatform;
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/run
|
||||
@@ -0,0 +1,61 @@
|
||||
plugins {
|
||||
id("miniplaceholders.auto.module")
|
||||
id("fabric-loom")
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
val shade: Configuration by configurations.creating
|
||||
|
||||
dependencies {
|
||||
minecraft(libs.minecraft)
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation(libs.fabric.loader)
|
||||
modImplementation(libs.fabric.api)
|
||||
|
||||
includeDependency(libs.adventure.platform.fabric)
|
||||
includeDependency(libs.adventure.serializer.legacy)
|
||||
includeDependency(libs.luckopermissionsapi)
|
||||
includeDependency(libs.cloud.fabric)
|
||||
includeDependency(libs.cloud.core)
|
||||
includeDependency(libs.cloud.extras)
|
||||
includeDependency(libs.desertwell)
|
||||
|
||||
shadeModule(projects.miniplaceholdersApi)
|
||||
shadeModule(projects.miniplaceholdersCommon)
|
||||
shadeModule(projects.miniplaceholdersConnect)
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.shadeModule(module: ProjectDependency) {
|
||||
shade(module) {
|
||||
isTransitive = false
|
||||
}
|
||||
implementation(module) {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.includeDependency(dependency: Any) {
|
||||
modImplementation(dependency)
|
||||
include(dependency)
|
||||
}
|
||||
|
||||
tasks {
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand("version" to project.version)
|
||||
}
|
||||
}
|
||||
remapJar {
|
||||
inputFile.set(shadowJar.get().archiveFile)
|
||||
archiveFileName.set("MiniPlaceholders-Fabric-${project.version}.jar")
|
||||
destinationDirectory.set(file("${project.rootDir}/jar"))
|
||||
}
|
||||
shadowJar {
|
||||
configurations = listOf(shade)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package io.github.miniplaceholders.fabric;
|
||||
|
||||
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.common.PlaceholdersCommand;
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FabricMod implements ModInitializer, PlaceholdersPlugin {
|
||||
private final Logger logger = LoggerFactory.getLogger("miniplaceholders");
|
||||
private static final DecimalFormat MSPT_FORMAT = new DecimalFormat("###.###");
|
||||
|
||||
private final TickManager tickManager = new TickManager();
|
||||
private MinecraftServer minecraftServer;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
logger.info("Starting MiniPlaceholders Fabric");
|
||||
InternalPlatform.platform(InternalPlatform.FABRIC);
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTING.register(minecraftServer -> {
|
||||
this.minecraftServer = minecraftServer;
|
||||
this.loadDefaultExpansions();
|
||||
});
|
||||
|
||||
this.registerPlatformCommand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDefaultExpansions() {
|
||||
Expansion.builder("server")
|
||||
.globalPlaceholder("name", Tag.selfClosingInserting(Component.text(this.minecraftServer.getServerModName())))
|
||||
.globalPlaceholder("online", (queue, ctx) -> Tag.preProcessParsed(Integer.toString(this.minecraftServer.getPlayerCount())))
|
||||
.globalPlaceholder("version", (ctx, queue) -> Tag.selfClosingInserting(Component.text(this.minecraftServer.getServerVersion())))
|
||||
.globalPlaceholder("max_players", (ctx, queue) -> Tag.selfClosingInserting(Component.text(this.minecraftServer.getMaxPlayers())))
|
||||
.globalPlaceholder("unique_joins", (queue, ctx) -> Tag.preProcessParsed(Integer.toString(this.minecraftServer.getProfileCache().load().size())))
|
||||
.globalPlaceholder("tps_1m", (ctx, queue) -> Tag.preProcessParsed(tickManager.getTps1m().formattedAverage()))
|
||||
.globalPlaceholder("tps_5m", (ctx, queue) -> Tag.preProcessParsed(tickManager.getTps5m().formattedAverage()))
|
||||
//.globalPlaceholder("tps_15m", (ctx, queue) -> Tag.preProcessParsed(tickManager.getTps15m().formattedAverage()))
|
||||
.globalPlaceholder("tick_count", (queue, ctx) -> Tag.selfClosingInserting(Component.text(this.minecraftServer.getTickCount())))
|
||||
.globalPlaceholder("has_whitelist", (queue, ctx) -> Tag.preProcessParsed(Boolean.toString(this.minecraftServer.getPlayerList().isUsingWhitelist())))
|
||||
.globalPlaceholder("total_chunks", (queue, ctx) -> {
|
||||
int chunks = 0;
|
||||
for (final ServerLevel level : this.minecraftServer.getAllLevels()) {
|
||||
chunks += level.getChunkSource().getLoadedChunksCount();
|
||||
}
|
||||
return Tag.preProcessParsed(Integer.toString(chunks));
|
||||
})
|
||||
.globalPlaceholder("total_entities", (queue, ctx) -> {
|
||||
int entities = 0;
|
||||
for (final ServerLevel level : this.minecraftServer.getAllLevels()) {
|
||||
for (final Entity ignored : level.getAllEntities()) {
|
||||
entities++;
|
||||
}
|
||||
}
|
||||
return Tag.preProcessParsed(Integer.toString(entities));
|
||||
})
|
||||
.globalPlaceholder("mspt", (queue, ctx) -> Tag.preProcessParsed(MSPT_FORMAT.format(this.minecraftServer.getAverageTickTime())))
|
||||
.globalPlaceholder("datapack_list", (queue, ctx) ->
|
||||
Tag.selfClosingInserting(this.minecraftServer.getResourceManager()
|
||||
.listPacks()
|
||||
.map(PackResources::packId)
|
||||
.map(id -> Component.text()
|
||||
.content("[")
|
||||
.append(Component.text(id))
|
||||
.append(Component.text("]"))
|
||||
.build())
|
||||
.collect(Component.toComponent(Component.space())))
|
||||
)
|
||||
.globalPlaceholder("datapack_count", (queue, ctx) ->
|
||||
Tag.preProcessParsed(Long.toString(this.minecraftServer.getResourceManager()
|
||||
.listPacks()
|
||||
.count()))
|
||||
)
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlatformCommand() {
|
||||
final FabricServerCommandManager<CommandSourceStack> commandManager = new FabricServerCommandManager<>(
|
||||
AsynchronousCommandExecutionCoordinator.simpleCoordinator(),
|
||||
Function.identity(),
|
||||
Function.identity()
|
||||
);
|
||||
PlaceholdersCommand.<CommandSourceStack>builder()
|
||||
.hasPermissionCheck((source, permission) -> Permissions.check(source, permission, 4))
|
||||
.toAudience(string -> this.minecraftServer.getPlayerList().getPlayerByName(string))
|
||||
.playerSuggestions(() -> new ArrayList<>(List.of(this.minecraftServer.getPlayerNames())))
|
||||
.manager(commandManager)
|
||||
.command("miniplaceholders")
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package io.github.miniplaceholders.fabric;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* Based on the MIT licensed Paper-Server patch "Further improve server tick loop".
|
||||
*
|
||||
* @author Daniel Ennis/Aikar
|
||||
*/
|
||||
final class RollingAverage {
|
||||
private static final DecimalFormat TPS_FORMAT = new DecimalFormat("###.##");
|
||||
static { TPS_FORMAT.setRoundingMode(RoundingMode.HALF_UP); }
|
||||
private static final int TPS = 20;
|
||||
private static final long SEC_IN_NANO = 1000000000;
|
||||
private final int size;
|
||||
private final BigDecimal[] samples;
|
||||
private final long[] times;
|
||||
private long time;
|
||||
private BigDecimal total;
|
||||
private int index = 0;
|
||||
|
||||
RollingAverage(final int size) {
|
||||
this.size = size;
|
||||
this.samples = new BigDecimal[size];
|
||||
this.times = new long[size];
|
||||
this.time = size * SEC_IN_NANO;
|
||||
this.total = dec(TPS).multiply(dec(SEC_IN_NANO)).multiply(dec(size));
|
||||
for (int i = 0; i < size; i++) {
|
||||
this.samples[i] = dec(TPS);
|
||||
this.times[i] = SEC_IN_NANO;
|
||||
}
|
||||
}
|
||||
|
||||
private static BigDecimal dec(final long t) {
|
||||
return new BigDecimal(t);
|
||||
}
|
||||
|
||||
void add(final BigDecimal x, final long t) {
|
||||
this.time -= this.times[this.index];
|
||||
this.total = this.total.subtract(this.samples[this.index].multiply(dec(this.times[this.index])));
|
||||
this.samples[this.index] = x;
|
||||
this.times[this.index] = t;
|
||||
this.time += t;
|
||||
this.total = this.total.add(x.multiply(dec(t)));
|
||||
if (++this.index == this.size) {
|
||||
this.index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
double average() {
|
||||
return this.total.divide(dec(this.time), 30, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
String formattedAverage() {
|
||||
return TPS_FORMAT.format(average());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.github.miniplaceholders.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
final class TickManager {
|
||||
private static final int TICK_DURATION = 20;
|
||||
|
||||
private static final BigDecimal TPS_BASE = new BigDecimal("1E9").multiply(new BigDecimal(TICK_DURATION));
|
||||
|
||||
private final RollingAverage tps1m = new RollingAverage(60);
|
||||
private final RollingAverage tps5m = new RollingAverage(60 * 5);
|
||||
private final RollingAverage tps15m = new RollingAverage(60 * 15);
|
||||
private long lastStartTick = 0;
|
||||
private long lastEndTick = 0;
|
||||
|
||||
TickManager() {
|
||||
ServerTickEvents.START_SERVER_TICK.register(server -> this.lastStartTick = System.nanoTime());
|
||||
|
||||
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
||||
if (server.getTickCount() % TICK_DURATION == 0) {
|
||||
final long diff = lastStartTick - lastEndTick;
|
||||
final BigDecimal currentTps = TPS_BASE.divide(new BigDecimal(diff), 30, RoundingMode.HALF_UP);
|
||||
this.tps1m.add(currentTps, diff);
|
||||
this.tps5m.add(currentTps, diff);
|
||||
this.tps15m.add(currentTps, diff);
|
||||
this.lastEndTick = System.nanoTime();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RollingAverage getTps1m() {
|
||||
return tps1m;
|
||||
}
|
||||
|
||||
public RollingAverage getTps5m() {
|
||||
return tps5m;
|
||||
}
|
||||
|
||||
public RollingAverage getTps15m() {
|
||||
return tps15m;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "miniplaceholders",
|
||||
"version": "${version}",
|
||||
"name": "MiniPlaceholders",
|
||||
"description": "MiniMessage Component-based Placeholders for PaperMC, Fabric, Krypton and Velocity platforms",
|
||||
"authors": [
|
||||
"4drian3d"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://github.com/MiniPlaceholders/MiniPlaceholders",
|
||||
"sources": "https://github.com/MiniPlaceholders/MiniPlaceholders",
|
||||
"issues": "https://github.com/MiniPlaceholders/MiniPlaceholders/issues"
|
||||
},
|
||||
"license": "GPL",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"io.github.miniplaceholders.fabric.FabricMod"
|
||||
]
|
||||
},
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.19",
|
||||
"fabric": "*",
|
||||
"java": ">=17",
|
||||
"minecraft": ">=1.19.4",
|
||||
"fabric-permissions-api-v0": "*"
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,3 +1,5 @@
|
||||
group = io.github.miniplaceholders
|
||||
version = 2.0.0
|
||||
description = MiniMessage Component-based Placeholders for PaperMC, Krypton and Velocity platforms
|
||||
version = 2.2.2
|
||||
description = MiniMessage Component-based Placeholders for Paper, Fabric, Sponge, Folia and Velocity platforms
|
||||
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
+44
-16
@@ -3,41 +3,68 @@ metadata.format.version = "1.1"
|
||||
[versions]
|
||||
|
||||
velocity = "3.2.0-SNAPSHOT"
|
||||
paper = "1.19.3-R0.1-SNAPSHOT"
|
||||
krypton = "7f7a457cdf"
|
||||
paper = "1.20.2-R0.1-SNAPSHOT"
|
||||
krypton = "7796647145"
|
||||
minecraft = "1.20.2"
|
||||
|
||||
runtask = "2.0.1"
|
||||
pluginyml = "0.5.3"
|
||||
userdev = "1.5.1"
|
||||
blossom = "1.3.1"
|
||||
indra = "3.0.1"
|
||||
shadow = "8.0.0"
|
||||
jmh = "0.7.0"
|
||||
dokka = "1.7.20"
|
||||
runtask = "2.2.0"
|
||||
pluginyml = "0.6.0"
|
||||
userdev = "1.5.9"
|
||||
blossom = "2.1.0"
|
||||
indra = "3.1.3"
|
||||
shadow = "8.1.1"
|
||||
jmh = "0.7.2"
|
||||
dokka = "1.9.10"
|
||||
|
||||
adventure = "4.12.0"
|
||||
brigadier = "1.0.18"
|
||||
kotlin="1.8.10"
|
||||
cloud = "1.8.4"
|
||||
adventure = "4.14.0"
|
||||
adventurefabric = "5.10.0"
|
||||
brigadier = "1.0.500"
|
||||
kotlin="1.9.20"
|
||||
|
||||
fabric-api = "0.90.1+1.20.3"
|
||||
fabric-loader = "0.14.24"
|
||||
|
||||
desertwell = "2.0.4"
|
||||
|
||||
[libraries]
|
||||
|
||||
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
||||
krypton-server = { group = "org.kryptonmc", name = "krypton-server", version.ref = "krypton" }
|
||||
minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" }
|
||||
|
||||
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
|
||||
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" }
|
||||
luckopermissionsapi = { group = "me.lucko", name = "fabric-permissions-api", version = "0.2-SNAPSHOT" }
|
||||
|
||||
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
|
||||
adventure-minimesssage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
|
||||
adventure-platform-fabric = { group = "net.kyori", name = "adventure-platform-fabric", version.ref = "adventurefabric" }
|
||||
adventure-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" }
|
||||
adventure-serializer-plain = { group = "net.kyori", name = "adventure-text-serializer-plain", version.ref = "adventure" }
|
||||
|
||||
cloud-core = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" }
|
||||
cloud-annotations = { group = "cloud.commandframework", name = "cloud-annotations", version.ref = "cloud" }
|
||||
cloud-velocity = { group = "cloud.commandframework", name = "cloud-velocity", version.ref = "cloud" }
|
||||
cloud-paper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" }
|
||||
cloud-fabric = { group = "cloud.commandframework", name = "cloud-fabric", version.ref = "cloud" }
|
||||
cloud-sponge = { group = "cloud.commandframework", name = "cloud-sponge", version = "1.8.0-SNAPSHOT" }
|
||||
cloud-extras = { group = "cloud.commandframework", name = "cloud-minecraft-extras", version.ref = "cloud" }
|
||||
|
||||
brigadier = { group = "com.mojang", name = "brigadier", version.ref = "brigadier" }
|
||||
|
||||
krypton-annotation = { group = "org.kryptonmc", name = "krypton-annotation-processor", version.ref = "krypton" }
|
||||
|
||||
plugin-shadow = { group = "gradle.plugin.com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
|
||||
plugin-shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
|
||||
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
plugin-indra-common = { module = "net.kyori:indra-common", version.ref = "indra" }
|
||||
plugin-indra-spotless = { module = "net.kyori:indra-licenser-spotless", version.ref = "indra" }
|
||||
plugin-dokka = "org.jetbrains.dokka:dokka-gradle-plugin:1.7.20"
|
||||
plugin-dokka = "org.jetbrains.dokka:dokka-gradle-plugin:1.9.10"
|
||||
|
||||
desertwell = { group = "net.william278", name = "DesertWell", version.ref = "desertwell" }
|
||||
|
||||
junit-bom = "org.junit:junit-bom:5.10.0"
|
||||
|
||||
[plugins]
|
||||
|
||||
@@ -48,4 +75,5 @@ runvelocity = { id = "xyz.jpenilla.run-velocity", version.ref = "runtask" }
|
||||
blossom = { id = "net.kyori.blossom", version.ref = "blossom" }
|
||||
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
|
||||
jmh = { id = "me.champeau.jmh", version.ref = "jmh" }
|
||||
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
|
||||
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
|
||||
idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.1.7" }
|
||||
Vendored
BIN
Binary file not shown.
+2
-1
@@ -1,6 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -83,10 +83,8 @@ done
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -133,10 +131,13 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
@@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
jdk:
|
||||
- openjdk17
|
||||
@@ -20,8 +20,8 @@ dependencies {
|
||||
implementation(projects.miniplaceholdersKotlinExt)
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
}
|
||||
@@ -73,13 +73,13 @@ class KotlinKryptonPlugin @Inject constructor(
|
||||
}
|
||||
|
||||
override fun registerPlatformCommand() {
|
||||
val command = PlaceholdersCommand<CommandExecutionContext>(
|
||||
{ server.players.map { it.name } },
|
||||
{ server.getPlayer(it) },
|
||||
{ it.sender }
|
||||
)
|
||||
val brigadierCMD = BrigadierCommand.of(command.placeholderTestCommand("miniplaceholders"))
|
||||
/*val command = PlaceholdersCommand.builder<CommandExecutionContext>()
|
||||
.fromSourceToAudience { it.sender }
|
||||
.playerSuggestions { server.players.map { it.name } }
|
||||
.toAudience { server.getPlayer(it) }
|
||||
.build()
|
||||
val brigadierCMD = BrigadierCommand.of(command.asNode("miniplaceholders"))
|
||||
val meta = KryptonCommandMeta.Builder("miniplaceholders").build()
|
||||
server.commandManager.register(brigadierCMD, meta)
|
||||
server.commandManager.register(brigadierCMD, meta)*/
|
||||
}
|
||||
}
|
||||
+5
-19
@@ -1,34 +1,20 @@
|
||||
plugins {
|
||||
alias(libs.plugins.userdev)
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.shadow")
|
||||
alias(libs.plugins.runpaper)
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
paperweight.paperDevBundle(libs.versions.paper.get())
|
||||
compileOnly(libs.paper)
|
||||
implementation(projects.miniplaceholdersCommon)
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
implementation(libs.cloud.paper)
|
||||
}
|
||||
|
||||
java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn(reobfJar)
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
||||
options.release.set(17)
|
||||
}
|
||||
runServer {
|
||||
minecraftVersion("1.19.3")
|
||||
}
|
||||
jar {
|
||||
manifest {
|
||||
attributes("Automatic-Module-Name" to "io.github.miniplaceholders.paper")
|
||||
}
|
||||
minecraftVersion("1.20.2")
|
||||
}
|
||||
processResources {
|
||||
filesMatching("paper-plugin.yml") {
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
package io.github.miniplaceholders.paper;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import io.papermc.paper.datapack.Datapack;
|
||||
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
|
||||
import cloud.commandframework.paper.PaperCommandManager;
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
import io.github.miniplaceholders.common.PlaceholdersCommand;
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import io.papermc.paper.datapack.Datapack;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class PaperPlugin extends JavaPlugin implements PlaceholdersPlugin {
|
||||
private final DecimalFormat tpsFormat = new DecimalFormat("###.##");
|
||||
private final DecimalFormat msptFormat = new DecimalFormat("###.###");
|
||||
private static final DecimalFormat TPS_FORMAT = new DecimalFormat("###.##");
|
||||
private static final DecimalFormat MSPT_FORMAT = new DecimalFormat("###.###");
|
||||
|
||||
static {
|
||||
InternalPlatform.platform(InternalPlatform.PAPER);
|
||||
TPS_FORMAT.setRoundingMode(RoundingMode.HALF_UP);
|
||||
MSPT_FORMAT.setRoundingMode(RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
this.getSLF4JLogger().info("Starting MiniPlaceholders Paper");
|
||||
InternalPlatform.platform(InternalPlatform.PAPER);
|
||||
|
||||
tpsFormat.setRoundingMode(RoundingMode.HALF_UP);
|
||||
msptFormat.setRoundingMode(RoundingMode.HALF_UP);
|
||||
|
||||
this.loadDefaultExpansions();
|
||||
this.registerPlatformCommand();
|
||||
}
|
||||
@@ -44,28 +49,28 @@ public final class PaperPlugin extends JavaPlugin implements PlaceholdersPlugin
|
||||
.globalPlaceholder("version", TagsUtils.staticTag(this.getServer().getVersion()))
|
||||
.globalPlaceholder("max_players", (queue, ctx) -> TagsUtils.staticTag(Component.text(this.getServer().getMaxPlayers())))
|
||||
.globalPlaceholder("unique_joins", (queue, ctx) -> TagsUtils.staticTag(Component.text(this.getServer().getOfflinePlayers().length)))
|
||||
.globalPlaceholder("tps_1", (queue, ctx) -> TagsUtils.staticTag(tpsFormat.format(this.getServer().getTPS()[0])))
|
||||
.globalPlaceholder("tps_5", (queue, ctx) -> TagsUtils.staticTag(tpsFormat.format(this.getServer().getTPS()[1])))
|
||||
.globalPlaceholder("tps_15", (queue, ctx) -> TagsUtils.staticTag(tpsFormat.format(this.getServer().getTPS()[2])))
|
||||
.globalPlaceholder("tps_1", (queue, ctx) -> TagsUtils.staticTag(TPS_FORMAT.format(this.getServer().getTPS()[0])))
|
||||
.globalPlaceholder("tps_5", (queue, ctx) -> TagsUtils.staticTag(TPS_FORMAT.format(this.getServer().getTPS()[1])))
|
||||
.globalPlaceholder("tps_15", (queue, ctx) -> TagsUtils.staticTag(TPS_FORMAT.format(this.getServer().getTPS()[2])))
|
||||
.globalPlaceholder("has_whitelist", (queue, ctx) -> TagsUtils.staticTag(Component.text(this.getServer().hasWhitelist())))
|
||||
.globalPlaceholder("total_chunks", (queue, ctx) -> {
|
||||
int chunkCount = 0;
|
||||
for(World world : this.getServer().getWorlds()){
|
||||
for (World world : this.getServer().getWorlds()){
|
||||
chunkCount += world.getLoadedChunks().length;
|
||||
}
|
||||
return TagsUtils.staticTag(Component.text(chunkCount));
|
||||
})
|
||||
.globalPlaceholder("total_entities", (queue, ctx) -> {
|
||||
int entityCount = 0;
|
||||
for(World world : this.getServer().getWorlds()){
|
||||
for (World world : this.getServer().getWorlds()){
|
||||
entityCount += world.getEntityCount();
|
||||
}
|
||||
return TagsUtils.staticTag(Component.text(entityCount));
|
||||
})
|
||||
.globalPlaceholder("mspt", (queue, ctx) -> TagsUtils.staticTag(msptFormat.format(this.getServer().getAverageTickTime())))
|
||||
.globalPlaceholder("mspt", (queue, ctx) -> TagsUtils.staticTag(MSPT_FORMAT.format(this.getServer().getAverageTickTime())))
|
||||
.globalPlaceholder("datapack_list", (queue, ctx) -> {
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for(Datapack datapack : this.getServer().getDatapackManager().getEnabledPacks()){
|
||||
final TextComponent.Builder builder = Component.text();
|
||||
for (Datapack datapack : this.getServer().getDatapackManager().getEnabledPacks()){
|
||||
builder.append(Component.text("[").append(Component.text(datapack.getName()).append(Component.text("] "))));
|
||||
}
|
||||
return Tag.selfClosingInserting(builder.build());
|
||||
@@ -78,15 +83,28 @@ public final class PaperPlugin extends JavaPlugin implements PlaceholdersPlugin
|
||||
@Override
|
||||
@SuppressWarnings({"sonarlint(java:s1874)"})
|
||||
public void registerPlatformCommand() {
|
||||
MinecraftServer.getServer()
|
||||
.getCommands()
|
||||
.getDispatcher()
|
||||
.register(new PlaceholdersCommand<>(
|
||||
() -> this.getServer().getOnlinePlayers().stream().map(Player::getName).toList(),
|
||||
(String st) -> this.getServer().getPlayer(st),
|
||||
CommandSourceStack::getBukkitSender,
|
||||
(source, permission) -> source.getBukkitSender().hasPermission(permission)
|
||||
).placeholderTestBuilder("miniplaceholders")
|
||||
try {
|
||||
PaperCommandManager<CommandSender> commandManager = new PaperCommandManager<>(
|
||||
this,
|
||||
AsynchronousCommandExecutionCoordinator.simpleCoordinator(),
|
||||
Function.identity(),
|
||||
Function.identity()
|
||||
);
|
||||
commandManager.registerBrigadier();
|
||||
|
||||
PlaceholdersCommand.<CommandSender>builder()
|
||||
.playerSuggestions(() -> getServer().getOnlinePlayers()
|
||||
.stream()
|
||||
.map(Player::getName)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.toAudience(st -> getServer().getPlayer(st))
|
||||
.hasPermissionCheck(Permissible::hasPermission)
|
||||
.manager(commandManager)
|
||||
.command("miniplaceholders")
|
||||
.build()
|
||||
.register();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,5 @@ name: MiniPlaceholders
|
||||
version: '${version}'
|
||||
main: io.github.miniplaceholders.paper.PaperPlugin
|
||||
description: MiniMessage Component-based Placeholders for PaperMC, Krypton and Velocity platforms
|
||||
api-version: '1.19'
|
||||
api-version: '1.19'
|
||||
folia-supported: true
|
||||
+2
-1
@@ -2,5 +2,6 @@
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
],
|
||||
"ignoreDeps": ["krypton", "krypton-api", "krypton-annotation-processor", "krypton-server"]
|
||||
}
|
||||
+28
-2
@@ -1,16 +1,40 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
|
||||
rootProject.name = "miniplaceholders-parent"
|
||||
|
||||
pluginManagement {
|
||||
@Suppress("UnstableApiUsage")
|
||||
includeBuild("build-logic")
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven("https://maven.fabricmc.net/")
|
||||
maven("https://maven.quiltmc.org/repository/release/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
maven("https://papermc.io/repo/repository/maven-public/")
|
||||
maven("https://repo.maven.apache.org/maven2/")
|
||||
maven("https://jitpack.io") {
|
||||
mavenContent {
|
||||
includeGroup("net.william278")
|
||||
}
|
||||
}
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven("https://repo.jpenilla.xyz/snapshots/")
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("fabric-loom") version "1.4.4"
|
||||
id("org.spongepowered.gradle.plugin") version "2.2.0"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
"connect",
|
||||
"api",
|
||||
@@ -18,7 +42,9 @@ arrayOf(
|
||||
"common",
|
||||
"paper",
|
||||
"velocity",
|
||||
"krypton"
|
||||
//"krypton",
|
||||
"fabric",
|
||||
"sponge"
|
||||
).forEach {
|
||||
include("miniplaceholders-$it")
|
||||
project(":miniplaceholders-$it").projectDir = file(it)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# run-paper files
|
||||
/run
|
||||
@@ -0,0 +1,47 @@
|
||||
import org.spongepowered.gradle.plugin.config.PluginLoaders
|
||||
import org.spongepowered.plugin.metadata.model.PluginDependency
|
||||
|
||||
plugins {
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.shadow")
|
||||
id("org.spongepowered.gradle.plugin")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.miniplaceholdersCommon)
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
implementation(libs.cloud.sponge)
|
||||
}
|
||||
|
||||
sponge {
|
||||
apiVersion("8.1.0")
|
||||
license("GPL-3")
|
||||
loader {
|
||||
name(PluginLoaders.JAVA_PLAIN)
|
||||
version("1.0")
|
||||
}
|
||||
plugin("miniplaceholders") {
|
||||
displayName("MiniPlaceholders")
|
||||
entrypoint("io.github.miniplaceholders.sponge.SpongePlugin")
|
||||
description(project.description)
|
||||
links {
|
||||
homepage("https://github.com/MiniPlaceholders/MiniPlaceholders")
|
||||
source("https://github.com/MiniPlaceholders/MiniPlaceholders")
|
||||
issues("https://github.com/MiniPlaceholders/MiniPlaceholders/issues")
|
||||
}
|
||||
contributor("4drian3d") {
|
||||
description("Lead Developer")
|
||||
}
|
||||
dependency("spongeapi") {
|
||||
loadOrder(PluginDependency.LoadOrder.AFTER)
|
||||
optional(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
exclude("io/leangen/geantyref/**")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package io.github.miniplaceholders.sponge;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.sponge.SpongeCommandManager;
|
||||
import com.google.inject.Inject;
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
import io.github.miniplaceholders.common.PlaceholdersCommand;
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.command.Command;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.lifecycle.RegisterCommandEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StartingEngineEvent;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
import org.spongepowered.plugin.builtin.jvm.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Plugin("miniplaceholders")
|
||||
public class SpongePlugin implements PlaceholdersPlugin {
|
||||
|
||||
@Inject
|
||||
private PluginContainer pluginContainer;
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
private Server server;
|
||||
|
||||
@Listener
|
||||
public void onServerStart(final StartingEngineEvent<Server> event) {
|
||||
this.server = event.engine();
|
||||
logger.info("Starting MiniPlaceholders Sponge");
|
||||
InternalPlatform.platform(InternalPlatform.SPONGE);
|
||||
|
||||
this.loadDefaultExpansions();
|
||||
}
|
||||
|
||||
private final AtomicInteger registration = new AtomicInteger(0);
|
||||
|
||||
@Listener
|
||||
public void onCommandRegister(final RegisterCommandEvent<Command.Parameterized> event) {
|
||||
if (registration.getAndIncrement() == 0) {
|
||||
this.registerPlatformCommand();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDefaultExpansions() {
|
||||
Expansion.builder("server")
|
||||
.globalPlaceholder("name", TagsUtils.staticTag("Sponge"))
|
||||
.globalPlaceholder("online", (queue, ctx) -> TagsUtils.staticTag(Component.text(server.onlinePlayers().size())))
|
||||
.globalPlaceholder("max_players", (queue, ctx) -> TagsUtils.staticTag(Component.text(server.maxPlayers())))
|
||||
.globalPlaceholder("unique_joins", (queue, ctx) -> TagsUtils.staticTag(Component.text(server.userManager().streamAll().count())))
|
||||
.globalPlaceholder("has_whitelist", (queue, ctx) -> TagsUtils.staticTag(Component.text(server.isWhitelistEnabled())))
|
||||
.globalPlaceholder("total_chunks", (queue, ctx) -> {
|
||||
int chunkCount = 0;
|
||||
for (ServerWorld world : server.worldManager().worlds()){
|
||||
chunkCount += world.entities().size();
|
||||
}
|
||||
return TagsUtils.staticTag(Component.text(chunkCount));
|
||||
})
|
||||
.globalPlaceholder("total_entities", (queue, ctx) -> {
|
||||
int entityCount = 0;
|
||||
for (ServerWorld world : server.worldManager().worlds()){
|
||||
entityCount += world.entities().size();
|
||||
}
|
||||
return TagsUtils.staticTag(Component.text(entityCount));
|
||||
})
|
||||
.globalPlaceholder("mspt", (queue, ctx) -> TagsUtils.staticTag(Component.text(server.averageTickTime())))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlatformCommand() {
|
||||
final SpongeCommandManager<AudienceHolder> commandManager = new SpongeCommandManager<>(
|
||||
pluginContainer,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
AudienceHolder::cause,
|
||||
AudienceHolder::new
|
||||
);
|
||||
|
||||
PlaceholdersCommand.<AudienceHolder>builder()
|
||||
.manager(commandManager)
|
||||
.command("miniplaceholders")
|
||||
.playerSuggestions(() -> server.onlinePlayers()
|
||||
.stream()
|
||||
.map(ServerPlayer::name)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.toAudience(st -> server.player(st).orElse(null))
|
||||
.hasPermissionCheck((holder, permission) -> holder.cause.hasPermission(permission))
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
|
||||
record AudienceHolder(@NotNull CommandCause cause) implements ForwardingAudience.Single {
|
||||
|
||||
@Override
|
||||
public @NotNull Audience audience() {
|
||||
return cause.audience();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#run velocity files
|
||||
/run
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("miniplaceholders.shadow")
|
||||
id("miniplaceholders.auto.module")
|
||||
alias(libs.plugins.runvelocity)
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -9,23 +10,10 @@ dependencies {
|
||||
implementation(projects.miniplaceholdersCommon)
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
implementation(libs.cloud.velocity)
|
||||
}
|
||||
|
||||
java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
||||
options.release.set(17)
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes("Automatic-Module-Name" to "io.github.miniplaceholders.velocity")
|
||||
}
|
||||
}
|
||||
|
||||
runVelocity {
|
||||
velocityVersion(libs.versions.velocity.get())
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package io.github.miniplaceholders.velocity;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.velocity.CloudInjectionModule;
|
||||
import cloud.commandframework.velocity.VelocityCommandManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.command.BrigadierCommand;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.utils.Components;
|
||||
import io.github.miniplaceholders.api.utils.TagsUtils;
|
||||
@@ -20,16 +22,24 @@ import io.github.miniplaceholders.common.PluginConstants;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Plugin(
|
||||
name = "MiniPlaceholders",
|
||||
id = "miniplaceholders",
|
||||
version = PluginConstants.VERSION,
|
||||
authors = {"4drian3d"}
|
||||
name = "MiniPlaceholders",
|
||||
id = "miniplaceholders",
|
||||
version = PluginConstants.VERSION,
|
||||
authors = {"4drian3d"}
|
||||
)
|
||||
public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
private final Logger logger;
|
||||
private final ProxyServer proxy;
|
||||
@Inject
|
||||
private Injector injector;
|
||||
|
||||
@Inject
|
||||
public VelocityPlugin(final Logger logger, final ProxyServer proxy) {
|
||||
this.logger = logger;
|
||||
@@ -49,31 +59,44 @@ public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
@Override
|
||||
public void loadDefaultExpansions() {
|
||||
Expansion.builder("proxy")
|
||||
.globalPlaceholder("online_players", (queue, ctx) -> {
|
||||
if(queue.hasNext()){
|
||||
String server = queue.pop().value();
|
||||
return Tag.selfClosingInserting(Component.text(proxy.getServer(server).map(sv -> sv.getPlayersConnected().size()).orElse(0)));
|
||||
}
|
||||
return Tag.selfClosingInserting(Component.text(proxy.getPlayerCount()));
|
||||
})
|
||||
.globalPlaceholder("server_count", (queue, ctx) -> Tag.selfClosingInserting(Component.text(proxy.getAllServers().size())))
|
||||
.globalPlaceholder("is_player_online", (queue, ctx) -> {
|
||||
String playerName = queue.popOr(() -> "you need to introduce an argument").value();
|
||||
return TagsUtils.staticTag(proxy.getPlayer(playerName).isPresent() ? Components.YES_COMPONENT : Components.NO_COMPONENT);
|
||||
})
|
||||
.globalPlaceholder("version", TagsUtils.staticTag(proxy.getVersion().getVersion()))
|
||||
.build()
|
||||
.register();
|
||||
.globalPlaceholder("online_players", (queue, ctx) -> {
|
||||
if (queue.hasNext()) {
|
||||
String server = queue.pop().value();
|
||||
return Tag.selfClosingInserting(Component.text(proxy.getServer(server).map(sv -> sv.getPlayersConnected().size()).orElse(0)));
|
||||
}
|
||||
return Tag.selfClosingInserting(Component.text(proxy.getPlayerCount()));
|
||||
})
|
||||
.globalPlaceholder("server_count", (queue, ctx) -> Tag.selfClosingInserting(Component.text(proxy.getAllServers().size())))
|
||||
.globalPlaceholder("is_player_online", (queue, ctx) -> {
|
||||
String playerName = queue.popOr(() -> "you need to introduce an argument").value();
|
||||
return TagsUtils.staticTag(proxy.getPlayer(playerName).isPresent() ? Components.YES_COMPONENT : Components.NO_COMPONENT);
|
||||
})
|
||||
.globalPlaceholder("version", TagsUtils.staticTag(proxy.getVersion().getVersion()))
|
||||
.build()
|
||||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlatformCommand() {
|
||||
final BrigadierCommand brigadierCMD = new BrigadierCommand(
|
||||
new PlaceholdersCommand<CommandSource>(
|
||||
() -> proxy.getAllPlayers().stream().map(Player::getUsername).toList(),
|
||||
(String st) -> proxy.getPlayer(st).orElse(null))
|
||||
.placeholderTestCommand("vminiplaceholders"));
|
||||
|
||||
proxy.getCommandManager().register(brigadierCMD);
|
||||
injector = injector.createChildInjector(
|
||||
new CloudInjectionModule<>(
|
||||
CommandSource.class,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
Function.identity(),
|
||||
Function.identity()
|
||||
)
|
||||
);
|
||||
final VelocityCommandManager<CommandSource> commandManager = injector.getInstance(
|
||||
Key.get(new TypeLiteral<>() {})
|
||||
);
|
||||
PlaceholdersCommand.<CommandSource>builder()
|
||||
.playerSuggestions(() -> proxy.getAllPlayers()
|
||||
.stream()
|
||||
.map(Player::getUsername)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.toAudience(st -> proxy.getPlayer(st).orElse(null))
|
||||
.command("vminiplaceholders")
|
||||
.manager(commandManager)
|
||||
.build().register();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user