mirror of
https://github.com/MiniPlaceholders/MiniPlaceholders.git
synced 2026-11-05 09:00:20 -05:00
Compare commits
248
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
681380680c | ||
|
|
907dd9b634 | ||
|
|
b305dd952e | ||
|
|
7cd1da177e | ||
|
|
a906efb081 | ||
|
|
aab13f8c7e | ||
|
|
d6220c99f7 | ||
|
|
bbbc32f57c | ||
|
|
a6f12f2dde | ||
|
|
79db257b98 | ||
|
|
780c80cd1c | ||
|
|
0568dc5814 | ||
|
|
83ea33d41e | ||
|
|
083151a5e2 | ||
|
|
6b97c3517d | ||
|
|
3585262807 | ||
|
|
0a0810c6cb | ||
|
|
71a5dab3ec | ||
|
|
87d7aa27d8 | ||
|
|
89970776e5 | ||
|
|
c55f2cc001 | ||
|
|
9cdcd643f8 | ||
|
|
51b9a7be9f | ||
|
|
5d39c94d17 | ||
|
|
ae0a4e7bf0 | ||
|
|
7ca1506171 | ||
|
|
aad471905b | ||
|
|
8c8a6b5d63 | ||
|
|
d5e8eb6063 | ||
|
|
6cab3dd85c | ||
|
|
d4d2847f8a | ||
|
|
efb5fd6e75 | ||
|
|
6d662ede17 | ||
|
|
254b586312 | ||
|
|
7336e25a33 | ||
|
|
9b639d8dcc | ||
|
|
34c76287ea | ||
|
|
5211b86ad7 | ||
|
|
7fff546717 | ||
|
|
69de4bf2a2 | ||
|
|
d84cf2aed5 | ||
|
|
5c12929b08 | ||
|
|
2cb82feb12 | ||
|
|
1be3d21dc6 | ||
|
|
52ebc4edc1 | ||
|
|
abb4af55eb | ||
|
|
ecb37ce3c5 | ||
|
|
a1783d2bb1 | ||
|
|
1c66606205 | ||
|
|
34c53e081d | ||
|
|
9ebececf7d | ||
|
|
0cc22db5b5 | ||
|
|
6cf533d711 | ||
|
|
c98b4e77d4 | ||
|
|
20ee1003dd | ||
|
|
b69ca1a465 | ||
|
|
cff2b5843d | ||
|
|
e8a165c7ba | ||
|
|
b08e9838aa | ||
|
|
cec7f562db | ||
|
|
7e391c054f | ||
|
|
342d36afa5 | ||
|
|
35a5e8a472 | ||
|
|
5bc31084d0 | ||
|
|
12c1ebcdbf | ||
|
|
50bb56140a | ||
|
|
59d48b7397 | ||
|
|
e946edaa35 | ||
|
|
798cf0913e | ||
|
|
0149d2e677 | ||
|
|
70a95f16e6 | ||
|
|
1e9d7d00e4 | ||
|
|
b01afe319e | ||
|
|
def00515a9 | ||
|
|
7d7bf3f326 | ||
|
|
d195095420 | ||
|
|
e3803adb80 | ||
|
|
933f976957 | ||
|
|
522386eeb0 | ||
|
|
12dc0c0a64 | ||
|
|
7c8d643099 | ||
|
|
2dd18817b3 | ||
|
|
650de3993f | ||
|
|
e88793b661 | ||
|
|
c75ebb85d6 | ||
|
|
043796fb3b | ||
|
|
ea761a0dd7 | ||
|
|
e600489031 | ||
|
|
e575fc557e | ||
|
|
5c1e8f81fc | ||
|
|
4eaf58be53 | ||
|
|
2f6da59161 | ||
|
|
ee57ec19fa | ||
|
|
cc1a96c58b | ||
|
|
472804b029 | ||
|
|
a9b8f03beb | ||
|
|
9b5bf06d71 | ||
|
|
21e36ecdfa | ||
|
|
8097cf1b22 | ||
|
|
95e2beae96 | ||
|
|
f6a0c88577 | ||
|
|
d7c619e8c4 | ||
|
|
fd1e4896ac | ||
|
|
1cfbcbad4c | ||
|
|
3a2ba24f3d | ||
|
|
3aa8519e6a | ||
|
|
fbdfc9fd1b | ||
|
|
38592abaa3 | ||
|
|
2628ef6279 | ||
|
|
6bf9c23e09 | ||
|
|
e99ae1a6fd | ||
|
|
e552a0e90d | ||
|
|
7146b1d348 | ||
|
|
e91b6796cb | ||
|
|
6e528c5d6b | ||
|
|
9c029ab519 | ||
|
|
114b38ba5b | ||
|
|
288a5ae5e0 | ||
|
|
ae720f3dce | ||
|
|
57df8615dc | ||
|
|
b00e37131d | ||
|
|
34c2330af8 | ||
|
|
6bc35b3e16 | ||
|
|
1eea547f7a | ||
|
|
68f8ce504c | ||
|
|
007b10e0c3 | ||
|
|
4c556c4925 | ||
|
|
39b20b1827 | ||
|
|
8206b99d00 | ||
|
|
35b3c31341 | ||
|
|
075cca14b0 | ||
|
|
4fb84b3ddc | ||
|
|
f9df6ddd1a | ||
|
|
6557d0c99d | ||
|
|
fbaada216a | ||
|
|
c97f2c2dc5 | ||
|
|
97f6561724 | ||
|
|
98835a90b2 | ||
|
|
a03ee83d54 | ||
|
|
7433aa0394 | ||
|
|
c392a112e5 | ||
|
|
4d8673aeeb | ||
|
|
b60ea1a9a9 | ||
|
|
ecfee088cd | ||
|
|
39b0e12c49 | ||
|
|
8c4158eee8 | ||
|
|
f425afc2bb | ||
|
|
373fc7f757 | ||
|
|
05619a4939 | ||
|
|
968c930060 | ||
|
|
b1bc70bba7 | ||
|
|
5c412ba2ff | ||
|
|
366f9b43a6 | ||
|
|
e699e48ae3 | ||
|
|
bc018cfb2d | ||
|
|
1c299e6595 | ||
|
|
510ca51111 | ||
|
|
a466dbd378 | ||
|
|
029b528669 | ||
|
|
a3f371105e | ||
|
|
f6fae9b54b | ||
|
|
5828f8d1ff | ||
|
|
88a27c40e6 | ||
|
|
34a33a0f44 | ||
|
|
c27bf3a907 | ||
|
|
7b332154bc | ||
|
|
132c1f8fac | ||
|
|
009873b5e9 | ||
|
|
0d27f10575 | ||
|
|
519d131a16 | ||
|
|
5e9da46f8c | ||
|
|
207a4e8db3 | ||
|
|
ad17ce84bd | ||
|
|
4aa9524cfd | ||
|
|
097203729f | ||
|
|
13cc13539d | ||
|
|
53bc542588 | ||
|
|
5f20e679c6 | ||
|
|
7fe01d729c | ||
|
|
42976b576a | ||
|
|
f50d95aa07 | ||
|
|
961f8d33ff | ||
|
|
2c1b24c586 | ||
|
|
c29774fb78 | ||
|
|
6524d599f2 | ||
|
|
dab817a653 | ||
|
|
06c908a2cc | ||
|
|
21a67c2d85 | ||
|
|
e7974dfbca | ||
|
|
bd80c435c0 | ||
|
|
c85e2cd1ac | ||
|
|
dbf167412d | ||
|
|
d17883962e | ||
|
|
f41e1e672a | ||
|
|
31355fa183 | ||
|
|
30ce81cf67 | ||
|
|
aeaa712d8c | ||
|
|
061d483f20 | ||
|
|
408c225b5d | ||
|
|
562e42c220 | ||
|
|
2e36e96d7f | ||
|
|
98ee83e714 | ||
|
|
34d33b2b81 | ||
|
|
882723c155 | ||
|
|
80fa0c07d0 | ||
|
|
fbc48c4c5c | ||
|
|
095228cce8 | ||
|
|
775d62233c | ||
|
|
67cb025d0f | ||
|
|
e296bf8a90 | ||
|
|
9f9950de70 | ||
|
|
ffe0e0f5d8 | ||
|
|
b5063d9a02 | ||
|
|
e0e0b4fe3e | ||
|
|
eeb756d1fc | ||
|
|
4c173ae8ee | ||
|
|
0dc6d85cdb | ||
|
|
944fef34f6 | ||
|
|
0c7e327323 | ||
|
|
17aef8b922 | ||
|
|
94baa536a4 | ||
|
|
f7a59f1279 | ||
|
|
9b314854a2 | ||
|
|
1579b264a8 | ||
|
|
17cc2016fe | ||
|
|
ea3a80a0bd | ||
|
|
2dee5f0d66 | ||
|
|
4efed28253 | ||
|
|
45b1a0da5d | ||
|
|
c4002e0a3d | ||
|
|
eb4fba66eb | ||
|
|
6a084a6d2e | ||
|
|
d02ac7abc1 | ||
|
|
9bcefee265 | ||
|
|
47dd5a96e9 | ||
|
|
36dbeed21d | ||
|
|
9dd473092a | ||
|
|
9139d2260f | ||
|
|
e19527a9d6 | ||
|
|
f648dd8f83 | ||
|
|
079b88d99f | ||
|
|
0f48a4baed | ||
|
|
2608e81fae | ||
|
|
afb4a4451d | ||
|
|
df53a0a2fa | ||
|
|
591df2e6df | ||
|
|
bf995b7103 | ||
|
|
02f30ead85 |
No files matched your search
@@ -8,24 +8,24 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: 'temurin'
|
||||
java-version: 25
|
||||
distribution: 'zulu'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Build with Gradle
|
||||
uses: nick-invision/retry@v3
|
||||
uses: nick-invision/retry@v4
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
max_attempts: 2
|
||||
command: gradle build
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: MiniPlaceholders
|
||||
path: jar/MiniPlaceholders-*.jar
|
||||
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
MiniPlaceholders Changelog
|
||||
-->
|
||||
|
||||
# 3.2.2 (unreleased)
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
### API Additions
|
||||
|
||||
|
||||
<!-- -->
|
||||
|
||||
# 3.2.1 (07/09/2026)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fixed Fabric 26.2 support
|
||||
|
||||
|
||||
## 3.2.0 (27/03/2026)
|
||||
|
||||
### Features
|
||||
|
||||
- Added support to Fabric 26.1+
|
||||
- Added Minestom support
|
||||
- Updated to Java 25
|
||||
|
||||
|
||||
## 3.1.0 (10/10/2025)
|
||||
|
||||
### Features
|
||||
|
||||
- [feat: Sponge commands implementation](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/7633ada70ed62571b707cbf709fbb5c027c44f46)
|
||||
- [feat: Implement parserel subcommand](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/ea725a81210911a8779545781b56a647d6b84cf3)
|
||||
- [feat: Add --null argument to parse node](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/3cdb7de9f2e675f494c84df693142a817535fe9a)
|
||||
- [misc: Added bstats metrics](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/f648dd8f836d5f2911eaf0bc53f6769ed2a0fdcc)
|
||||
|
||||
### Fixes
|
||||
|
||||
- [fix: Fixed multiple loading expansions](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/f67690f41347031a32d4acd7bb4bb493b42bb4f9)
|
||||
- [fix: Added nullability checks to RelationalAudience](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/8aec3e592ff6774737602a3a3a6187ddb577a681)
|
||||
- [fix: Fixed command formatting](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/de7d14d55d6aeff8dbaf1706dd06bb6812b54390)
|
||||
|
||||
|
||||
### API Additions
|
||||
|
||||
- [feat: Added LoadRequirement#requiredClass and LoadRequirement#anyOf](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/31ee16e41234cabf992736f81eda5bbbdc09d954)
|
||||
- [docs: Replaced some uses of JetBrains annotations with jspecify](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/0f48a4baed91ec5d0fe285649822f189e69a5b57)
|
||||
- [feat: Allow the use of injected constructors when creating an ExpansionProvider](https://github.com/MiniPlaceholders/MiniPlaceholders/commit/bf995b71030064a174532d38282407ab6baa7170)
|
||||
|
||||
@@ -12,9 +12,10 @@ MiniMessage Component-based Placeholders API for Minecraft Platforms.
|
||||
|
||||
## Compatibility
|
||||
- Paper 1.21+
|
||||
- Velocity 3.4+
|
||||
- Fabric 1.21.6+
|
||||
- Velocity 3.5+
|
||||
- Fabric 26.1+
|
||||
- Sponge API 12+
|
||||
- Minestom 1.21.11+
|
||||
|
||||
## User Usage
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ tasks {
|
||||
val o = options as StandardJavadocDocletOptions
|
||||
o.encoding = Charsets.UTF_8.name()
|
||||
o.links(
|
||||
"https://jd.advntr.dev/api/${libs.versions.adventure.get()}/",
|
||||
"https://jd.advntr.dev/text-minimessage/${libs.versions.adventure.get()}/"
|
||||
"https://jd.papermc.io/adventure/${libs.versions.adventure.get()}/",
|
||||
)
|
||||
o.tags(
|
||||
"apiNote:a:API Note:",
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -34,390 +34,360 @@ import java.util.Collection;
|
||||
* TagResolver resolver = expansion.resolver();
|
||||
* player.sendMessage(MiniMessage.miniMessage().deserialize("Hello {@literal <luckperms_prefix> <player_name>}", player, resolver));
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
public sealed interface Expansion permits ExpansionImpl {
|
||||
/**
|
||||
* Get the expansion name
|
||||
*
|
||||
* @return the expansion name
|
||||
* @since 1.0.0
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Get the author of this expansion
|
||||
*
|
||||
* @return the author or null
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Nullable String author();
|
||||
|
||||
/**
|
||||
* Get the version of this expansion
|
||||
*
|
||||
* @return the version or null
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Nullable String version();
|
||||
|
||||
/**
|
||||
* Get the {@link TagResolver} of an {@link Audience}
|
||||
*
|
||||
* @return A TagResolver with variable placeholders of an Audience
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver audiencePlaceholders();
|
||||
|
||||
/**
|
||||
* Get the relational placeholders based on two audiences
|
||||
*
|
||||
* <p>The resulting TagResolver will give results according
|
||||
* to the 2 {@link Audience} provided and when called
|
||||
* at any time will retrieve the required values</p>
|
||||
*
|
||||
* @return A TagResolver with variable placeholders between 2 {@link Audience}s
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver relationalPlaceholders();
|
||||
|
||||
/**
|
||||
* Get global placeholders
|
||||
*
|
||||
* @return the global placeholders
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver globalPlaceholders();
|
||||
|
||||
/**
|
||||
* Register this expansion
|
||||
*
|
||||
* @throws IllegalStateException if the expansion you are trying to register is already registered
|
||||
* @see Expansion#registered()
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void register();
|
||||
|
||||
/**
|
||||
* Unregisters this expansion
|
||||
*
|
||||
* @throws IllegalStateException if the expansion you are trying to unregister is not registered
|
||||
* @see Expansion#registered()
|
||||
* @since 2.1.0
|
||||
*/
|
||||
void unregister();
|
||||
|
||||
/**
|
||||
* Get the registration status of this expansion
|
||||
*
|
||||
* @return true if the expansion is registered, otherwise false
|
||||
* @since 2.1.0
|
||||
*/
|
||||
boolean registered();
|
||||
|
||||
/**
|
||||
* Get the registered audience placeholders
|
||||
*
|
||||
* @return registered audience placeholders
|
||||
*/
|
||||
Collection<AudiencePlaceholder<?>> registeredAudiencePlaceholders();
|
||||
|
||||
/**
|
||||
* Get the registered relational placeholders
|
||||
*
|
||||
* @return registered relational placeholders
|
||||
*/
|
||||
Collection<RelationalPlaceholder<?>> registeredRelationalPlaceholders();
|
||||
|
||||
/**
|
||||
* Get an Audience Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("player")
|
||||
* AudiencePlaceholder<?> placeholder = expansion.audiencePlaceholderByName("name");
|
||||
* }</pre>
|
||||
*
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
*/
|
||||
@Nullable AudiencePlaceholder<?> audiencePlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Get a Relational Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("expansion")
|
||||
* RelationalPlaceholder<?> placeholder = expansion.relationalPlaceholderByName("placeholder");
|
||||
* }</pre>
|
||||
*
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
* @apiNote The name of a relational placeholder does not contain the prefix “rel”,
|
||||
* just the name assigned when it was created
|
||||
*/
|
||||
@Nullable RelationalPlaceholder<?> relationalPlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Get a Global Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("player")
|
||||
* GlobalPlaceholder placeholder = expansion.globalPlaceholderByName("name");
|
||||
* }</pre>
|
||||
*
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
*/
|
||||
@Nullable GlobalPlaceholder globalPlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Checks whether an audience placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasAudiencePlaceholder(final String name) {
|
||||
return audiencePlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a relational placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasRelationalPlaceholder(final String name) {
|
||||
return relationalPlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a global placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasGlobalPlaceholder(final String name) {
|
||||
return globalPlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a TagResolver that contains all placeholders of a specific type in this expansion.
|
||||
*
|
||||
* @param type the desired type
|
||||
* @return a TagResolver containing all placeholder of a specific type
|
||||
*/
|
||||
TagResolver placeholdersByType(PlaceholderType type);
|
||||
|
||||
/**
|
||||
* Creates a new Expansion Builder
|
||||
*
|
||||
* @param name the expansion name
|
||||
* @return a new expansion builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static Expansion.Builder builder(final String name) {
|
||||
return new ExpansionImpl.Builder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a shorter ToString with the details of this expansion.
|
||||
*
|
||||
* @return a shorter ToString
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "3.1.0")
|
||||
default String shortToString() {
|
||||
final StringBuilder builder = new StringBuilder(name()).append('[');
|
||||
if (author() != null) {
|
||||
builder.append("Author: ").append(author());
|
||||
}
|
||||
if (version() != null) {
|
||||
if (author() != null) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append("Version: ").append(version());
|
||||
}
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expansion Builder
|
||||
* <p>Example use:</p>
|
||||
* <pre>
|
||||
* Expansion.Builder builder = Expansion.builder("player");
|
||||
* builder
|
||||
* // Thanks to this filter, a cast can be performed without the probability of a ClassCastException
|
||||
* .filter(Player.class)
|
||||
* .resolver("name", (audience, queue, ctx) -> Tag.selfClosingInserting(Component.text(((Player)audience).getUsername())));
|
||||
* Expansion expansion = builder.build();
|
||||
* </pre>
|
||||
* <p>
|
||||
* then use it:
|
||||
*
|
||||
* <pre>
|
||||
* Player player = event.getPlayer();
|
||||
* TagResolver resolver = expansion.resolver(player);
|
||||
* Component messageReplaced = MiniMessage.deserialize({@link String}, resolver);
|
||||
* </pre>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
interface Builder extends AbstractBuilder<Expansion> {
|
||||
|
||||
/**
|
||||
* Adds an audience placeholder
|
||||
* Get the expansion name
|
||||
*
|
||||
* <p>This type of Placeholder depends on a specific audience to obtain its values</p>
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param targetClass the target class
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param audiencePlaceholder the single placeholder
|
||||
* @param <A> the type of audience that this placeholder supports, must be the same as targetClass
|
||||
* @return the {@link Builder} itself
|
||||
* @return the expansion name
|
||||
* @since 1.0.0
|
||||
*/
|
||||
<A extends Audience> Builder audiencePlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final String key,
|
||||
final AudienceTagResolver<A> audiencePlaceholder
|
||||
);
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Adds an audience placeholder
|
||||
* Get the author of this expansion
|
||||
*
|
||||
* <p>This type of Placeholder depends on a specific audience to obtain its values</p>
|
||||
*
|
||||
* <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
|
||||
* @since 3.0.0
|
||||
*/
|
||||
default Builder audiencePlaceholder(final String key, final AudienceTagResolver<Audience> audiencePlaceholder) {
|
||||
return this.audiencePlaceholder(null, key, audiencePlaceholder);
|
||||
}
|
||||
|
||||
<A extends Audience> Builder audiencePlaceholder(
|
||||
final Class<A> targetClass,
|
||||
final AudiencePlaceholder.Builder.Provider<A> builderProvider
|
||||
);
|
||||
|
||||
default Builder audiencePlaceholder(final AudiencePlaceholder.Builder.Provider<Audience> builderProvider) {
|
||||
return audiencePlaceholder(Audience.class, builderProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Relational Placeholder based on two audiences
|
||||
*
|
||||
* <p>This type of placeholder allows you to create
|
||||
* components based on a 2-audiences relationship,
|
||||
* one is the one on which the placeholder
|
||||
* is based and the other is the one on which
|
||||
* the placeholder is displayed.</p>
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param targetClass the target class
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param relationalPlaceholder the relational placeholder
|
||||
* @param <A> the type of audience that this placeholder supports, must be the same as targetClass
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
<A extends Audience> Builder relationalPlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final String key,
|
||||
final RelationalTagResolver<A> relationalPlaceholder
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a Relational Placeholder based on two audiences
|
||||
*
|
||||
* <p>This type of placeholder allows you to create
|
||||
* components based on a 2-audiences relationship,
|
||||
* one is the one on which the placeholder
|
||||
* is based and the other is the one on which
|
||||
* the placeholder is displayed.</p>
|
||||
*
|
||||
* <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 relationalResolver the relational placeholder
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
default Builder relationalPlaceholder(
|
||||
final String key,
|
||||
final RelationalTagResolver<Audience> relationalResolver
|
||||
) {
|
||||
return this.relationalPlaceholder(null, key, relationalResolver);
|
||||
}
|
||||
|
||||
<A extends Audience> Builder relationalPlaceholder(
|
||||
final Class<A> targetClass,
|
||||
final RelationalPlaceholder.Builder.Provider<A> builderProvider
|
||||
);
|
||||
|
||||
default Builder relationalPlaceholder(final RelationalPlaceholder.Builder.Provider<Audience> builderProvider) {
|
||||
return relationalPlaceholder(Audience.class, builderProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a global placeholder
|
||||
*
|
||||
* <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 resolver the function
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
Builder globalPlaceholder(final String key, final GlobalTagResolver resolver);
|
||||
|
||||
/**
|
||||
* Adds a global placeholder
|
||||
*
|
||||
* <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
|
||||
* @since 1.1.0
|
||||
*/
|
||||
default Builder globalPlaceholder(final String key, final Tag tag) {
|
||||
return this.globalPlaceholder(key, (queue, context) -> tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this expansion
|
||||
*
|
||||
* @param author the author of this expansion
|
||||
* @return the {@link Builder} itself
|
||||
* @return the author or null
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
Builder author(final @Nullable String author);
|
||||
@Nullable String author();
|
||||
|
||||
/**
|
||||
* Sets the version of this expansion
|
||||
* Get the version of this expansion
|
||||
*
|
||||
* @param version the version of this expansion
|
||||
* @return the {@link Builder} itself
|
||||
* @return the version or null
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
Builder version(final @Nullable String version);
|
||||
}
|
||||
@Nullable String version();
|
||||
|
||||
/**
|
||||
* Get the {@link TagResolver} of an {@link Audience}
|
||||
* @return A TagResolver with variable placeholders of an Audience
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver audiencePlaceholders();
|
||||
|
||||
/**
|
||||
* Get the relational placeholders based on two audiences
|
||||
*
|
||||
* <p>The resulting TagResolver will give results according
|
||||
* to the 2 {@link Audience} provided and when called
|
||||
* at any time will retrieve the required values</p>
|
||||
* @return A TagResolver with variable placeholders between 2 {@link Audience}s
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver relationalPlaceholders();
|
||||
|
||||
/**
|
||||
* Get global placeholders
|
||||
* @return the global placeholders
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TagResolver globalPlaceholders();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Get the registered audience placeholders
|
||||
*
|
||||
* @return registered audience placeholders
|
||||
*/
|
||||
Collection<AudiencePlaceholder<?>> registeredAudiencePlaceholders();
|
||||
|
||||
/**
|
||||
* Get the registered relational placeholders
|
||||
*
|
||||
* @return registered relational placeholders
|
||||
*/
|
||||
Collection<RelationalPlaceholder<?>> registeredRelationalPlaceholders();
|
||||
|
||||
/**
|
||||
* Get an Audience Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("player")
|
||||
* AudiencePlaceholder<?> placeholder = expansion.audiencePlaceholderByName("name");
|
||||
* }</pre>
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
*/
|
||||
@Nullable AudiencePlaceholder<?> audiencePlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Get a Relational Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("expansion")
|
||||
* RelationalPlaceholder<?> placeholder = expansion.relationalPlaceholderByName("placeholder");
|
||||
* }</pre>
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
* @apiNote The name of a relational placeholder does not contain the prefix “rel”,
|
||||
* just the name assigned when it was created
|
||||
*/
|
||||
@Nullable RelationalPlaceholder<?> relationalPlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Get a Global Placeholder by name
|
||||
*
|
||||
* <pre>{@code
|
||||
* Expansion expansion = MiniPlaceholders.expansionByName("player")
|
||||
* GlobalPlaceholder placeholder = expansion.globalPlaceholderByName("name");
|
||||
* }</pre>
|
||||
* @param name the name of the placeholder to search
|
||||
* @return the desired placeholder or null
|
||||
*/
|
||||
@Nullable GlobalPlaceholder globalPlaceholderByName(final String name);
|
||||
|
||||
/**
|
||||
* Checks whether an audience placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasAudiencePlaceholder(final String name) {
|
||||
return audiencePlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a relational placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasRelationalPlaceholder(final String name) {
|
||||
return relationalPlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a global placeholder with the specified name has been registered in this expansion.
|
||||
*
|
||||
* @param name the name of the placeholder to check
|
||||
* @return true if the placeholder is registered, else false
|
||||
*/
|
||||
default boolean hasGlobalPlaceholder(final String name) {
|
||||
return globalPlaceholderByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a TagResolver that contains all placeholders of a specific type in this expansion.
|
||||
*
|
||||
* @param type the desired type
|
||||
* @return a TagResolver containing all placeholder of a specific type
|
||||
*/
|
||||
TagResolver placeholdersByType(PlaceholderType type);
|
||||
|
||||
/**
|
||||
* Creates a new Expansion Builder
|
||||
* @param name the expansion name
|
||||
* @return a new expansion builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static Expansion.Builder builder(final String name){
|
||||
return new ExpansionImpl.Builder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a shorter ToString with the details of this expansion.
|
||||
* @return a shorter ToString
|
||||
* @deprecated Starting with MiniPlaceholders 3.1, the way loaded expansions
|
||||
* are displayed in the console has changed, so this method is no longer used
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "3.1.0")
|
||||
default String shortToString() {
|
||||
final StringBuilder builder = new StringBuilder(name()).append('[');
|
||||
if (author() != null) {
|
||||
builder.append("Author: ").append(author());
|
||||
}
|
||||
if (version() != null) {
|
||||
if (author() != null) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append("Version: ").append(version());
|
||||
}
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expansion Builder
|
||||
* <p>Example use:</p>
|
||||
* <pre>
|
||||
* Expansion.Builder builder = Expansion.builder("player");
|
||||
* builder
|
||||
* // Thanks to this filter, a cast can be performed without the probability of a ClassCastException
|
||||
* .filter(Player.class)
|
||||
* .resolver("name", (audience, queue, ctx) -> Tag.selfClosingInserting(Component.text(((Player)audience).getUsername())));
|
||||
* Expansion expansion = builder.build();
|
||||
* </pre>
|
||||
*
|
||||
* then use it:
|
||||
*
|
||||
* <pre>
|
||||
* Player player = event.getPlayer();
|
||||
* TagResolver resolver = expansion.resolver(player);
|
||||
* Component messageReplaced = MiniMessage.deserialize({@link String}, resolver);
|
||||
* </pre>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
interface Builder extends AbstractBuilder<Expansion> {
|
||||
|
||||
/**
|
||||
* Adds an audience placeholder
|
||||
*
|
||||
* <p>This type of Placeholder depends on a specific audience to obtain its values</p>
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param targetClass the target class
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param audiencePlaceholder the single placeholder
|
||||
* @param <A> the type of audience that this placeholder supports, must be the same as targetClass
|
||||
* @return the {@link Builder} itself
|
||||
* @since 1.0.0
|
||||
*/
|
||||
<A extends Audience> Builder audiencePlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final String key,
|
||||
final AudienceTagResolver<A> audiencePlaceholder
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds an audience placeholder
|
||||
*
|
||||
* <p>This type of Placeholder depends on a specific audience to obtain its values</p>
|
||||
*
|
||||
* <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
|
||||
* @since 3.0.0
|
||||
*/
|
||||
default Builder audiencePlaceholder(final String key, final AudienceTagResolver<Audience> audiencePlaceholder) {
|
||||
return this.audiencePlaceholder(null, key, audiencePlaceholder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Relational Placeholder based on two audiences
|
||||
*
|
||||
* <p>This type of placeholder allows you to create
|
||||
* components based on a 2-audiences relationship,
|
||||
* one is the one on which the placeholder
|
||||
* is based and the other is the one on which
|
||||
* the placeholder is displayed.</p>
|
||||
*
|
||||
* <p>The content of this Placeholder is cached
|
||||
* and can mutate depending on when it is invoked</p>
|
||||
*
|
||||
* @param targetClass the target class
|
||||
* @param key the placeholder key, cannot be an empty or black string
|
||||
* @param relationalPlaceholder the relational placeholder
|
||||
* @param <A> the type of audience that this placeholder supports, must be the same as targetClass
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
<A extends Audience> Builder relationalPlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final String key,
|
||||
final RelationalTagResolver<A> relationalPlaceholder
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a Relational Placeholder based on two audiences
|
||||
*
|
||||
* <p>This type of placeholder allows you to create
|
||||
* components based on a 2-audiences relationship,
|
||||
* one is the one on which the placeholder
|
||||
* is based and the other is the one on which
|
||||
* the placeholder is displayed.</p>
|
||||
*
|
||||
* <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 relationalResolver the relational placeholder
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
default Builder relationalPlaceholder(
|
||||
final String key,
|
||||
final RelationalTagResolver<Audience> relationalResolver
|
||||
) {
|
||||
return this.relationalPlaceholder(null, key, relationalResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a global placeholder
|
||||
*
|
||||
* <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 resolver the function
|
||||
* @return the {@link Builder} itself
|
||||
* @since 3.0.0
|
||||
*/
|
||||
Builder globalPlaceholder(final String key, final GlobalTagResolver resolver);
|
||||
|
||||
/**
|
||||
* Adds a global placeholder
|
||||
*
|
||||
* <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
|
||||
* @since 1.1.0
|
||||
*/
|
||||
default Builder globalPlaceholder(final String key, final Tag tag) {
|
||||
return this.globalPlaceholder(key, (queue, context) -> tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this expansion
|
||||
*
|
||||
* @param author the author of this expansion
|
||||
* @return the {@link Builder} itself
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
Builder author(final @Nullable String author);
|
||||
|
||||
/**
|
||||
* Sets the version of this expansion
|
||||
*
|
||||
* @param version the version of this expansion
|
||||
* @return the {@link Builder} itself
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
Builder version(final @Nullable String version);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,8 @@ import io.github.miniplaceholders.api.types.PlaceholderType;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.intellij.lang.annotations.Subst;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
|
||||
import java.util.*;
|
||||
@@ -18,7 +17,6 @@ import java.util.*;
|
||||
import static io.github.miniplaceholders.api.utils.Conditions.nonNullOrEmptyString;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@NullMarked
|
||||
final class ExpansionImpl implements Expansion {
|
||||
private static final AudiencePlaceholder<?>[] EMPTY_SINGLE_AUDIENCE = new AudiencePlaceholder[0];
|
||||
private static final RelationalPlaceholder<?>[] EMPTY_RELATIONAL_AUDIENCE = new RelationalPlaceholder[0];
|
||||
@@ -34,23 +32,23 @@ final class ExpansionImpl implements Expansion {
|
||||
private final String version;
|
||||
|
||||
ExpansionImpl(
|
||||
final String expansionName,
|
||||
@Nullable final Collection<AudiencePlaceholder<?>> audiencePlaceholders,
|
||||
@Nullable final Collection<RelationalPlaceholder<?>> relationalPlaceholders,
|
||||
@Nullable final Collection<GlobalPlaceholder> globalPlaceholders,
|
||||
@Nullable final String author,
|
||||
@Nullable final String version
|
||||
final String expansionName,
|
||||
@Nullable final Collection<AudiencePlaceholder<?>> audiencePlaceholders,
|
||||
@Nullable final Collection<RelationalPlaceholder<?>> relationalPlaceholders,
|
||||
@Nullable final Collection<GlobalPlaceholder> globalPlaceholders,
|
||||
@Nullable final String author,
|
||||
@Nullable final String version
|
||||
) {
|
||||
this.name = expansionName;
|
||||
this.audiencePlaceholders = audiencePlaceholders != null
|
||||
? new PlaceholderTagResolver(audiencePlaceholders.toArray(EMPTY_SINGLE_AUDIENCE))
|
||||
: PlaceholderTagResolver.EMPTY;
|
||||
? new PlaceholderTagResolver(audiencePlaceholders.toArray(EMPTY_SINGLE_AUDIENCE))
|
||||
: PlaceholderTagResolver.EMPTY;
|
||||
this.relationalPlaceholders = relationalPlaceholders != null
|
||||
? new PlaceholderTagResolver(relationalPlaceholders.toArray(EMPTY_RELATIONAL_AUDIENCE))
|
||||
: PlaceholderTagResolver.EMPTY;
|
||||
? new PlaceholderTagResolver(relationalPlaceholders.toArray(EMPTY_RELATIONAL_AUDIENCE))
|
||||
: PlaceholderTagResolver.EMPTY;
|
||||
this.globalPlaceholders = globalPlaceholders == null
|
||||
? PlaceholderTagResolver.EMPTY
|
||||
: new PlaceholderTagResolver(globalPlaceholders.toArray(EMPTY_GLOBAL_PLACEHOLDER));
|
||||
? PlaceholderTagResolver.EMPTY
|
||||
: new PlaceholderTagResolver(globalPlaceholders.toArray(EMPTY_GLOBAL_PLACEHOLDER));
|
||||
this.author = author;
|
||||
this.version = version;
|
||||
}
|
||||
@@ -164,7 +162,7 @@ final class ExpansionImpl implements Expansion {
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
public static final class Builder implements Expansion.Builder {
|
||||
static final class Builder implements Expansion.Builder {
|
||||
private final String expansionName;
|
||||
@Subst("server")
|
||||
private final String expansionPrefix;
|
||||
@@ -174,49 +172,31 @@ final class ExpansionImpl implements Expansion {
|
||||
private String author;
|
||||
private String version;
|
||||
|
||||
Builder(@NotNull final String name) {
|
||||
Builder(final @NonNull String name) {
|
||||
this.expansionName = nonNullOrEmptyString(name, "Expansion name");
|
||||
this.expansionPrefix = name.toLowerCase(Locale.ROOT).concat("_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Audience> Expansion.Builder audiencePlaceholder(
|
||||
final Class<A> targetClass,
|
||||
final @NotNull @Subst("placeholder") String key,
|
||||
final @NotNull AudienceTagResolver<@NotNull A> audiencePlaceholder
|
||||
) {
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(audiencePlaceholder, "the audience placeholder cannot be null");
|
||||
|
||||
if (this.audiencePlaceholders == null) this.audiencePlaceholders = new HashSet<>();
|
||||
|
||||
this.audiencePlaceholders.add(AudiencePlaceholder.single(targetClass, expansionPrefix + key, key, audiencePlaceholder));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Audience> Expansion.Builder audiencePlaceholder(
|
||||
final @NotNull Class<A> targetClass,
|
||||
final @NotNull AudiencePlaceholder.Builder.Provider<A> builderProvider
|
||||
public <A extends Audience> @NonNull Builder audiencePlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final @Subst("name") @NonNull String key,
|
||||
final @NonNull AudienceTagResolver<@NonNull A> audiencePlaceholder
|
||||
) {
|
||||
requireNonNull(targetClass, "target class");
|
||||
requireNonNull(builderProvider, "builder");
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(audiencePlaceholder, "the audience placeholder cannot be null");
|
||||
|
||||
if (this.audiencePlaceholders == null) this.audiencePlaceholders = new HashSet<>();
|
||||
|
||||
final AudiencePlaceholder.Builder<A> builder = AudiencePlaceholder.builder(targetClass);
|
||||
builderProvider.provide(builder);
|
||||
final AudiencePlaceholder<@NotNull A> placeholder = builder.build(expansionPrefix);
|
||||
|
||||
this.audiencePlaceholders.add(placeholder);
|
||||
this.audiencePlaceholders.add(AudiencePlaceholder.single(targetClass, expansionPrefix + key, key, audiencePlaceholder));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Audience> @NotNull Builder relationalPlaceholder(
|
||||
@Nullable Class<A> targetClass,
|
||||
@Subst("relation") @NotNull String key,
|
||||
@NotNull RelationalTagResolver<@NotNull A> relationalPlaceholder
|
||||
public <A extends Audience> @NonNull Builder relationalPlaceholder(
|
||||
final Class<A> targetClass,
|
||||
final @Subst("relation") @NonNull String key,
|
||||
final @NonNull RelationalTagResolver<@NonNull A> relationalPlaceholder
|
||||
) {
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(relationalPlaceholder, "the relational placeholder cannot be null");
|
||||
@@ -229,27 +209,9 @@ final class ExpansionImpl implements Expansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A extends Audience> Expansion.Builder relationalPlaceholder(
|
||||
final @NotNull Class<A> targetClass,
|
||||
final @NotNull RelationalPlaceholder.Builder.Provider<A> builderProvider
|
||||
) {
|
||||
requireNonNull(targetClass, "target class");
|
||||
requireNonNull(builderProvider, "builder");
|
||||
|
||||
if (this.relationalPlaceholders == null) this.relationalPlaceholders = new HashSet<>();
|
||||
|
||||
final RelationalPlaceholder.Builder<A> builder = RelationalPlaceholder.builder(targetClass);
|
||||
builderProvider.provide(builder);
|
||||
final RelationalPlaceholder<@NotNull A> placeholder = builder.build(expansionPrefix);
|
||||
|
||||
this.relationalPlaceholders.add(placeholder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Builder globalPlaceholder(
|
||||
@Subst("time") @NotNull final String key,
|
||||
@NotNull final GlobalTagResolver function
|
||||
public @NonNull Builder globalPlaceholder(
|
||||
final @Subst("time") @NonNull String key,
|
||||
final @NonNull GlobalTagResolver function
|
||||
) {
|
||||
nonNullOrEmptyString(key, "Placeholder key");
|
||||
requireNonNull(function, "the global placeholder cannot be null");
|
||||
@@ -262,26 +224,26 @@ final class ExpansionImpl implements Expansion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expansion.@NotNull Builder author(@Nullable final String author) {
|
||||
public @NonNull Builder author(final @Nullable String author) {
|
||||
this.author = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expansion.@NotNull Builder version(@Nullable final String version) {
|
||||
public @NonNull Builder version(final @Nullable String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Expansion build() {
|
||||
public @NonNull Expansion build() {
|
||||
return new ExpansionImpl(
|
||||
this.expansionName,
|
||||
this.audiencePlaceholders,
|
||||
this.relationalPlaceholders,
|
||||
this.globalPlaceholders,
|
||||
this.author,
|
||||
this.version
|
||||
this.expansionName,
|
||||
this.audiencePlaceholders,
|
||||
this.relationalPlaceholders,
|
||||
this.globalPlaceholders,
|
||||
this.author,
|
||||
this.version
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -302,12 +264,12 @@ final class ExpansionImpl implements Expansion {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExpansionImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
", audiencePlaceholders=" + audiencePlaceholders +
|
||||
", relationalPlaceholders=" + relationalPlaceholders +
|
||||
", globalPlaceholders=" + globalPlaceholders +
|
||||
", author='" + author + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
"name='" + name + '\'' +
|
||||
", audiencePlaceholders=" + audiencePlaceholders +
|
||||
", relationalPlaceholders=" + relationalPlaceholders +
|
||||
", globalPlaceholders=" + globalPlaceholders +
|
||||
", author='" + author + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,8 @@ import io.github.miniplaceholders.api.types.RelationalAudience;
|
||||
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 org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -40,12 +39,13 @@ public final class MiniPlaceholders {
|
||||
* @return the platform
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static @NotNull Platform platform() {
|
||||
public static Platform platform() {
|
||||
return switch (InternalPlatform.platform()) {
|
||||
case PAPER -> Platform.PAPER;
|
||||
case VELOCITY -> Platform.VELOCITY;
|
||||
case FABRIC -> Platform.FABRIC;
|
||||
case SPONGE -> Platform.SPONGE;
|
||||
case MINESTOM -> Platform.MINESTOM;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public final class MiniPlaceholders {
|
||||
* @see TagResolver
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static @NotNull TagResolver globalPlaceholders() {
|
||||
public static TagResolver globalPlaceholders() {
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
final TagResolver resolver = expansion.globalPlaceholders();
|
||||
@@ -80,7 +80,7 @@ public final class MiniPlaceholders {
|
||||
* @return {@link TagResolver} with placeholders based on an audience
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static @NotNull TagResolver audiencePlaceholders() {
|
||||
public static TagResolver audiencePlaceholders() {
|
||||
final TagResolver.Builder resolvers = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
final TagResolver resolver = expansion.audiencePlaceholders();
|
||||
@@ -104,7 +104,7 @@ public final class MiniPlaceholders {
|
||||
* @since 3.0.0
|
||||
* @see RelationalAudience
|
||||
*/
|
||||
public static @NotNull TagResolver relationalPlaceholders() {
|
||||
public static TagResolver relationalPlaceholders() {
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
applyIfNotEmpty(expansion.relationalPlaceholders(), builder);
|
||||
@@ -133,7 +133,7 @@ public final class MiniPlaceholders {
|
||||
* @return {@link TagResolver} with placeholders based on an audience and the global placeholders
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public static @NotNull TagResolver audienceGlobalPlaceholders() {
|
||||
public static TagResolver audienceGlobalPlaceholders() {
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
|
||||
for (final Expansion expansion : expansions) {
|
||||
@@ -165,7 +165,7 @@ public final class MiniPlaceholders {
|
||||
* @apiNote In the case of audience placeholders, the audience to be used will be the {@link RelationalAudience#audience()}
|
||||
* @see RelationalAudience
|
||||
*/
|
||||
public static @NotNull TagResolver relationalGlobalPlaceholders() {
|
||||
public static TagResolver relationalGlobalPlaceholders() {
|
||||
final TagResolver.Builder builder = TagResolver.builder();
|
||||
for (final Expansion expansion : expansions) {
|
||||
applyIfNotEmpty(expansion.audiencePlaceholders(), builder);
|
||||
@@ -222,7 +222,7 @@ public final class MiniPlaceholders {
|
||||
* @see Expansion#builder(String)
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static @Nullable Expansion expansionByName(final @NotNull String name) {
|
||||
public static @Nullable Expansion expansionByName(final String name) {
|
||||
for (final Expansion expansion : expansions) {
|
||||
if (Objects.equals(expansion.name(), name)) {
|
||||
return expansion;
|
||||
|
||||
+22
-127
@@ -8,90 +8,45 @@ import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.TagPattern;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import org.intellij.lang.annotations.Subst;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A placeholder that can be applied based on an audience of the specified type.
|
||||
*
|
||||
* @param targetClass the type of audience from which this placeholder can obtain information
|
||||
* @param targetFilter the filter that will be applied to the audience before being able to evaluate its return tag
|
||||
* @param key the full placeholder key
|
||||
* @param name the name of this placeholder
|
||||
* @param resolver the object responsible for obtaining audience information
|
||||
* @param <A> the parametrized type
|
||||
* @param targetClass the type of audience from which this placeholder can obtain information
|
||||
* @param key the full placeholder key
|
||||
* @param name the name of this placeholder
|
||||
* @param resolver the object responsible for obtaining audience information
|
||||
* @param <A> the parametrized type
|
||||
*/
|
||||
@NullMarked
|
||||
public record AudiencePlaceholder<A extends Audience>(
|
||||
@Nullable Class<A> targetClass,
|
||||
@Nullable Predicate<A> targetFilter,
|
||||
@TagPattern String key,
|
||||
@TagPattern String name,
|
||||
AudienceTagResolver<A> resolver,
|
||||
@Nullable PlaceholderMetadata placeholderMetadata
|
||||
@Nullable Class<A> targetClass,
|
||||
@TagPattern String key,
|
||||
String name,
|
||||
AudienceTagResolver<A> resolver
|
||||
) implements Placeholder {
|
||||
|
||||
/**
|
||||
* A placeholder that can be applied based on an audience of the specified type.
|
||||
*
|
||||
* @param targetClass the type of audience from which this placeholder can obtain information
|
||||
* @param key the full placeholder key
|
||||
* @param name the name of this placeholder
|
||||
* @param resolver the object responsible for obtaining audience information
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public AudiencePlaceholder(
|
||||
final @Nullable Class<A> targetClass,
|
||||
final @TagPattern String key,
|
||||
final @TagPattern String name,
|
||||
final AudienceTagResolver<A> resolver
|
||||
) {
|
||||
this(targetClass, null, key, name, resolver, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AudiencePlaceholder.
|
||||
*
|
||||
* @param targetClass the type of audience from which this placeholder can obtain information
|
||||
* @param key the placeholder key
|
||||
* @param name the name of this placeholder
|
||||
* @param resolver the object responsible for obtaining audience information
|
||||
* @param <A> the parametrized type
|
||||
* @param key the placeholder key
|
||||
* @param name the name of this placeholder
|
||||
* @param resolver the object responsible for obtaining audience information
|
||||
* @return a new AudiencePlaceholder
|
||||
* @since 3.0.0
|
||||
* @param <A> the parametrized type
|
||||
*/
|
||||
public static <A extends Audience> AudiencePlaceholder<A> single(
|
||||
@Nullable Class<A> targetClass,
|
||||
@TagPattern String key,
|
||||
@TagPattern String name,
|
||||
AudienceTagResolver<A> resolver
|
||||
@Nullable Class<A> targetClass,
|
||||
@TagPattern String key,
|
||||
String name,
|
||||
AudienceTagResolver<A> resolver
|
||||
) {
|
||||
return new AudiencePlaceholder<>(
|
||||
targetClass,
|
||||
null,
|
||||
requireNonNull(key),
|
||||
requireNonNull(name),
|
||||
requireNonNull(resolver),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public static <A extends Audience> Builder<A> builder(final Class<A> clazz) {
|
||||
requireNonNull(clazz);
|
||||
return new Builder<>(clazz);
|
||||
}
|
||||
|
||||
public static Builder<Audience> builder() {
|
||||
return new Builder<>(Audience.class);
|
||||
return new AudiencePlaceholder<>(targetClass, requireNonNull(key), requireNonNull(name), requireNonNull(resolver));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,19 +63,15 @@ public record AudiencePlaceholder<A extends Audience>(
|
||||
if (audience == null) {
|
||||
return null;
|
||||
}
|
||||
if (targetFilter != null && !targetFilter.test(audience)) {
|
||||
return null;
|
||||
}
|
||||
return resolveA(name, audience, arguments, ctx);
|
||||
}
|
||||
|
||||
private @Nullable Tag resolveA(String key, A audience, ArgumentQueue queue, Context ctx) {
|
||||
return this.has(key)
|
||||
? resolver.tag(audience, queue, ctx)
|
||||
: null;
|
||||
? resolver.tag(audience, queue, ctx)
|
||||
: null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("OverrideOnly")
|
||||
private @Nullable A forwardingFilter(final Pointered source) {
|
||||
//noinspection DataFlowIssue
|
||||
if (targetClass.isInstance(source)) {
|
||||
@@ -152,63 +103,7 @@ public record AudiencePlaceholder<A extends Audience>(
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AudiencePlaceholder{" +
|
||||
"key='" + key + '\'' +
|
||||
'}';
|
||||
"key='" + key + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
public static final class Builder<A extends Audience> {
|
||||
@NotNull
|
||||
private final Class<A> targetClass;
|
||||
@TagPattern
|
||||
private String name;
|
||||
@Nullable
|
||||
private Predicate<A> targetFilter;
|
||||
private AudienceTagResolver<@NotNull A> resolver;
|
||||
@Nullable
|
||||
private PlaceholderMetadata metadata;
|
||||
|
||||
Builder(final @NotNull Class<A> targetClass) {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public Builder<A> name(final @NonNull @TagPattern String name) {
|
||||
this.name = requireNonNull(name, "placeholder name");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> targetFilter(final Predicate<A> targetFilter) {
|
||||
this.targetFilter = targetFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> resolver(final @NotNull AudienceTagResolver<@NotNull A> resolver) {
|
||||
this.resolver = requireNonNull(resolver);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> metadata(final PlaceholderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull AudiencePlaceholder<@NonNull A> build(final @NotNull @Subst("expansion") String expansionPrefix) {
|
||||
requireNonNull(this.name, "name");
|
||||
requireNonNull(this.resolver, "resolver");
|
||||
return new AudiencePlaceholder<>(
|
||||
targetClass,
|
||||
targetFilter,
|
||||
expansionPrefix+name,
|
||||
name,
|
||||
resolver,
|
||||
metadata
|
||||
);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Provider<A extends Audience> {
|
||||
void provide(Builder<A> builderProvider);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,7 @@ import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.TagPattern;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -20,21 +19,21 @@ import java.util.Objects;
|
||||
*/
|
||||
public record GlobalPlaceholder(@TagPattern String key, String name, GlobalTagResolver resolver) implements Placeholder {
|
||||
@Override
|
||||
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull Context ctx) {
|
||||
public @Nullable Tag resolve(final String name, final ArgumentQueue arguments, final Context ctx) {
|
||||
return this.has(name) ? resolver.tag(arguments, ctx) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(@NotNull String name) {
|
||||
public boolean has(final String name) {
|
||||
return key.equalsIgnoreCase(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof GlobalPlaceholder(var oKey, var __, var ___)) {
|
||||
if (obj instanceof GlobalPlaceholder(var oKey, var _, var _)) {
|
||||
return Objects.equals(oKey, this.key);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package io.github.miniplaceholders.api.placeholder;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Base class of all Placeholders
|
||||
*/
|
||||
@NullMarked
|
||||
public sealed interface Placeholder extends TagResolver permits AudiencePlaceholder, GlobalPlaceholder, RelationalPlaceholder {
|
||||
/**
|
||||
* The key of this placeholder.<br>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.github.miniplaceholders.api.placeholder;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@NullMarked
|
||||
public record PlaceholderMetadata(String displayName, String description) {
|
||||
public PlaceholderMetadata {
|
||||
requireNonNull(displayName);
|
||||
requireNonNull(description);
|
||||
}
|
||||
|
||||
public static PlaceholderMetadata data(final String displayName, final String description) {
|
||||
return new PlaceholderMetadata(displayName, description);
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -5,7 +5,6 @@ import net.kyori.adventure.text.minimessage.ParsingException;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -16,7 +15,7 @@ public record PlaceholderTagResolver(Placeholder... placeholders) implements Tag
|
||||
public static final PlaceholderTagResolver EMPTY = new PlaceholderTagResolver();
|
||||
|
||||
@Override
|
||||
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull Context ctx) throws ParsingException {
|
||||
public @Nullable Tag resolve(final String name, final ArgumentQueue arguments, final Context ctx) throws ParsingException {
|
||||
@Nullable Tag tag;
|
||||
for (final Placeholder placeholder : placeholders) {
|
||||
tag = placeholder.resolve(name, arguments, ctx);
|
||||
@@ -28,7 +27,7 @@ public record PlaceholderTagResolver(Placeholder... placeholders) implements Tag
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(final @NotNull String name) {
|
||||
public boolean has(final String name) {
|
||||
for (final Placeholder placeholder : placeholders) {
|
||||
if (placeholder.has(name)) {
|
||||
return true;
|
||||
|
||||
+14
-99
@@ -1,7 +1,7 @@
|
||||
package io.github.miniplaceholders.api.placeholder;
|
||||
|
||||
import io.github.miniplaceholders.api.resolver.RelationalTagResolver;
|
||||
import io.github.miniplaceholders.api.types.RelationalAudience;
|
||||
import io.github.miniplaceholders.api.resolver.RelationalTagResolver;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.pointer.Pointered;
|
||||
@@ -9,15 +9,9 @@ import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.TagPattern;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import org.intellij.lang.annotations.Subst;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -38,25 +32,13 @@ import static java.util.Objects.requireNonNull;
|
||||
* the {@linkplain #key()} method will return {@code server_name}.
|
||||
* @see RelationalTagResolver
|
||||
*/
|
||||
@NullMarked
|
||||
public record RelationalPlaceholder<A extends Audience>(
|
||||
@Nullable Class<A> targetClass,
|
||||
@Nullable Predicate<A> targetFilter,
|
||||
@TagPattern String key,
|
||||
@TagPattern String name,
|
||||
RelationalTagResolver<A> resolver,
|
||||
@Nullable PlaceholderMetadata placeholderMetadata
|
||||
String name,
|
||||
RelationalTagResolver<A> resolver
|
||||
) implements Placeholder {
|
||||
|
||||
public RelationalPlaceholder(
|
||||
@Nullable Class<A> targetClass,
|
||||
@TagPattern String key,
|
||||
@TagPattern String name,
|
||||
RelationalTagResolver<A> resolver
|
||||
) {
|
||||
this(targetClass, null, key, name, resolver, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method capable of creating an instance of a relational placeholder.
|
||||
*
|
||||
@@ -70,24 +52,16 @@ public record RelationalPlaceholder<A extends Audience>(
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static <A extends Audience> RelationalPlaceholder<A> relational(
|
||||
@Nullable Class<A> targetClass,
|
||||
@TagPattern String key,
|
||||
@TagPattern String name,
|
||||
RelationalTagResolver<A> resolver
|
||||
final @Nullable Class<A> targetClass,
|
||||
final @TagPattern String key,
|
||||
final String name,
|
||||
final RelationalTagResolver<A> resolver
|
||||
) {
|
||||
return new RelationalPlaceholder<>(targetClass, requireNonNull(key), name, requireNonNull(resolver));
|
||||
}
|
||||
|
||||
public static <A extends Audience> Builder<A> builder(Class<A> targetClazz) {
|
||||
return new Builder<>(targetClazz);
|
||||
}
|
||||
|
||||
public static Builder<Audience> builder() {
|
||||
return new Builder<>(Audience.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Tag resolve(String name, ArgumentQueue arguments, Context ctx) {
|
||||
public @Nullable Tag resolve(final String name, final ArgumentQueue arguments, final Context ctx) {
|
||||
final Pointered targetRaw = ctx.target();
|
||||
if (targetRaw == null) {
|
||||
return null;
|
||||
@@ -107,25 +81,21 @@ public record RelationalPlaceholder<A extends Audience>(
|
||||
if (relationalAudience == null) {
|
||||
return null;
|
||||
}
|
||||
if (targetFilter != null && (!targetFilter.test(audience) || !targetFilter.test(relationalAudience))) {
|
||||
return null;
|
||||
}
|
||||
return this.resolveA(name, audience, relationalAudience, arguments, ctx);
|
||||
}
|
||||
|
||||
private @Nullable Tag resolveA(
|
||||
String name,
|
||||
A audience,
|
||||
A relationalAudience,
|
||||
ArgumentQueue arguments,
|
||||
Context ctx
|
||||
final String name,
|
||||
final A audience,
|
||||
final A relationalAudience,
|
||||
final ArgumentQueue arguments,
|
||||
final Context ctx
|
||||
) {
|
||||
return this.has(name)
|
||||
? resolver.tag(audience, relationalAudience, arguments, ctx)
|
||||
: null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("OverrideOnly")
|
||||
private @Nullable A forwardingFilter(final Pointered source) {
|
||||
//noinspection DataFlowIssue
|
||||
if (targetClass.isInstance(source)) {
|
||||
@@ -138,7 +108,7 @@ public record RelationalPlaceholder<A extends Audience>(
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String name) {
|
||||
public boolean has(final String name) {
|
||||
return key.equalsIgnoreCase(name);
|
||||
}
|
||||
|
||||
@@ -160,59 +130,4 @@ public record RelationalPlaceholder<A extends Audience>(
|
||||
"key='" + key + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@NullUnmarked
|
||||
public static final class Builder<A extends Audience> {
|
||||
@NotNull
|
||||
private final Class<A> targetClass;
|
||||
@TagPattern
|
||||
private String name;
|
||||
@Nullable
|
||||
private Predicate<A> targetFilter;
|
||||
private RelationalTagResolver<@NotNull A> resolver;
|
||||
@Nullable
|
||||
private PlaceholderMetadata metadata;
|
||||
|
||||
Builder(final @NotNull Class<A> targetClass) {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public Builder<A> name(final @NonNull @TagPattern String name) {
|
||||
this.name = requireNonNull(name, "placeholder name");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> targetFilter(final Predicate<A> targetFilter) {
|
||||
this.targetFilter = targetFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> resolver(final @NotNull RelationalTagResolver<@NotNull A> resolver) {
|
||||
this.resolver = requireNonNull(resolver);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<A> metadata(final PlaceholderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull RelationalPlaceholder<@NonNull A> build(final @NotNull @Subst("expansion") String expansionPrefix) {
|
||||
requireNonNull(this.name, "name");
|
||||
requireNonNull(this.resolver, "resolver");
|
||||
return new RelationalPlaceholder<>(
|
||||
targetClass,
|
||||
targetFilter,
|
||||
expansionPrefix + name,
|
||||
name,
|
||||
resolver,
|
||||
metadata
|
||||
);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Provider<A extends Audience> {
|
||||
void provide(final Builder<A> builderProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,8 @@ import org.intellij.lang.annotations.Pattern;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -17,7 +16,6 @@ import static java.util.Objects.requireNonNull;
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
public sealed interface LoadRequirement {
|
||||
|
||||
/**
|
||||
@@ -162,6 +160,12 @@ public sealed interface LoadRequirement {
|
||||
@ApiStatus.Internal
|
||||
@NullMarked
|
||||
record MultiLoadRequirement(LoadRequirement... requirements) implements LoadRequirement {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MultiLoadRequirement{" +
|
||||
"requirements=" + Arrays.toString(requirements) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,11 +179,8 @@ public sealed interface LoadRequirement {
|
||||
record PlatformRequirement(Platform... platforms) implements LoadRequirement {
|
||||
@Override
|
||||
public String toString() {
|
||||
final String platforms = Stream.of(this.platforms)
|
||||
.map(Platform::name)
|
||||
.collect(Collectors.joining(", "));
|
||||
return "PlatformRequirement{" +
|
||||
"platforms=" + platforms +
|
||||
"platforms=" + Arrays.toString(platforms()) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -212,5 +213,11 @@ public sealed interface LoadRequirement {
|
||||
@ApiStatus.Internal
|
||||
@NullMarked
|
||||
record AnyOfRequirement(LoadRequirement... requirements) implements LoadRequirement {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AnyOfRequirement{" +
|
||||
"requirements=" + Arrays.toString(requirements) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Package responsible for providing tools to load expansions provided through installable files
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
package io.github.miniplaceholders.api.provider;
|
||||
@@ -1,12 +1,10 @@
|
||||
package io.github.miniplaceholders.api.resolver;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
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 org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Audience Placeholder based on an Audience
|
||||
@@ -14,7 +12,6 @@ import org.jspecify.annotations.NullMarked;
|
||||
* @param <A> the audience type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@NullMarked
|
||||
public interface AudienceTagResolver<A extends Audience> {
|
||||
/**
|
||||
* A Tag based on an Audience
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.github.miniplaceholders.api.resolver;
|
||||
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 org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -20,5 +19,5 @@ public interface GlobalTagResolver {
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Nullable
|
||||
Tag tag(@NonNull ArgumentQueue queue, @NonNull Context context);
|
||||
Tag tag(ArgumentQueue queue, Context context);
|
||||
}
|
||||
+1
-3
@@ -4,8 +4,7 @@ import net.kyori.adventure.audience.Audience;
|
||||
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 org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Relational Placeholder based on two Audiences.
|
||||
@@ -15,7 +14,6 @@ import org.jspecify.annotations.NullMarked;
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@NullMarked
|
||||
public interface RelationalTagResolver<A extends Audience> {
|
||||
/**
|
||||
* A Tag based on two audiences
|
||||
|
||||
@@ -29,5 +29,11 @@ public enum Platform {
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
SPONGE
|
||||
SPONGE,
|
||||
/**
|
||||
* Minestom Platform
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
MINESTOM,
|
||||
}
|
||||
@@ -2,34 +2,33 @@ package io.github.miniplaceholders.api.types;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A relationship between 2 Audiences.
|
||||
*
|
||||
* @param audience the principal audience
|
||||
* @param audience the principal audience
|
||||
* @param relational the secondary audience, with which the relationship will be evaluated
|
||||
* @param <A> the audiences type
|
||||
* @param <A> the audiences type
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
public record RelationalAudience<A extends Audience>(A audience, A relational) implements ForwardingAudience.Single {
|
||||
public RelationalAudience {
|
||||
requireNonNull(audience);
|
||||
requireNonNull(relational);
|
||||
}
|
||||
/**
|
||||
* Creates a new relation between two audiences.
|
||||
*
|
||||
* @param audience the principal audience
|
||||
* @param relational the secondary audience, with which the relationship will be evaluated
|
||||
* @param <A> the audiences type
|
||||
* @return a new relation
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static <A extends Audience> RelationalAudience<A> from(A audience, A relational) {
|
||||
return new RelationalAudience<>(audience, relational);
|
||||
}
|
||||
public RelationalAudience {
|
||||
requireNonNull(audience);
|
||||
requireNonNull(relational);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new relation between two audiences.
|
||||
*
|
||||
* @param audience the principal audience
|
||||
* @param relational the secondary audience, with which the relationship will be evaluated
|
||||
* @return a new relation
|
||||
* @param <A> the audiences type
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static <A extends Audience> RelationalAudience<A> from(A audience, A relational) {
|
||||
return new RelationalAudience<>(audience, relational);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
/**Plugin enums */
|
||||
/**
|
||||
* Plugin types
|
||||
*/
|
||||
package io.github.miniplaceholders.api.types;
|
||||
@@ -4,7 +4,9 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
/**Common components used in expansions */
|
||||
/**
|
||||
* Common components used in expansions
|
||||
*/
|
||||
public final class Components {
|
||||
private Components(){}
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.github.miniplaceholders.api.utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -23,7 +22,7 @@ public final class Conditions {
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String nonNullOrEmptyString(@Nullable String string, @NotNull Supplier<@NotNull String> name) {
|
||||
public static String nonNullOrEmptyString(final @Nullable String string, final Supplier<String> name) {
|
||||
if (string == null)
|
||||
throw new NullPointerException(name.get() + " cannot be null");
|
||||
if (string.isBlank())
|
||||
@@ -40,7 +39,7 @@ public final class Conditions {
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public static String nonNullOrEmptyString(@Nullable String string, @NotNull String name) {
|
||||
public static String nonNullOrEmptyString(final @Nullable String string, final String name) {
|
||||
if (string == null)
|
||||
throw new NullPointerException(name + " cannot be null");
|
||||
if (string.isBlank())
|
||||
@@ -57,7 +56,7 @@ public final class Conditions {
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String nonEmptyString(@NotNull String string, @NotNull Supplier<@NotNull String> reason) {
|
||||
public static String nonEmptyString(final String string, final Supplier<String> reason) {
|
||||
if (string.isBlank()) throw new IllegalStateException(reason.get());
|
||||
return string;
|
||||
}
|
||||
@@ -71,7 +70,7 @@ public final class Conditions {
|
||||
* @throws IllegalStateException if the provided string is empty
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public static String nonEmptyString(@NotNull String string, @NotNull String reason) {
|
||||
public static String nonEmptyString(final String string, final String reason) {
|
||||
if (string.isBlank()) throw new IllegalStateException(reason);
|
||||
return string;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ 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.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -17,7 +16,6 @@ import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@NullMarked
|
||||
public final class LegacyStrings {
|
||||
private LegacyStrings() {
|
||||
}
|
||||
@@ -26,7 +24,10 @@ public final class LegacyStrings {
|
||||
* Legacy serializer with hex support
|
||||
* <p>Use this as the last available alternative,
|
||||
* it is recommended to use MiniMessage instead of this serializer</p>
|
||||
*
|
||||
* @deprecated Legacy format “support” will be removed in future versions
|
||||
*/
|
||||
@Deprecated(since = "3.1.0")
|
||||
public static final LegacyComponentSerializer LEGACY_HEX_SERIALIZER = LegacyComponentSerializer.builder()
|
||||
.character('&')
|
||||
.hexColors()
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
package io.github.miniplaceholders.api.utils;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Class of utilities to manage TagResolvers.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@NullMarked
|
||||
public final class Resolvers {
|
||||
private Resolvers() {}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import io.github.miniplaceholders.api.resolver.RelationalTagResolver;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Tags basic instances.
|
||||
@@ -29,7 +29,7 @@ public final class Tags {
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static final Tag NULL_TAG = null;
|
||||
public static final @Nullable Tag NULL_TAG = null;
|
||||
|
||||
/**
|
||||
* An Audience placeholder that returns a null Tag
|
||||
@@ -38,7 +38,7 @@ public final class Tags {
|
||||
* @return an empty audience resolver
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static <A extends Audience> AudienceTagResolver<@NonNull A> emptyAudienceResolver() {
|
||||
public static <A extends Audience> AudienceTagResolver<A> emptyAudienceResolver() {
|
||||
return (audience, queue, ctx) -> NULL_TAG;
|
||||
}
|
||||
|
||||
@@ -49,17 +49,10 @@ public final class Tags {
|
||||
* @return an empty relational resolver
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static <A extends Audience> RelationalTagResolver<@NonNull A> emptyRelationalResolver() {
|
||||
public static <A extends Audience> RelationalTagResolver<A> emptyRelationalResolver() {
|
||||
return (audience, relational, queue, ctx) -> NULL_TAG;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Global placeholder that returns a null tag
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
private static final GlobalTagResolver EMPTY_GLOBAL_PLACEHOLDER = (queue, ctx) -> NULL_TAG;
|
||||
|
||||
/**
|
||||
* A Global placeholder that returns a null tag
|
||||
*
|
||||
@@ -67,7 +60,7 @@ public final class Tags {
|
||||
* @return an empty global placeholder
|
||||
*/
|
||||
public static GlobalTagResolver emptyGlobalPlaceholder() {
|
||||
return EMPTY_GLOBAL_PLACEHOLDER;
|
||||
return (queue, ctx) -> NULL_TAG;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* MiniPlaceholders API Module
|
||||
*/
|
||||
@NullMarked
|
||||
open module io.github.miniplaceholders.api {
|
||||
requires io.github.miniplaceholders.connect;
|
||||
|
||||
requires net.kyori.adventure;
|
||||
requires net.kyori.adventure.api;
|
||||
requires net.kyori.adventure.text.minimessage;
|
||||
requires net.kyori.adventure.text.serializer.legacy;
|
||||
requires net.kyori.examination.api;
|
||||
|
||||
requires static org.jetbrains.annotations;
|
||||
requires static org.jspecify;
|
||||
requires static team.unnamed.inject;
|
||||
|
||||
exports io.github.miniplaceholders.api;
|
||||
exports io.github.miniplaceholders.api.types;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
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 net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ArgumentTest implements MiniTest {
|
||||
@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"));
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,13 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class ExpansionsTest implements MiniTest {
|
||||
@Test
|
||||
@DisplayName("Expansion Equality")
|
||||
void equalsExpansions() {
|
||||
void equalsExpansions(){
|
||||
final Expansion firstExpansion = Expansion.builder("equals")
|
||||
.audiencePlaceholder("test", Tags.emptyAudienceResolver())
|
||||
.build();
|
||||
.audiencePlaceholder("test", Tags.emptyAudienceResolver())
|
||||
.build();
|
||||
final Expansion secondExpansion = Expansion.builder("equals")
|
||||
.audiencePlaceholder("test", Tags.emptyAudienceResolver())
|
||||
.build();
|
||||
.audiencePlaceholder("test", Tags.emptyAudienceResolver())
|
||||
.build();
|
||||
|
||||
assertEquals(firstExpansion, secondExpansion);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class MiniPlaceholdersTest implements MiniTest {
|
||||
void methodEquality(){
|
||||
Expansion.builder("equality")
|
||||
.audiencePlaceholder("audience", Tags.emptyAudienceResolver())
|
||||
.globalPlaceholder("global", (queue, ctx) -> Tags.EMPTY_TAG)
|
||||
.globalPlaceholder("global", (_, _) -> Tags.EMPTY_TAG)
|
||||
.build()
|
||||
.register();
|
||||
|
||||
|
||||
@@ -1,22 +1,83 @@
|
||||
package io.github.miniplaceholders.test;
|
||||
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import io.github.miniplaceholders.api.types.RelationalAudience;
|
||||
import io.github.miniplaceholders.test.instances.TestAudience;
|
||||
import io.github.miniplaceholders.test.instances.TestAudienceHolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.MiniPlaceholders;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PlaceholderTest implements MiniTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Audience Placeholder Test")
|
||||
void audienceExpansionPlaceholdersTest() {
|
||||
TestAudience player = new TestAudience("4drian3d");
|
||||
|
||||
Expansion expansion = Expansion.builder("example")
|
||||
.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().deserialize("Player Name: <example_name>", player, expansion.audiencePlaceholders());
|
||||
|
||||
assertContentEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Relational Placeholder Test")
|
||||
void relationalExpansionPlaceholdersTest() {
|
||||
Audience p1 = new TestAudience("PlayerOne");
|
||||
Audience p2 = new TestAudience("PlayerTwo");
|
||||
|
||||
Expansion expansion = Expansion.builder("relational")
|
||||
.relationalPlaceholder(TestAudience.class, "enemy",
|
||||
(aud, relational, queue, ctx) ->
|
||||
Tag.selfClosingInserting(this.isEnemy(aud, relational)
|
||||
? Component.text("Enemy", NamedTextColor.RED)
|
||||
: Component.text("Neutral", NamedTextColor.GREEN)
|
||||
))
|
||||
.build();
|
||||
|
||||
assertEquals(
|
||||
MiniMessage.miniMessage().deserialize("You are <red>Enemy"),
|
||||
MiniMessage.miniMessage().deserialize("You are <relational_rel_enemy>",
|
||||
RelationalAudience.from(p1, p2),
|
||||
expansion.relationalPlaceholders()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Global Placeholder Test")
|
||||
void globalExpansionPlaceholderTest() {
|
||||
Expansion expansion = Expansion.builder("global")
|
||||
.globalPlaceholder("players", (queue, ctx) -> Tag.selfClosingInserting(Component.text(1305)))
|
||||
.globalPlaceholder("servers", (queue, ctx) -> Tag.selfClosingInserting(Component.text(7)))
|
||||
.build();
|
||||
|
||||
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());
|
||||
|
||||
assertContentEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Registered Placeholders")
|
||||
void instancePlaceholdersTest() {
|
||||
Expansion.builder("instance")
|
||||
.globalPlaceholder("hello", (queue, ctx) ->
|
||||
Tag.selfClosingInserting(Component.text("hello", NamedTextColor.RED)))
|
||||
.globalPlaceholder("hello", (queue, ctx) -> Tag.selfClosingInserting(Component.text("hello", NamedTextColor.RED)))
|
||||
.build()
|
||||
.register();
|
||||
|
||||
@@ -26,4 +87,65 @@ class PlaceholderTest implements MiniTest {
|
||||
assertContentEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Filtered Expansion")
|
||||
void filteredExpansion() {
|
||||
Expansion expansion = Expansion.builder("filter")
|
||||
.audiencePlaceholder(TestAudience.class, "name",
|
||||
(aud, queue, ctx) -> Tag.selfClosingInserting(Component.text(aud.name())))
|
||||
.build();
|
||||
|
||||
Audience player = new TestAudience("TestPlayer04");
|
||||
Audience emptyAudience = Audience.empty();
|
||||
|
||||
String string = "Player Name: <filter_name>";
|
||||
|
||||
Component playerExpected = Component.text("Player Name: TestPlayer04");
|
||||
Component emptyExpected = Component.text("Player Name: <filter_name>");
|
||||
|
||||
assertContentEquals(playerExpected, MiniMessage.miniMessage().deserialize(string, player, expansion.audiencePlaceholders()));
|
||||
assertContentEquals(emptyExpected, MiniMessage.miniMessage().deserialize(string, emptyAudience, expansion.audiencePlaceholders()));
|
||||
}
|
||||
|
||||
@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")
|
||||
.audiencePlaceholder(TestAudience.class, "testing",
|
||||
(audience, queue, ctx) -> Tag.selfClosingInserting(Component.text("Name: " + audience.name())))
|
||||
.build();
|
||||
|
||||
TestAudience testAudience = new TestAudience("4drian3d");
|
||||
Audience forward = new TestAudienceHolder(testAudience);
|
||||
|
||||
Component parsed = miniMessage().deserialize("<test_testing>.", forward, expansion.audiencePlaceholders());
|
||||
Component expected = Component.text("Name: 4drian3d.");
|
||||
|
||||
assertContentEquals(parsed, expected);
|
||||
}
|
||||
|
||||
private boolean isEnemy(TestAudience a1, TestAudience a2) {
|
||||
return a1.name().equals("PlayerOne") && a2.name().equals("PlayerTwo");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,10 +10,9 @@ import net.kyori.adventure.text.minimessage.tag.ParserDirective;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TagTest implements MiniTest {
|
||||
@@ -35,7 +34,7 @@ public class TagTest implements MiniTest {
|
||||
|
||||
public record FilteringTag(ArgumentQueue queue, Context context) implements Modifying {
|
||||
@Override
|
||||
public Component apply(@NotNull Component current, int depth) {
|
||||
public Component apply(@NonNull Component current, int depth) {
|
||||
if (depth != 0) {
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.github.miniplaceholders.test.instances;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
public record TestAudience(@NotNull String name) implements Audience {}
|
||||
@NullMarked
|
||||
public record TestAudience(String name) implements Audience {}
|
||||
@@ -1,11 +1,12 @@
|
||||
package io.github.miniplaceholders.test.instances;
|
||||
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public record TestAudienceHolder(TestAudience audience) implements ForwardingAudience.Single {
|
||||
@Override
|
||||
public @NotNull TestAudience audience() {
|
||||
public TestAudience audience() {
|
||||
return audience;
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
package io.github.miniplaceholders.test.placeholder;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.placeholder.PlaceholderMetadata;
|
||||
import io.github.miniplaceholders.test.MiniTest;
|
||||
import io.github.miniplaceholders.test.instances.TestAudience;
|
||||
import io.github.miniplaceholders.test.instances.TestAudienceHolder;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
|
||||
public class AudiencePlaceholderTest implements MiniTest {
|
||||
@Test
|
||||
@DisplayName("Audience Placeholder Test")
|
||||
void audienceExpansionPlaceholdersTest() {
|
||||
TestAudience player = new TestAudience("4drian3d");
|
||||
|
||||
Expansion expansion = Expansion.builder("example")
|
||||
.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().deserialize("Player Name: <example_name>", player, expansion.audiencePlaceholders());
|
||||
|
||||
assertContentEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Forwarding Audience Parsing Test")
|
||||
void forwardingAudienceTest() {
|
||||
Expansion expansion = Expansion.builder("test")
|
||||
.audiencePlaceholder(TestAudience.class, "testing",
|
||||
(audience, queue, ctx) -> Tag.selfClosingInserting(Component.text("Name: " + audience.name())))
|
||||
.build();
|
||||
|
||||
TestAudience testAudience = new TestAudience("4drian3d");
|
||||
Audience forward = new TestAudienceHolder(testAudience);
|
||||
|
||||
Component parsed = miniMessage().deserialize("<test_testing>.", forward, expansion.audiencePlaceholders());
|
||||
Component expected = Component.text("Name: 4drian3d.");
|
||||
|
||||
assertContentEquals(parsed, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Filtered Expansion")
|
||||
void filteredExpansion() {
|
||||
Expansion expansion = Expansion.builder("filter")
|
||||
.audiencePlaceholder(TestAudience.class, "name",
|
||||
(aud, queue, ctx) -> Tag.selfClosingInserting(Component.text(aud.name())))
|
||||
.build();
|
||||
|
||||
Audience player = new TestAudience("TestPlayer04");
|
||||
Audience emptyAudience = Audience.empty();
|
||||
|
||||
String string = "Player Name: <filter_name>";
|
||||
|
||||
Component playerExpected = Component.text("Player Name: TestPlayer04");
|
||||
Component emptyExpected = Component.text("Player Name: <filter_name>");
|
||||
|
||||
assertContentEquals(playerExpected, MiniMessage.miniMessage().deserialize(string, player, expansion.audiencePlaceholders()));
|
||||
assertContentEquals(emptyExpected, MiniMessage.miniMessage().deserialize(string, emptyAudience, expansion.audiencePlaceholders()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("AudiencePlaceholder Builder creation")
|
||||
void builderAudiencePlaceholderCreation() {
|
||||
final Expansion expansion = Expansion.builder("builder")
|
||||
.audiencePlaceholder(
|
||||
TestAudience.class,
|
||||
builder -> builder.name("test")
|
||||
.resolver((audience, queue, ctx) -> {
|
||||
final String name = audience.name();
|
||||
return Tag.preProcessParsed(name);
|
||||
})
|
||||
.metadata(PlaceholderMetadata.data("Builder Test", "Returns the Audience Name"))
|
||||
.targetFilter(target -> target.name().length() <= 16)
|
||||
).build();
|
||||
final TestAudience audience = new TestAudience("4drian3d");
|
||||
|
||||
Component expected = Component.text("My name is: 4drian3d");
|
||||
Component parsed = miniMessage().deserialize("My name is: <builder_test>", audience, expansion.audiencePlaceholders());
|
||||
|
||||
assertContentEquals(expected, parsed);
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package io.github.miniplaceholders.test.placeholder;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.test.MiniTest;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class GlobalPlaceholderTest implements MiniTest {
|
||||
@Test
|
||||
@DisplayName("Global Placeholder Test")
|
||||
void globalExpansionPlaceholderTest() {
|
||||
Expansion expansion = Expansion.builder("global")
|
||||
.globalPlaceholder("players", (queue, ctx) -> Tag.selfClosingInserting(Component.text(1305)))
|
||||
.globalPlaceholder("servers", (queue, ctx) -> Tag.selfClosingInserting(Component.text(7)))
|
||||
.build();
|
||||
|
||||
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());
|
||||
|
||||
assertContentEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
package io.github.miniplaceholders.test.placeholder;
|
||||
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.placeholder.PlaceholderMetadata;
|
||||
import io.github.miniplaceholders.api.types.RelationalAudience;
|
||||
import io.github.miniplaceholders.test.MiniTest;
|
||||
import io.github.miniplaceholders.test.instances.TestAudience;
|
||||
import io.github.miniplaceholders.test.instances.TestAudienceHolder;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class RelationalPlaceholderTest implements MiniTest {
|
||||
@Test
|
||||
@DisplayName("Relational Placeholder Test")
|
||||
void relationalExpansionPlaceholdersTest() {
|
||||
Audience p1 = new TestAudience("PlayerOne");
|
||||
Audience p2 = new TestAudience("PlayerTwo");
|
||||
|
||||
Expansion expansion = Expansion.builder("relational")
|
||||
.relationalPlaceholder(TestAudience.class, "enemy",
|
||||
(aud, relational, queue, ctx) ->
|
||||
Tag.selfClosingInserting(this.isEnemy(aud, relational)
|
||||
? Component.text("Enemy", NamedTextColor.RED)
|
||||
: Component.text("Neutral", NamedTextColor.GREEN)
|
||||
))
|
||||
.build();
|
||||
|
||||
assertEquals(
|
||||
MiniMessage.miniMessage().deserialize("You are <red>Enemy"),
|
||||
MiniMessage.miniMessage().deserialize("You are <relational_rel_enemy>",
|
||||
RelationalAudience.from(p1, p2),
|
||||
expansion.relationalPlaceholders()));
|
||||
}
|
||||
|
||||
private boolean isEnemy(TestAudience a1, TestAudience a2) {
|
||||
return a1.name().equals("PlayerOne") && a2.name().equals("PlayerTwo");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Relational Forwarding Audience Parsing Test")
|
||||
void relationalForwardingAudienceTest() {
|
||||
Expansion expansion = Expansion.builder("test")
|
||||
.relationalPlaceholder(TestAudience.class, "testing",
|
||||
(audience, another, queue, ctx) ->
|
||||
Tag.selfClosingInserting(Component.text("Name: " + audience.name() + ", Other Name: " + another.name())))
|
||||
.build();
|
||||
|
||||
TestAudience testAudience = new TestAudience("4drian3d");
|
||||
TestAudience secondAudience = new TestAudience("PepitoAlcachofa");
|
||||
Audience forward = new TestAudienceHolder(testAudience);
|
||||
Audience secondForward = new TestAudienceHolder(secondAudience);
|
||||
|
||||
Component parsed = miniMessage().deserialize("<test_rel_testing>.",
|
||||
RelationalAudience.from(forward, secondForward), expansion.relationalPlaceholders());
|
||||
Component expected = Component.text("Name: 4drian3d, Other Name: PepitoAlcachofa.");
|
||||
|
||||
assertContentEquals(expected, parsed);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Relational Filtered Expansion")
|
||||
void relationalFilteredExpansion() {
|
||||
Expansion expansion = Expansion.builder("filter")
|
||||
.relationalPlaceholder(TestAudience.class, "name",
|
||||
(aud, another, queue, ctx) ->
|
||||
Tag.selfClosingInserting(Component.text(aud.name().replace(another.name(), ""))))
|
||||
.build();
|
||||
|
||||
Audience player = new TestAudience("TestPlayer04");
|
||||
Audience second = new TestAudience("Player");
|
||||
Audience emptyAudience = Audience.empty();
|
||||
|
||||
String string = "Player Name: <filter_rel_name>";
|
||||
|
||||
Component playerExpected = Component.text("Player Name: Test04");
|
||||
Component emptyExpected = Component.text("Player Name: <filter_rel_name>");
|
||||
|
||||
assertContentEquals(playerExpected, MiniMessage.miniMessage().deserialize(string,
|
||||
RelationalAudience.from(player, second), expansion.relationalPlaceholders()));
|
||||
assertContentEquals(emptyExpected, MiniMessage.miniMessage().deserialize(string,
|
||||
RelationalAudience.from(player, emptyAudience), expansion.relationalPlaceholders()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("RelationalPlaceholder Builder creation")
|
||||
void builderRelationalPlaceholderCreation() {
|
||||
final Expansion expansion = Expansion.builder("builder")
|
||||
.relationalPlaceholder(
|
||||
TestAudience.class,
|
||||
builder -> builder.name("test")
|
||||
.resolver((audience, relational, queue, ctx) -> {
|
||||
final String name = audience.name();
|
||||
final String relationalName = relational.name();
|
||||
return Tag.preProcessParsed(name + " and " + relationalName);
|
||||
})
|
||||
.metadata(PlaceholderMetadata.data("Builder Test", "Returns the Audience plus the Relational Audience combined Names"))
|
||||
.targetFilter(target -> target.name().length() <= 16)
|
||||
).build();
|
||||
final TestAudience audience = new TestAudience("4drian3d");
|
||||
final TestAudience relational = new TestAudience("PepitoAlcachofa");
|
||||
final RelationalAudience<@NotNull TestAudience> relationalAudience = RelationalAudience.from(audience, relational);
|
||||
|
||||
Component expected = Component.text("Our names are: 4drian3d and PepitoAlcachofa");
|
||||
Component parsed = miniMessage().deserialize("Our names are: <builder_test>", relationalAudience, expansion.relationalPlaceholders());
|
||||
|
||||
assertContentEquals(expected, parsed);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ plugins {
|
||||
dependencies {
|
||||
implementation(libs.plugin.shadow)
|
||||
implementation(libs.plugin.kotlin)
|
||||
implementation(libs.plugin.runtask)
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -13,6 +14,6 @@ repositories {
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
languageVersion = JavaLanguageVersion.of(25)
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@ val Project.capitalizeName: String
|
||||
get() = this.name.substring(17)
|
||||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
|
||||
|
||||
fun Project.simpleName(): String = this.name.substring(17)
|
||||
fun Project.simpleName(): String = this.name.substring(17)
|
||||
@@ -1,4 +1,4 @@
|
||||
import java.util.Date
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
java
|
||||
@@ -7,7 +7,7 @@ plugins {
|
||||
tasks {
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(21)
|
||||
options.release.set(25)
|
||||
}
|
||||
jar {
|
||||
manifest {
|
||||
@@ -22,7 +22,7 @@ tasks {
|
||||
|
||||
java{
|
||||
toolchain{
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
//vendor.set(JvmVendorSpec.ADOPTIUM)
|
||||
languageVersion.set(JavaLanguageVersion.of(25))
|
||||
vendor.set(JvmVendorSpec.AZUL)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import xyz.jpenilla.runtask.task.RunWithPlugins
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.deleteIfExists
|
||||
|
||||
tasks {
|
||||
withType<RunWithPlugins> {
|
||||
val exampleExpansionProviderProject = project(":miniplaceholders-example-expansion-provider")
|
||||
val exampleExpansionJarTask = exampleExpansionProviderProject.tasks.named<Jar>("jar")
|
||||
dependsOn(exampleExpansionJarTask)
|
||||
doFirst {
|
||||
val folderName = if (project.name.contains("velocity")) "miniplaceholders" else "MiniPlaceholders"
|
||||
val expansionsDirectory = runDirectory.get().file("plugins/$folderName/expansions").asFile.toPath()
|
||||
if (Files.exists(expansionsDirectory)) {
|
||||
Files.newDirectoryStream(expansionsDirectory).use {
|
||||
it.forEach { file ->
|
||||
file.deleteIfExists()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Files.createDirectories(expansionsDirectory)
|
||||
}
|
||||
val exampleExpansionFile = exampleExpansionJarTask.get().archiveFile.get().asFile.toPath()
|
||||
Files.copy(
|
||||
exampleExpansionFile,
|
||||
expansionsDirectory.resolve(exampleExpansionFile.fileName),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,8 @@ tasks {
|
||||
archiveClassifier.set("")
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
relocate("net.william278.desertwell", "io.github.miniplaceholders.libs.desertwell")
|
||||
relocate("org.incendo.cloud", "io.github.miniplaceholders.libs.cloud")
|
||||
// if (project.simpleName() != "sponge") {
|
||||
// relocate("io.leangen.geantyref", "io.github.miniplaceholders.libs.geantyref")
|
||||
// }
|
||||
relocate("org.bstats", "io.github.miniplaceholders.libs.bstats")
|
||||
|
||||
destinationDirectory.set(file("${project.rootDir}/jar"))
|
||||
}
|
||||
build {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "2.2.20" apply false
|
||||
kotlin("jvm") version "2.4.21" apply false
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -14,6 +14,7 @@ dependencies {
|
||||
compileOnly(libs.adventure.minimessage)
|
||||
compileOnly(libs.jspecify)
|
||||
compileOnly(libs.brigadier)
|
||||
compileOnly(libs.bstats.core)
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.github.miniplaceholders.common.loader.ExpansionProviderLoader;
|
||||
import io.github.miniplaceholders.common.loader.FailedToLoadExpansion;
|
||||
import io.github.miniplaceholders.common.loader.ProviderLoadResult;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
@@ -23,13 +24,13 @@ public interface PlaceholdersPlugin {
|
||||
default void registerPlatformCommand() {
|
||||
}
|
||||
|
||||
default void loadProvidedExpansions(Path providersFolderDirectory) throws Exception {
|
||||
default void loadProvidedExpansions(final Path providersFolderDirectory) throws Exception {
|
||||
final List<Expansion> loadedExpansions = new ArrayList<>();
|
||||
final PlatformData platformData = new PlatformData(this.platformServerInstance(), this);
|
||||
final Injector injector = Injector.create(binder -> binder.bind(PlatformData.class).toInstance(platformData));
|
||||
for (ExpansionProvider provider : ExpansionProviderLoader.loadProvidersFromFolder(providersFolderDirectory)) {
|
||||
injector.injectMembers(provider);
|
||||
ProviderLoadResult loadResult = tryLoad(provider, provider.loadRequirement());
|
||||
for (Class<?> providerClass : ExpansionProviderLoader.loadProvidersFromFolder(providersFolderDirectory)) {
|
||||
final ExpansionProvider provider = (ExpansionProvider) injector.getInstance(providerClass);
|
||||
final ProviderLoadResult loadResult = tryLoad(provider, provider.loadRequirement());
|
||||
final ExpansionProvider loadedProvider = loadResult.provider();
|
||||
if (loadedProvider != null) {
|
||||
final Expansion loadedExpansion = loadedProvider.provideExpansion();
|
||||
@@ -39,7 +40,7 @@ public interface PlaceholdersPlugin {
|
||||
}
|
||||
final FailedToLoadExpansion failedToLoad = loadResult.failed();
|
||||
logError(Component.text("The expansion "
|
||||
+ provider.getClass() +
|
||||
+ providerClass +
|
||||
" could not be loaded because the requirement " + failedToLoad.requirement() + " could not be resolved",
|
||||
NamedTextColor.RED));
|
||||
}
|
||||
@@ -51,11 +52,13 @@ public interface PlaceholdersPlugin {
|
||||
|
||||
final Component expansionsInfo = loadedExpansions.stream()
|
||||
.map(this::expansionInfo)
|
||||
// Adventure 5.x/4.x support
|
||||
.map(ComponentLike::asComponent)
|
||||
.collect(Component.toComponent(Component.text(", ", NamedTextColor.WHITE)));
|
||||
logInfo(Component.text("Loaded expansions: ", NamedTextColor.GREEN).append(expansionsInfo));
|
||||
}
|
||||
|
||||
private Component expansionInfo(Expansion expansion) {
|
||||
private ComponentLike expansionInfo(Expansion expansion) {
|
||||
final TextComponent.Builder builder = Component.text();
|
||||
builder.append(Component.text(expansion.name(), NamedTextColor.AQUA));
|
||||
final String author = expansion.author();
|
||||
@@ -84,7 +87,7 @@ public interface PlaceholdersPlugin {
|
||||
);
|
||||
}
|
||||
builder.append(Component.text(']', NamedTextColor.DARK_GRAY));
|
||||
return builder.build();
|
||||
return builder;
|
||||
}
|
||||
|
||||
default ProviderLoadResult tryLoad(final ExpansionProvider provider, final LoadRequirement loadRequirement) {
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
package io.github.miniplaceholders.common.command;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AudienceConverter {
|
||||
@Nullable Audience convert(@NotNull String string);
|
||||
@Nullable Audience convert(@NonNull String string);
|
||||
}
|
||||
+1
-1
@@ -80,7 +80,7 @@ public final class CommandConstants {
|
||||
)
|
||||
.append(newline(), miniMessage().deserialize(
|
||||
"<gradient:aqua:#94d1ff>" + command + "</gradient> <aqua>expansions</aqua>")
|
||||
.clickEvent(ClickEvent.runCommand(command + " help"))
|
||||
.clickEvent(ClickEvent.runCommand(command + " expansions"))
|
||||
)
|
||||
.append(newline(), FOOTER)
|
||||
.build();
|
||||
|
||||
@@ -8,4 +8,6 @@ import org.jspecify.annotations.NullMarked;
|
||||
@FunctionalInterface
|
||||
public interface PermissionTester {
|
||||
TriState permissionValue(Audience audience, String permission);
|
||||
|
||||
PermissionTester NO_OP = (audience, permission) -> TriState.NOT_SET;
|
||||
}
|
||||
+11
-15
@@ -21,7 +21,7 @@ import java.util.jar.JarInputStream;
|
||||
@NullMarked
|
||||
public final class ExpansionProviderLoader {
|
||||
|
||||
public static List<ExpansionProvider> loadProvidersFromFolder(final Path folferPath) throws Exception {
|
||||
public static List<Class<?>> loadProvidersFromFolder(final Path folferPath) throws Exception {
|
||||
if (Files.notExists(folferPath)) {
|
||||
try {
|
||||
Files.createDirectories(folferPath);
|
||||
@@ -32,7 +32,7 @@ public final class ExpansionProviderLoader {
|
||||
}
|
||||
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(folferPath,
|
||||
filtered -> Files.isRegularFile(filtered) && filtered.toString().endsWith(".jar"))) {
|
||||
final List<ExpansionProvider> providerList = new ArrayList<>();
|
||||
final List<Class<?>> providerList = new ArrayList<>();
|
||||
for (final Path possibleProviderPath : stream) {
|
||||
loadPossibleProviderFromPath(possibleProviderPath, providerList);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public final class ExpansionProviderLoader {
|
||||
|
||||
private static void loadPossibleProviderFromPath(
|
||||
final Path filePath,
|
||||
final List<ExpansionProvider> providers
|
||||
final List<Class<?>> providers
|
||||
) throws Exception {
|
||||
String mainClassName = null;
|
||||
try (final JarInputStream jarStream = new JarInputStream(Files.newInputStream(filePath))) {
|
||||
@@ -58,9 +58,7 @@ public final class ExpansionProviderLoader {
|
||||
mainClassName = properties.getProperty("provider-class");
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
throw new IOException(
|
||||
"Unable to read expansion_provider.properties from " + filePath + "file",
|
||||
e);
|
||||
throw new IOException("Unable to read expansion_provider.properties from " + filePath + "file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,13 +72,15 @@ public final class ExpansionProviderLoader {
|
||||
|
||||
private static void loadFoundProvider(
|
||||
final String providerClass,
|
||||
final List<ExpansionProvider> providers,
|
||||
final List<Class<?>> providers,
|
||||
final Path providerPath
|
||||
) throws Exception {
|
||||
//noinspection resource
|
||||
final URLClassLoader classLoader = new URLClassLoader(new URL[] {
|
||||
providerPath.toUri().toURL(),
|
||||
}, ExpansionProviderLoader.class.getClassLoader());
|
||||
final URLClassLoader classLoader = new URLClassLoader(
|
||||
"MiniPlaceholders ClassLoader",
|
||||
new URL[] { providerPath.toUri().toURL() },
|
||||
ExpansionProviderLoader.class.getClassLoader()
|
||||
);
|
||||
Class<?> mainClass;
|
||||
try {
|
||||
mainClass = classLoader.loadClass(providerClass);
|
||||
@@ -90,10 +90,6 @@ public final class ExpansionProviderLoader {
|
||||
if (!ExpansionProvider.class.isAssignableFrom(mainClass) || mainClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
providers.add((ExpansionProvider) mainClass.getConstructors()[0].newInstance());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to create expansion provider from file " + providerPath, e);
|
||||
}
|
||||
providers.add(mainClass);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package io.github.miniplaceholders.common.metrics;
|
||||
|
||||
import io.github.miniplaceholders.api.MiniPlaceholders;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public final class LoadedExpansionsMetric implements Callable<Integer> {
|
||||
@Override
|
||||
public Integer call() {
|
||||
return MiniPlaceholders.expansionsAvailable().size();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package io.github.miniplaceholders.connect;
|
||||
public enum InternalPlatform {
|
||||
|
||||
PAPER, VELOCITY,
|
||||
FABRIC, SPONGE;
|
||||
FABRIC, SPONGE, MINESTOM;
|
||||
|
||||
private static InternalPlatform actualPlatform;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
alias(libs.plugins.blossom)
|
||||
}
|
||||
|
||||
version = "1.0.0"
|
||||
version = "1.4.0"
|
||||
|
||||
dependencies {
|
||||
compileOnly(projects.miniplaceholdersApi)
|
||||
|
||||
+52
-24
@@ -3,34 +3,62 @@ package io.miniplaceholders.provider.example;
|
||||
import io.github.miniplaceholders.api.Expansion;
|
||||
import io.github.miniplaceholders.api.provider.ExpansionProvider;
|
||||
import io.github.miniplaceholders.api.provider.LoadRequirement;
|
||||
import io.github.miniplaceholders.api.provider.PlatformData;
|
||||
import io.github.miniplaceholders.api.types.Platform;
|
||||
import io.github.miniplaceholders.provider.example.ExpansionConstants;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import team.unnamed.inject.Inject;
|
||||
|
||||
public final class ExampleProvider implements ExpansionProvider {
|
||||
// For advanced usage only
|
||||
@team.unnamed.inject.Inject
|
||||
private io.github.miniplaceholders.api.provider.PlatformData platformData;
|
||||
public record ExampleProvider(PlatformData platformData) implements ExpansionProvider {
|
||||
@Inject
|
||||
public ExampleProvider {}
|
||||
|
||||
@Override
|
||||
public Expansion provideExpansion() {
|
||||
@Override
|
||||
public Expansion provideExpansion() {
|
||||
return Expansion.builder("example")
|
||||
.author("MiniPlaceholders Contributors")
|
||||
.globalPlaceholder("test", (queue, context) ->
|
||||
Tag.preProcessParsed("""
|
||||
Platform Instance Class: %s
|
||||
MiniPlaceholders Instance Class: %s
|
||||
""".formatted(
|
||||
platformData.serverInstance(),
|
||||
platformData.complementInstance()
|
||||
)))
|
||||
.audiencePlaceholder("audience", (audience, queue, ctx) -> Tag.preProcessParsed("""
|
||||
Audience Instance Class: %s
|
||||
MiniPlaceholders Instance Class: %s
|
||||
""".formatted(
|
||||
audience,
|
||||
platformData.complementInstance()
|
||||
)))
|
||||
.relationalPlaceholder("test", (audience, relational, queue, ctx) -> Tag.preProcessParsed("""
|
||||
Audience Instance Class: %s
|
||||
Relational Instance Class: %s
|
||||
Is Audience equals Relational? %s
|
||||
MiniPlaceholders Instance Class: %s
|
||||
""".formatted(
|
||||
audience,
|
||||
relational,
|
||||
audience.equals(relational),
|
||||
platformData.complementInstance()
|
||||
)))
|
||||
.version(ExpansionConstants.VERSION)
|
||||
.build();
|
||||
}
|
||||
|
||||
return Expansion.builder("example")
|
||||
.version("2.0.0")
|
||||
.author("MiniPlaceholders Contributors")
|
||||
.globalPlaceholder("test", (queue, context) ->
|
||||
Tag.preProcessParsed("""
|
||||
Platform Instance Class: %s
|
||||
MiniPlaceholders Instance Class: %s
|
||||
""".formatted(
|
||||
platformData.serverInstance(),
|
||||
platformData.complementInstance())))
|
||||
.version(ExpansionConstants.VERSION)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadRequirement loadRequirement() {
|
||||
return LoadRequirement.allOf(LoadRequirement.allOf(LoadRequirement.platform(Platform.VELOCITY)));
|
||||
}
|
||||
@Override
|
||||
public LoadRequirement loadRequirement() {
|
||||
return LoadRequirement.anyOf(
|
||||
LoadRequirement.platform(Platform.SPONGE),
|
||||
LoadRequirement.allOf(
|
||||
LoadRequirement.requiredComplement(
|
||||
"MiniPlaceholders",
|
||||
"miniplaceholders"
|
||||
),
|
||||
LoadRequirement.platform(Platform.PAPER)
|
||||
),
|
||||
LoadRequirement.requiredClass("io.github.miniplaceholders.common.command.node.PlayerCompleterNode")
|
||||
);
|
||||
}
|
||||
}
|
||||
+49
-15
@@ -1,23 +1,35 @@
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.deleteIfExists
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.fabric.loom)
|
||||
id("miniplaceholders.auto.module")
|
||||
id("quiet-fabric-loom")
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://central.sonatype.com/repository/maven-snapshots/") {
|
||||
name = "sonatype-snapshots"
|
||||
mavenContent {
|
||||
snapshotsOnly()
|
||||
}
|
||||
}
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
val shade: Configuration by configurations.creating
|
||||
|
||||
dependencies {
|
||||
minecraft(libs.minecraft)
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation(libs.fabric.loader)
|
||||
modImplementation(libs.fabric.api)
|
||||
compileOnly(libs.fabric.loader)
|
||||
compileOnly(libs.fabric.api)
|
||||
|
||||
includeDependency(libs.adventure.platform.fabric)
|
||||
includeDependency(libs.adventure.serializer.legacy)
|
||||
includeDependency(libs.adventure.minimessage)
|
||||
includeDependency(libs.luckopermissionsapi)
|
||||
includeDependency(libs.desertwell)
|
||||
includeDependency(libs.unnamedinject)
|
||||
includeDependency(libs.desertwell)
|
||||
|
||||
shadeModule(projects.miniplaceholdersApi)
|
||||
shadeModule(projects.miniplaceholdersCommon)
|
||||
@@ -25,21 +37,19 @@ dependencies {
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.shadeModule(module: ProjectDependency) {
|
||||
shade(module) {
|
||||
implementation(module) {
|
||||
isTransitive = false
|
||||
}
|
||||
implementation(module) {
|
||||
include(module) {
|
||||
isTransitive = false
|
||||
}
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.includeDependency(dependency: Any) {
|
||||
modImplementation(dependency)
|
||||
implementation(dependency)
|
||||
include(dependency)
|
||||
}
|
||||
|
||||
|
||||
|
||||
tasks {
|
||||
val projectVersion = project.version
|
||||
val rootDir = project.rootDir
|
||||
@@ -49,13 +59,37 @@ tasks {
|
||||
expand("version" to projectVersion)
|
||||
}
|
||||
}
|
||||
remapJar {
|
||||
inputFile.set(shadowJar.get().archiveFile)
|
||||
jar {
|
||||
archiveFileName.set("MiniPlaceholders-Fabric-${projectVersion}.jar")
|
||||
destinationDirectory.set(file("${rootDir}/jar"))
|
||||
}
|
||||
shadowJar {
|
||||
configurations = listOf(shade)
|
||||
// I know it's exactly the same logic for all modules,
|
||||
// but for some reason in this module it only works
|
||||
// if it's declared in the same project configuration
|
||||
// and not with a plugin like with all other projects...
|
||||
// ¯\_(ツ)_/¯
|
||||
runServer {
|
||||
val exampleExpansionProviderProject = project(":miniplaceholders-example-expansion-provider")
|
||||
val exampleExpansionJarTask = exampleExpansionProviderProject.tasks.named<Jar>("jar")
|
||||
dependsOn(exampleExpansionJarTask)
|
||||
doFirst {
|
||||
val expansionsDirectory = projectDir.resolve("run/config/miniplaceholders/expansions").toPath()
|
||||
if (Files.exists(expansionsDirectory)) {
|
||||
Files.newDirectoryStream(expansionsDirectory).use {
|
||||
it.forEach { file ->
|
||||
file.deleteIfExists()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Files.createDirectories(expansionsDirectory)
|
||||
}
|
||||
val exampleExpansionFile = exampleExpansionJarTask.get().archiveFile.get().asFile.toPath()
|
||||
Files.copy(
|
||||
exampleExpansionFile,
|
||||
expansionsDirectory.resolve(exampleExpansionFile.fileName),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ public final class FabricMod implements DedicatedServerModInitializer, Placehold
|
||||
return switch (Permissions.getPermissionValue(commandSourceStack, permission)) {
|
||||
case TRUE -> TriState.TRUE;
|
||||
case FALSE -> TriState.FALSE;
|
||||
case DEFAULT -> commandSourceStack.hasPermission(3) ? TriState.TRUE : TriState.NOT_SET;
|
||||
case DEFAULT -> commandSourceStack.permissions()
|
||||
.hasPermission(net.minecraft.server.permissions.Permissions.COMMANDS_GAMEMASTER)
|
||||
? TriState.TRUE : TriState.NOT_SET;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
]
|
||||
},
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.19",
|
||||
"fabric": "*",
|
||||
"java": ">=21",
|
||||
"adventure-platform-fabric": "~6.6.0",
|
||||
"minecraft": ">=1.21.6 <=1.21.8",
|
||||
"fabric-permissions-api-v0": "~0.4.1"
|
||||
"fabricloader": ">=0.18.0",
|
||||
"fabric-api": "*",
|
||||
"java": ">=25",
|
||||
"adventure-platform-fabric": ">6.8.0",
|
||||
"minecraft": ">=26.2",
|
||||
"fabric-permissions-api-v0": ">=0.7.0"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
group = io.github.miniplaceholders
|
||||
version = 3.1.0-SNAPSHOT
|
||||
version = 3.2.2-SNAPSHOT
|
||||
description = MiniMessage Component-based Placeholders API
|
||||
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
|
||||
+46
-29
@@ -2,59 +2,76 @@ metadata.format.version = "1.1"
|
||||
|
||||
[versions]
|
||||
|
||||
velocity = "3.4.0-SNAPSHOT"
|
||||
paper = "1.21.8-R0.1-SNAPSHOT"
|
||||
minecraft = "1.21.8"
|
||||
|
||||
runtask = "3.0.0"
|
||||
blossom = "2.1.0"
|
||||
shadow = "9.2.2"
|
||||
jmh = "0.7.3"
|
||||
dokka = "2.0.0"
|
||||
|
||||
adventure = "4.24.0"
|
||||
adventureModded = "6.6.0"
|
||||
kotlin = "2.2.20"
|
||||
|
||||
fabric-api = "0.133.14+1.21.9"
|
||||
fabric-loader = "0.17.2"
|
||||
# Platform
|
||||
minecraft = "26.1"
|
||||
paper = "1.21.11-R0.1-SNAPSHOT"
|
||||
velocity = "4.3.0"
|
||||
minestom = "2026.10.07-26.2"
|
||||
fabric-loader = "0.20.1"
|
||||
fabric-api = "0.145.0+26.1"
|
||||
|
||||
# Libraries
|
||||
kotlin = "2.4.21"
|
||||
adventure = "5.2.0"
|
||||
adventureModded = "7.2.0"
|
||||
desertwell = "2.0.4"
|
||||
bstats = "3.2.1"
|
||||
jspecify = "1.0.1"
|
||||
|
||||
# Gradle Plugins
|
||||
runtask = "3.1.0"
|
||||
blossom = "2.2.0"
|
||||
shadow = "9.6.1"
|
||||
jmh = "0.7.3"
|
||||
dokka = "2.2.0"
|
||||
|
||||
[libraries]
|
||||
|
||||
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
||||
# Platforms
|
||||
minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" }
|
||||
|
||||
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
|
||||
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
||||
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
minestom = { group = "net.minestom", name = "minestom", version.ref = "minestom" }
|
||||
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" }
|
||||
luckopermissionsapi = { group = "me.lucko", name = "fabric-permissions-api", version = "0.4.1" }
|
||||
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
|
||||
|
||||
# Adventure
|
||||
adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
|
||||
adventure-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
|
||||
adventure-platform-fabric = { group = "net.kyori", name = "adventure-platform-fabric", version.ref = "adventureModded" }
|
||||
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" }
|
||||
|
||||
# Build-Logic Gradle Plugins
|
||||
plugin-shadow = { module = "com.gradleup.shadow:shadow-gradle-plugin", version.ref = "shadow" }
|
||||
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
plugin-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
plugin-runtask = { module = "xyz.jpenilla.run-velocity:xyz.jpenilla.run-velocity.gradle.plugin", version.ref = "runtask" }
|
||||
|
||||
# Libraries
|
||||
desertwell = { group = "net.william278", name = "DesertWell", version.ref = "desertwell" }
|
||||
|
||||
junit-bom = "org.junit:junit-bom:6.0.0"
|
||||
jspecify = "org.jspecify:jspecify:1.0.0"
|
||||
|
||||
junit-bom = "org.junit:junit-bom:6.1.3"
|
||||
jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" }
|
||||
luckopermissionsapi = { group = "me.lucko", name = "fabric-permissions-api", version = "0.7.0" }
|
||||
unnamedinject = "team.unnamed:inject:2.0.1"
|
||||
brigadier = "com.mojang:brigadier:1.0.500"
|
||||
slf4j = "org.slf4j:slf4j-api:2.0.20"
|
||||
|
||||
# Bstats
|
||||
bstats-core = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" }
|
||||
bstats-velocity = { group = "org.bstats", name = "bstats-velocity", version.ref = "bstats" }
|
||||
bstats-sponge = { group = "org.bstats", name = "bstats-sponge", version.ref = "bstats" }
|
||||
bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
|
||||
|
||||
[plugins]
|
||||
|
||||
# Platform Plugins
|
||||
runpaper = { id = "xyz.jpenilla.run-paper", version.ref = "runtask" }
|
||||
runvelocity = { id = "xyz.jpenilla.run-velocity", version.ref = "runtask" }
|
||||
fabric-loom = { id = "net.fabricmc.fabric-loom", version = "1.18.4"}
|
||||
spongegradle = { id = "org.spongepowered.gradle.plugin", version = "2.5.1" }
|
||||
|
||||
# General Plugins
|
||||
blossom = { id = "net.kyori.blossom", version.ref = "blossom" }
|
||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||
jmh = { id = "me.champeau.jmh", version.ref = "jmh" }
|
||||
idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.3" }
|
||||
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
|
||||
idea-ext = { id = "org.jetbrains.gradle.plugin.idea-ext", version = "1.4.1" }
|
||||
Vendored
BIN
Binary file not shown.
+3
-1
@@ -1,7 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
# gradlew start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
@@ -29,7 +29,7 @@
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
# ksh gradlew
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
||||
Vendored
+52
-33
@@ -19,12 +19,39 @@
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem gradlew startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
@rem Catch executions from older scripts and ensure they exit cleanly.
|
||||
@rem This can be removed once we can be reasonably confident that few people
|
||||
@rem will be migrating directly to this new wrapper.
|
||||
goto afterSafetyNet
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
goto exitWithErrorLevel
|
||||
:afterSafetyNet
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@@ -45,13 +72,14 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
1>&2 echo.
|
||||
1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
1>&2 echo.
|
||||
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||
1>&2 echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
goto exitWithErrorLevel
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
@@ -59,35 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
1>&2 echo.
|
||||
1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
1>&2 echo.
|
||||
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||
1>&2 echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
goto exitWithErrorLevel
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
@rem Execute gradlew
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
@@ -1,11 +1,12 @@
|
||||
import com.vanniktech.maven.publish.KotlinJvm
|
||||
import com.vanniktech.maven.publish.JavadocJar
|
||||
import com.vanniktech.maven.publish.SourcesJar
|
||||
import java.time.LocalDate
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("com.vanniktech.maven.publish")
|
||||
id("org.jetbrains.dokka") version "2.0.0"
|
||||
alias(libs.plugins.dokka)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -18,7 +19,7 @@ dependencies {
|
||||
kotlin {
|
||||
explicitApi()
|
||||
jvmToolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
languageVersion.set(JavaLanguageVersion.of(25))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,12 +76,8 @@ mavenPublishing {
|
||||
}
|
||||
}
|
||||
configure(KotlinJvm(
|
||||
// configures the -javadoc artifact, possible values:
|
||||
// - `JavadocJar.None()` don't publish this artifact
|
||||
// - `JavadocJar.Empty()` publish an empty jar
|
||||
// - `JavadocJar.Dokka("dokkaHtml")` when using Kotlin with Dokka, where `dokkaHtml` is the name of the Dokka task that should be used as input
|
||||
javadocJar = JavadocJar.Dokka("dokkaGeneratePublicationHtml"),
|
||||
sourcesJar = true,
|
||||
sourcesJar = SourcesJar.Sources(),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#run minestom files
|
||||
/run
|
||||
/test
|
||||
@@ -0,0 +1,96 @@
|
||||
import java.time.LocalDate
|
||||
|
||||
plugins {
|
||||
id("miniplaceholders.shadow")
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.runtask")
|
||||
`java-library`
|
||||
id("com.vanniktech.maven.publish")
|
||||
}
|
||||
|
||||
val shadowInclude by configurations.creating
|
||||
|
||||
configurations {
|
||||
compileOnly.get().extendsFrom(shadowInclude)
|
||||
testImplementation.get().extendsFrom(shadowInclude)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.minestom)
|
||||
compileOnly(libs.adventure.api)
|
||||
compileOnly(libs.slf4j)
|
||||
annotationProcessor(libs.minestom)
|
||||
shadowInclude(projects.miniplaceholdersCommon)
|
||||
api(projects.miniplaceholdersApi)
|
||||
shadowInclude(projects.miniplaceholdersConnect)
|
||||
|
||||
testImplementation(libs.minestom)
|
||||
testImplementation(libs.adventure.api)
|
||||
testImplementation(libs.adventure.minimessage)
|
||||
testImplementation("ch.qos.logback:logback-classic:1.6.6") // logger
|
||||
testImplementation("com.google.guava:guava:33.7.2-jre")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
configurations = listOf(shadowInclude)
|
||||
}
|
||||
test {
|
||||
failOnNoDiscoveredTests = false
|
||||
}
|
||||
}
|
||||
|
||||
mavenPublishing {
|
||||
publishToMavenCentral()
|
||||
signAllPublications()
|
||||
coordinates(project.group as String, "miniplaceholders-minestom", project.version as String)
|
||||
|
||||
pom {
|
||||
name.set(project.name)
|
||||
description.set(project.description)
|
||||
inceptionYear.set(LocalDate.now().year.toString())
|
||||
url.set("https://github.com/MiniPlaceholders/MiniPlaceholders")
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache License, Version 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
distribution.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id.set("4drian3d")
|
||||
name.set("Adrian Gonzales")
|
||||
email.set("adriangonzalesval@gmail.com")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection.set("scm:git:https://github.com/MiniPlaceholders/MiniPlaceholders.git")
|
||||
developerConnection.set("scm:git:ssh://git@github.com/MiniPlaceholders/MiniPlaceholders.git")
|
||||
url.set("https://github.com/MiniPlaceholders/MiniPlaceholders")
|
||||
}
|
||||
ciManagement {
|
||||
name.set("GitHub Actions")
|
||||
url.set("https://github.com/MiniPlaceholders/MiniPlaceholders/actions")
|
||||
}
|
||||
issueManagement {
|
||||
name.set("GitHub")
|
||||
url.set("https://github.com/MiniPlaceholders/MiniPlaceholders/issues")
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
named("runtimeElements") {
|
||||
outgoing {
|
||||
artifacts.clear()
|
||||
artifact(tasks.shadowJar)
|
||||
}
|
||||
}
|
||||
named("apiElements") {
|
||||
outgoing {
|
||||
artifacts.clear()
|
||||
artifact(tasks.shadowJar)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package io.github.miniplaceholders.minestom;
|
||||
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.common.command.PermissionTester;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import io.github.miniplaceholders.minestom.command.MinestomCommand;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public final class MinestomMiniPlaceholders implements PlaceholdersPlugin {
|
||||
private static final ComponentLogger LOGGER = ComponentLogger.logger("miniplaceholders");
|
||||
private final PermissionTester permissionTester;
|
||||
|
||||
private MinestomMiniPlaceholders(PermissionTester permissionTester) {
|
||||
this.permissionTester = permissionTester;
|
||||
}
|
||||
|
||||
public static MinestomMiniPlaceholders initialize(Path dataDirectory, PermissionTester permissionTester) {
|
||||
InternalPlatform.platform(InternalPlatform.MINESTOM);
|
||||
LOGGER.info(Component.text("Initializing MiniPlaceholders", NamedTextColor.GREEN));
|
||||
final MinestomMiniPlaceholders miniPlaceholders = new MinestomMiniPlaceholders(permissionTester);
|
||||
miniPlaceholders.registerPlatformCommand();
|
||||
|
||||
try {
|
||||
miniPlaceholders.loadProvidedExpansions(dataDirectory.resolve("expansions"));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Unable to load expansion providers", e);
|
||||
}
|
||||
|
||||
return miniPlaceholders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes MiniPlaceholders with a default no-op permission tester.
|
||||
* This is not recommended for production use!
|
||||
*/
|
||||
public static MinestomMiniPlaceholders initialize(final Path dataDirectory) {
|
||||
return MinestomMiniPlaceholders.initialize(dataDirectory, PermissionTester.NO_OP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlatformCommand() {
|
||||
MinecraftServer.getCommandManager().register(new MinestomCommand(permissionTester));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean platformHasComplementLoaded(String complementName) {
|
||||
return false; // Minestom doesn't plugins.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object platformServerInstance() {
|
||||
return MinecraftServer.getServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(Component component) {
|
||||
LOGGER.info(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(Component component) {
|
||||
LOGGER.error(component);
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
package io.github.miniplaceholders.minestom.command;
|
||||
|
||||
import io.github.miniplaceholders.common.command.AudienceConverter;
|
||||
import io.github.miniplaceholders.common.command.PermissionTester;
|
||||
import io.github.miniplaceholders.common.command.PlaceholderCommandExecutor;
|
||||
import io.github.miniplaceholders.common.command.PlayersNameProvider;
|
||||
import io.github.miniplaceholders.common.command.node.*;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.minestom.server.command.builder.CommandExecutor;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||
import net.minestom.server.command.builder.condition.CommandCondition;
|
||||
import net.minestom.server.command.builder.suggestion.SuggestionEntry;
|
||||
import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MinestomCommand extends Command {
|
||||
private final PermissionTester permissionTester;
|
||||
private final PlayersNameProvider playerSuggestions;
|
||||
private final AudienceConverter audienceConverter;
|
||||
|
||||
public MinestomCommand(PermissionTester permissionTester) {
|
||||
super("miniplaceholders");
|
||||
|
||||
this.permissionTester = permissionTester;
|
||||
this.playerSuggestions = () -> MinecraftServer.getConnectionManager().getOnlinePlayers()
|
||||
.stream()
|
||||
.map(Player::getName)
|
||||
.map(PlainTextComponentSerializer.plainText()::serialize)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
this.audienceConverter = string -> MinecraftServer.getConnectionManager().getOnlinePlayerByUsername(string);
|
||||
|
||||
final RootNode rootNode = new RootNode(permissionTester);
|
||||
|
||||
this.setCondition(new WrappingCondition(rootNode::hasPermission));
|
||||
this.setDefaultExecutor(new WrappingExecutor(rootNode::execute));
|
||||
|
||||
this.addSubcommands(new ExpansionsCommand(), new HelpCommand(), new ParseCommand(), new ParseRelCommand());
|
||||
}
|
||||
|
||||
private class ExpansionsCommand extends Command {
|
||||
public ExpansionsCommand() {
|
||||
super("expansions");
|
||||
|
||||
final ExpansionsNode expansionsNode = new ExpansionsNode(permissionTester);
|
||||
|
||||
this.setCondition(new WrappingCondition(expansionsNode::hasPermission));
|
||||
this.setDefaultExecutor(new WrappingExecutor(expansionsNode::showExpansions));
|
||||
}
|
||||
}
|
||||
|
||||
private class HelpCommand extends Command {
|
||||
public HelpCommand() {
|
||||
super("help");
|
||||
|
||||
final HelpNode helpNode = new HelpNode(permissionTester);
|
||||
|
||||
this.setCondition(new WrappingCondition(helpNode::hasPermission));
|
||||
this.setDefaultExecutor(new WrappingExecutor(helpNode::execute));
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseCommand extends Command {
|
||||
public ParseCommand() {
|
||||
super("parse");
|
||||
|
||||
final ParseNode parseNode = new ParseNode(playerSuggestions, audienceConverter, permissionTester);
|
||||
final Argument<String> sourceArgument = ArgumentType.String("source")
|
||||
.setSuggestionCallback((_, _, suggestion) -> parseNode.providePlayerSuggestions()
|
||||
.stream()
|
||||
.filter(s -> {
|
||||
final String[] args = suggestion.getInput().replace("\0", "").split(" ");
|
||||
return args.length < 3 || s.toLowerCase().startsWith(args[2].toLowerCase());
|
||||
})
|
||||
.map(SuggestionEntry::new)
|
||||
.forEach(suggestion::addEntry));
|
||||
final Argument<String[]> messageArgument = ArgumentType.StringArray("message");
|
||||
|
||||
this.setCondition(new WrappingCondition(parseNode::hasPermission));
|
||||
this.addSyntax((sender, context) -> {
|
||||
final String source = context.get(sourceArgument);
|
||||
final String[] message = context.get(messageArgument);
|
||||
|
||||
parseNode.parseString(sender, source, String.join(" ", message));
|
||||
}, sourceArgument, messageArgument);
|
||||
}
|
||||
}
|
||||
|
||||
private class ParseRelCommand extends Command {
|
||||
public ParseRelCommand() {
|
||||
super("parserel");
|
||||
|
||||
final ParseRelNode parseRelNode = new ParseRelNode(playerSuggestions, audienceConverter, permissionTester);
|
||||
final Argument<String> sourceArgument = ArgumentType.String("source")
|
||||
.setSuggestionCallback((_, _, suggestion) -> parseRelNode.providePlayerSuggestions()
|
||||
.stream()
|
||||
.filter(s -> {
|
||||
final String[] args = suggestion.getInput().replace("\0", "").split(" ");
|
||||
return args.length < 3 || s.toLowerCase().startsWith(args[2].toLowerCase());
|
||||
})
|
||||
.map(SuggestionEntry::new)
|
||||
.forEach(suggestion::addEntry));
|
||||
final Argument<String> relationalSourceArgument = ArgumentType.String("relational")
|
||||
.setSuggestionCallback((_, _, suggestion) -> parseRelNode.providePlayerSuggestions()
|
||||
.stream()
|
||||
.filter(s -> {
|
||||
final String[] args = suggestion.getInput().replace("\0", "").split(" ");
|
||||
return args.length < 4 || s.toLowerCase().startsWith(args[3].toLowerCase());
|
||||
})
|
||||
.map(SuggestionEntry::new)
|
||||
.forEach(suggestion::addEntry));
|
||||
final Argument<String[]> messageArgument = ArgumentType.StringArray("message");
|
||||
|
||||
this.setCondition(new WrappingCondition(parseRelNode::hasPermission));
|
||||
this.addSyntax((sender, context) -> {
|
||||
final String source = context.get(sourceArgument);
|
||||
final String relationalSource = context.get(relationalSourceArgument);
|
||||
final String[] message = context.get(messageArgument);
|
||||
|
||||
parseRelNode.parseString(sender, source, relationalSource, String.join(" ", message));
|
||||
}, sourceArgument, relationalSourceArgument, messageArgument);
|
||||
}
|
||||
}
|
||||
|
||||
private record WrappingCondition(Predicate<Audience> predicate) implements CommandCondition {
|
||||
@Override
|
||||
public boolean canUse(@NonNull CommandSender sender, @Nullable String commandString) {
|
||||
return predicate.test(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private record WrappingExecutor(PlaceholderCommandExecutor executor) implements CommandExecutor {
|
||||
@Override
|
||||
public void apply(@NonNull CommandSender sender, @NonNull CommandContext context) {
|
||||
executor.execute(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package io.github.miniplaceholders.minestom;
|
||||
|
||||
import io.github.miniplaceholders.minestom.listener.AsyncPlayerConfigurationListener;
|
||||
import net.kyori.adventure.util.TriState;
|
||||
import net.minestom.server.Auth;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.extras.lan.OpenToLAN;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.Duration;
|
||||
|
||||
public class MinestomServer {
|
||||
|
||||
private static final Path MINIPLACEHOLDERS_TEST_FOLDER = Path.of("minestom", "test", "miniplaceholders");
|
||||
private static final Path TEST_EXPANSION_FOLDER = Path.of("example-expansion-provider", "build", "libs");
|
||||
|
||||
static void main() throws IOException {
|
||||
final MinecraftServer server = MinecraftServer.init(new Auth.Online());
|
||||
MinecraftServer.getGlobalEventHandler().addListener(new AsyncPlayerConfigurationListener());
|
||||
MinestomServer.copyTestExpansion();
|
||||
|
||||
MinestomMiniPlaceholders.initialize(
|
||||
MINIPLACEHOLDERS_TEST_FOLDER,
|
||||
(_, _) -> TriState.TRUE
|
||||
);
|
||||
|
||||
OpenToLAN.open();
|
||||
server.start("0.0.0.0", 25565);
|
||||
|
||||
Thread.ofPlatform().start(() -> {
|
||||
try {
|
||||
Thread.sleep(Duration.ofMinutes(2));
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
private static void copyTestExpansion() throws IOException {
|
||||
if (!Files.exists(TEST_EXPANSION_FOLDER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Path expansionsFolder = MINIPLACEHOLDERS_TEST_FOLDER.resolve("expansions");
|
||||
// Delete previous expansions files
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
|
||||
expansionsFolder,
|
||||
file -> file.getFileName().toString().endsWith(".jar"))
|
||||
) {
|
||||
stream.forEach(file -> {
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Copy latest example expansion file
|
||||
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(
|
||||
TEST_EXPANSION_FOLDER,
|
||||
file -> file.getFileName()
|
||||
.toString().startsWith("miniplaceholders-example-expansion-provider"))
|
||||
) {
|
||||
stream.forEach(file -> {
|
||||
if (!Files.exists(expansionsFolder)) {
|
||||
try {
|
||||
Files.createDirectories(expansionsFolder);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
Files.copy(file, expansionsFolder.resolve(file.getFileName()), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
System.out.println("An error occurred while loading expansion provider" + e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package io.github.miniplaceholders.minestom.listener;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.EventListener;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
public class AsyncPlayerConfigurationListener implements EventListener<AsyncPlayerConfigurationEvent> {
|
||||
|
||||
private final Instance instance;
|
||||
|
||||
public AsyncPlayerConfigurationListener() {
|
||||
this.instance = MinecraftServer.getInstanceManager().createInstanceContainer();
|
||||
instance.setGenerator(unit -> unit.modifier().fillHeight(0, 32, Block.GRASS_BLOCK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Class<AsyncPlayerConfigurationEvent> eventType() {
|
||||
return AsyncPlayerConfigurationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Result run(AsyncPlayerConfigurationEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
event.setSpawningInstance(instance);
|
||||
player.setRespawnPoint(new Pos(0, 33, 0));
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.shadow")
|
||||
id("miniplaceholders.runtask")
|
||||
alias(libs.plugins.runpaper)
|
||||
}
|
||||
|
||||
@@ -9,15 +10,17 @@ dependencies {
|
||||
implementation(projects.miniplaceholdersCommon)
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
|
||||
implementation(libs.bstats.bukkit)
|
||||
}
|
||||
|
||||
tasks {
|
||||
runServer {
|
||||
minecraftVersion(libs.versions.minecraft.get())
|
||||
jvmArgs("-Dcom.mojang.eula.agree=true")
|
||||
minecraftVersion(libs.versions.paper.get().substringBefore('-'))
|
||||
}
|
||||
val projectVersion = project.version
|
||||
processResources {
|
||||
//val version = project.version
|
||||
filesMatching("paper-plugin.yml") {
|
||||
expand("version" to projectVersion)
|
||||
}
|
||||
|
||||
@@ -11,16 +11,17 @@ import net.kyori.adventure.util.TriState;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings({"unused", "UnstableApiUsage"})
|
||||
@NullMarked
|
||||
public final class PaperBootstrap implements PluginBootstrap {
|
||||
@Override
|
||||
public void bootstrap(@NotNull BootstrapContext bootstrapContext) {
|
||||
public void bootstrap(final BootstrapContext bootstrapContext) {
|
||||
InternalPlatform.platform(InternalPlatform.PAPER);
|
||||
final LiteralCommandNode<CommandSourceStack> command = BrigadierCommandProvider.provideCommand(
|
||||
"miniplaceholders",
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package io.github.miniplaceholders.paper;
|
||||
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.common.metrics.LoadedExpansionsMetric;
|
||||
import io.github.miniplaceholders.paper.listener.ServerFinishedLoadListener;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
@@ -15,11 +19,9 @@ public final class PaperPlugin extends JavaPlugin implements PlaceholdersPlugin
|
||||
final ComponentLogger componentLogger = getComponentLogger();
|
||||
componentLogger.info(text("Starting MiniPlaceholders Paper", NamedTextColor.GREEN));
|
||||
|
||||
try {
|
||||
this.loadProvidedExpansions(getDataPath().resolve("expansions"));
|
||||
} catch (Throwable e) {
|
||||
componentLogger.error("Unable to load expansion providers", e);
|
||||
}
|
||||
new ServerFinishedLoadListener(this).register();
|
||||
final Metrics metrics = new Metrics(this, 27515);
|
||||
metrics.addCustomChart(new SingleLineChart("loaded_expansions", new LoadedExpansionsMetric()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package io.github.miniplaceholders.paper.listener;
|
||||
|
||||
import io.github.miniplaceholders.paper.PaperPlugin;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerLoadEvent;
|
||||
import org.bukkit.plugin.EventExecutor;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
public record ServerFinishedLoadListener(PaperPlugin plugin) implements Listener, EventExecutor {
|
||||
|
||||
public void register() {
|
||||
plugin.getServer()
|
||||
.getPluginManager()
|
||||
.registerEvent(ServerLoadEvent.class, this, EventPriority.HIGH, this, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final @NonNull Listener listener, final @NonNull Event event) {
|
||||
final ServerLoadEvent loadEvent = (ServerLoadEvent) event;
|
||||
if (loadEvent.getType() != ServerLoadEvent.LoadType.STARTUP) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
plugin.loadProvidedExpansions(plugin.getDataPath().resolve("expansions"));
|
||||
} catch (Throwable e) {
|
||||
plugin.getComponentLogger().error("Unable to load expansion providers", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-16
@@ -16,31 +16,19 @@ pluginManagement {
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
maven("https://central.sonatype.com/repository/maven-snapshots/") {
|
||||
name = "sonatype-snapshots"
|
||||
mavenContent {
|
||||
snapshotsOnly()
|
||||
}
|
||||
}
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://repo.maven.apache.org/maven2/")
|
||||
maven("https://repo.spongepowered.org/repository/")
|
||||
maven("https://jitpack.io") {
|
||||
mavenContent {
|
||||
includeGroup("net.william278")
|
||||
}
|
||||
}
|
||||
maven("https://jitpack.io")
|
||||
maven("https://repo.jpenilla.xyz/snapshots/")
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("quiet-fabric-loom") version "1.11.325"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
id("com.vanniktech.maven.publish") version "0.34.0" apply false
|
||||
kotlin("jvm") version "2.2.20" apply false
|
||||
id("com.vanniktech.maven.publish") version "0.37.0" apply false
|
||||
kotlin("jvm") version "2.4.21" apply false
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
@@ -49,6 +37,7 @@ arrayOf(
|
||||
"kotlin-ext",
|
||||
"common",
|
||||
"paper",
|
||||
"minestom",
|
||||
"velocity",
|
||||
"fabric",
|
||||
"sponge",
|
||||
@@ -56,4 +45,4 @@ arrayOf(
|
||||
).forEach {
|
||||
include("miniplaceholders-$it")
|
||||
project(":miniplaceholders-$it").projectDir = file(it)
|
||||
}
|
||||
}
|
||||
+31
-1
@@ -1,10 +1,13 @@
|
||||
import org.spongepowered.gradle.plugin.config.PluginLoaders
|
||||
import org.spongepowered.plugin.metadata.model.PluginDependency
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.deleteIfExists
|
||||
|
||||
plugins {
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.shadow")
|
||||
id("org.spongepowered.gradle.plugin") version "2.3.0"
|
||||
alias(libs.plugins.spongegradle)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -13,6 +16,7 @@ dependencies {
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
|
||||
compileOnly(libs.jspecify)
|
||||
implementation(libs.bstats.sponge)
|
||||
}
|
||||
|
||||
sponge {
|
||||
@@ -41,3 +45,29 @@ sponge {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
runServer {
|
||||
val exampleExpansionProviderProject = project(":miniplaceholders-example-expansion-provider")
|
||||
val exampleExpansionJarTask = exampleExpansionProviderProject.tasks.named<Jar>("jar")
|
||||
dependsOn(exampleExpansionJarTask)
|
||||
doFirst {
|
||||
val expansionsDirectory = projectDir.resolve("run/config/miniplaceholders/expansions").toPath()
|
||||
if (Files.exists(expansionsDirectory)) {
|
||||
Files.newDirectoryStream(expansionsDirectory).use {
|
||||
it.forEach { file ->
|
||||
file.deleteIfExists()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Files.createDirectories(expansionsDirectory)
|
||||
}
|
||||
val exampleExpansionFile = exampleExpansionJarTask.get().archiveFile.get().asFile.toPath()
|
||||
Files.copy(
|
||||
exampleExpansionFile,
|
||||
expansionsDirectory.resolve(exampleExpansionFile.fileName),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,20 @@ package io.github.miniplaceholders.sponge;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.common.metrics.LoadedExpansionsMetric;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import io.github.miniplaceholders.sponge.command.SpongeCommand;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bstats.sponge.Metrics;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.command.Command;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.lifecycle.RegisterCommandEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StartingEngineEvent;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
import org.spongepowered.plugin.builtin.jvm.Plugin;
|
||||
@@ -28,8 +32,11 @@ public class SpongePlugin implements PlaceholdersPlugin {
|
||||
private Path configDir;
|
||||
@Inject
|
||||
private PluginContainer pluginContainer;
|
||||
@Inject
|
||||
private Metrics.Factory factory;
|
||||
|
||||
private Server server;
|
||||
private Metrics metrics;
|
||||
|
||||
@Listener
|
||||
public void onServerStart(final StartingEngineEvent<Server> event) {
|
||||
@@ -37,11 +44,20 @@ public class SpongePlugin implements PlaceholdersPlugin {
|
||||
InternalPlatform.platform(InternalPlatform.SPONGE);
|
||||
logger.info("Starting MiniPlaceholders Sponge");
|
||||
|
||||
this.metrics = factory.make(27517);
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onLateServerStart(final StartedEngineEvent<Server> event) {
|
||||
try {
|
||||
this.loadProvidedExpansions(configDir.resolve("expansions"));
|
||||
} catch (Throwable e) {
|
||||
logger.error("Unable to load expansion providers", e);
|
||||
}
|
||||
|
||||
// bstats sponge weird initialization workaround
|
||||
this.metrics.startup(null);
|
||||
this.metrics.addCustomChart(new SingleLineChart("expansions_loaded", new LoadedExpansionsMetric()));
|
||||
}
|
||||
|
||||
@Listener
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.github.miniplaceholders.sponge.command;
|
||||
import io.github.miniplaceholders.common.command.*;
|
||||
import io.github.miniplaceholders.common.command.node.*;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.util.TriState;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.*;
|
||||
@@ -22,7 +21,7 @@ import java.util.stream.Collectors;
|
||||
public final class SpongeCommand {
|
||||
public static Command.Parameterized provideCommand() {
|
||||
final AudienceExtractor<CommandCause> audienceExtractor = CommandCause::audience;
|
||||
final PermissionTester permissionTester = (audience, permission) -> TriState.NOT_SET; // Not really used here
|
||||
final PermissionTester permissionTester = PermissionTester.NO_OP; // Not really used here
|
||||
final PlayersNameProvider playerSuggestions = () -> Sponge.server().onlinePlayers()
|
||||
.stream()
|
||||
.map(ServerPlayer::user)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("miniplaceholders.shadow")
|
||||
id("miniplaceholders.auto.module")
|
||||
id("miniplaceholders.runtask")
|
||||
alias(libs.plugins.runvelocity)
|
||||
}
|
||||
|
||||
@@ -10,6 +11,8 @@ dependencies {
|
||||
implementation(projects.miniplaceholdersCommon)
|
||||
implementation(projects.miniplaceholdersApi)
|
||||
implementation(projects.miniplaceholdersConnect)
|
||||
|
||||
implementation(libs.bstats.velocity)
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -15,10 +15,13 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import io.github.miniplaceholders.common.PlaceholdersPlugin;
|
||||
import io.github.miniplaceholders.common.PluginConstants;
|
||||
import io.github.miniplaceholders.common.command.brigadier.BrigadierCommandProvider;
|
||||
import io.github.miniplaceholders.common.metrics.LoadedExpansionsMetric;
|
||||
import io.github.miniplaceholders.connect.InternalPlatform;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bstats.velocity.Metrics;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -41,6 +44,8 @@ public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
private CommandManager commandManager;
|
||||
@Inject
|
||||
private ComponentLogger componentLogger;
|
||||
@Inject
|
||||
private Metrics.Factory metricsFactory;
|
||||
|
||||
@Subscribe(priority = 999)
|
||||
public void onEarlyProxyInitialize(final ProxyInitializeEvent event) {
|
||||
@@ -48,6 +53,9 @@ public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
componentLogger.info(Component.text("Starting MiniPlaceholders Velocity", NamedTextColor.GREEN));
|
||||
|
||||
this.registerPlatformCommand();
|
||||
|
||||
final Metrics metrics = metricsFactory.make(this, 27516);
|
||||
metrics.addCustomChart(new SingleLineChart("expansions_count", new LoadedExpansionsMetric()));
|
||||
}
|
||||
|
||||
@Subscribe(priority = -404)
|
||||
@@ -63,7 +71,7 @@ public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
public void registerPlatformCommand() {
|
||||
final LiteralCommandNode<CommandSource> node = BrigadierCommandProvider.provideCommand(
|
||||
"vminiplaceholders",
|
||||
() -> proxyServer.getAllPlayers()
|
||||
() -> this.proxyServer.getAllPlayers()
|
||||
.stream()
|
||||
.map(Player::getUsername)
|
||||
.collect(Collectors.toCollection(ArrayList::new)),
|
||||
@@ -73,10 +81,10 @@ public final class VelocityPlugin implements PlaceholdersPlugin {
|
||||
.toAdventureTriState()
|
||||
);
|
||||
final BrigadierCommand command = new BrigadierCommand(node);
|
||||
final CommandMeta meta = commandManager.metaBuilder(command)
|
||||
final CommandMeta meta = this.commandManager.metaBuilder(command)
|
||||
.plugin(this)
|
||||
.build();
|
||||
commandManager.register(meta, command);
|
||||
this.commandManager.register(meta, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user