mirror of
https://github.com/PlaceholderAPI/PlaceholderAPI
synced 2026-02-07 12:37:14 +01:00
Compare commits
26 Commits
feature/co
...
2.12.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9022daf07f | ||
|
|
675b305cac | ||
|
|
d49c76c560 | ||
|
|
13e492cf44 | ||
|
|
d561afbb63 | ||
|
|
2a3f4482a0 | ||
|
|
4ee2840a0a | ||
|
|
c52d117f12 | ||
|
|
e307aba414 | ||
|
|
5ea5a18fe8 | ||
|
|
9c1db4b48a | ||
|
|
b233c92ca1 | ||
|
|
1b1d2e61b9 | ||
|
|
2dc5b93133 | ||
|
|
880ddc22b5 | ||
|
|
d378f782b4 | ||
|
|
1f2d969a69 | ||
|
|
cac79a26af | ||
|
|
8b078f9058 | ||
|
|
d3a5d01f55 | ||
|
|
9a677d46a1 | ||
|
|
8116cbb385 | ||
|
|
b9affd0879 | ||
|
|
ec8657015c | ||
|
|
38a86e6d2d | ||
|
|
35376e43ca |
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
Support for specific plugins are provided either by the plugin itself or through expansions. The expansions may be downloaded in-game through the PAPI Expansion Cloud. There are currently over 240+ expansions that support a wide variety of plugins, such as Essentials, Factions, LuckPerms, and Vault.
|
Support for specific plugins are provided either by the plugin itself or through expansions. The expansions may be downloaded in-game through the PAPI Expansion Cloud. There are currently over 240+ expansions that support a wide variety of plugins, such as Essentials, Factions, LuckPerms, and Vault.
|
||||||
|
|
||||||
PlaceholderAPI has been downloaded over 1,700,000 times on Spigot and has been used concurrently on over 45,000 servers, which makes it a must-have for a server of any type or scale.
|
PlaceholderAPI has been downloaded over 2,000,000 times on Spigot and has been used concurrently on over 50,000 servers, which makes it a must-have for a server of any type or scale.
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
If you would like to contribute towards PlaceholderAPI should you take a look at our [Contributing file][contributing] for the ins and outs on how you can do that and what you need to keep in mind.
|
If you would like to contribute towards PlaceholderAPI should you take a look at our [Contributing file][contributing] for the ins and outs on how you can do that and what you need to keep in mind.
|
||||||
|
|||||||
222
build.gradle.kts
222
build.gradle.kts
@@ -3,103 +3,191 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
id("com.github.hierynomus.license") version "0.16.1"
|
// id("com.github.hierynomus.license") version "0.16.1"
|
||||||
id("io.github.goooler.shadow") version "8.1.7"
|
id("io.github.goooler.shadow") version "8.1.7"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
group = "me.clip"
|
||||||
apply(plugin = "java-library")
|
version = "2.12.2-DEV-${System.getProperty("BUILD_NUMBER")}"
|
||||||
apply(plugin = "maven-publish")
|
|
||||||
apply(plugin = "com.github.hierynomus.license")
|
|
||||||
apply(plugin = "io.github.goooler.shadow")
|
|
||||||
|
|
||||||
group = "me.clip"
|
description = "An awesome placeholder provider!"
|
||||||
version = "2.11.8-DEV-${System.getProperty("BUILD_NUMBER")}"
|
|
||||||
|
|
||||||
description = "An awesome placeholder provider!"
|
val paper by sourceSets.creating {
|
||||||
|
java.srcDir("src/paper/java")
|
||||||
|
|
||||||
repositories {
|
// paper can see main code
|
||||||
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
compileClasspath += sourceSets.main.get().output
|
||||||
|
runtimeClasspath += output + compileClasspath
|
||||||
|
}
|
||||||
|
|
||||||
mavenCentral()
|
repositories {
|
||||||
mavenLocal()
|
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||||
|
|
||||||
maven("https://repo.codemc.org/repository/maven-public/")
|
mavenCentral()
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
mavenLocal()
|
||||||
maven("https://repo.papermc.io/repository/maven-public/")
|
|
||||||
|
maven("https://repo.codemc.org/repository/maven-public/")
|
||||||
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||||
|
maven("https://repo.papermc.io/repository/maven-public/")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.bstats:bstats-bukkit:3.1.0")
|
||||||
|
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
|
||||||
|
|
||||||
|
add(paper.compileOnlyConfigurationName, "net.kyori:adventure-platform-bukkit:4.4.1")
|
||||||
|
add(paper.compileOnlyConfigurationName, "dev.folia:folia-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
|
compileOnly("dev.folia:folia-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
|
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
||||||
|
|
||||||
|
testImplementation("org.openjdk.jmh:jmh-core:1.32")
|
||||||
|
testImplementation("org.openjdk.jmh:jmh-generator-annprocess:1.32")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
|
withJavadocJar()
|
||||||
|
withSourcesJar()
|
||||||
|
|
||||||
|
disableAutoTargetJvm()
|
||||||
|
}
|
||||||
|
|
||||||
|
val javaComponent: SoftwareComponent = components["java"]
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
processResources {
|
||||||
|
eachFile { expand("version" to project.version) }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
build {
|
||||||
implementation("org.bstats:bstats-bukkit:3.0.1")
|
dependsOn(named("shadowJar"))
|
||||||
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
|
|
||||||
|
|
||||||
compileOnly("dev.folia:folia-api:1.21.11-R0.1-SNAPSHOT")
|
|
||||||
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
|
||||||
|
|
||||||
testImplementation("org.openjdk.jmh:jmh-core:1.32")
|
|
||||||
testImplementation("org.openjdk.jmh:jmh-generator-annprocess:1.32")
|
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register<JavaCompile>("compilePaper") {
|
||||||
java {
|
source = paper.java
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
classpath = paper.compileClasspath
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
destinationDirectory.set(layout.buildDirectory.dir("classes/java/paper"))
|
||||||
|
options.encoding = "UTF-8"
|
||||||
withJavadocJar()
|
options.release = 8
|
||||||
withSourcesJar()
|
|
||||||
|
|
||||||
disableAutoTargetJvm()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
license {
|
val plainJar by registering(Jar::class) {
|
||||||
header = rootProject.file("config/headers/main.txt")
|
dependsOn("compilePaper")
|
||||||
|
|
||||||
include("**/*.java")
|
archiveClassifier.set("plain")
|
||||||
mapping("java", "JAVADOC_STYLE")
|
from(sourceSets.main.get().output)
|
||||||
|
from(paper.output)
|
||||||
|
}
|
||||||
|
|
||||||
encoding = "UTF-8"
|
val combinedSourcesJar by registering(Jar::class) {
|
||||||
|
archiveClassifier.set("sources")
|
||||||
|
from(sourceSets.main.get().allSource)
|
||||||
|
from(paper.allSource)
|
||||||
|
|
||||||
ext {
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
set("year", 2026)
|
}
|
||||||
|
|
||||||
|
val combinedJavadoc by registering(Javadoc::class) {
|
||||||
|
isFailOnError = false
|
||||||
|
|
||||||
|
source = sourceSets.main.get().allJava + paper.allJava
|
||||||
|
classpath = sourceSets.main.get().compileClasspath + paper.compileClasspath
|
||||||
|
|
||||||
|
with(options as StandardJavadocDocletOptions) {
|
||||||
|
addStringOption("Xdoclint:none", "-quiet")
|
||||||
|
addStringOption("encoding", "UTF-8")
|
||||||
|
addStringOption("charSet", "UTF-8")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
val combinedJavadocJar by registering(Jar::class) {
|
||||||
processResources {
|
archiveClassifier.set("javadoc")
|
||||||
eachFile { expand("version" to project.version) }
|
dependsOn(combinedJavadoc)
|
||||||
|
from(combinedJavadoc.get().destinationDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<JavaCompile> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.release = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<ShadowJar> {
|
||||||
|
configurations = listOf(project.configurations.runtimeClasspath.get())
|
||||||
|
|
||||||
|
from(sourceSets.main.get().output)
|
||||||
|
|
||||||
|
archiveClassifier.set("")
|
||||||
|
|
||||||
|
relocate("org.bstats", "me.clip.placeholderapi.metrics")
|
||||||
|
relocate("net.kyori", "me.clip.placeholderapi.libs.kyori")
|
||||||
|
|
||||||
|
exclude("META-INF/versions/**")
|
||||||
|
|
||||||
|
dependsOn("compilePaper")
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
val paperDir = layout.buildDirectory.dir("classes/java/paper").get().asFile
|
||||||
|
val jarFile = archiveFile.get().asFile
|
||||||
|
|
||||||
|
ant.invokeMethod("zip", mapOf(
|
||||||
|
"destfile" to jarFile,
|
||||||
|
"update" to "true",
|
||||||
|
"basedir" to paperDir
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
build {
|
test {
|
||||||
dependsOn(named("shadowJar"))
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
withType<JavaCompile> {
|
publishing {
|
||||||
options.encoding = "UTF-8"
|
publications {
|
||||||
options.release = 8
|
create<MavenPublication>("maven") {
|
||||||
}
|
artifactId = "placeholderapi"
|
||||||
|
|
||||||
withType<Javadoc> {
|
artifact(plainJar) {
|
||||||
isFailOnError = false
|
builtBy(plainJar)
|
||||||
|
classifier = ""
|
||||||
|
}
|
||||||
|
|
||||||
with(options as StandardJavadocDocletOptions) {
|
artifact(combinedSourcesJar) {
|
||||||
addStringOption("Xdoclint:none", "-quiet")
|
builtBy(combinedSourcesJar)
|
||||||
addStringOption("encoding", "UTF-8")
|
}
|
||||||
addStringOption("charSet", "UTF-8")
|
|
||||||
|
artifact(combinedJavadocJar) {
|
||||||
|
builtBy(combinedJavadocJar)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
repositories {
|
||||||
useJUnitPlatform()
|
maven {
|
||||||
|
if ("-DEV" in version.toString()) {
|
||||||
|
url = uri("https://repo.extendedclip.com/snapshots")
|
||||||
|
} else {
|
||||||
|
url = uri("https://repo.extendedclip.com/releases")
|
||||||
|
}
|
||||||
|
|
||||||
|
credentials {
|
||||||
|
username = System.getenv("JENKINS_USER")
|
||||||
|
password = System.getenv("JENKINS_PASS")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
publish.get().setDependsOn(listOf(build.get()))
|
||||||
testImplementation {
|
}
|
||||||
extendsFrom(compileOnly.get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
testImplementation {
|
||||||
|
extendsFrom(compileOnly.get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api(project(":spigot"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val javaComponent: SoftwareComponent = components["java"]
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
withType<ShadowJar> {
|
|
||||||
archiveClassifier.set("")
|
|
||||||
archiveBaseName.set("PlaceholderAPI-Paper")
|
|
||||||
|
|
||||||
relocate("org.bstats", "me.clip.placeholderapi.metrics")
|
|
||||||
|
|
||||||
exclude("META-INF/versions/**")
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create<MavenPublication>("maven") {
|
|
||||||
artifactId = "placeholderapi-paper"
|
|
||||||
from(javaComponent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
if ("-DEV" in version.toString()) {
|
|
||||||
url = uri("https://repo.extendedclip.com/snapshots")
|
|
||||||
} else {
|
|
||||||
url = uri("https://repo.extendedclip.com/releases")
|
|
||||||
}
|
|
||||||
|
|
||||||
credentials {
|
|
||||||
username = System.getenv("JENKINS_USER")
|
|
||||||
password = System.getenv("JENKINS_PASS")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publish.get().setDependsOn(listOf(build.get()))
|
|
||||||
}
|
|
||||||
@@ -1,3 +1 @@
|
|||||||
rootProject.name = "PlaceholderAPI"
|
rootProject.name = "PlaceholderAPI"
|
||||||
|
|
||||||
include("spigot", "paper")
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
||||||
|
|
||||||
val javaComponent: SoftwareComponent = components["java"]
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
withType<ShadowJar> {
|
|
||||||
archiveClassifier.set("")
|
|
||||||
archiveBaseName.set("PlaceholderAPI-Spigot")
|
|
||||||
|
|
||||||
relocate("org.bstats", "me.clip.placeholderapi.metrics")
|
|
||||||
relocate("net.kyori", "me.clip.placeholderapi.libs.kyori")
|
|
||||||
|
|
||||||
exclude("META-INF/versions/**")
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create<MavenPublication>("maven") {
|
|
||||||
artifactId = "placeholderapi"
|
|
||||||
from(javaComponent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
if ("-DEV" in version.toString()) {
|
|
||||||
url = uri("https://repo.extendedclip.com/snapshots")
|
|
||||||
} else {
|
|
||||||
url = uri("https://repo.extendedclip.com/releases")
|
|
||||||
}
|
|
||||||
|
|
||||||
credentials {
|
|
||||||
username = System.getenv("JENKINS_USER")
|
|
||||||
password = System.getenv("JENKINS_PASS")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publish.get().setDependsOn(listOf(build.get()))
|
|
||||||
}
|
|
||||||
@@ -261,12 +261,6 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
final PlaceholderCommandRouter router = new PlaceholderCommandRouter(this);
|
final PlaceholderCommandRouter router = new PlaceholderCommandRouter(this);
|
||||||
pluginCommand.setExecutor(router);
|
pluginCommand.setExecutor(router);
|
||||||
pluginCommand.setTabCompleter(router);
|
pluginCommand.setTabCompleter(router);
|
||||||
|
|
||||||
try {
|
|
||||||
getServer().getPluginManager().registerEvents((Listener) Class.forName("me.clip.placeholderapi.TestListener").newInstance(), this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupMetrics() {
|
private void setupMetrics() {
|
||||||
@@ -32,6 +32,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.impl.cloud.CommandECloud;
|
import me.clip.placeholderapi.commands.impl.cloud.CommandECloud;
|
||||||
import me.clip.placeholderapi.commands.impl.local.CommandDump;
|
import me.clip.placeholderapi.commands.impl.local.CommandDump;
|
||||||
@@ -119,14 +120,18 @@ public final class PlaceholderCommandRouter implements CommandExecutor, TabCompl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(@NotNull final CommandSender sender,
|
public List<String> onTabComplete(@NotNull final CommandSender sender, @NotNull final Command command,
|
||||||
@NotNull final Command command, @NotNull final String alias, @NotNull final String[] args) {
|
@NotNull final String alias, @NotNull final String[] args) {
|
||||||
final List<String> suggestions = new ArrayList<>();
|
final List<String> suggestions = new ArrayList<>();
|
||||||
|
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
final PlaceholderCommand target = this.commands.get(args[0].toLowerCase(Locale.ROOT));
|
final PlaceholderCommand target = this.commands.get(args[0].toLowerCase(Locale.ROOT));
|
||||||
|
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
|
if (target.getPermission() != null && !target.getPermission().isEmpty() && !sender.hasPermission(target.getPermission())) {
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
target.complete(plugin, sender, args[0].toLowerCase(Locale.ROOT),
|
target.complete(plugin, sender, args[0].toLowerCase(Locale.ROOT),
|
||||||
Arrays.asList(Arrays.copyOfRange(args, 1, args.length)), suggestions);
|
Arrays.asList(Arrays.copyOfRange(args, 1, args.length)), suggestions);
|
||||||
}
|
}
|
||||||
@@ -118,6 +118,11 @@ public final class CommandECloud extends PlaceholderCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!target.getLabel().equalsIgnoreCase("refresh") && plugin.getCloudExpansionManager().isEmpty()) {
|
||||||
|
Msg.msg(sender, "&cThere is no available data from the eCloud. Please try running &f/papi ecloud refresh&c. If this does not resolve the issue, the eCloud may be blocked by your firewall, server host, or service provider.\n&r\n&cMore information: &fhttps://placeholderapi.com/ecloud-blocked");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
target.evaluate(plugin, sender, search, params.subList(1, params.size()));
|
target.evaluate(plugin, sender, search, params.subList(1, params.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +170,8 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
|
|||||||
.append(newline()).append(newline())
|
.append(newline()).append(newline())
|
||||||
.append(text("Author: ", AQUA)).append(text(expansion.getAuthor(), WHITE))
|
.append(text("Author: ", AQUA)).append(text(expansion.getAuthor(), WHITE))
|
||||||
.append(newline())
|
.append(newline())
|
||||||
|
.append(text("Version: ", AQUA)).append(text(expansion.getVersion().getVersion(), WHITE))
|
||||||
|
.append(newline())
|
||||||
.append(text("Verified: ", AQUA)).append(text(expansion.getVersion().isVerified() ? "✔" : "❌", expansion.getVersion().isVerified() ? GREEN : RED, TextDecoration.BOLD))
|
.append(text("Verified: ", AQUA)).append(text(expansion.getVersion().isVerified() ? "✔" : "❌", expansion.getVersion().isVerified() ? GREEN : RED, TextDecoration.BOLD))
|
||||||
.append(newline())
|
.append(newline())
|
||||||
.append(text("Released: ", AQUA)).append(text(format.format(expansion.getLastUpdate()), WHITE))
|
.append(text("Released: ", AQUA)).append(text(format.format(expansion.getLastUpdate()), WHITE))
|
||||||
@@ -54,6 +54,10 @@ public final class PlaceholderAPIConfig {
|
|||||||
return plugin.getConfig().getBoolean("debug", false);
|
return plugin.getConfig().getBoolean("debug", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean useAdventureReplacer() {
|
||||||
|
return plugin.getConfig().getBoolean("use_adventure_provided_replacer", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Optional<ExpansionSort> getExpansionSort() {
|
public Optional<ExpansionSort> getExpansionSort() {
|
||||||
final String option = plugin.getConfig()
|
final String option = plugin.getConfig()
|
||||||
@@ -87,8 +91,11 @@ public final class PlaceholderAPIConfig {
|
|||||||
return plugin.getConfig().getString("boolean.false", "false");
|
return plugin.getConfig().getString("boolean.false", "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean useAdventureProvidedReplacer() {
|
||||||
|
return plugin.getConfig().getBoolean("use_adventure_provided_replacer", false);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean detectMaliciousExpansions() {
|
public boolean detectMaliciousExpansions() {
|
||||||
return plugin.getConfig().getBoolean("detect_malicious_expansions", true);
|
return plugin.getConfig().getBoolean("detect_malicious_expansions", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -31,6 +31,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -62,7 +63,7 @@ import org.jetbrains.annotations.Unmodifiable;
|
|||||||
public final class CloudExpansionManager {
|
public final class CloudExpansionManager {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final String API_URL = "https://ecloud.placeholderapi.com/api/v3/";
|
private static final String API_URL = "https://ecloud.placeholderapi.com/api/v3/?platform=bukkit";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
@@ -115,6 +116,10 @@ public final class CloudExpansionManager {
|
|||||||
return ImmutableMap.copyOf(cache);
|
return ImmutableMap.copyOf(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return cache.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
public Map<String, CloudExpansion> getCloudExpansionsInstalled() {
|
public Map<String, CloudExpansion> getCloudExpansionsInstalled() {
|
||||||
@@ -197,6 +202,8 @@ public final class CloudExpansionManager {
|
|||||||
for (String name : toRemove) {
|
for (String name : toRemove) {
|
||||||
values.remove(name);
|
values.remove(name);
|
||||||
}
|
}
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
plugin.getLogger().log(Level.WARNING, "There is no data available from the eCloud. Please try running /papi refresh. If this does not resolve the issue, the eCloud may be blocked by your firewall, server host, or service provider.\n\nMore information: https://placeholderapi.com/ecloud-blocked", e);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// ugly swallowing of every throwable, but we have to be defensive
|
// ugly swallowing of every throwable, but we have to be defensive
|
||||||
plugin.getLogger().log(Level.WARNING, "Failed to download expansion information", e);
|
plugin.getLogger().log(Level.WARNING, "Failed to download expansion information", e);
|
||||||
@@ -26,6 +26,8 @@ import java.net.URL;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
@@ -36,12 +38,13 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
public class UpdateChecker implements Listener {
|
public class UpdateChecker implements Listener {
|
||||||
|
private static final String MODRINTH_URL = "https://api.modrinth.com/v2/project/lKEzGugV/version";
|
||||||
|
|
||||||
private static final int RESOURCE_ID = 6245;
|
private static final int RESOURCE_ID = 6245;
|
||||||
private final PlaceholderAPIPlugin plugin;
|
private final PlaceholderAPIPlugin plugin;
|
||||||
private final TaskScheduler scheduler;
|
private final TaskScheduler scheduler;
|
||||||
private final String pluginVersion;
|
private final String pluginVersion;
|
||||||
private String spigotVersion;
|
private String modrinthVersion;
|
||||||
private boolean updateAvailable;
|
private boolean updateAvailable;
|
||||||
|
|
||||||
public UpdateChecker(PlaceholderAPIPlugin plugin) {
|
public UpdateChecker(PlaceholderAPIPlugin plugin) {
|
||||||
@@ -54,27 +57,27 @@ public class UpdateChecker implements Listener {
|
|||||||
return updateAvailable;
|
return updateAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSpigotVersion() {
|
public String getModrinthVersion() {
|
||||||
return spigotVersion;
|
return modrinthVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetch() {
|
public void fetch() {
|
||||||
scheduler.runTaskAsynchronously(() -> {
|
scheduler.runTaskAsynchronously(() -> {
|
||||||
try {
|
try {
|
||||||
HttpsURLConnection con = (HttpsURLConnection) new URL(
|
HttpsURLConnection con = (HttpsURLConnection) new URL(MODRINTH_URL).openConnection();
|
||||||
"https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).openConnection();
|
|
||||||
con.setRequestMethod("GET");
|
con.setRequestMethod("GET");
|
||||||
spigotVersion = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();
|
final JsonElement json = JsonParser.parseReader(new BufferedReader(new InputStreamReader(con.getInputStream())));
|
||||||
|
modrinthVersion = json.getAsJsonArray().get(0).getAsJsonObject().get("version_number").getAsString();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
plugin.getLogger().info("Failed to check for updates on spigot.");
|
plugin.getLogger().info("Failed to check for updates on modrinth.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spigotVersion == null || spigotVersion.isEmpty()) {
|
if (modrinthVersion == null || modrinthVersion.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAvailable = spigotIsNewer();
|
updateAvailable = modrinthIsNewer();
|
||||||
|
|
||||||
if (!updateAvailable) {
|
if (!updateAvailable) {
|
||||||
return;
|
return;
|
||||||
@@ -82,21 +85,21 @@ public class UpdateChecker implements Listener {
|
|||||||
|
|
||||||
scheduler.runTask(() -> {
|
scheduler.runTask(() -> {
|
||||||
plugin.getLogger()
|
plugin.getLogger()
|
||||||
.info("An update for PlaceholderAPI (v" + getSpigotVersion() + ") is available at:");
|
.info("An update for PlaceholderAPI (v" + getModrinthVersion() + ") is available at:");
|
||||||
plugin.getLogger()
|
plugin.getLogger()
|
||||||
.info("https://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID + "/");
|
.info("https://modrinth.com/plugin/placeholderapi");
|
||||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean spigotIsNewer() {
|
private boolean modrinthIsNewer() {
|
||||||
if (spigotVersion == null || spigotVersion.isEmpty()) {
|
if (modrinthVersion == null || modrinthVersion.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] plV = toReadable(pluginVersion);
|
int[] plV = toReadable(pluginVersion);
|
||||||
int[] spV = toReadable(spigotVersion);
|
int[] spV = toReadable(modrinthVersion);
|
||||||
|
|
||||||
if (plV[0] < spV[0]) {
|
if (plV[0] < spV[0]) {
|
||||||
return true;
|
return true;
|
||||||
@@ -119,10 +122,9 @@ public class UpdateChecker implements Listener {
|
|||||||
public void onJoin(PlayerJoinEvent e) {
|
public void onJoin(PlayerJoinEvent e) {
|
||||||
if (e.getPlayer().hasPermission("placeholderapi.updatenotify")) {
|
if (e.getPlayer().hasPermission("placeholderapi.updatenotify")) {
|
||||||
Msg.msg(e.getPlayer(),
|
Msg.msg(e.getPlayer(),
|
||||||
"&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getSpigotVersion()
|
"&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getModrinthVersion()
|
||||||
+ "&e)"
|
+ "&e)"
|
||||||
, "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID
|
, "&bis available at &ehttps://modrinth.com/plugin/placeholderapi");
|
||||||
+ "/");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
# Expansions: https://placeholderapi.com/ecloud
|
# Expansions: https://placeholderapi.com/ecloud
|
||||||
# Wiki: https://wiki.placeholderapi.com/
|
# Wiki: https://wiki.placeholderapi.com/
|
||||||
# Discord: https://helpch.at/discord
|
# Discord: https://helpch.at/discord
|
||||||
|
# If you're seeing performance issues with plugins that use component replacement, or things don't look quite right,
|
||||||
|
# switch to the replacer provided by adventure itself by changing use_adventure_provided_replacer to true
|
||||||
# No placeholders are provided with this plugin by default.
|
# No placeholders are provided with this plugin by default.
|
||||||
# Download placeholders: /papi ecloud
|
# Download placeholders: /papi ecloud
|
||||||
check_updates: true
|
check_updates: true
|
||||||
@@ -16,4 +18,5 @@ boolean:
|
|||||||
'false': 'no'
|
'false': 'no'
|
||||||
date_format: MM/dd/yy HH:mm:ss
|
date_format: MM/dd/yy HH:mm:ss
|
||||||
detect_malicious_expansions: true
|
detect_malicious_expansions: true
|
||||||
|
use_adventure_provided_replacer: false
|
||||||
debug: false
|
debug: false
|
||||||
@@ -1,7 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of PlaceholderAPI
|
||||||
|
*
|
||||||
|
* PlaceholderAPI
|
||||||
|
* Copyright (c) 2015 - 2026 PlaceholderAPI Team
|
||||||
|
*
|
||||||
|
* PlaceholderAPI free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PlaceholderAPI is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package me.clip.placeholderapi;
|
package me.clip.placeholderapi;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.replacer.ComponentReplacer;
|
||||||
import me.clip.placeholderapi.expansion.Relational;
|
|
||||||
import me.clip.placeholderapi.replacer.ExactReplacer;
|
import me.clip.placeholderapi.replacer.ExactReplacer;
|
||||||
import me.clip.placeholderapi.replacer.RelationalExactReplacer;
|
import me.clip.placeholderapi.replacer.RelationalExactReplacer;
|
||||||
import me.clip.placeholderapi.replacer.Replacer;
|
import me.clip.placeholderapi.replacer.Replacer;
|
||||||
@@ -30,9 +49,12 @@ public final class PAPIComponents {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Component setPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
public static Component setPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
||||||
// TODO: explore a custom TextReplacementRenderer which doesn't use regex for performance benefits i.e. merge CharsReplacer with kyori TextReplacementRenderer
|
if (PlaceholderAPIPlugin.getInstance().getPlaceholderAPIConfig().useAdventureProvidedReplacer()) {
|
||||||
return component.replaceText(config -> config.match(PlaceholderAPI.PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
return component.replaceText(config -> config.match(PlaceholderAPI.PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
||||||
builder.content(PERCENT_EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
builder.content(PERCENT_EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentReplacer.replace(component, str -> PlaceholderAPI.setPlaceholders(player, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,8 +106,12 @@ public final class PAPIComponents {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Component setBracketPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
public static Component setBracketPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
||||||
return component.replaceText(config -> config.match(PlaceholderAPI.BRACKET_PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
if (PlaceholderAPIPlugin.getInstance().getPlaceholderAPIConfig().useAdventureReplacer()) {
|
||||||
builder.content(BRACKET_EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
return component.replaceText(config -> config.match(PlaceholderAPI.BRACKET_PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
||||||
|
builder.content(BRACKET_EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ComponentReplacer.replace(component, str -> PlaceholderAPI.setBracketPlaceholders(player, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,6 +163,7 @@ public final class PAPIComponents {
|
|||||||
* @return The Component containing the parsed relational placeholders
|
* @return The Component containing the parsed relational placeholders
|
||||||
*/
|
*/
|
||||||
public static Component setRelationalPlaceholders(Player one, Player two, Component component) {
|
public static Component setRelationalPlaceholders(Player one, Player two, Component component) {
|
||||||
|
//todo: custom replacer
|
||||||
return component.replaceText(config -> config.match(RELATIONAL_PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
return component.replaceText(config -> config.match(RELATIONAL_PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
||||||
builder.content(RELATIONAL_EXACT_REPLACER.apply(result.group(2), one, two, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
builder.content(RELATIONAL_EXACT_REPLACER.apply(result.group(2), one, two, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
||||||
}
|
}
|
||||||
@@ -154,9 +181,4 @@ public final class PAPIComponents {
|
|||||||
return components.stream().map(line -> setRelationalPlaceholders(one, two, line))
|
return components.stream().map(line -> setRelationalPlaceholders(one, two, line))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
// kyori doesn't seem to have a method that can do a contains with regex, we don't want to do a more expensive replace
|
|
||||||
// public static boolean containsPlaceholders(@Nullable final Component text) {
|
|
||||||
// return text != null && text.replaceText()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
|
import net.kyori.adventure.text.*;
|
||||||
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
|
import net.kyori.adventure.text.event.DataComponentValue;
|
||||||
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class ComponentReplacer {
|
||||||
|
@NotNull
|
||||||
|
public static Component replace(@NotNull final Component component, @NotNull final Function<String, String> replacer) {
|
||||||
|
return rebuild(component, replacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Component rebuild(@NotNull final Component component, @NotNull final Function<String, String> replacer) {
|
||||||
|
Component rebuilt;
|
||||||
|
|
||||||
|
if (component instanceof TextComponent) {
|
||||||
|
final TextComponent text = (TextComponent) component;
|
||||||
|
final String replaced = replacer.apply(text.content());
|
||||||
|
|
||||||
|
rebuilt = Component.text(replaced);
|
||||||
|
} else if (component instanceof TranslatableComponent) {
|
||||||
|
final TranslatableComponent translatable = (TranslatableComponent) component;
|
||||||
|
final List<Component> arguments = new ArrayList<>();
|
||||||
|
|
||||||
|
for (final ComponentLike arg : translatable.arguments()) {
|
||||||
|
arguments.add(rebuild(arg.asComponent(), replacer));
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuilt = Component.translatable(translatable.key(), arguments);
|
||||||
|
} else if (component instanceof KeybindComponent) {
|
||||||
|
final KeybindComponent keybind = (KeybindComponent) component;
|
||||||
|
rebuilt = Component.keybind(keybind.keybind());
|
||||||
|
} else if (component instanceof ScoreComponent) {
|
||||||
|
final ScoreComponent score = (ScoreComponent) component;
|
||||||
|
rebuilt = Component.score(score.name(), score.objective());
|
||||||
|
} else if (component instanceof SelectorComponent) {
|
||||||
|
final SelectorComponent selector = (SelectorComponent) component;
|
||||||
|
rebuilt = Component.selector(selector.pattern());
|
||||||
|
} else {
|
||||||
|
rebuilt = Component.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuilt = rebuilt.style(rebuildStyle(component.style(), replacer));
|
||||||
|
|
||||||
|
if (!component.children().isEmpty()) {
|
||||||
|
final List<Component> children = new ArrayList<>();
|
||||||
|
for (Component child : component.children()) {
|
||||||
|
children.add(rebuild(child, replacer));
|
||||||
|
}
|
||||||
|
rebuilt = rebuilt.children(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rebuilt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Style rebuildStyle(@NotNull final Style style, @NotNull final Function<String, String> replacer) {
|
||||||
|
final Style.Builder builder = style.toBuilder();
|
||||||
|
final ClickEvent click = style.clickEvent();
|
||||||
|
|
||||||
|
if (click != null) {
|
||||||
|
builder.clickEvent(rebuildClickEvent(click, replacer));
|
||||||
|
}
|
||||||
|
|
||||||
|
final HoverEvent<?> hover = style.hoverEvent();
|
||||||
|
|
||||||
|
if (hover != null) {
|
||||||
|
builder.hoverEvent(rebuildHoverEvent(hover, replacer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ClickEvent rebuildClickEvent(@NotNull final ClickEvent click, @NotNull final Function<String, String> replacer) {
|
||||||
|
final ClickEvent.Payload payload = click.payload();
|
||||||
|
|
||||||
|
if (!(payload instanceof ClickEvent.Payload.Text)) {
|
||||||
|
return click;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String original = ((ClickEvent.Payload.Text) payload).value();
|
||||||
|
final String replaced = replacer.apply(original);
|
||||||
|
|
||||||
|
final ClickEvent.Action action = click.action();
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case OPEN_URL:
|
||||||
|
return ClickEvent.openUrl(replaced);
|
||||||
|
case OPEN_FILE:
|
||||||
|
return ClickEvent.openFile(replaced);
|
||||||
|
case RUN_COMMAND:
|
||||||
|
return ClickEvent.runCommand(replaced);
|
||||||
|
case SUGGEST_COMMAND:
|
||||||
|
return ClickEvent.suggestCommand(replaced);
|
||||||
|
case COPY_TO_CLIPBOARD:
|
||||||
|
return ClickEvent.copyToClipboard(replaced);
|
||||||
|
default:
|
||||||
|
return click;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static HoverEvent<?> rebuildHoverEvent(@NotNull final HoverEvent<?> hover, @NotNull final Function<String, String> replacer) {
|
||||||
|
final Object value = hover.value();
|
||||||
|
|
||||||
|
if (value instanceof Component) {
|
||||||
|
final Component rebuilt = rebuild((Component) value, replacer);
|
||||||
|
return HoverEvent.showText(rebuilt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof HoverEvent.ShowItem) {
|
||||||
|
return rebuildShowItem((HoverEvent.ShowItem) value, replacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof HoverEvent.ShowEntity) {
|
||||||
|
final HoverEvent.ShowEntity entity = (HoverEvent.ShowEntity) value;
|
||||||
|
|
||||||
|
Component rebuiltName = null;
|
||||||
|
if (entity.name() != null) {
|
||||||
|
rebuiltName = rebuild(entity.name(), replacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HoverEvent.showEntity(entity.type(), entity.id(), rebuiltName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static HoverEvent<?> rebuildShowItem(@NotNull final HoverEvent.ShowItem item, @NotNull final Function<String, String> replacer) {
|
||||||
|
final BinaryTagHolder nbt = item.nbt();
|
||||||
|
|
||||||
|
if (nbt != null && !nbt.string().isEmpty()) {
|
||||||
|
final String replaced = replacer.apply(nbt.string());
|
||||||
|
|
||||||
|
return HoverEvent.showItem(item.item(), item.count(), BinaryTagHolder.binaryTagHolder(replaced));
|
||||||
|
}
|
||||||
|
|
||||||
|
//I'm not 100% sure this is how we're meant to support data components but let's give it a go and see if it causes any issues :)
|
||||||
|
final Map<Key, DataComponentValue> components = item.dataComponents();
|
||||||
|
|
||||||
|
if (!components.isEmpty()) {
|
||||||
|
final Map<Key, DataComponentValue> rebuilt = new HashMap<>();
|
||||||
|
|
||||||
|
for (final Map.Entry<Key, DataComponentValue> entry : components.entrySet()) {
|
||||||
|
final DataComponentValue value = entry.getValue();
|
||||||
|
|
||||||
|
if (!(value instanceof BinaryTagHolder)) {
|
||||||
|
rebuilt.put(entry.getKey(), value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuilt.put(entry.getKey(), BinaryTagHolder.binaryTagHolder(replacer.apply(((BinaryTagHolder) value).string())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HoverEvent.showItem(item.item(), item.count(), rebuilt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HoverEvent.showItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of PlaceholderAPI
|
||||||
|
*
|
||||||
|
* PlaceholderAPI
|
||||||
|
* Copyright (c) 2015 - 2026 PlaceholderAPI Team
|
||||||
|
*
|
||||||
|
* PlaceholderAPI free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PlaceholderAPI is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package me.clip.placeholderapi.replacer;
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of PlaceholderAPI
|
||||||
|
*
|
||||||
|
* PlaceholderAPI
|
||||||
|
* Copyright (c) 2015 - 2026 PlaceholderAPI Team
|
||||||
|
*
|
||||||
|
* PlaceholderAPI free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PlaceholderAPI is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package me.clip.placeholderapi.replacer;
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
Reference in New Issue
Block a user