mirror of
https://github.com/Xiao-MoMi/Custom-Nameplates.git
synced 2026-11-06 09:22:36 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfef863636 | ||
|
|
92fe8b1dc0 | ||
|
|
61d66eb731 | ||
|
|
d0a6d7800b | ||
|
|
77d9006533 | ||
|
|
923c7d115a | ||
|
|
d561ba7378 | ||
|
|
dd2a868e81 | ||
|
|
22e1ef21ea | ||
|
|
5dd7747dba | ||
|
|
4317718e9d | ||
|
|
2a6704444b | ||
|
|
c461e872c4 | ||
|
|
8224aea281 | ||
|
|
bad0e2dbf2 | ||
|
|
c01330a92a | ||
|
|
bbdd5e8a6f | ||
|
|
0e9edf59bc | ||
|
|
8917675b46 | ||
|
|
e09b13677e | ||
|
|
dd71132845 | ||
|
|
dfde885861 |
No files matched your search
@@ -21,7 +21,7 @@ dependencies {
|
||||
// Cache
|
||||
compileOnly("com.github.ben-manes.caffeine:caffeine:${rootProject.properties["caffeine_version"]}")
|
||||
// Netty
|
||||
compileOnly("io.netty:netty-all:4.1.117.Final")
|
||||
compileOnly("io.netty:netty-all:${rootProject.properties["netty_version"]}")
|
||||
// GSON
|
||||
compileOnly("com.google.code.gson:gson:${rootProject.properties["gson_version"]}")
|
||||
// Fast util
|
||||
|
||||
@@ -20,6 +20,7 @@ package net.momirealms.customnameplates.api;
|
||||
import io.netty.channel.Channel;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
import net.momirealms.customnameplates.api.feature.Feature;
|
||||
import net.momirealms.customnameplates.api.feature.TimeStampData;
|
||||
import net.momirealms.customnameplates.api.feature.tag.TeamView;
|
||||
@@ -33,8 +34,6 @@ import net.momirealms.customnameplates.api.storage.data.PlayerData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
@@ -115,11 +114,11 @@ public abstract class AbstractCNPlayer<P> implements CNPlayer {
|
||||
@Override
|
||||
public List<Placeholder> activePlaceholdersToRefresh() {
|
||||
Placeholder[] activePlaceholders = activePlaceholders();
|
||||
List<Placeholder> placeholderWithChildren = new ObjectArrayList<>();
|
||||
Set<Placeholder> placeholderWithChildren = new ObjectLinkedOpenHashSet<>();
|
||||
for (Placeholder placeholder : activePlaceholders) {
|
||||
childrenFirstList(placeholder, placeholderWithChildren);
|
||||
}
|
||||
return placeholderWithChildren.stream().distinct().toList();
|
||||
return List.copyOf(placeholderWithChildren);
|
||||
}
|
||||
|
||||
private String updatePlayerPlaceholder(PlayerPlaceholder placeholder) {
|
||||
@@ -187,11 +186,10 @@ public abstract class AbstractCNPlayer<P> implements CNPlayer {
|
||||
@Override
|
||||
public void forceUpdatePlaceholders(Set<Placeholder> placeholders, Collection<CNPlayer> others) {
|
||||
if (placeholders.isEmpty()) return;
|
||||
List<Placeholder> placeholderWithChildren = new ObjectArrayList<>();
|
||||
Set<Placeholder> placeholderWithChildren = new ObjectLinkedOpenHashSet<>();
|
||||
for (Placeholder placeholder : placeholders) {
|
||||
childrenFirstList(placeholder, placeholderWithChildren);
|
||||
}
|
||||
placeholderWithChildren = placeholderWithChildren.stream().distinct().toList();
|
||||
for (Placeholder placeholder : placeholderWithChildren) {
|
||||
if (placeholder instanceof PlayerPlaceholder playerPlaceholder) {
|
||||
updatePlayerPlaceholder(playerPlaceholder);
|
||||
@@ -203,15 +201,12 @@ public abstract class AbstractCNPlayer<P> implements CNPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
private void childrenFirstList(Placeholder placeholder, List<Placeholder> list) {
|
||||
if (placeholder.children().isEmpty()) {
|
||||
list.add(placeholder);
|
||||
} else {
|
||||
for (Placeholder child : placeholder.children()) {
|
||||
childrenFirstList(child, list);
|
||||
}
|
||||
list.add(placeholder);
|
||||
private void childrenFirstList(Placeholder placeholder, Set<Placeholder> list) {
|
||||
if (list.contains(placeholder)) return;
|
||||
for (Placeholder child : placeholder.children()) {
|
||||
childrenFirstList(child, list);
|
||||
}
|
||||
list.add(placeholder);
|
||||
}
|
||||
|
||||
private void parentLastList(Placeholder placeholder, List<Placeholder> list) {
|
||||
|
||||
+15
@@ -112,6 +112,13 @@ public interface BubbleConfig {
|
||||
*/
|
||||
Vector3 scale();
|
||||
|
||||
/**
|
||||
* Checks if the bubble is affected by scaling.
|
||||
*
|
||||
* @return true if affected by scaling, false otherwise
|
||||
*/
|
||||
boolean affectedByScaling();
|
||||
|
||||
/**
|
||||
* Creates a new builder for constructing a BubbleConfig.
|
||||
*
|
||||
@@ -206,6 +213,14 @@ public interface BubbleConfig {
|
||||
*/
|
||||
Builder scale(Vector3 scale);
|
||||
|
||||
/**
|
||||
* Sets if the bubble is affected by scaling
|
||||
*
|
||||
* @param affectedByScaling affected by scaling
|
||||
* @return the builder instance
|
||||
*/
|
||||
Builder affectedByScaling(boolean affectedByScaling);
|
||||
|
||||
/**
|
||||
* Sets if the text has shadow
|
||||
*
|
||||
|
||||
+18
-2
@@ -41,6 +41,7 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
private final Vector3 scale;
|
||||
private final boolean hasShadow;
|
||||
private final Billboard billboard;
|
||||
private final boolean affectedByScaling;
|
||||
|
||||
/**
|
||||
* Constructs a new BubbleConfigImpl.
|
||||
@@ -56,8 +57,10 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
* @param textSuffix a suffix that will be added after the text in the bubble
|
||||
* @param scale the scale of the bubble display (as a Vector3)
|
||||
* @param hasShadow has shadow or not
|
||||
* @param billboard billboard
|
||||
* @param affectedByScaling if the bubble is affected by scaling
|
||||
*/
|
||||
public BubbleConfigImpl(String id, String commandSuggestion, String displayName, int backgroundColor, int lineWidth, int maxLines, Bubble[] bubbles, String textPrefix, String textSuffix, Vector3 scale, boolean hasShadow, Billboard billboard) {
|
||||
public BubbleConfigImpl(String id, String commandSuggestion, String displayName, int backgroundColor, int lineWidth, int maxLines, Bubble[] bubbles, String textPrefix, String textSuffix, Vector3 scale, boolean hasShadow, Billboard billboard, boolean affectedByScaling) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
this.lineWidth = lineWidth;
|
||||
this.maxLines = maxLines;
|
||||
@@ -70,6 +73,7 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
this.scale = requireNonNull(scale);
|
||||
this.hasShadow = hasShadow;
|
||||
this.billboard = billboard;
|
||||
this.affectedByScaling = affectedByScaling;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,6 +136,11 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
return billboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean affectedByScaling() {
|
||||
return affectedByScaling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder implementation for creating BubbleConfigImpl instances.
|
||||
*/
|
||||
@@ -148,6 +157,7 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
private Vector3 scale;
|
||||
private boolean hasShadow;
|
||||
private Billboard billboard;
|
||||
private boolean affectedByScaling = true;
|
||||
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
@@ -221,9 +231,15 @@ public class BubbleConfigImpl implements BubbleConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder affectedByScaling(boolean affectedByScaling) {
|
||||
this.affectedByScaling = affectedByScaling;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BubbleConfig build() {
|
||||
return new BubbleConfigImpl(id, Optional.ofNullable(this.commandSuggestion).orElse(id), displayName, backgroundColor, lineWidth, maxLines, bubbles, textPrefix, textSuffix, scale, hasShadow, billboard);
|
||||
return new BubbleConfigImpl(id, Optional.ofNullable(this.commandSuggestion).orElse(id), displayName, backgroundColor, lineWidth, maxLines, bubbles, textPrefix, textSuffix, scale, hasShadow, billboard, affectedByScaling);
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -137,6 +137,21 @@ public interface BubbleManager extends Reloadable {
|
||||
*/
|
||||
int stayDuration();
|
||||
|
||||
/**
|
||||
* Returns the additional duration (in ticks) added per visible character in the Bubble text.
|
||||
*
|
||||
* @return the duration per character in ticks
|
||||
*/
|
||||
double durationPerCharacter();
|
||||
|
||||
/**
|
||||
* Returns the maximum duration (in ticks) for which the Bubble remains visible.
|
||||
* A value of 0 means no maximum.
|
||||
*
|
||||
* @return the maximum stay duration in ticks
|
||||
*/
|
||||
int maxStayDuration();
|
||||
|
||||
/**
|
||||
* Returns the duration (in ticks) for the Bubble to appear.
|
||||
*
|
||||
|
||||
@@ -27,6 +27,7 @@ import net.kyori.adventure.text.serializer.json.JSONOptions;
|
||||
import net.kyori.adventure.text.serializer.json.legacyimpl.NBTLegacyHoverEventSerializer;
|
||||
import net.momirealms.customnameplates.api.ConfigManager;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.common.text.minimessage.HeadTextureTag;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
@@ -52,8 +53,9 @@ public class AdventureHelper {
|
||||
private final Cache<String, String> jsonToMiniMessageCache;
|
||||
|
||||
private AdventureHelper() {
|
||||
this.miniMessage = MiniMessage.builder().build();
|
||||
this.miniMessageStrict = MiniMessage.builder().strict(true).build();
|
||||
MiniMessage.Builder miniMessageBuilder = MiniMessage.builder().editTags(tags -> tags.resolver(HeadTextureTag.INSTANCE));
|
||||
this.miniMessage = miniMessageBuilder.build();
|
||||
this.miniMessageStrict = miniMessageBuilder.strict(true).build();
|
||||
GsonComponentSerializer.Builder builder = GsonComponentSerializer.builder();
|
||||
if (!VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
builder.legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get());
|
||||
|
||||
@@ -179,6 +179,14 @@ public class VersionHelper {
|
||||
return version >= 260100;
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan26_2() {
|
||||
return version >= 260200;
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan26_3() {
|
||||
return version >= 260300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the server version is newer than 1.21.9
|
||||
*
|
||||
|
||||
@@ -19,13 +19,18 @@ package net.momirealms.customnameplates.api.network;
|
||||
|
||||
import net.momirealms.customnameplates.common.event.Cancellable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Represents a packet event, which can be cancelled and supports delayed tasks that are executed later.
|
||||
*/
|
||||
public class PacketEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
private final Object packet;
|
||||
private boolean cancelled;
|
||||
private List<Runnable> afterSendTasks;
|
||||
|
||||
/**
|
||||
* Constructs a new PacketEvent with the specified packet.
|
||||
@@ -45,6 +50,42 @@ public class PacketEvent implements Cancellable {
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a task that must run only after this packet has been forwarded
|
||||
* to the next outbound handler.
|
||||
*
|
||||
* @param task task to execute after the packet is sent
|
||||
*/
|
||||
public void afterSend(Runnable task) {
|
||||
this.afterSendTasks().add(Objects.requireNonNull(task, "task"));
|
||||
}
|
||||
|
||||
public List<Runnable> afterSendTasks() {
|
||||
if (this.afterSendTasks == null) {
|
||||
this.afterSendTasks = new ArrayList<>(1);
|
||||
}
|
||||
return this.afterSendTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes and clears all registered after-send tasks. A failure in one
|
||||
* task is reported without preventing the remaining tasks from running.
|
||||
*
|
||||
* @param exceptionHandler handler for failures raised by after-send tasks
|
||||
*/
|
||||
public void runAfterSendTasks(Consumer<Throwable> exceptionHandler) {
|
||||
if (this.afterSendTasks != null) {
|
||||
Objects.requireNonNull(exceptionHandler, "exceptionHandler");
|
||||
for (Runnable task : this.afterSendTasks) {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Throwable throwable) {
|
||||
exceptionHandler.accept(throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the event has been cancelled.
|
||||
*
|
||||
@@ -64,4 +105,4 @@ public class PacketEvent implements Cancellable {
|
||||
public void cancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,9 @@ package net.momirealms.customnameplates.api.network;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@@ -31,7 +33,7 @@ public class Tracker {
|
||||
private boolean isCrouching;
|
||||
private double scale;
|
||||
private boolean isSpectator;
|
||||
private final CNPlayer tracker;
|
||||
private final WeakReference<CNPlayer> tracker;
|
||||
private final CopyOnWriteArrayList<Integer> passengerIDs = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
@@ -42,16 +44,17 @@ public class Tracker {
|
||||
public Tracker(CNPlayer tracker) {
|
||||
this.isCrouching = false;
|
||||
this.scale = 1;
|
||||
this.tracker = tracker;
|
||||
this.tracker = new WeakReference<>(tracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the tracker
|
||||
*
|
||||
* @return the tracker
|
||||
* @return the tracker, or {@code null} if it is no longer reachable
|
||||
*/
|
||||
@Nullable
|
||||
public CNPlayer tracker() {
|
||||
return tracker;
|
||||
return tracker.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -419,6 +419,10 @@ public enum Dependency {
|
||||
return s.replace("{}", ".");
|
||||
}
|
||||
|
||||
public String toLocalPath() {
|
||||
return rewriteEscaping(groupId).replace(".", "/") + "/" + rewriteEscaping(artifactId) + "/" + getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename for the dependency's JAR file, optionally with a classifier.
|
||||
*
|
||||
|
||||
+46
-3
@@ -35,8 +35,10 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -53,7 +55,7 @@ public class DependencyManagerImpl implements DependencyManager {
|
||||
/** The classpath appender to preload dependencies into */
|
||||
private final ClassPathAppender classPathAppender;
|
||||
/** A map of dependencies which have already been loaded. */
|
||||
private final EnumMap<Dependency, Path> loaded = new EnumMap<>(Dependency.class);
|
||||
private final Map<Dependency, Path> loaded = Collections.synchronizedMap(new EnumMap<>(Dependency.class));
|
||||
/** A map of isolated classloaders which have been created. */
|
||||
private final Map<Set<Dependency>, IsolatedClassLoader> loaders = new HashMap<>();
|
||||
/** Cached relocation handler instance. */
|
||||
@@ -152,7 +154,8 @@ public class DependencyManagerImpl implements DependencyManager {
|
||||
|
||||
private Path downloadDependency(Dependency dependency) throws DependencyDownloadException {
|
||||
String fileName = dependency.getFileName(null);
|
||||
Path file = this.cacheDirectory.resolve(fileName);
|
||||
Path file = this.cacheDirectory.resolve(dependency.toLocalPath()).resolve(fileName);
|
||||
cleanOutdatedVersions(file.getParent());
|
||||
|
||||
// if the file already exists, don't attempt to re-download it.
|
||||
if (Files.exists(file)) {
|
||||
@@ -179,13 +182,39 @@ public class DependencyManagerImpl implements DependencyManager {
|
||||
throw Objects.requireNonNull(lastError);
|
||||
}
|
||||
|
||||
private void cleanOutdatedVersions(Path currentVersionDirectory) {
|
||||
Path artifactDirectory = currentVersionDirectory.getParent();
|
||||
if (!Files.isDirectory(artifactDirectory)) return;
|
||||
|
||||
Set<Path> loadedVersionDirectories = new HashSet<>();
|
||||
synchronized (this.loaded) {
|
||||
this.loaded.values().forEach(path -> loadedVersionDirectories.add(path.getParent()));
|
||||
}
|
||||
try (DirectoryStream<Path> directories = Files.newDirectoryStream(artifactDirectory)) {
|
||||
for (Path directory : directories) {
|
||||
if (!Files.isDirectory(directory) || directory.equals(currentVersionDirectory)
|
||||
|| loadedVersionDirectories.contains(directory)) continue;
|
||||
try (Stream<Path> paths = Files.walk(directory)) {
|
||||
for (Path path : paths.sorted(Comparator.reverseOrder()).toList()) {
|
||||
Files.delete(path);
|
||||
}
|
||||
this.plugin.getPluginLogger().info("Cleaned up outdated dependency " + directory);
|
||||
} catch (IOException | RuntimeException e) {
|
||||
this.plugin.getPluginLogger().warn("Failed to clean outdated dependency " + directory, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.plugin.getPluginLogger().warn("Failed to clean outdated dependencies in " + artifactDirectory, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Path remapDependency(Dependency dependency, Path normalFile) throws Exception {
|
||||
List<Relocation> rules = new ArrayList<>(dependency.getRelocations());
|
||||
if (rules.isEmpty()) {
|
||||
return normalFile;
|
||||
}
|
||||
|
||||
Path remappedFile = this.cacheDirectory.resolve(dependency.getFileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped"));
|
||||
Path remappedFile = normalFile.resolveSibling(dependency.getFileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped"));
|
||||
|
||||
// if the remapped source exists already, just use that.
|
||||
if (Files.exists(remappedFile)) {
|
||||
@@ -202,6 +231,7 @@ public class DependencyManagerImpl implements DependencyManager {
|
||||
Path cacheDirectory = plugin.getDataDirectory().resolve("libs");
|
||||
try {
|
||||
if (Files.exists(cacheDirectory) && (Files.isDirectory(cacheDirectory) || Files.isSymbolicLink(cacheDirectory))) {
|
||||
cleanDirectoryJars(plugin, cacheDirectory);
|
||||
return cacheDirectory;
|
||||
}
|
||||
|
||||
@@ -217,6 +247,19 @@ public class DependencyManagerImpl implements DependencyManager {
|
||||
return cacheDirectory;
|
||||
}
|
||||
|
||||
private static void cleanDirectoryJars(NameplatesPlugin plugin, Path directory) throws IOException {
|
||||
try (DirectoryStream<Path> files = Files.newDirectoryStream(directory, "*.jar")) {
|
||||
for (Path file : files) {
|
||||
if (!Files.isRegularFile(file)) continue;
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException e) {
|
||||
plugin.getPluginLogger().warn("Failed to clean legacy dependency " + file, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IOException firstEx = null;
|
||||
|
||||
+1
@@ -142,6 +142,7 @@ public enum DependencyRepository {
|
||||
*/
|
||||
public void download(Dependency dependency, Path file) throws DependencyDownloadException {
|
||||
try {
|
||||
Files.createDirectories(file.getParent());
|
||||
Files.write(file, download(dependency));
|
||||
} catch (IOException e) {
|
||||
throw new DependencyDownloadException(e);
|
||||
|
||||
-1
@@ -38,7 +38,6 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@ package net.momirealms.customnameplates.common.locale;
|
||||
import dev.dejvokep.boostedyaml.YamlDocument;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.translation.Translator;
|
||||
import net.momirealms.customnameplates.api.helper.AdventureHelper;
|
||||
import net.momirealms.customnameplates.common.plugin.CustomNameplatesProperties;
|
||||
import net.momirealms.customnameplates.common.plugin.NameplatesPlugin;
|
||||
import net.momirealms.customnameplates.common.util.Pair;
|
||||
@@ -69,7 +69,7 @@ public class TranslationManager {
|
||||
this.plugin.getConfigManager().saveResource("translations/" + lang + ".yml");
|
||||
}
|
||||
|
||||
this.registry = MiniMessageTranslationRegistry.create(Key.key("customnameplates", "main"), MiniMessage.miniMessage());
|
||||
this.registry = MiniMessageTranslationRegistry.create(Key.key("customnameplates", "main"), AdventureHelper.miniMessage());
|
||||
this.registry.defaultLocale(DEFAULT_LOCALE);
|
||||
this.loadFromFileSystem(this.translationsDirectory, false);
|
||||
MiniMessageTranslator.translator().addSource(this.registry);
|
||||
|
||||
+4
-3
@@ -25,6 +25,7 @@
|
||||
|
||||
package net.momirealms.customnameplates.common.plugin.scheduler;
|
||||
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.common.plugin.NameplatesPlugin;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
@@ -96,7 +97,7 @@ public abstract class AbstractJavaScheduler<T> implements SchedulerAdapter<T> {
|
||||
private void reportRunningTasks(Predicate<Thread> predicate) {
|
||||
Thread.getAllStackTraces().forEach((thread, stack) -> {
|
||||
if (predicate.test(thread)) {
|
||||
this.plugin.getPluginLogger().warn("Thread " + thread.getName() + " is blocked, and may be the reason for the slow shutdown!\n" +
|
||||
CustomNameplates.getInstance().getPluginLogger().warn("Thread " + thread.getName() + " is blocked, and may be the reason for the slow shutdown!\n" +
|
||||
Arrays.stream(stack).map(el -> " " + el).collect(Collectors.joining("\n"))
|
||||
);
|
||||
}
|
||||
@@ -115,10 +116,10 @@ public abstract class AbstractJavaScheduler<T> implements SchedulerAdapter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ExceptionHandler implements UncaughtExceptionHandler {
|
||||
private static final class ExceptionHandler implements UncaughtExceptionHandler {
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
AbstractJavaScheduler.this.plugin.getPluginLogger().warn("Thread " + t.getName() + " threw an uncaught exception", e);
|
||||
CustomNameplates.getInstance().getPluginLogger().warn("Thread " + t.getName() + " threw an uncaught exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package net.momirealms.customnameplates.common.sender;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customnameplates.common.plugin.NameplatesPlugin;
|
||||
import net.momirealms.customnameplates.common.util.Tristate;
|
||||
@@ -54,8 +53,6 @@ public abstract class SenderFactory<P extends NameplatesPlugin, T> implements Au
|
||||
|
||||
protected abstract String getName(T sender);
|
||||
|
||||
public abstract Audience getAudience(T sender);
|
||||
|
||||
protected abstract void sendMessage(T sender, Component message);
|
||||
|
||||
protected abstract Tristate getPermissionValue(T sender, String node);
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package net.momirealms.customnameplates.common.text.minimessage;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.Context;
|
||||
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 net.kyori.adventure.text.object.ObjectContents;
|
||||
import net.kyori.adventure.text.object.PlayerHeadObjectContents;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
public final class HeadTextureTag implements TagResolver {
|
||||
public static final HeadTextureTag INSTANCE = new HeadTextureTag();
|
||||
|
||||
private HeadTextureTag() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull Context ctx) throws ParsingException {
|
||||
if (!has(name)) return null;
|
||||
|
||||
String texture = arguments.popOr("No texture hash provided").lowerValue();
|
||||
if (!isTextureHash(texture)) {
|
||||
throw ctx.newException("Invalid texture hash", arguments);
|
||||
}
|
||||
if (arguments.hasNext()) {
|
||||
throw ctx.newException("Too many arguments present", arguments);
|
||||
}
|
||||
String profile = "{\"textures\":{\"SKIN\":{\"url\":\"https://textures.minecraft.net/texture/" + texture + "\"}}}";
|
||||
String encoded = Base64.getEncoder().encodeToString(profile.getBytes(StandardCharsets.UTF_8));
|
||||
return Tag.selfClosingInserting(Component.object(ObjectContents.playerHead()
|
||||
.profileProperty(PlayerHeadObjectContents.property("textures", encoded))
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(@NotNull String name) {
|
||||
return name.equals("head_texture");
|
||||
}
|
||||
|
||||
private static boolean isTextureHash(String texture) {
|
||||
int length = texture.length();
|
||||
if (length == 0 || length > 64) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = texture.charAt(i);
|
||||
if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-1
@@ -54,7 +54,6 @@ import net.momirealms.customnameplates.api.util.CharacterUtils;
|
||||
import net.momirealms.customnameplates.backend.util.FreeTypeUtils;
|
||||
import net.momirealms.customnameplates.common.util.Tuple;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bson.types.MaxKey;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
+24
-2
@@ -29,6 +29,7 @@ import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
|
||||
import dev.dejvokep.boostedyaml.utils.format.NodeRole;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.ConfigManager;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
@@ -52,6 +53,9 @@ import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
private static final TagResolver IGNORE_HOVER = TagResolver.resolver(
|
||||
"hover", (arguments, context) -> net.kyori.adventure.text.minimessage.tag.Tag.styling());
|
||||
|
||||
private final CustomNameplates plugin;
|
||||
private final Map<String, Bubble> bubbles = new Object2ObjectOpenHashMap<>();
|
||||
private Requirement[] sendBubbleRequirements;
|
||||
@@ -61,6 +65,8 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
private int stayDuration;
|
||||
private int appearDuration;
|
||||
private int disappearDuration;
|
||||
private double durationPerCharacter;
|
||||
private int maxStayDuration;
|
||||
private float viewRange;
|
||||
private Set<String> blacklistChannels;
|
||||
private ChannelMode channelMode;
|
||||
@@ -162,6 +168,16 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
return stayDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double durationPerCharacter() {
|
||||
return durationPerCharacter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxStayDuration() {
|
||||
return maxStayDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int appearDuration() {
|
||||
return appearDuration;
|
||||
@@ -219,7 +235,9 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
viewBubbleRequirements = plugin.getRequirementManager().parseRequirements(document.getSection("viewer-requirements"));
|
||||
defaultBubbleId = document.getString("default-bubble", "chat");
|
||||
yOffset = document.getDouble("y-offset", 0.2);
|
||||
stayDuration = document.getInt("stay-duration", 160);
|
||||
stayDuration = document.getInt("stay-duration", 100);
|
||||
durationPerCharacter = document.getDouble("duration-per-character", 2.0);
|
||||
maxStayDuration = document.getInt("max-stay-duration", 0);
|
||||
appearDuration = document.getInt("appear-duration", 20);
|
||||
disappearDuration = document.getInt("disappear-duration", 10);
|
||||
viewRange = document.getFloat("view-range", 0.5f);
|
||||
@@ -248,6 +266,7 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
.scale(ConfigUtils.vector3(inner.getString("scale", "1,1,1")))
|
||||
.hasShadow(inner.getBoolean("has-shadow", false))
|
||||
.billboard(inner.getEnum("billboard", Billboard.class, Billboard.CENTER))
|
||||
.affectedByScaling(inner.getBoolean("affected-by-scale-attribute", true))
|
||||
.build();
|
||||
this.bubbleConfigs.put(bubble.id(), bubble);
|
||||
this.bubbleConfigsByCommand.put(bubble.commandSuggestion(), bubble);
|
||||
@@ -319,6 +338,8 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
}
|
||||
|
||||
String fullText = config.textPrefix().fastCreate(player).render(player) + message.replace("\\", "\\\\") + config.textSuffix().fastCreate(player).render(player);
|
||||
// Bubbles only display text; discard hover payloads before layout and component conversion.
|
||||
fullText = AdventureHelper.miniMessage().serialize(AdventureHelper.miniMessage().deserialize(fullText, IGNORE_HOVER));
|
||||
int lines = plugin.getAdvanceManager().getLines(fullText, config.lineWidth());
|
||||
if (lines > config.maxLines()) return;
|
||||
if (lines <= 0) return;
|
||||
@@ -342,9 +363,10 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
|
||||
advance = config.lineWidth();
|
||||
}
|
||||
|
||||
int textLength = AdventureHelper.stripTags(message).length();
|
||||
BubbleTag bubbleTag = new BubbleTag(player, renderer, channel, config,
|
||||
AdventureHelper.miniMessageToMinecraftComponent(fullText),
|
||||
bubble == null ? null : AdventureHelper.miniMessageToMinecraftComponent(AdventureHelper.surroundWithNameplatesFont(bubble.createImage(advance, 1,1))), this);
|
||||
bubble == null ? null : AdventureHelper.miniMessageToMinecraftComponent(AdventureHelper.surroundWithNameplatesFont(bubble.createImage(advance, 1,1))), this, textLength);
|
||||
renderer.addTag(bubbleTag);
|
||||
if (delay != 0) {
|
||||
plugin.getScheduler().asyncLater(() -> bubbleTag.setCanShow(true), delay * 50L, TimeUnit.MILLISECONDS);
|
||||
|
||||
+14
-8
@@ -26,7 +26,6 @@ import net.momirealms.customnameplates.api.feature.tag.Tag;
|
||||
import net.momirealms.customnameplates.api.feature.tag.TagRenderer;
|
||||
import net.momirealms.customnameplates.api.network.Tracker;
|
||||
import net.momirealms.customnameplates.api.util.Alignment;
|
||||
import net.momirealms.customnameplates.api.util.Billboard;
|
||||
import net.momirealms.customnameplates.api.util.SelfIncreaseEntityID;
|
||||
import net.momirealms.customnameplates.api.util.Vector3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -45,6 +44,7 @@ public class BubbleTag extends AbstractTag {
|
||||
private final Object background;
|
||||
private final BubbleManager manager;
|
||||
private final BubbleConfig bubbleConfig;
|
||||
private final int stayDuration;
|
||||
private int ticker;
|
||||
private boolean canShow;
|
||||
private final String channel;
|
||||
@@ -53,13 +53,19 @@ public class BubbleTag extends AbstractTag {
|
||||
protected final int subEntityID = SelfIncreaseEntityID.getAndIncrease();
|
||||
protected final UUID subEntityUUID = UUID.randomUUID();
|
||||
|
||||
public BubbleTag(CNPlayer owner, TagRenderer renderer, String channel, BubbleConfig bubbleConfig, Object text, @Nullable Object background, BubbleManager bubbleManager) {
|
||||
public BubbleTag(CNPlayer owner, TagRenderer renderer, String channel, BubbleConfig bubbleConfig, Object text, @Nullable Object background, BubbleManager bubbleManager, int textLength) {
|
||||
super(owner, renderer);
|
||||
this.text = text;
|
||||
this.manager = bubbleManager;
|
||||
this.bubbleConfig = bubbleConfig;
|
||||
this.channel = channel;
|
||||
this.background = background;
|
||||
int base = bubbleManager.stayDuration();
|
||||
int extra = (int) (textLength * bubbleManager.durationPerCharacter());
|
||||
int duration = base + extra;
|
||||
int max = bubbleManager.maxStayDuration();
|
||||
if (max > 0 && duration > max) duration = max;
|
||||
this.stayDuration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,7 +80,7 @@ public class BubbleTag extends AbstractTag {
|
||||
text, bubbleConfig.backgroundColor(), (byte) -1, bubbleConfig.hasShadow(), false, false,
|
||||
Alignment.CENTER, bubbleConfig.billboard(), manager.viewRange(), 0.0f, 1.0f,
|
||||
new Vector3(0.001, 0.001, 0.001),
|
||||
affectedByScaling() ? translation.multiply(tracker.getScale()).add(0.01, 0, 0.01) : translation,
|
||||
affectedByScaling() ? translation.multiply(tracker.getScale()).add(0.02, 0, 0.02) : translation.add(0.02, 0, 0.02),
|
||||
bubbleConfig.lineWidth(),
|
||||
(affectedByCrouching() && tracker.isCrouching())
|
||||
));
|
||||
@@ -162,7 +168,7 @@ public class BubbleTag extends AbstractTag {
|
||||
@Override
|
||||
public void tick() {
|
||||
if (!canShow) return;
|
||||
if (ticker >= manager.stayDuration()) {
|
||||
if (ticker >= stayDuration) {
|
||||
renderer.removeTag(this);
|
||||
return;
|
||||
}
|
||||
@@ -173,7 +179,7 @@ public class BubbleTag extends AbstractTag {
|
||||
public void onPlayerScaleUpdate(CNPlayer viewer, double scale) {
|
||||
Consumer<List<Object>> modifier1 = CustomNameplates.getInstance().getPlatform().createScaleModifier(scale(viewer).multiply(scale));
|
||||
Vector3 translation = translation(viewer);
|
||||
Consumer<List<Object>> modifier2 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(translation.multiply(scale).add(0.01,0,0.01));
|
||||
Consumer<List<Object>> modifier2 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(translation.multiply(scale).add(0.02,0,0.02));
|
||||
Object packet1 = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(entityID, List.of(modifier1, modifier2));
|
||||
if (background != null) {
|
||||
Consumer<List<Object>> modifier3 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(translation.multiply(scale));
|
||||
@@ -189,10 +195,10 @@ public class BubbleTag extends AbstractTag {
|
||||
Tracker tracker = owner.getTracker(viewer);
|
||||
if (tracker != null) {
|
||||
Vector3 translation = translation(viewer);
|
||||
Consumer<List<Object>> modifier1 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(translation.multiply(tracker.getScale()).add(0.01,0,0.01));
|
||||
Consumer<List<Object>> modifier1 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(affectedByScaling() ? translation.multiply(tracker.getScale()).add(0.02,0,0.02) : translation.add(0.02,0,0.02));
|
||||
Object packet1 = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(entityID, List.of(modifier1));
|
||||
if (background != null) {
|
||||
Consumer<List<Object>> modifier2 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(translation.multiply(tracker.getScale()));
|
||||
Consumer<List<Object>> modifier2 = CustomNameplates.getInstance().getPlatform().createTranslationModifier(affectedByScaling() ? translation.multiply(tracker.getScale()) : translation);
|
||||
Object packet2 = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(subEntityID, List.of(modifier2));
|
||||
CustomNameplates.getInstance().getPacketSender().sendPacket(viewer, List.of(packet1, packet2));
|
||||
} else {
|
||||
@@ -309,7 +315,7 @@ public class BubbleTag extends AbstractTag {
|
||||
|
||||
@Override
|
||||
public boolean affectedByScaling() {
|
||||
return true;
|
||||
return bubbleConfig.affectedByScaling();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-1
@@ -33,7 +33,6 @@ import net.momirealms.customnameplates.api.feature.image.Animation;
|
||||
import net.momirealms.customnameplates.api.feature.image.Image;
|
||||
import net.momirealms.customnameplates.api.feature.nameplate.Nameplate;
|
||||
import net.momirealms.customnameplates.api.feature.pack.ResourcePackManager;
|
||||
import net.momirealms.customnameplates.api.helper.AdventureHelper;
|
||||
import net.momirealms.customnameplates.api.util.CharacterUtils;
|
||||
import net.momirealms.customnameplates.api.util.ZipUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
+12
-14
@@ -79,7 +79,7 @@ public class TagRendererImpl implements TagRenderer {
|
||||
|
||||
@Override
|
||||
public synchronized void onTick() {
|
||||
if (!isValid()) return;
|
||||
if (!isValid() || tagArray.length == 0) return;
|
||||
this.ticks++;
|
||||
|
||||
Set<CNPlayer> playersToUpdatePassengers = new ObjectOpenHashSet<>();
|
||||
@@ -185,7 +185,7 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(Tag tag) {
|
||||
public synchronized void addTag(Tag tag) {
|
||||
if (tagVector.contains(tag)) {
|
||||
return;
|
||||
}
|
||||
@@ -200,7 +200,7 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(Tag tag, int index) {
|
||||
public synchronized void addTag(Tag tag, int index) {
|
||||
if (index < 0 || index > this.tagArray.length) {
|
||||
throw new IndexOutOfBoundsException("Index out of bounds: " + index);
|
||||
}
|
||||
@@ -220,13 +220,12 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeTagIf(Predicate<Tag> predicate) {
|
||||
List<Integer> removedIndexes = new ArrayList<>();
|
||||
public synchronized int removeTagIf(Predicate<Tag> predicate) {
|
||||
List<Tag> toRemove = new ArrayList<>();
|
||||
boolean hasRTag = false;
|
||||
for (int i = 0; i < this.tagArray.length; i++) {
|
||||
Tag tag = this.tagArray[i];
|
||||
for (Tag tag : this.tagVector) {
|
||||
if (predicate.test(tag)) {
|
||||
removedIndexes.add(i);
|
||||
toRemove.add(tag);
|
||||
tag.hide();
|
||||
if (tag instanceof Feature feature) {
|
||||
this.owner.removeFeature(feature);
|
||||
@@ -236,18 +235,17 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removedIndexes.isEmpty()) {
|
||||
if (toRemove.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
Collections.reverse(removedIndexes);
|
||||
for (int index : removedIndexes) {
|
||||
this.tagVector.remove(index);
|
||||
for (Tag tag : toRemove) {
|
||||
this.tagVector.remove(tag);
|
||||
}
|
||||
resetTagArray();
|
||||
if (hasRTag) {
|
||||
resetRTagArray();
|
||||
}
|
||||
return removedIndexes.size();
|
||||
return toRemove.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,7 +259,7 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(Tag tag) {
|
||||
public synchronized void removeTag(Tag tag) {
|
||||
int i = 0;
|
||||
boolean has = false;
|
||||
for (Tag display : this.tagArray) {
|
||||
|
||||
+4
-2
@@ -593,8 +593,8 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
|
||||
public void refreshPlaceholders() {
|
||||
for (CNPlayer player : plugin.getOnlinePlayers()) {
|
||||
if (!player.isOnline()) continue;
|
||||
Set<Feature> featuresToNotifyUpdates = new ObjectOpenHashSet<>();
|
||||
Map<Feature, List<CNPlayer>> relationalFeaturesToNotifyUpdates = new Object2ObjectOpenHashMap<>();
|
||||
Set<Feature> featuresToNotifyUpdates = new ObjectOpenHashSet<>(0);
|
||||
Map<Feature, List<CNPlayer>> relationalFeaturesToNotifyUpdates = new Object2ObjectOpenHashMap<>(0);
|
||||
List<RelationalPlaceholder> delayedPlaceholdersToUpdate = new ObjectArrayList<>();
|
||||
for (Placeholder placeholder : player.activePlaceholdersToRefresh()) {
|
||||
if (placeholder instanceof PlayerPlaceholder playerPlaceholder) {
|
||||
@@ -706,6 +706,8 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (featuresToNotifyUpdates.isEmpty() && relationalFeaturesToNotifyUpdates.isEmpty()) continue;
|
||||
|
||||
// Switch to another thread for updating
|
||||
plugin.getScheduler().async().execute(() -> {
|
||||
// Async task takes time and the player might have been offline
|
||||
|
||||
@@ -13,7 +13,12 @@ channel-mode: ALL
|
||||
default-bubble: 'chat'
|
||||
y-offset: 0.1
|
||||
view-range: 0.5
|
||||
stay-duration: 150
|
||||
stay-duration: 100
|
||||
# Additional ticks added per visible character of the chat message.
|
||||
# Set to 0.0 to disable length-based duration.
|
||||
duration-per-character: 2.0
|
||||
# Maximum stay duration in ticks. 0 means no limit.
|
||||
max-stay-duration: 0
|
||||
appear-duration: 4
|
||||
disappear-duration: 2
|
||||
bubble-settings:
|
||||
@@ -28,4 +33,5 @@ bubble-settings:
|
||||
background-color: 0,0,0,0
|
||||
text-prefix: "<black><font:{namespace}:shift_0>" # {namespace} would be replaced by the namespace set in config.yml
|
||||
text-suffix: "</font></black>"
|
||||
command-suggestion: "White Chat Bubble"
|
||||
command-suggestion: "White Chat Bubble"
|
||||
affected-by-scale-attribute: true
|
||||
+30
-30
@@ -1,6 +1,6 @@
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=3.0.39
|
||||
project_version=3.0.45
|
||||
config_version=40
|
||||
project_group=net.momirealms
|
||||
|
||||
@@ -9,42 +9,42 @@ lang=en,zh_cn,ko_kr
|
||||
|
||||
# Dependency settings
|
||||
paper_version=1.20.4
|
||||
jetbrains_annotations_version=26.0.2
|
||||
slf4j_version=2.0.17
|
||||
log4j_version=2.25.2
|
||||
gson_version=2.13.2
|
||||
asm_version=9.9.1
|
||||
asm_commons_version=9.9.1
|
||||
jetbrains_annotations_version=26.1.0
|
||||
slf4j_version=2.0.20
|
||||
log4j_version=2.26.1
|
||||
gson_version=2.14.0
|
||||
asm_version=9.10.1
|
||||
asm_commons_version=9.10.1
|
||||
jar_relocator_version=1.7
|
||||
h2_driver_version=2.4.240
|
||||
sqlite_driver_version=3.50.3.0
|
||||
adventure_bundle_version=5.0.1
|
||||
adventure_platform_version=4.4.1
|
||||
cloud_core_version=2.0.0
|
||||
cloud_services_version=2.0.0
|
||||
cloud_brigadier_version=2.0.0-beta.15
|
||||
cloud_bukkit_version=2.0.0-beta.15
|
||||
cloud_paper_version=2.0.0-beta.15
|
||||
cloud_minecraft_extras_version=2.0.0-beta.15
|
||||
h2_driver_version=2.5.252
|
||||
sqlite_driver_version=3.53.4.0
|
||||
adventure_bundle_version=5.2.0
|
||||
cloud_core_version=2.1.0
|
||||
cloud_services_version=2.1.0
|
||||
cloud_brigadier_version=2.0.1
|
||||
cloud_bukkit_version=2.0.1
|
||||
cloud_paper_version=2.0.1
|
||||
cloud_minecraft_extras_version=2.0.1
|
||||
boosted_yaml_version=1.3.7
|
||||
byte_buddy_version=1.18.8
|
||||
byte_buddy_version=1.18.14
|
||||
mojang_brigadier_version=1.0.18
|
||||
mongodb_driver_version=5.6.5
|
||||
mariadb_driver_version=3.5.8
|
||||
mysql_driver_version=9.6.0
|
||||
hikari_version=7.0.2
|
||||
commons_pool_version=2.12.1
|
||||
mongodb_driver_version=5.13.0
|
||||
mariadb_driver_version=3.5.10
|
||||
mysql_driver_version=26.7.0
|
||||
hikari_version=7.1.0
|
||||
commons_pool_version=2.13.1
|
||||
bstats_version=3.2.1
|
||||
geantyref_version=1.3.16
|
||||
caffeine_version=3.2.3
|
||||
jedis_version=7.4.1
|
||||
geantyref_version=2.0.1
|
||||
caffeine_version=3.3.0
|
||||
jedis_version=8.0.1
|
||||
exp4j_version=0.4.8
|
||||
placeholder_api_version=2.11.7
|
||||
vault_version=1.7
|
||||
guava_version=33.5.0-jre
|
||||
commons_io_version=2.21.0
|
||||
lwjgl_version=3.4.1
|
||||
fastutil_version=8.5.18
|
||||
guava_version=33.7.1-jre
|
||||
commons_io_version=2.22.0
|
||||
lwjgl_version=3.4.3
|
||||
netty_version=4.2.18.Final
|
||||
fastutil_version=8.5.19
|
||||
|
||||
# Proxy settings
|
||||
#systemProp.socks.proxyHost=127.0.0.1
|
||||
|
||||
@@ -13,6 +13,7 @@ repositories {
|
||||
maven("https://repo.papermc.io/repository/maven-public/") // paper
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // spigot
|
||||
maven("https://repo.momirealms.net/releases/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -24,6 +25,8 @@ dependencies {
|
||||
|
||||
compileOnly("dev.folia:folia-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:${rootProject.properties["placeholder_api_version"]}")
|
||||
compileOnly("com.mojang:datafixerupper:10.0.21")
|
||||
compileOnly("com.mojang:brigadier:1.3.10")
|
||||
|
||||
// YAML
|
||||
compileOnly("dev.dejvokep:boosted-yaml:${rootProject.properties["boosted_yaml_version"]}")
|
||||
@@ -31,11 +34,17 @@ dependencies {
|
||||
// Adventure
|
||||
implementation("net.kyori:adventure-api:${rootProject.properties["adventure_bundle_version"]}")
|
||||
implementation("net.kyori:adventure-text-minimessage:${rootProject.properties["adventure_bundle_version"]}")
|
||||
implementation("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}")
|
||||
implementation("net.kyori:adventure-text-serializer-gson:${rootProject.properties["adventure_bundle_version"]}") {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
}
|
||||
implementation("net.kyori:adventure-text-serializer-json-legacy-impl:${rootProject.properties["adventure_bundle_version"]}")
|
||||
implementation("net.kyori:adventure-text-serializer-legacy:${project.properties["adventure_bundle_version"]}")
|
||||
|
||||
implementation("net.momirealms:sparrow-reflection:0.34")
|
||||
implementation("net.momirealms:sparrow-nbt:0.22")
|
||||
implementation("net.momirealms:sparrow-nbt-codec:0.22")
|
||||
implementation("net.momirealms:sparrow-nbt-legacy-codec:0.22")
|
||||
implementation("net.momirealms:sparrow-nbt-parser:0.22")
|
||||
|
||||
// BStats
|
||||
compileOnly("org.bstats:bstats-bukkit:${rootProject.properties["bstats_version"]}")
|
||||
@@ -45,7 +54,7 @@ dependencies {
|
||||
compileOnly("org.incendo:cloud-minecraft-extras:${rootProject.properties["cloud_minecraft_extras_version"]}")
|
||||
compileOnly("org.incendo:cloud-paper:${rootProject.properties["cloud_paper_version"]}")
|
||||
// Netty
|
||||
compileOnly("io.netty:netty-all:4.1.117.Final")
|
||||
compileOnly("io.netty:netty-all:${rootProject.properties["netty_version"]}")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -67,6 +76,8 @@ tasks {
|
||||
relocate("com.github.benmanes.caffeine", "net.momirealms.customnameplates.libraries.caffeine")
|
||||
relocate("net.objecthunter.exp4j", "net.momirealms.customnameplates.libraries.exp4j")
|
||||
relocate("redis.clients.jedis", "net.momirealms.customnameplates.libraries.jedis")
|
||||
relocate("net.momirealms.sparrow.reflection", "net.momirealms.customnameplates.libraries.reflection")
|
||||
relocate("net.momirealms.sparrow.nbt", "net.momirealms.customnameplates.libraries.nbt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,4 +113,4 @@ tasks.register("run-paper", RunServer::class) {
|
||||
jvmArgs("-Ddisable.watchdog=true")
|
||||
jvmArgs("-Xlog:redefine+class*=info")
|
||||
jvmArgs("-XX:+AllowEnhancedClassRedefinition")
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ repositories {
|
||||
maven("https://repo.opencollab.dev/main/") // geyser
|
||||
maven("https://maven.enginehub.org/repo/") // worldguard worldedit
|
||||
maven("https://repo.alessiodp.com/releases/") // parties
|
||||
maven("https://maven.devs.beer/") // ia
|
||||
maven("https://repo.pinodev.it/releases/") // zelchat
|
||||
maven("https://repo.hibiscusmc.com/releases") // hmccosmetics
|
||||
}
|
||||
@@ -50,8 +49,8 @@ dependencies {
|
||||
// compileOnly("com.github.Brikster:Chatty:v2.19.14")
|
||||
compileOnly(files("libs/Chatty-3.0.0-SNAPSHOT.jar"))
|
||||
// Emoji
|
||||
compileOnly("dev.lone:api-itemsadder:4.0.10")
|
||||
compileOnly("io.th0rgal:oraxen:1.182.0")
|
||||
compileOnly("beer.devs:itemsadder-api:4.0.17")
|
||||
compileOnly("io.th0rgal:oraxen:1.217.0")
|
||||
// PAPI
|
||||
compileOnly("me.clip:placeholderapi:${rootProject.properties["placeholder_api_version"]}")
|
||||
// Disguise
|
||||
|
||||
-2
@@ -22,11 +22,9 @@ import mineverse.Aust1n46.chat.api.MineverseChatPlayer;
|
||||
import mineverse.Aust1n46.chat.api.events.VentureChatEvent;
|
||||
import mineverse.Aust1n46.chat.channel.ChatChannel;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.ConfigManager;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.api.feature.chat.AbstractChatMessageProvider;
|
||||
import net.momirealms.customnameplates.api.feature.chat.ChatManager;
|
||||
import net.momirealms.customnameplates.api.helper.AdventureHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ package net.momirealms.customnameplates.bukkit.compatibility.chat;
|
||||
|
||||
import it.pino.zelchat.api.ZelChatAPI;
|
||||
import it.pino.zelchat.api.message.ChatMessage;
|
||||
import it.pino.zelchat.api.message.channel.ChannelType;
|
||||
import it.pino.zelchat.api.message.channel.ChatChannel;
|
||||
import it.pino.zelchat.api.message.state.MessageState;
|
||||
import it.pino.zelchat.api.module.ChatModule;
|
||||
|
||||
+7
-29
@@ -18,49 +18,27 @@
|
||||
package net.momirealms.customnameplates.bukkit.compatibility.emoji;
|
||||
|
||||
import io.th0rgal.oraxen.OraxenPlugin;
|
||||
import io.th0rgal.oraxen.font.FontManager;
|
||||
import io.th0rgal.oraxen.font.Glyph;
|
||||
import io.th0rgal.oraxen.fonts.FontManager;
|
||||
import io.th0rgal.oraxen.glyphs.Glyph;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.feature.chat.emoji.EmojiProvider;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class OraxenEmojiProvider implements EmojiProvider {
|
||||
private final FontManager fontManager;
|
||||
private final Function<Glyph, String> characterFunction;
|
||||
|
||||
public OraxenEmojiProvider(int version) {
|
||||
if (version == 1) {
|
||||
this.fontManager = OraxenPlugin.get().getFontManager();
|
||||
this.characterFunction = Glyph::getCharacter;
|
||||
} else {
|
||||
try {
|
||||
Method fm = OraxenPlugin.class.getMethod("fontManager");
|
||||
this.fontManager = (FontManager) fm.invoke(OraxenPlugin.get());
|
||||
Method cm = Glyph.class.getMethod("character");
|
||||
this.characterFunction = (glyph -> {
|
||||
try {
|
||||
return (String) cm.invoke(glyph);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public OraxenEmojiProvider() {
|
||||
this.fontManager = OraxenPlugin.get().getFontManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String replace(CNPlayer player, String text) {
|
||||
for (Map.Entry<String, Glyph> entry : this.fontManager.getGlyphByPlaceholderMap().entrySet()) {
|
||||
if (entry.getValue().hasPermission((Player) player.player())) {
|
||||
text = text.replace(entry.getKey(), "<white><font:default>" + characterFunction.apply(entry.getValue()) + "</font></white>");
|
||||
}
|
||||
String unicode = entry.getValue().getCharacters();
|
||||
if (entry.getValue().hasPermission((Player) player.player()))
|
||||
text = text.replace(entry.getKey(), "<white>" + unicode + "</white>");
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
+4
-4
@@ -21,17 +21,17 @@ import io.netty.channel.Channel;
|
||||
import net.momirealms.customnameplates.api.AbstractCNPlayer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.api.util.Vector3;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BukkitCNPlayer extends AbstractCNPlayer<Player> {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class BukkitChatManager extends AbstractChatManager {
|
||||
}
|
||||
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
|
||||
try {
|
||||
this.emojiProviders.add(new OraxenEmojiProvider(Bukkit.getPluginManager().getPlugin("Oraxen").getDescription().getVersion().startsWith("1") ? 1 : 2));
|
||||
this.emojiProviders.add(new OraxenEmojiProvider());
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
+20
-7
@@ -34,7 +34,6 @@ import net.momirealms.customnameplates.backend.feature.bubble.BubbleManagerImpl;
|
||||
import net.momirealms.customnameplates.backend.feature.image.ImageManagerImpl;
|
||||
import net.momirealms.customnameplates.backend.feature.nameplate.NameplateManagerImpl;
|
||||
import net.momirealms.customnameplates.backend.feature.pack.ResourcePackManagerImpl;
|
||||
import net.momirealms.customnameplates.backend.feature.tag.AbstractUnlimitedTagManager;
|
||||
import net.momirealms.customnameplates.backend.placeholder.PlaceholderManagerImpl;
|
||||
import net.momirealms.customnameplates.backend.storage.StorageManagerImpl;
|
||||
import net.momirealms.customnameplates.bukkit.command.BukkitCommandManager;
|
||||
@@ -429,23 +428,34 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
|
||||
if (cnPlayer == null) {
|
||||
return;
|
||||
}
|
||||
for (JoinQuitListener listener : joinQuitListeners) {
|
||||
listener.onPlayerQuit(cnPlayer);
|
||||
}
|
||||
entityIDFastLookup.remove(cnPlayer.entityID());
|
||||
if (VersionHelper.isFolia()) {
|
||||
foliaLocationTracker.remove(player.getName());
|
||||
try {
|
||||
for (JoinQuitListener listener : joinQuitListeners) {
|
||||
listener.onPlayerQuit(cnPlayer);
|
||||
}
|
||||
} finally {
|
||||
removePlayerFromTrackers(cnPlayer);
|
||||
entityIDFastLookup.remove(cnPlayer.entityID());
|
||||
if (VersionHelper.isFolia()) {
|
||||
foliaLocationTracker.remove(player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleQuit(CNPlayer cnPlayer) {
|
||||
entityIDFastLookup.remove(cnPlayer.entityID());
|
||||
onlinePlayerMap.remove(cnPlayer.uuid());
|
||||
removePlayerFromTrackers(cnPlayer);
|
||||
if (VersionHelper.isFolia()) {
|
||||
foliaLocationTracker.remove(cnPlayer.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void removePlayerFromTrackers(CNPlayer player) {
|
||||
for (CNPlayer onlinePlayer : getOnlinePlayers()) {
|
||||
onlinePlayer.removePlayerFromTracker(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onChangeWorld(PlayerChangedWorldEvent event) {
|
||||
if (VersionHelper.isFolia()) return;
|
||||
@@ -469,6 +479,9 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onTeleport(PlayerTeleportEvent event) {
|
||||
if (!event.getFrom().getWorld().equals(event.getTo().getWorld())) {
|
||||
return;
|
||||
}
|
||||
CNPlayer cnPlayer = getPlayer(event.getPlayer().getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
for (PlayerListener listener : playerListeners) {
|
||||
|
||||
+28
-15
@@ -74,17 +74,28 @@ public class BukkitNetworkManager implements PacketSender, PipelineInjector {
|
||||
};
|
||||
} else {
|
||||
packetConsumer = (player, packet) -> {
|
||||
Vector3 vector3 = player.position();
|
||||
Location location = new Location(Bukkit.getWorld(player.world()), vector3.x(), vector3.y(), vector3.z());
|
||||
plugin.getScheduler().executeSync(() -> {
|
||||
try {
|
||||
Reflections.method$SendPacket.invoke(
|
||||
Reflections.field$PlayerConnection.get(
|
||||
Reflections.method$CraftPlayer$getHandle.invoke(player.player())), packet);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, location);
|
||||
Player bukkitPlayer = (Player) player.player();
|
||||
if (VersionHelper.isFolia()) {
|
||||
// Follow the player across regions/worlds and discard tasks when the entity retires.
|
||||
bukkitPlayer.getScheduler().execute(plugin.getBootstrap(), () -> {
|
||||
if (!bukkitPlayer.isOnline()) return;
|
||||
try {
|
||||
Reflections.method$SendPacket.invoke(Reflections.field$PlayerConnection.get(Reflections.method$CraftPlayer$getHandle.invoke(bukkitPlayer)), packet);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, null, 1L);
|
||||
} else {
|
||||
Vector3 vector3 = player.position();
|
||||
Location location = new Location(Bukkit.getWorld(player.world()), vector3.x(), vector3.y(), vector3.z());
|
||||
plugin.getScheduler().executeSync(() -> {
|
||||
try {
|
||||
Reflections.method$SendPacket.invoke(Reflections.field$PlayerConnection.get(Reflections.method$CraftPlayer$getHandle.invoke(player.player())), packet);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, location);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.active = true;
|
||||
@@ -289,15 +300,17 @@ public class BukkitNetworkManager implements PacketSender, PipelineInjector {
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext context, Object packet, ChannelPromise channelPromise) throws Exception {
|
||||
PacketEvent event = new PacketEvent(packet);
|
||||
try {
|
||||
PacketEvent event = new PacketEvent(packet);
|
||||
plugin.getPlatform().onPacketSend(player, event);
|
||||
if (event.cancelled()) return;
|
||||
super.write(context, packet, channelPromise);
|
||||
} catch (Throwable e) {
|
||||
plugin.getPluginLogger().severe("An error occurred when reading packets", e);
|
||||
plugin.getPluginLogger().severe("An error occurred when processing an outbound packet", e);
|
||||
super.write(context, packet, channelPromise);
|
||||
return;
|
||||
}
|
||||
if (event.cancelled()) return;
|
||||
super.write(context, packet, channelPromise);
|
||||
event.runAfterSendTasks(e -> plugin.getPluginLogger().severe("An error occurred in an after-send packet task", e));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+75
-8
@@ -17,8 +17,13 @@
|
||||
|
||||
package net.momirealms.customnameplates.bukkit;
|
||||
|
||||
import com.google.gson.JsonNull;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||
import net.kyori.adventure.text.event.DataComponentValueConverterRegistry;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonDataComponentValue;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.ConfigManager;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
@@ -40,6 +45,18 @@ import net.momirealms.customnameplates.bukkit.util.EntityData;
|
||||
import net.momirealms.customnameplates.bukkit.util.Reflections;
|
||||
import net.momirealms.customnameplates.common.util.TriConsumer;
|
||||
import net.momirealms.customnameplates.common.util.UUIDUtils;
|
||||
import net.momirealms.sparrow.nbt.EndTag;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import net.momirealms.sparrow.nbt.codec.JsonOps;
|
||||
import net.momirealms.sparrow.nbt.codec.LegacyJavaOps;
|
||||
import net.momirealms.sparrow.nbt.codec.LegacyJsonOps;
|
||||
import net.momirealms.sparrow.nbt.codec.NBTOps;
|
||||
import net.momirealms.sparrow.nbt.parser.TagParser;
|
||||
import net.momirealms.sparrow.reflection.clazz.SparrowClass;
|
||||
import net.momirealms.sparrow.reflection.constructor.SConstructor2;
|
||||
import net.momirealms.sparrow.reflection.constructor.matcher.ConstructorMatcher;
|
||||
import net.momirealms.sparrow.reflection.field.SField;
|
||||
import net.momirealms.sparrow.reflection.field.matcher.FieldMatcher;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@@ -47,6 +64,7 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -100,6 +118,8 @@ public class BukkitPlatform implements Platform {
|
||||
}
|
||||
|
||||
static {
|
||||
injectAdventure();
|
||||
|
||||
// ThrowableFunction<Object, String> scoreContentNameFunction = VersionHelper.isVersionNewerThan1_21_2() ? (o -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// Optional<String> optional = (Optional<String>) Reflections.method$Either$right.invoke(o);
|
||||
@@ -208,9 +228,11 @@ public class BukkitPlatform implements Platform {
|
||||
int entityID = (int) Reflections.field$ClientboundAddEntityPacket$entityId.get(packet);
|
||||
CNPlayer added = CustomNameplates.getInstance().getPlayer(entityID);
|
||||
if (added != null) {
|
||||
Tracker tracker = added.addPlayerToTracker(player);
|
||||
tracker.setSpectator(added.isSpectator());
|
||||
CustomNameplates.getInstance().getUnlimitedTagManager().onAddPlayer(added, player);
|
||||
event.afterSend(() -> {
|
||||
Tracker tracker = added.addPlayerToTracker(player);
|
||||
tracker.setSpectator(added.isSpectator());
|
||||
CustomNameplates.getInstance().getUnlimitedTagManager().onAddPlayer(added, player);
|
||||
});
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CustomNameplates.getInstance().getPluginLogger().severe("Failed to handle ClientboundAddEntityPacket", e);
|
||||
@@ -224,9 +246,11 @@ public class BukkitPlatform implements Platform {
|
||||
int entityID = (int) Reflections.field$PacketPlayOutNamedEntitySpawn$entityId.get(packet);
|
||||
CNPlayer added = CustomNameplates.getInstance().getPlayer(entityID);
|
||||
if (added != null) {
|
||||
Tracker tracker = added.addPlayerToTracker(player);
|
||||
tracker.setSpectator(added.isSpectator());
|
||||
CustomNameplates.getInstance().getUnlimitedTagManager().onAddPlayer(added, player);
|
||||
event.afterSend(() -> {
|
||||
Tracker tracker = added.addPlayerToTracker(player);
|
||||
tracker.setSpectator(added.isSpectator());
|
||||
CustomNameplates.getInstance().getUnlimitedTagManager().onAddPlayer(added, player);
|
||||
});
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CustomNameplates.getInstance().getPluginLogger().severe("Failed to handle PacketPlayOutNamedEntitySpawn", e);
|
||||
@@ -418,6 +442,7 @@ public class BukkitPlatform implements Platform {
|
||||
}, "ClientboundSetEntityDataPacket", "PacketPlayOutEntityMetadata");
|
||||
|
||||
// not a perfect solution but would work in most cases
|
||||
SField visibilityField = VersionHelper.isVersionNewerThan26_2() ? SparrowClass.of(Reflections.clazz$ClientboundSetPlayerTeamPacket$Parameters).getDeclaredSparrowField(FieldMatcher.named("nameTagVisibility")).mh() : null;
|
||||
registerPacketConsumer((player, event, packet) -> {
|
||||
if (!ConfigManager.nametagModule()) return;
|
||||
if (!ConfigManager.hideTeamNames()) return;
|
||||
@@ -451,7 +476,11 @@ public class BukkitPlatform implements Platform {
|
||||
Optional<Object> optionalParameters = (Optional<Object>) Reflections.field$ClientboundSetPlayerTeamPacket$parameters.get(packet);
|
||||
if (optionalParameters.isPresent()) {
|
||||
Object parameters = optionalParameters.get();
|
||||
Reflections.field$ClientboundSetPlayerTeamPacket$Parameters$nametagVisibility.set(parameters, VersionHelper.isVersionNewerThan1_21_5() ? Reflections.instance$Team$Visibility$NEVER : "never");
|
||||
if (VersionHelper.isVersionNewerThan26_2()) {
|
||||
visibilityField.set(parameters, Reflections.instance$Team$Visibility$NEVER);
|
||||
} else {
|
||||
Reflections.field$ClientboundSetPlayerTeamPacket$Parameters$nametagVisibility.set(parameters, VersionHelper.isVersionNewerThan1_21_5() ? Reflections.instance$Team$Visibility$NEVER : "never");
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove
|
||||
@@ -481,7 +510,11 @@ public class BukkitPlatform implements Platform {
|
||||
Optional<Object> optionalParameters = (Optional<Object>) Reflections.field$ClientboundSetPlayerTeamPacket$parameters.get(packet);
|
||||
if (optionalParameters.isPresent()) {
|
||||
Object parameters = optionalParameters.get();
|
||||
Reflections.field$ClientboundSetPlayerTeamPacket$Parameters$nametagVisibility.set(parameters, VersionHelper.isVersionNewerThan1_21_5() ? Reflections.instance$Team$Visibility$NEVER : "never");
|
||||
if (VersionHelper.isVersionNewerThan26_2()) {
|
||||
visibilityField.set(parameters, Reflections.instance$Team$Visibility$NEVER);
|
||||
} else {
|
||||
Reflections.field$ClientboundSetPlayerTeamPacket$Parameters$nametagVisibility.set(parameters, VersionHelper.isVersionNewerThan1_21_5() ? Reflections.instance$Team$Visibility$NEVER : "never");
|
||||
}
|
||||
}
|
||||
}
|
||||
// add members
|
||||
@@ -762,4 +795,38 @@ public class BukkitPlatform implements Platform {
|
||||
Optional.ofNullable(packetFunctions.get(packet.getClass().getSimpleName()))
|
||||
.ifPresent(function -> function.accept(player, event, packet));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void injectAdventure() {
|
||||
Map<Class<?>, Map<Class<?>, Object>> CACHE = (Map<Class<?>, Map<Class<?>, Object>>) SparrowClass.of(SparrowClass.find("net.kyori.adventure.text.event.DataComponentValueConverterRegistry$ConversionCache"))
|
||||
.getDeclaredSparrowField(FieldMatcher.named("CACHE"))
|
||||
.mh()
|
||||
.get(null);
|
||||
Class<?> tagClass = SparrowClass.find("net.kyori.adventure.nbt.api.BinaryTagHolderImpl");
|
||||
DataComponentValueConverterRegistry.Conversion<BinaryTagHolder, GsonDataComponentValue> convertor1 = DataComponentValueConverterRegistry.Conversion.convert(
|
||||
BinaryTagHolder.class,
|
||||
GsonDataComponentValue.class,
|
||||
(key, srcValue) -> {
|
||||
try {
|
||||
Tag tag = TagParser.parseTagFully(srcValue.string());
|
||||
if (tag == EndTag.INSTANCE) {
|
||||
return GsonDataComponentValue.gsonDataComponentValue(JsonNull.INSTANCE);
|
||||
} else {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
return GsonDataComponentValue.gsonDataComponentValue(NBTOps.INSTANCE.convertTo(JsonOps.INSTANCE, tag));
|
||||
} else {
|
||||
return GsonDataComponentValue.gsonDataComponentValue(LegacyJavaOps.INSTANCE.convertTo(LegacyJsonOps.INSTANCE, tag));
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
return GsonDataComponentValue.gsonDataComponentValue(JsonNull.INSTANCE);
|
||||
}
|
||||
}
|
||||
);
|
||||
SConstructor2 constructor = SparrowClass.of(SparrowClass.find("net.kyori.adventure.text.event.DataComponentValueConverterRegistry$RegisteredConversion"))
|
||||
.getDeclaredSparrowConstructor(ConstructorMatcher.takeArguments(Key.class, DataComponentValueConverterRegistry.Conversion.class))
|
||||
.asm$2();
|
||||
CACHE.computeIfAbsent(tagClass, $ -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(GsonDataComponentValue.class, $ -> constructor.newInstance(Key.key("nameplates", "serializer/nbt"), convertor1));
|
||||
}
|
||||
}
|
||||
+2
-13
@@ -25,9 +25,8 @@
|
||||
|
||||
package net.momirealms.customnameplates.bukkit;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.momirealms.customnameplates.api.helper.AdventureHelper;
|
||||
import net.momirealms.customnameplates.bukkit.util.Reflections;
|
||||
import net.momirealms.customnameplates.common.sender.Sender;
|
||||
@@ -41,11 +40,9 @@ import org.bukkit.entity.Player;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitSenderFactory extends SenderFactory<BukkitCustomNameplates, CommandSender> {
|
||||
private final BukkitAudiences audiences;
|
||||
|
||||
public BukkitSenderFactory(BukkitCustomNameplates plugin) {
|
||||
super(plugin);
|
||||
this.audiences = BukkitAudiences.create(plugin.getBootstrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,11 +61,6 @@ public class BukkitSenderFactory extends SenderFactory<BukkitCustomNameplates, C
|
||||
return Sender.CONSOLE_UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Audience getAudience(CommandSender sender) {
|
||||
return this.audiences.sender(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMessage(CommandSender sender, Component message) {
|
||||
if (sender instanceof Player player) {
|
||||
@@ -78,10 +70,8 @@ public class BukkitSenderFactory extends SenderFactory<BukkitCustomNameplates, C
|
||||
} catch (ReflectiveOperationException e) {
|
||||
getPlugin().getPluginLogger().warn("Failed to send message to player " + sender.getName(), e);
|
||||
}
|
||||
} else if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
|
||||
getAudience(sender).sendMessage(message);
|
||||
} else {
|
||||
getPlugin().getScheduler().executeSync(() -> getAudience(sender).sendMessage(message));
|
||||
sender.sendMessage(LegacyComponentSerializer.legacySection().serialize(message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +104,5 @@ public class BukkitSenderFactory extends SenderFactory<BukkitCustomNameplates, C
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
this.audiences.close();
|
||||
}
|
||||
}
|
||||
-1
@@ -22,7 +22,6 @@ import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.ConfigManager;
|
||||
import net.momirealms.customnameplates.api.feature.bubble.BubbleConfig;
|
||||
import net.momirealms.customnameplates.api.helper.AdventureHelper;
|
||||
import net.momirealms.customnameplates.api.util.CharacterUtils;
|
||||
import net.momirealms.customnameplates.bukkit.BukkitCustomNameplates;
|
||||
import net.momirealms.customnameplates.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customnameplates.common.command.CustomNameplatesCommandManager;
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package net.momirealms.customnameplates.bukkit.reflection;
|
||||
|
||||
import net.momirealms.sparrow.reflection.clazz.SparrowClass;
|
||||
import net.momirealms.sparrow.reflection.proxy.ASMProxyFactory;
|
||||
import net.momirealms.sparrow.reflection.proxy.annotation.MethodInvoker;
|
||||
import net.momirealms.sparrow.reflection.proxy.annotation.ReflectionProxy;
|
||||
|
||||
@ReflectionProxy(name = "net.minecraft.nbt.CompoundTag")
|
||||
public interface CompoundTagProxy {
|
||||
CompoundTagProxy INSTANCE = ASMProxyFactory.create(CompoundTagProxy.class);
|
||||
Class<?> CLASS = SparrowClass.find("net.minecraft.nbt.CompoundTag");
|
||||
|
||||
@MethodInvoker(name = "get")
|
||||
Object get(Object target, String key);
|
||||
}
|
||||
+2
-2
@@ -1000,7 +1000,7 @@ public final class Reflections {
|
||||
|
||||
public static final Field field$ClientboundSetPlayerTeamPacket$players = requireNonNull(
|
||||
ReflectionUtils.getInstanceDeclaredField(
|
||||
clazz$ClientboundSetPlayerTeamPacket, Collection.class, 0
|
||||
clazz$ClientboundSetPlayerTeamPacket, VersionHelper.isVersionNewerThan26_3() ? List.class : Collection.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1210,7 +1210,7 @@ public final class Reflections {
|
||||
);
|
||||
|
||||
public static final Method method$GsonComponentSerializer$builder = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$GsonComponentSerializer, clazz$GsonComponentSerializer$Builder
|
||||
)
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user