35 Commits
Author SHA1 Message Date
XiaoMoMi 28ccd9130c improved scale support 2025-01-25 17:46:35 +08:00
XiaoMoMi 16976e6347 fix scale 2025-01-24 19:28:39 +08:00
XiaoMoMi c8f8c38cc8 work 2025-01-16 18:17:10 +08:00
XiaoMoMi ddbe549900 Improve data storage 2025-01-16 18:15:28 +08:00
XiaoMoMi b4608394f7 Update gradle-wrapper.properties 2025-01-10 00:20:58 +08:00
XiaoMoMi 7b7fe63364 Update gradle.properties 2025-01-10 00:20:44 +08:00
XiaoMoMi 906390aa78 Update plugin.yml 2025-01-06 17:52:48 +08:00
XiaoMoMi c491a99b1e add zip 2025-01-06 17:28:07 +08:00
XiaoMoMi 5733338584 fix repo 2025-01-03 16:42:06 +08:00
XiaoMoMi 2fb0e311c9 Update BedrockPlayerRequirement.java 2024-12-30 22:37:55 +08:00
XiaoMoMi 44656962ac fix debug stick 2024-12-30 03:21:59 +08:00
XiaoMoMi 87703736c3 Update gradle.properties 2024-12-28 17:40:52 +08:00
XiaoMoMi 1053b36f75 clean up cache 2024-12-28 17:34:30 +08:00
XiaoMoMi 9b26ce4e19 Added craftengine support 2024-12-28 17:04:52 +08:00
XiaoMoMi 0270830517 Added API to take over actionbars 2024-12-26 18:14:06 +08:00
XiaoMoMi 23bde6ab9d Fix npe caused by other plugins 2024-12-22 15:56:12 +08:00
XiaoMoMi 6f0e61ae48 shut down scheduler on disable 2024-12-21 19:39:30 +08:00
XiaoMoMi 26b593950d bump version 3.0.15.2 2024-12-10 16:24:46 +08:00
XiaoMoMi 63896acda6 use snapshot adventure 2024-12-10 16:24:06 +08:00
XiaoMoMi 6eb5dee611 Update custom-placeholders.yml 2024-12-10 16:23:48 +08:00
XiaoMoMi 69869d1cb1 update pack format 2024-12-10 16:02:48 +08:00
XiaoMoMi 2e702d8945 Fix thread safety issue 2024-12-09 03:29:06 +08:00
XiaoMoMi 56c77bd294 3.0.15.1 2024-12-04 15:35:12 +08:00
XiaoMoMi 4d195820a0 improve send delay 2024-11-29 17:40:54 +08:00
XiaoMoMi 2874ab7c4e send bossbar immediately 2024-11-29 17:34:40 +08:00
XiaoMoMi cd1a0bffb6 chatty 2024-11-28 18:49:59 +08:00
XiaoMoMi 20d3919c6b Fix regex 2024-11-22 00:57:24 +08:00
XiaoMoMi fccaa059ff Added generate option for bitmaps 2024-11-21 02:14:49 +08:00
XiaoMoMi ed2fb60748 Update settings.gradle.kts 2024-11-19 18:38:26 +08:00
XiaoMoMi 378dc2e3bc Update gradle.properties 2024-11-19 18:37:38 +08:00
XiaoMoMi 6144423110 Update gradle.properties 2024-11-19 18:33:13 +08:00
XiaoMoMi d21fa8a3f7 work 2024-11-19 18:33:04 +08:00
XiaoMoMi 7e68a6cda7 move packages 2024-11-19 16:52:02 +08:00
XiaoMoMi 3df6d66efb better support 2024-11-19 16:46:01 +08:00
XiaoMoMi 001ecd28ed remove debug 2024-11-18 15:14:05 +08:00
146 changed files with 1291 additions and 246 deletions

No files matched your search

+3
View File
@@ -5,6 +5,9 @@ target/
!**/src/main/**/build/
!**/src/test/**/build/
### Unfinished ###
platforms/sponge/
### IntelliJ IDEA ###
.idea
*.iws
+2 -2
View File
@@ -5,8 +5,8 @@ plugins {
repositories {
maven("https://jitpack.io/")
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
@@ -18,7 +18,6 @@
package net.momirealms.customnameplates.api;
import io.netty.channel.Channel;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.momirealms.customnameplates.api.feature.Feature;
@@ -37,6 +36,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public abstract class AbstractCNPlayer implements CNPlayer {
@@ -45,33 +46,51 @@ public abstract class AbstractCNPlayer implements CNPlayer {
protected Object player;
private boolean isLoaded = false;
private volatile boolean isLoaded = false;
private volatile boolean tempPreviewing = false;
private volatile boolean toggleablePreviewing = false;
private boolean tempPreviewing = false;
private boolean toggleablePreviewing = false;
private String equippedNameplate;
private String equippedBubble;
private String currentNameplate;
private String nameplateData;
private String currentBubble;
private String bubbleData;
private final TeamView teamView = new TeamView();
// these maps might be visited by other threads through PlaceholderAPI
private final Map<Integer, TimeStampData<String>> cachedValues = new ConcurrentHashMap<>(128);
private final Map<Integer, WeakHashMap<CNPlayer, TimeStampData<String>>> cachedRelationalValues = new ConcurrentHashMap<>(128);
private final Map<Integer, TimeStampData<Boolean>> cachedRequirements = new Int2ObjectOpenHashMap<>(32);
private final Map<Integer, WeakHashMap<CNPlayer, TimeStampData<Boolean>>> cachedRelationalRequirements = new Int2ObjectOpenHashMap<>(32);
private final Map<Integer, TimeStampData<Boolean>> cachedRequirements = new ConcurrentHashMap<>(32);
private final Map<Integer, WeakHashMap<CNPlayer, TimeStampData<Boolean>>> cachedRelationalRequirements = new ConcurrentHashMap<>(32);
private final Set<Feature> activeFeatures = new CopyOnWriteArraySet<>();
private final Map<Placeholder, Set<Feature>> placeholder2Features = new ConcurrentHashMap<>();
private final Map<Feature, Set<Placeholder>> feature2Placeholders = new ConcurrentHashMap<>();
private final Map<CNPlayer, Tracker> trackers = Collections.synchronizedMap(new WeakHashMap<>());
private final Map<CNPlayer, Tracker> trackers = new WeakHashMap<>();
private final ReadWriteLock trackerLock = new ReentrantReadWriteLock();
private final List<String> otherActionBarFeatures = new ArrayList<>();
protected AbstractCNPlayer(CustomNameplates plugin, Channel channel) {
this.plugin = plugin;
this.channel = channel;
}
@Override
public void acquireActionBar(String id) {
this.otherActionBarFeatures.add(id);
}
@Override
public void releaseActionBar(String id) {
this.otherActionBarFeatures.remove(id);
}
@Override
public boolean shouldCNTakeOverActionBar() {
return otherActionBarFeatures.isEmpty();
}
@Override
public List<Placeholder> activePlaceholdersToRefresh() {
Placeholder[] activePlaceholders = activePlaceholders();
@@ -437,87 +456,144 @@ public abstract class AbstractCNPlayer implements CNPlayer {
@Override
public Tracker addPlayerToTracker(CNPlayer another) {
Tracker tracker = trackers.get(another);
if (tracker != null) {
trackerLock.writeLock().lock();
try {
Tracker tracker = trackers.get(another);
if (tracker != null) {
return tracker;
}
tracker = new Tracker(another);
trackers.put(another, tracker);
return tracker;
} finally {
trackerLock.writeLock().unlock();
}
tracker = new Tracker(another);
trackers.put(another, tracker);
// for (Placeholder placeholder : activePlaceholders()) {
// if (placeholder instanceof RelationalPlaceholder relationalPlaceholder) {
// String value = relationalPlaceholder.request(this, another);
// setRelationalValue(relationalPlaceholder, another, value);
// }
// }
return tracker;
}
@Override
public void removePlayerFromTracker(CNPlayer another) {
trackers.remove(another);
trackerLock.writeLock().lock();
try {
trackers.remove(another);
} finally {
trackerLock.writeLock().unlock();
}
}
@Override
public Collection<CNPlayer> nearbyPlayers() {
return new ObjectArrayList<>(trackers.keySet());
trackerLock.readLock().lock();
try {
// Create a snapshot of keys to avoid concurrent modification
return new ObjectArrayList<>(trackers.keySet());
} finally {
trackerLock.readLock().unlock();
}
}
@Override
public void trackPassengers(CNPlayer another, int... passengers) {
Tracker tracker = trackers.get(another);
if (tracker != null) {
for (int passenger : passengers) {
tracker.addPassengerID(passenger);
}
}
trackerLock.writeLock().lock();
try {
Tracker tracker = trackers.get(another);
if (tracker != null) {
for (int passenger : passengers) {
tracker.addPassengerID(passenger);
}
}
} finally {
trackerLock.writeLock().unlock();
}
}
@Override
public void untrackPassengers(CNPlayer another, int... passengers) {
Optional.ofNullable(trackers.get(another)).ifPresent(tracker -> {
for (int passenger : passengers) {
tracker.removePassengerID(passenger);
trackerLock.writeLock().lock();
try {
Tracker tracker = trackers.get(another);
if (tracker != null) {
for (int passenger : passengers) {
tracker.removePassengerID(passenger);
}
}
});
} finally {
trackerLock.writeLock().unlock();
}
}
@Override
public Set<Integer> getTrackedPassengerIds(CNPlayer another) {
return Optional.ofNullable(trackers.get(another)).map(Tracker::getPassengerIDs).orElse(new ObjectOpenHashSet<>());
trackerLock.readLock().lock();
try {
Tracker tracker = trackers.get(another);
return tracker != null ? tracker.getPassengerIDs() : new ObjectOpenHashSet<>();
} finally {
trackerLock.readLock().unlock();
}
}
@Override
public Tracker getTracker(CNPlayer another) {
return trackers.get(another);
trackerLock.readLock().lock();
try {
return trackers.get(another);
} finally {
trackerLock.readLock().unlock();
}
}
@Override
public String equippedBubble() {
if (equippedNameplate == null) return "none";
return equippedBubble;
public String currentBubble() {
if (currentNameplate == null) return "none";
return currentBubble;
}
@Override
public boolean equippedBubble(String equippedBubble) {
public boolean setCurrentBubble(String bubble) {
if (!isLoaded()) return false;
if (!equippedBubble.equals(this.equippedBubble)) {
this.equippedBubble = equippedBubble;
this.currentBubble = bubble;
return true;
}
@Override
public String bubbleData() {
if (bubbleData == null) return "none";
return bubbleData;
}
@Override
public boolean setBubbleData(String bubble) {
if (!isLoaded()) return false;
this.currentBubble = bubble;
this.bubbleData = bubble;
return true;
}
@Override
public String currentNameplate() {
if (currentNameplate == null) return "none";
return currentNameplate;
}
@Override
public boolean setCurrentNameplate(String nameplate) {
if (!isLoaded()) return false;
if (!nameplate.equals(this.currentNameplate)) {
this.currentNameplate = nameplate;
}
return true;
}
@Override
public String equippedNameplate() {
if (equippedNameplate == null) return "none";
return equippedNameplate;
public String nameplateData() {
return nameplateData;
}
@Override
public boolean equippedNameplate(String equippedNameplate) {
public boolean setNameplateData(String nameplate) {
if (!isLoaded()) return false;
if (!equippedNameplate.equals(this.equippedNameplate)) {
this.equippedNameplate = equippedNameplate;
}
this.nameplateData = nameplate;
this.currentNameplate = nameplate;
return true;
}
@@ -525,8 +601,8 @@ public abstract class AbstractCNPlayer implements CNPlayer {
public void save() {
plugin.getStorageManager().dataSource().updatePlayerData(PlayerData.builder()
.uuid(uuid())
.nameplate(equippedNameplate())
.bubble(equippedBubble())
.nameplate(nameplateData())
.bubble(bubbleData())
.previewTags(isToggleablePreviewing())
.build(), plugin.getScheduler().async());
}
@@ -181,6 +181,27 @@ public interface CNPlayer {
*/
Placeholder[] activePlaceholders();
/**
* Acquires the actionbar, preventing CustomNameplates from taking control of it.
*
* @param id The feature ID requesting the actionbar.
*/
void acquireActionBar(String id);
/**
* Releases the actionbar, allowing CustomNameplates to take control again if no other features are active.
*
* @param id The feature ID releasing the actionbar.
*/
void releaseActionBar(String id);
/**
* Checks if CustomNameplates should take control of the actionbar.
*
* @return True if CustomNameplates should take over the actionbar, false otherwise.
*/
boolean shouldCNTakeOverActionBar();
/**
* Retrieves the list of placeholders that need to be refreshed based on their refresh intervals.
*
@@ -389,36 +410,64 @@ public interface CNPlayer {
Tracker getTracker(CNPlayer another);
/**
* Returns the ID of the currently equipped bubble for the player.
* Gets the bubble currently in use (Includes temp bubble used in preview)
*
* @return the ID of the equipped bubble
* @return bubble
*/
String equippedBubble();
String currentBubble();
/**
* Sets the equipped bubble for the player.
* Operation would fail if player is not loaded.
* Sets the bubble currently in use, which would not be saved
*
* @param equippedBubble the new bubble ID to equip
* @return success or not
* @param bubble id
* @return false if data not loaded
*/
boolean equippedBubble(String equippedBubble);
boolean setCurrentBubble(String bubble);
/**
* Returns the ID of the currently equipped nameplate for the player.
* Sets the bubble data
*
* @return the ID of the equipped nameplate
* @param bubble id
* @return false if data not loaded
*/
String equippedNameplate();
boolean setBubbleData(String bubble);
/**
* Sets the equipped nameplate for the player.
* Operation would fail if player is not loaded.
* Gets the bubble data
*
* @param equippedNameplate the new nameplate ID to equip
* @return success or not
* @return bubble id
*/
boolean equippedNameplate(String equippedNameplate);
String bubbleData();
/**
* Gets the nameplate currently in use (Includes temp nameplate used in preview)
*
* @return nameplate
*/
String currentNameplate();
/**
* Sets the nameplate currently in use, which would not be saved
*
* @param nameplate id
* @return false if data not loaded
*/
boolean setCurrentNameplate(String nameplate);
/**
* Gets the nameplate data
*
* @return the nameplate id
*/
String nameplateData();
/**
* Sets the nameplate data
*
* @param nameplate id
* @return false if data not loaded
*/
boolean setNameplateData(String nameplate);
/**
* Save the player's current nameplate/bubble to database
@@ -102,7 +102,9 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected boolean packItemsAdder;
protected boolean packItemsAdderLegacy;
protected boolean packOraxen;
protected boolean packNexo;
protected boolean packCreativeCentral;
protected boolean packCraftEngine;
protected boolean chatUnsafe;
protected boolean chatTR;
@@ -111,6 +113,11 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected boolean chatCarbon;
protected boolean chatAdvanced;
protected boolean chatEss;
protected boolean chatChatControlRed;
protected boolean chatChatty;
protected boolean twDialogue;
protected boolean twCinematic;
protected String configVersion;
@@ -181,6 +188,8 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
if (packItemsAdder) packItemsAdderLegacy = false;
packOraxen = config.getBoolean("integrations.resource-pack.Oraxen", false);
packCreativeCentral = config.getBoolean("integrations.resource-pack.Creative-Central");
packNexo = config.getBoolean("integrations.resource-pack.Nexo");
packCraftEngine = config.getBoolean("integrations.resource-pack.CraftEngine", false);
chatUnsafe = config.getBoolean("other-settings.unsafe-chat-event", false);
chatEss = config.getBoolean("integrations.chat.Essentials", false);
@@ -189,6 +198,11 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
chatAdvanced = config.getBoolean("integrations.chat.AdvancedChat", false);
chatTR = config.getBoolean("integrations.chat.TrChat", false);
chatVenture = config.getBoolean("integrations.chat.VentureChat", false);
chatChatControlRed = config.getBoolean("integrations.chat.ChatControlRed", false);
chatChatty = config.getBoolean("integrations.chat.Chatty", false);
twDialogue = config.getBoolean("integrations.typewriter.dialogue", true);
twCinematic = config.getBoolean("integrations.typewriter.cinematic", true);
// Packs
generateOnStart = !config.getBoolean("resource-pack.disable-generation-on-start", false);
@@ -305,6 +319,14 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.packOraxen;
}
public static boolean packNexo() {
return instance.packNexo;
}
public static boolean packCraftEngine() {
return instance.packCraftEngine;
}
public static boolean packCreativeCentral() { return instance.packCreativeCentral; }
public static boolean hideScoreBoardNumber() {
@@ -355,6 +377,14 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.metrics;
}
public static boolean twDialogue() {
return instance.twDialogue;
}
public static boolean twCinematic() {
return instance.twCinematic;
}
public static int defaultPlaceholderRefreshInterval() {
return instance.defaultPlaceholderRefreshInterval;
}
@@ -411,6 +441,14 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.chatAdvanced;
}
public static boolean chatChatControlRed() {
return instance.chatChatControlRed;
}
public static boolean chatChatty() {
return instance.chatChatty;
}
@Override
public YamlDocument loadConfig(String filePath) {
return loadConfig(filePath, '.');
@@ -29,6 +29,7 @@ import net.momirealms.customnameplates.api.feature.image.ImageManager;
import net.momirealms.customnameplates.api.feature.nameplate.NameplateManager;
import net.momirealms.customnameplates.api.feature.pack.ResourcePackManager;
import net.momirealms.customnameplates.api.feature.tag.UnlimitedTagManager;
import net.momirealms.customnameplates.api.helper.VersionHelper;
import net.momirealms.customnameplates.api.network.PacketSender;
import net.momirealms.customnameplates.api.network.PipelineInjector;
import net.momirealms.customnameplates.api.placeholder.PlaceholderManager;
@@ -69,7 +70,7 @@ public abstract class CustomNameplates implements NameplatesPlugin {
protected MainTask mainTask;
protected SchedulerTask scheduledMainTask;
protected ConcurrentHashMap<UUID, CNPlayer> onlinePlayerMap = new ConcurrentHashMap<>();
protected Int2ObjectOpenHashMap<CNPlayer> entityIDFastLookup = new Int2ObjectOpenHashMap<>();
protected ConcurrentHashMap<Integer, CNPlayer> entityIDFastLookup = new ConcurrentHashMap<>();
protected AdvanceManager advanceManager;
protected BackgroundManager backgroundManager;
protected EventManager eventManager;
@@ -81,6 +82,13 @@ public abstract class CustomNameplates implements NameplatesPlugin {
protected ResourcePackManager resourcePackManager;
protected CustomNameplatesAPI api;
private String buildByBit = "%%__BUILTBYBIT__%%";
private String polymart = "%%__POLYMART__%%";
private String time = "%%__TIMESTAMP__%%";
private String user = "%%__USER__%%";
private String username = "%%__USERNAME__%%";
private boolean isLatest = false;
protected CustomNameplates() {
instance = this;
}
@@ -97,6 +105,36 @@ public abstract class CustomNameplates implements NameplatesPlugin {
@Override
public abstract void disable();
@Override
public void enable() {
boolean downloadFromPolymart = polymart.equals("1");
boolean downloadFromBBB = buildByBit.equals("true");
if (ConfigManager.checkUpdate()) {
VersionHelper.UPDATE_CHECKER.apply(this).thenAccept(result -> {
String link;
if (downloadFromPolymart) {
link = "https://polymart.org/resource/2543/";
} else if (downloadFromBBB) {
link = "https://builtbybit.com/resources/36359/";
} else {
link = "https://github.com/Xiao-MoMi/Custom-Nameplates/";
}
if (!result) {
this.getPluginLogger().info("You are using the latest version.");
isLatest = true;
} else {
this.getPluginLogger().warn("Update is available: " + link);
isLatest = false;
}
});
}
}
@Override
public boolean isUpToDate() {
return isLatest;
}
/**
* Logs debug messages through the provided supplier.
*
@@ -34,6 +34,7 @@ public class MainTask implements Runnable {
private int timer;
private final CustomNameplates plugin;
private boolean state;
public MainTask(CustomNameplates plugin) {
this.plugin = plugin;
@@ -53,24 +54,31 @@ public class MainTask implements Runnable {
@Override
public void run() {
RUN_TICKS++;
requestedSharedPlaceholders.clear();
long time1 = System.nanoTime();
plugin.actionBarManager.refreshConditions();
plugin.bossBarManager.onTick();
plugin.unlimitedTagManager.onTick();
long time2 = System.nanoTime();
plugin.placeholderManager.refreshPlaceholders();
long time3 = System.nanoTime();
plugin.actionBarManager.checkHeartBeats();
int diff1 = (int) (time2 - time1);
TIME_1.put(timer, diff1);
int diff2 = (int) (time3 - time2);
TIME_2.put(timer, diff2);
timer++;
if (timer >= 1200) timer = 0;
if (RUN_TICKS < 0) {
CustomNameplates.getInstance().reload();
// we should skip the task if the server is heavily loaded
if (this.state) return;
this.state = true;
try {
RUN_TICKS++;
requestedSharedPlaceholders.clear();
long time1 = System.nanoTime();
plugin.actionBarManager.refreshConditions();
plugin.bossBarManager.onTick();
plugin.unlimitedTagManager.onTick();
long time2 = System.nanoTime();
plugin.placeholderManager.refreshPlaceholders();
long time3 = System.nanoTime();
plugin.actionBarManager.checkHeartBeats();
int diff1 = (int) (time2 - time1);
TIME_1.put(timer, diff1);
int diff2 = (int) (time3 - time2);
TIME_2.put(timer, diff2);
timer++;
if (timer >= 1200) timer = 0;
if (RUN_TICKS < 0) {
CustomNameplates.getInstance().reload();
}
} finally {
this.state = false;
}
}
@@ -61,12 +61,18 @@ public class VersionHelper {
private static float version;
private static boolean mojmap;
private static boolean folia;
private static boolean mohist;
private static boolean paper;
public static void init(String serverVersion) {
String[] split = serverVersion.split("\\.");
version = Float.parseFloat(split[1] + "." + (split.length == 3 ? split[2] : "0"));
checkMojMap();
checkFolia();
checkMohist();
checkPaper();
boolean isModdedServer = mohist;
paper = paper && !isModdedServer;
}
public static float version() {
@@ -90,6 +96,22 @@ public class VersionHelper {
}
}
private static void checkMohist() {
try {
Class.forName("com.mohistmc.api.ServerAPI");
mohist = true;
} catch (ClassNotFoundException ignored) {
}
}
private static void checkPaper() {
try {
Class.forName("com.destroystokyo.paper.Metrics");
paper = true;
} catch (ClassNotFoundException ignored) {
}
}
public static boolean isVersionNewerThan1_21_2() {
return version >= 21.19;
}
@@ -118,6 +140,14 @@ public class VersionHelper {
return folia;
}
public static boolean isMohist() {
return mohist;
}
public static boolean isPaperOrItsForks() {
return paper;
}
public static boolean isMojmap() {
return mojmap;
}
@@ -19,7 +19,9 @@ package net.momirealms.customnameplates.api.placeholder.internal;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.api.CustomNameplatesAPI;
import net.momirealms.customnameplates.api.feature.AdaptiveImage;
import net.momirealms.customnameplates.api.feature.OffsetFont;
import net.momirealms.customnameplates.api.feature.PreParsedDynamicText;
import net.momirealms.customnameplates.api.helper.AdventureHelper;
import org.jetbrains.annotations.ApiStatus;
@@ -99,4 +101,9 @@ public class AdaptiveImageText<T extends AdaptiveImage> {
public String getText(CNPlayer p1, CNPlayer p2) {
return preParsedDynamicText.fastCreate(p1).render(p2);
}
@NotNull
public String getTextOffsetCharacters(CNPlayer p1, CNPlayer p2) {
return OffsetFont.createOffsets(CustomNameplatesAPI.getInstance().getTextAdvance(preParsedDynamicText.fastCreate(p1).render(p2)));
}
}
@@ -0,0 +1,57 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* This program is 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
* any later version.
*
* This program 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 <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customnameplates.api.util;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
public static void zipDirectory(Path folderPath, Path zipFilePath) throws IOException {
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
try (Stream<Path> paths = Files.walk(folderPath)) {
for (Path path : (Iterable<Path>) paths::iterator) {
if (Files.isDirectory(path)) {
continue;
}
String zipEntryName = folderPath.relativize(path).toString().replace("\\", "/");
ZipEntry zipEntry = new ZipEntry(zipEntryName);
try (InputStream is = Files.newInputStream(path)) {
addToZip(zipEntry, is, zos);
}
}
}
}
}
public static void addToZip(ZipEntry zipEntry, InputStream is, ZipOutputStream zos) throws IOException {
zos.putNextEntry(zipEntry);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
}
}
+11 -1
View File
@@ -2,6 +2,10 @@ plugins {
id("io.github.goooler.shadow") version "8.1.8"
}
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
compileOnly(project(":common"))
compileOnly(project(":api"))
@@ -28,4 +32,10 @@ dependencies {
compileOnly("org.lwjgl:lwjgl:${rootProject.properties["lwjgl_version"]}")
// Fast util
compileOnly("it.unimi.dsi:fastutil:${rootProject.properties["fastutil_version"]}")
}
}
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
options.release.set(17)
dependsOn(tasks.clean)
}
@@ -124,14 +124,19 @@ public class ActionBarManagerImpl implements ActionBarManager, JoinQuitListener
@Override
public void onPlayerJoin(CNPlayer player) {
if (!ConfigManager.actionbarModule()) return;
plugin.getScheduler().asyncLater(() -> {
Runnable r = () -> {
if (!player.isOnline()) return;
ActionBarSender sender = new ActionBarSender(this, player);
ActionBarSender previous = senders.put(player.uuid(), sender);
if (previous != null) {
previous.destroy();
}
}, ConfigManager.delaySend() * 50L, TimeUnit.MILLISECONDS);
};
if (ConfigManager.delaySend() < 0) {
r.run();
} else {
plugin.getScheduler().asyncLater(r, ConfigManager.delaySend() * 50L, TimeUnit.MILLISECONDS);
}
}
@Override
@@ -80,7 +80,7 @@ public class ActionBarSender implements Feature {
this.onConditionTimerCheck();
}
public void onConditionTimerCheck() {
public synchronized void onConditionTimerCheck() {
ActionBarConfig[] configs = manager.actionBarConfigs();
outer: {
for (ActionBarConfig config : configs) {
@@ -160,6 +160,8 @@ public class ActionBarSender implements Feature {
if (isTemporarilyHidden()) return;
if (latestContent != null) {
updateLastUpdateTime();
// do not send if other plugins have taken over the actionbar
if (!owner.shouldCNTakeOverActionBar()) return;
Object packet = CustomNameplates.getInstance().getPlatform().setActionBarTextPacket(AdventureHelper.miniMessageToMinecraftComponent(latestContent, "nameplates", "actionbar"));
CustomNameplates.getInstance().getPacketSender().sendPacket(owner, packet);
}
@@ -522,6 +522,8 @@ public class AdvanceManagerImpl implements AdvanceManager {
String codePoints = requireNonNull(section.getString("codepoints", ""), "codepoints should be NonNull");
int height = section.getInt("height", 8);
boolean custom = section.getBoolean("custom", false);
boolean copy = section.getBoolean("generate", false);
String namespace = section.getString("namespace", ConfigManager.namespace());
File bitmapCache = new File(plugin.getDataDirectory().toFile(), "tmp" + File.separator + id + ".tmp");
if (!bitmapCache.exists()) {
@@ -586,9 +588,25 @@ public class AdvanceManagerImpl implements AdvanceManager {
}
registerCharacterFontData(id, bitmapCache, (properties) -> {
int ascent = (int) properties.get("shift_y");
String filePath = custom ? ConfigManager.namespace() + ":font/" + file : "minecraft:font/" + codePoints + ".png";
String filePath = custom ? namespace + ":font/" + file : "minecraft:font/" + codePoints + ".png";
plugin.getConfigManager().saveResource("tmp/" + codePoints + ".json");
StringBuilder jsonContent = new StringBuilder();
if (copy) {
File pngFile = new File(plugin.getDataDirectory().toFile(), "font" + File.separator + file);
File destination = new File(plugin.getDataDirectory().toFile(),
"ResourcePack"
+ File.separator + "assets"
+ File.separator + (custom ? namespace : "minecraft")
+ File.separator + "textures"
+ File.separator + "font"
+ File.separator + (custom ? file : codePoints + ".png")
);
try {
FileUtils.copyFile(pngFile, destination);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
try (BufferedReader reader = new BufferedReader(new FileReader(new File(plugin.getDataDirectory().toFile(), "tmp" + File.separator + codePoints + ".json")))) {
String line;
while ((line = reader.readLine()) != null) {
@@ -84,14 +84,19 @@ public class BossBarManagerImpl implements BossBarManager, JoinQuitListener {
@Override
public void onPlayerJoin(CNPlayer player) {
if (!ConfigManager.bossbarModule()) return;
plugin.getScheduler().asyncLater(() -> {
Runnable r = () -> {
if (!player.isOnline()) return;
BossBarDisplayController sender = new BossBarDisplayController(this, player);
BossBarDisplayController previous = senders.put(player.uuid(), sender);
if (previous != null) {
previous.destroy();
}
}, ConfigManager.delaySend() * 50L, TimeUnit.MILLISECONDS);
};
if (ConfigManager.delaySend() < 0) {
r.run();
} else {
plugin.getScheduler().asyncLater(r, ConfigManager.delaySend() * 50L, TimeUnit.MILLISECONDS);
}
}
@Override
@@ -98,7 +98,7 @@ public class BossBarSender implements Feature, BossBar {
timeLeft = 0;
}
public void tick() {
public synchronized void tick() {
if (timeLeft > 0)
timeLeft--;
@@ -296,7 +296,7 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener {
// check requirements
if (!player.isMet(sendBubbleRequirements())) return;
String equippedBubble = player.equippedBubble();
String equippedBubble = player.currentBubble();
if (equippedBubble.equals("none")) equippedBubble = defaultBubbleId;
BubbleConfig config = bubbleConfigs.get(equippedBubble);
@@ -35,6 +35,7 @@ import net.momirealms.customnameplates.api.feature.nameplate.Nameplate;
import net.momirealms.customnameplates.api.feature.pack.ResourcePackManager;
import net.momirealms.customnameplates.api.helper.VersionHelper;
import net.momirealms.customnameplates.api.util.CharacterUtils;
import net.momirealms.customnameplates.api.util.ZipUtils;
import org.apache.commons.io.FileUtils;
import javax.imageio.ImageIO;
@@ -123,6 +124,12 @@ public class ResourcePackManagerImpl implements ResourcePackManager {
this.setPackFormat();
// copy the resource pack to hooked plugins
this.copyResourcePackToHookedPlugins(resourcePackFolder);
try {
ZipUtils.zipDirectory(resourcePackFolder.toPath(), plugin.getDataFolder().toPath().resolve("resourcepack.zip"));
} catch (IOException e) {
plugin.getPluginLogger().warn("Failed to zip resourcepack.zip", e);
}
}
private void saveFont(JsonObject fontJson) {
@@ -236,6 +243,24 @@ public class ResourcePackManagerImpl implements ResourcePackManager {
plugin.getPluginLogger().warn("Failed to copy files to Oraxen", e);
}
}
if (ConfigManager.packNexo()){
try {
FileUtils.deleteDirectory(new File(pluginsFolder, "Nexo" + File.separator + "pack" + File.separator + "external_packs" + File.separator + "CustomNameplates"));
FileUtils.copyDirectory(resourcePackFolder, new File(pluginsFolder, "Nexo" + File.separator + "pack" + File.separator + "external_packs" + File.separator + "CustomNameplates"));
} catch (IOException e){
plugin.getPluginLogger().warn("Failed to copy files to Nexo", e);
}
}
if (ConfigManager.packCraftEngine()){
try {
FileUtils.deleteDirectory(new File(pluginsFolder, "CraftEngine" + File.separator + "resources" + File.separator + "nameplates"));
FileUtils.copyDirectory(resourcePackFolder, new File(pluginsFolder, "CraftEngine" + File.separator + "resources" + File.separator + "CustomNameplates" + File.separator + "resourcepack"));
FileUtils.delete(new File(pluginsFolder, "CraftEngine" + File.separator + "resources" + File.separator + "CustomNameplates" + File.separator + "resourcepack" + File.separator + "pack.mcmeta"));
FileUtils.delete(new File(pluginsFolder, "CraftEngine" + File.separator + "resources" + File.separator + "CustomNameplates" + File.separator + "resourcepack" + File.separator + "pack.png"));
} catch (IOException e){
plugin.getPluginLogger().warn("Failed to copy files to CraftEngine", e);
}
}
if(ConfigManager.packCreativeCentral()) {
try {
FileUtils.copyDirectory(new File(resourcePackFolder, "assets"), new File(pluginsFolder, "creative-central" + File.separator + "resources" + File.separator + "assets"));
@@ -25,6 +25,7 @@ import net.momirealms.customnameplates.api.feature.tag.NameTagConfig;
import net.momirealms.customnameplates.api.feature.tag.Tag;
import net.momirealms.customnameplates.api.feature.tag.TagRenderer;
import net.momirealms.customnameplates.api.feature.tag.UnlimitedTagManager;
import net.momirealms.customnameplates.api.helper.VersionHelper;
import net.momirealms.customnameplates.api.network.Tracker;
import java.util.*;
@@ -75,7 +76,7 @@ public class TagRendererImpl implements TagRenderer {
}
@Override
public void onTick() {
public synchronized void onTick() {
if (!isValid()) return;
Set<CNPlayer> playersToUpdatePassengers = new ObjectOpenHashSet<>();
@@ -301,7 +302,13 @@ public class TagRendererImpl implements TagRenderer {
passengers[index++] = passenger;
}
Object packet = CustomNameplates.getInstance().getPlatform().setPassengersPacket(owner.entityID(), passengers);
CustomNameplates.getInstance().getPacketSender().sendPacket(another, packet);
if (VersionHelper.isPaperOrItsForks()) {
CustomNameplates.getInstance().getPacketSender().sendPacket(another, packet);
} else {
CustomNameplates.getInstance().getScheduler().sync().runLater(() -> {
CustomNameplates.getInstance().getPacketSender().sendPacket(another, packet);
}, 0, null);
}
}
public void handleEntityDataChange(CNPlayer another, boolean isCrouching) {
@@ -114,10 +114,18 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
}
private void loadNestNameplatePlaceholders() {
if (!ConfigManager.nameplateModule()) return;
if (!ConfigManager.nameplateModule()) {
this.registerPlayerPlaceholder("%np_tag-image%", (player -> "Please remove %np_tag-image% if you have disabled nameplates module"));
this.registerPlayerPlaceholder("%rel_np_tag-image%", (player -> "Please remove %rel_np_tag-image% if you have disabled nameplates module"));
this.registerPlayerPlaceholder("%np_tag-text%", (player -> "Please remove %np_tag-text% if you have disabled nameplates module"));
this.registerPlayerPlaceholder("%rel_np_tag-text%", (player -> "Please remove %rel_np_tag-text% if you have disabled nameplates module"));
this.registerPlayerPlaceholder("%np_tag%", (player -> "Please remove %np_tag% if you have disabled nameplates module"));
this.registerPlayerPlaceholder("%rel_np_tag%", (player -> "Please remove %rel_np_tag% if you have disabled nameplates module"));
return;
}
PreParsedDynamicText nameTag = new PreParsedDynamicText(plugin.getNameplateManager().playerNameTag());
Placeholder placeholder1 = this.registerPlayerPlaceholder("%np_tag-image%", (player -> {
String equippedNameplate = player.equippedNameplate();
String equippedNameplate = player.currentNameplate();
if (equippedNameplate.equals("none")) equippedNameplate = plugin.getNameplateManager().defaultNameplateId();
Nameplate nameplate = plugin.getNameplateManager().nameplateById(equippedNameplate);
if (nameplate == null) return "";
@@ -126,7 +134,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
return AdventureHelper.surroundWithNameplatesFont(nameplate.createImage(advance, 0, 0));
}));
Placeholder placeholder2 = this.registerRelationalPlaceholder("%rel_np_tag-image%", (p1, p2) -> {
String equippedNameplate = p1.equippedNameplate();
String equippedNameplate = p1.currentNameplate();
if (equippedNameplate.equals("none")) equippedNameplate = plugin.getNameplateManager().defaultNameplateId();
Nameplate nameplate = plugin.getNameplateManager().nameplateById(equippedNameplate);
if (nameplate == null) return "";
@@ -137,7 +145,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
Placeholder placeholder3 = this.registerPlayerPlaceholder("%np_tag-text%", (player -> nameTag.fastCreate(player).render(player)));
Placeholder placeholder4 = this.registerRelationalPlaceholder("%rel_np_tag-text%", (p1, p2) -> nameTag.fastCreate(p1).render(p2));
Placeholder placeholder5 = this.registerPlayerPlaceholder("%np_tag%", (player -> {
String equippedNameplate = player.equippedNameplate();
String equippedNameplate = player.currentNameplate();
if (equippedNameplate.equals("none")) equippedNameplate = plugin.getNameplateManager().defaultNameplateId();
Nameplate nameplate = plugin.getNameplateManager().nameplateById(equippedNameplate);
String tag = nameTag.fastCreate(player).render(player);
@@ -147,7 +155,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
+ tag + AdventureHelper.surroundWithNameplatesFont(nameplate.createImageSuffix(advance, 0, 0));
}));
Placeholder placeholder6 = this.registerRelationalPlaceholder("%rel_np_tag%", (p1, p2) -> {
String equippedNameplate = p1.equippedNameplate();
String equippedNameplate = p1.currentNameplate();
Nameplate nameplate = plugin.getNameplateManager().nameplateById(equippedNameplate);
if (nameplate == null) return p1.name();
String tag = nameTag.fastCreate(p1).render(p2);
@@ -184,16 +192,16 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
this.registerPlayerPlaceholder("%np_offset_" + i + "%", (p) -> AdventureHelper.surroundWithNameplatesFont(characters));
}
if (ConfigManager.nameplateModule()) {
this.registerPlayerPlaceholder("%np_equipped_nameplate%", CNPlayer::equippedNameplate);
this.registerPlayerPlaceholder("%np_equipped_nameplate%", CNPlayer::currentNameplate);
this.registerPlayerPlaceholder("%np_equipped_nameplate-name%", (player) -> {
Nameplate nameplate = plugin.getNameplateManager().nameplateById(player.equippedNameplate());
Nameplate nameplate = plugin.getNameplateManager().nameplateById(player.currentNameplate());
return Optional.ofNullable(nameplate).map(Nameplate::displayName).orElse("");
});
}
if (ConfigManager.bubbleModule()) {
this.registerPlayerPlaceholder("%np_equipped_bubble%", CNPlayer::equippedBubble);
this.registerPlayerPlaceholder("%np_equipped_bubble%", CNPlayer::currentBubble);
this.registerPlayerPlaceholder("%np_equipped_bubble-name%", (player) -> {
BubbleConfig bubble = plugin.getBubbleManager().bubbleConfigById(player.equippedBubble());
BubbleConfig bubble = plugin.getBubbleManager().bubbleConfigById(player.currentBubble());
return Optional.ofNullable(bubble).map(BubbleConfig::displayName).orElse("");
});
}
@@ -504,6 +512,9 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
Placeholder placeholder7 = this.registerSharedPlaceholder("%shared_np_background-image_" + id + "%", () -> adaptiveImageText.getImage(null, null));
Placeholder placeholder8 = this.registerPlayerPlaceholder("%np_background-image_" + id + "%", (p) -> adaptiveImageText.getImage(p, p));
Placeholder placeholder9 = this.registerRelationalPlaceholder("%rel_np_background-image_" + id + "%", adaptiveImageText::getImage);
Placeholder placeholder40 = this.registerSharedPlaceholder("%shared_np_background-text-offset_" + id + "%", () -> adaptiveImageText.getTextOffsetCharacters(null, null));
Placeholder placeholder50 = this.registerPlayerPlaceholder("%np_background-text-offset_" + id + "%", (p) -> adaptiveImageText.getTextOffsetCharacters(p, p));
Placeholder placeholder60 = this.registerRelationalPlaceholder("%rel_np_background-text-offset_" + id + "%", adaptiveImageText::getTextOffsetCharacters);
childrenText.put(placeholder1, list);
childrenText.put(placeholder2, list);
childrenText.put(placeholder3, list);
@@ -513,6 +524,9 @@ public class PlaceholderManagerImpl implements PlaceholderManager {
childrenText.put(placeholder7, list);
childrenText.put(placeholder8, list);
childrenText.put(placeholder9, list);
childrenText.put(placeholder40, list);
childrenText.put(placeholder50, list);
childrenText.put(placeholder60, list);
} else {
plugin.getPluginLogger().warn("Background [" + bgID + "] not exists");
}
@@ -124,10 +124,17 @@ public abstract class AbstractRequirementManager implements RequirementManager {
this.registerRequirement((args, interval) -> {
Section section = ConfigUtils.safeCast(args, Section.class);
if (section == null) return Requirement.empty();
PreParsedDynamicText dynamicText1 = new PreParsedDynamicText(section.getString("value1", ""), true);
String regex = section.getString("value2", "");
PreParsedDynamicText dynamicText1 = new PreParsedDynamicText(section.getString("papi", ""), true);
String regex = section.getString("regex", "");
return new RegexRequirement(interval, dynamicText1, regex);
}, "regex");
this.registerRequirement((args, interval) -> {
Section section = ConfigUtils.safeCast(args, Section.class);
if (section == null) return Requirement.empty();
PreParsedDynamicText dynamicText1 = new PreParsedDynamicText(section.getString("papi", ""), true);
String regex = section.getString("regex", "");
return new NotRegexRequirement(interval, dynamicText1, regex);
}, "!regex");
this.registerRequirement((args, interval) -> {
Section section = ConfigUtils.safeCast(args, Section.class);
if (section == null) return Requirement.empty();
@@ -37,7 +37,7 @@ public class BubbleRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.bubbleModule()) return false;
String bubble = p1.equippedBubble();
String bubble = p1.currentBubble();
if (bubble.equals("none")) bubble = CustomNameplates.getInstance().getBubbleManager().defaultBubbleId();
return bubbles.contains(bubble);
}
@@ -34,7 +34,7 @@ public class HasBubbleRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.bubbleModule()) return !has;
String bubble = p1.equippedBubble();
String bubble = p1.currentBubble();
if (bubble.equals("none")) bubble = CustomNameplates.getInstance().getBubbleManager().defaultBubbleId();
if (has) {
return !bubble.equals("none");
@@ -34,7 +34,7 @@ public class HasNameplateRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.nameplateModule()) return !has;
String nameplate = p1.equippedNameplate();
String nameplate = p1.currentNameplate();
if (nameplate.equals("none")) nameplate = CustomNameplates.getInstance().getNameplateManager().defaultNameplateId();
if (has) {
return !nameplate.equals("none");
@@ -37,7 +37,7 @@ public class NameplateRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.nameplateModule()) return false;
String nameplate = p1.equippedNameplate();
String nameplate = p1.currentNameplate();
if (nameplate.equals("none")) nameplate = CustomNameplates.getInstance().getNameplateManager().defaultNameplateId();
return nameplates.contains(nameplate);
}
@@ -37,7 +37,7 @@ public class NotBubbleRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.bubbleModule()) return false;
String bubble = p1.equippedBubble();
String bubble = p1.currentBubble();
if (bubble.equals("none")) bubble = CustomNameplates.getInstance().getBubbleManager().defaultBubbleId();
return !bubbles.contains(bubble);
}
@@ -37,7 +37,7 @@ public class NotNameplateRequirement extends AbstractRequirement {
@Override
public boolean isSatisfied(CNPlayer p1, CNPlayer p2) {
if (!ConfigManager.nameplateModule()) return false;
String nameplate = p1.equippedNameplate();
String nameplate = p1.currentNameplate();
if (nameplate.equals("none")) nameplate = CustomNameplates.getInstance().getNameplateManager().defaultNameplateId();
return !nameplates.contains(nameplate);
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* This program is 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
* any later version.
*
* This program 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 <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customnameplates.backend.requirement.builtin;
import net.momirealms.customnameplates.api.feature.PreParsedDynamicText;
public class NotRegexRequirement extends PlaceholderRequirement<String> {
public NotRegexRequirement(int refreshInterval, PreParsedDynamicText text, String any) {
super(refreshInterval, text, any);
}
@Override
protected boolean checkArgument(String a1, String a2) {
return !a1.matches(a2);
}
@Override
public String type() {
return "!regex";
}
}
@@ -93,8 +93,8 @@ public class StorageManagerImpl implements StorageManager, JoinQuitListener {
}
private void handleDataLoad(CNPlayer player, PlayerData data) {
player.equippedBubble(data.bubble());
player.equippedNameplate(data.nameplate());
player.setBubbleData(data.bubble());
player.setNameplateData(data.nameplate());
plugin.getUnlimitedTagManager().togglePreviewing(player, data.previewTags());
}
@@ -4,7 +4,7 @@
"description": "CustomNameplates",
"supported_formats": {
"min_inclusive": 13,
"max_inclusive": 43
"max_inclusive": 46
}
},
"overlays": {
@@ -19,7 +19,7 @@
{
"formats": {
"min_inclusive": 42,
"max_inclusive": 43
"max_inclusive": 46
},
"directory": "overlay_1_21_2"
}
@@ -4,7 +4,7 @@
"description": "CustomNameplates",
"supported_formats": {
"min_inclusive": 32,
"max_inclusive": 42
"max_inclusive": 46
}
},
"overlays": {
@@ -19,7 +19,7 @@
{
"formats": {
"min_inclusive": 42,
"max_inclusive": 43
"max_inclusive": 46
},
"directory": "overlay_1_21_2"
}
@@ -4,7 +4,7 @@
"description": "CustomNameplates",
"supported_formats": {
"min_inclusive": 42,
"max_inclusive": 43
"max_inclusive": 46
}
}
}
+18 -7
View File
@@ -22,9 +22,11 @@ modules:
# Plugin Integrations: Integrate resource packs and chat plugins with other plugins.
integrations:
resource-pack:
CraftEngine: false # Integration with CraftEngine
ItemsAdder: false # Integration with ItemsAdder
ItemsAdder-old-method: false # Old method for ItemsAdder
ItemsAdder-old-method: false # Legacy integration with ItemsAdder
Oraxen: false # Integration with Oraxen
Nexo: false # Integration with Nexo
Creative-Central: false # Integration with Creative-Central
chat:
TrChat: false # Integration with TrChat
@@ -33,6 +35,12 @@ integrations:
CarbonChat: false # Integration with CarbonChat
AdvancedChat: false # Integration with AdvancedChat
Essentials: false # Integration with Essentials chat
ChatControlRed: false # Integration with ChatControlRed
Chatty: false # Integration with Chatty
# Let typewriter take over actionbar on certain events
typewriter:
dialogue: true
cinematic: true
# Resource Pack Generation Settings: Configure resource pack generation behavior.
resource-pack:
@@ -60,18 +68,19 @@ resource-pack:
# Additional Settings: Extra options to control behavior and performance.
other-settings:
legacy-color-code-support: true # Enable support for legacy color codes using &
send-delay: 20 # Set actionbar/bossbar send delay (ticks)
send-delay: 20 # Set actionbar/bossbar send delay (ticks) (0 = send immediately on async threads, -1 = send immediately on main thread)
catch-other-plugin-actionbar: true # Capture actionbars from other plugins
other-actionbar-stay-time: 3000 # How long does other actionsbars stay (ms)
display-system-actionbar: true # Should the plugin display system actionbar and temporarily hide the custom actionbar?
hide-team-names: true # Hide the team name sent by other plugins or vanilla team system
unsafe-chat-event: false # Listen for canceled(unsafe) chat events from unknown plugins
default-condition-refresh-interval: 20 # Set default condition refresh interval
default-placeholder-refresh-interval: 1 # Set default placeholder refresh interval
default-condition-refresh-interval: 10 # Set default condition refresh interval in ticks
default-placeholder-refresh-interval: 1 # Set default placeholder refresh interval in ticks
placeholder-refresh-interval: # Custom placeholder refresh intervals for performance optimization
"%player_name%": 100
"%vault_prefix%": 20
# Font Templates: Define different fonts and their settings.
# Requires a restart to apply because it can be laggy to read thousands of character
font-templates:
space:
space:
@@ -80,7 +89,7 @@ other-settings:
unihex:
unifont:
file: unifont.zip # Load font from unifont.zip
generate: false # Don't include font in the generated resource pack
generate: false # Should this unihex file be included in the generated pack
size_overrides: # Override size for specific Unicode ranges
- from: "\\u3001"
to: "\\u30FF"
@@ -120,7 +129,7 @@ other-settings:
right: 15
unifont_jp:
file: unifont_jp.zip # Load Japanese unifont
generate: false # Don't generate in the resource pack
generate: false # Should this unihex file be included in the generated pack
filter:
"jp": true # Apply to Japanese characters only
size_overrides:
@@ -137,7 +146,9 @@ other-settings:
codepoints: ascii # Define ASCII bitmap font
file: ascii.png # Use ascii.png file for the font
height: 8 # Font height is 8 units
custom: false # Not a custom font (default Minecraft)
custom: false # Does this png path point to a non-default font path??
generate: false # Should this png file be included in the generated pack
# namespace: custom # Optional namespace if you don't want to use the global namespace set in config.yml
ascii_sga:
codepoints: ascii_sga
file: ascii_sga.png
@@ -169,7 +169,8 @@ switch-text:
'egg': "</gradient>"
'xmas': "</WHITE>"
'angel': "</#8B4513>"
'sign': "</WHITE>"
'sign': "</BLACK>"
'banner': "</WHITE>"
'enter': "</WHITE>"
world:
switch: '%player_world%'
+1 -1
View File
@@ -26,7 +26,7 @@ subprojects {
expand(rootProject.properties)
}
filesMatching(arrayListOf("*.yml", "*/*.yml")) {
filesMatching(arrayListOf("*.yml", "*/*.yml", "META-INF/sponge_plugins.json")) {
expand(
Pair("project_version", rootProject.properties["project_version"]),
Pair("config_version", rootProject.properties["config_version"])
+4
View File
@@ -1,3 +1,7 @@
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
compileOnly("net.kyori:adventure-api:${rootProject.properties["adventure_bundle_version"]}") {
exclude(module = "adventure-bom")
@@ -113,6 +113,14 @@ public enum Dependency {
Relocation.of("cloud", "org{}incendo{}cloud"),
Relocation.of("geantyref", "io{}leangen{}geantyref")
),
CLOUD_SPONGE(
"org{}incendo",
"cloud-sponge7",
"maven",
"cloud-sponge7",
Relocation.of("cloud", "org{}incendo{}cloud"),
Relocation.of("geantyref", "io{}leangen{}geantyref")
),
CLOUD_MINECRAFT_EXTRAS(
"org{}incendo",
"cloud-minecraft-extras",
@@ -226,6 +234,18 @@ public enum Dependency {
return Dependency.BSTATS_BASE.getVersion();
}
},
BSTATS_SPONGE(
"org{}bstats",
"bstats-sponge",
"maven",
"bstats-sponge",
Relocation.of("bstats", "org{}bstats")
) {
@Override
public String getVersion() {
return Dependency.BSTATS_BASE.getVersion();
}
},
GSON(
"com.google.code.gson",
"gson",
@@ -81,28 +81,12 @@ public abstract class AbstractJavaScheduler<T> implements SchedulerAdapter<T> {
@Override
public void shutdownScheduler() {
this.scheduler.shutdown();
try {
if (!this.scheduler.awaitTermination(1, TimeUnit.MINUTES)) {
this.plugin.getPluginLogger().severe("Timed out waiting for the CustomNameplates scheduler to terminate");
reportRunningTasks(thread -> thread.getName().equals("nameplates-scheduler"));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
this.scheduler.shutdownNow();
}
@Override
public void shutdownExecutor() {
this.worker.shutdown();
try {
if (!this.worker.awaitTermination(1, TimeUnit.MINUTES)) {
this.plugin.getPluginLogger().severe("Timed out waiting for the CustomNameplates worker thread pool to terminate");
reportRunningTasks(thread -> thread.getName().startsWith("nameplates-worker-"));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
this.worker.shutdownNow();
}
private void reportRunningTasks(Predicate<Thread> predicate) {
+13 -13
View File
@@ -1,7 +1,7 @@
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=3.0.12
config_version=32
project_version=3.0.19
config_version=36
project_group=net.momirealms
# Supported languages
@@ -10,16 +10,16 @@ lang=en,zh_cn
# Dependency settings
paper_version=1.20.4
jetbrains_annotations_version=24.0.0
slf4j_version=2.0.13
log4j_version=2.23.1
slf4j_version=2.0.16
log4j_version=2.24.1
gson_version=2.11.0
asm_version=9.7.1
asm_commons_version=9.7.1
jar_relocator_version=1.7
h2_driver_version=2.2.224
sqlite_driver_version=3.46.1.0
adventure_bundle_version=4.17.0
adventure_platform_version=4.3.4
h2_driver_version=2.3.232
sqlite_driver_version=3.47.0.0
adventure_bundle_version=4.18.0
adventure_platform_version=4.3.5-SNAPSHOT
cloud_core_version=2.0.0
cloud_services_version=2.0.0
cloud_brigadier_version=2.0.0-beta.10
@@ -27,14 +27,14 @@ cloud_bukkit_version=2.0.0-beta.10
cloud_paper_version=2.0.0-beta.10
cloud_minecraft_extras_version=2.0.0-beta.10
boosted_yaml_version=1.3.7
byte_buddy_version=1.14.18
byte_buddy_version=1.15.10
mojang_brigadier_version=1.0.18
mongodb_driver_version=5.1.4
mariadb_driver_version=3.4.1
mysql_driver_version=9.0.0
mongodb_driver_version=5.2.1
mariadb_driver_version=3.5.0
mysql_driver_version=9.1.0
hikari_version=5.1.0
commons_pool_version=2.12.0
bstats_version=3.0.2
bstats_version=3.1.0
geantyref_version=1.3.16
caffeine_version=3.1.8
jedis_version=5.1.5
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
File renamed without changes.
@@ -6,8 +6,8 @@ repositories {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // papi
maven("https://libraries.minecraft.net") // brigadier
maven("https://jitpack.io/")
maven("https://papermc.io/repo/repository/maven-public/") // paper
maven("https://oss.sonatype.org/content/repositories/snapshots")
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
}
@@ -17,7 +17,7 @@ dependencies {
}
implementation(project(":common"))
implementation(project(":backend"))
implementation(project(":compatibility"))
implementation(project(":platforms:bukkit:compatibility"))
compileOnly("dev.folia:folia-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
compileOnly("me.clip:placeholderapi:${rootProject.properties["placeholder_api_version"]}")
@@ -46,7 +46,7 @@ dependencies {
tasks {
shadowJar {
archiveFileName = "CustomNameplates-${rootProject.properties["project_version"]}.jar"
archiveFileName = "CustomNameplates-Bukkit-${rootProject.properties["project_version"]}.jar"
destinationDirectory.set(file("$rootDir/target"))
relocate("net.kyori", "net.momirealms.customnameplates.libraries")
relocate("org.incendo", "net.momirealms.customnameplates.libraries")
@@ -3,7 +3,7 @@ plugins {
}
repositories {
maven("https://papermc.io/repo/repository/maven-public/") // paper
maven("https://repo.papermc.io/repository/maven-public/") // paper
maven("https://repo.william278.net/releases/") // husk
maven("https://jitpack.io/")
maven("https://repo.oraxen.com/releases/")
@@ -29,9 +29,13 @@ dependencies {
compileOnly(files("libs/carbonchat-paper-3.0.0-beta.27.jar"))
compileOnly(files("libs/AdvancedChat-1.3.7.jar"))
compileOnly(files("libs/CMIAPI-9.7.4.1.jar"))
compileOnly(files("libs/ChatControl-Red-10.28.3.jar"))
compileOnly(files("libs/Typewriter.jar"))
compileOnly("net.william278.huskchat:huskchat-bukkit:3.0.4")
compileOnly("net.essentialsx:EssentialsX:2.20.1")
compileOnly("net.essentialsx:EssentialsXChat:2.20.1")
// compileOnly("com.github.Brikster:Chatty:v2.19.14")
compileOnly(files("libs/Chatty-3.0.0-SNAPSHOT.jar"))
// Emoji
compileOnly("com.github.LoneDev6:api-itemsadder:3.6.3-beta-14")
compileOnly("io.th0rgal:oraxen:1.182.0")
Binary file not shown.
@@ -0,0 +1,85 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is 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
* any later version.
*
* This program 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 <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customnameplates.bukkit.compatibility.chat;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.api.feature.chat.AbstractChatMessageProvider;
import net.momirealms.customnameplates.api.feature.chat.ChatManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.mineacademy.chatcontrol.PlayerCache;
import org.mineacademy.chatcontrol.api.ChatChannelEvent;
import org.mineacademy.chatcontrol.model.Channel;
import java.util.Objects;
public class ChatControlRedProvider extends AbstractChatMessageProvider implements Listener {
public ChatControlRedProvider(CustomNameplates plugin, ChatManager manager) {
super(plugin, manager);
}
@EventHandler(ignoreCancelled = true)
public void onChat(ChatChannelEvent event) {
plugin.debug(() -> "ChatChannelEvent triggered");
final CommandSender sender = event.getSender();
if (!(sender instanceof Player player)) {
return;
}
if (!player.isOnline()) return;
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
if (cnPlayer == null) return;
plugin.getScheduler().async().execute(() -> {
manager.onChat(cnPlayer, event.getMessage(), event.getChannel().getName());
});
}
@Override
public boolean hasJoinedChannel(CNPlayer player, String channelID) {
Channel channel = Channel.findChannel(channelID);
if (channel == null) return false;
return channel.isInChannel((Player) player.player());
}
@Override
public boolean canJoinChannel(CNPlayer player, String channelID) {
return ((Player) player).hasPermission("chatcontrol.channel.join."+channelID+".read");
}
@Override
public boolean isIgnoring(CNPlayer sender, CNPlayer receiver) {
PlayerCache cache = PlayerCache.from((Player) receiver.player());
if (cache == null) return false;
return cache.isIgnoringPlayer(sender.uuid());
}
@Override
public void register() {
Bukkit.getPluginManager().registerEvents(this, Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("CustomNameplates")));
}
@Override
public void unregister() {
HandlerList.unregisterAll(this);
}
}
@@ -0,0 +1,82 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is 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
* any later version.
*
* This program 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 <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customnameplates.bukkit.compatibility.chat;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.api.feature.chat.AbstractChatMessageProvider;
import net.momirealms.customnameplates.api.feature.chat.ChatManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import ru.brikster.chatty.api.ChattyApi;
import ru.brikster.chatty.api.chat.Chat;
import ru.brikster.chatty.api.event.ChattyMessageEvent;
import java.util.Objects;
public class ChattyProvider extends AbstractChatMessageProvider implements Listener {
public ChattyProvider(CustomNameplates plugin, ChatManager manager) {
super(plugin, manager);
}
@EventHandler(ignoreCancelled = true)
public void onChat(ChattyMessageEvent event) {
final String message = event.getPlainMessage();
final Player player = event.getSender();
if (!player.isOnline()) return;
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
if (cnPlayer == null) return;
plugin.getScheduler().async().execute(() -> {
manager.onChat(cnPlayer, message, event.getChat().getId());
});
}
@Override
public boolean hasJoinedChannel(CNPlayer player, String channelID) {
return true;
}
@Override
public boolean canJoinChannel(CNPlayer player, String channelID) {
Chat chat = ChattyApi.instance().getChats().get(channelID);
if (chat == null) {
return false;
}
if (!chat.isPermissionRequired()) return true;
return chat.hasReadPermission((Player) player.player());
}
@Override
public boolean isIgnoring(CNPlayer sender, CNPlayer receiver) {
return false;
}
@Override
public void register() {
Bukkit.getPluginManager().registerEvents(this, Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("CustomNameplates")));
}
@Override
public void unregister() {
HandlerList.unregisterAll(this);
}
}
@@ -0,0 +1,70 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* This program is 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
* any later version.
*
* This program 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 <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customnameplates.bukkit.compatibility.quest;
import com.typewritermc.engine.paper.events.AsyncCinematicEndEvent;
import com.typewritermc.engine.paper.events.AsyncCinematicStartEvent;
import com.typewritermc.engine.paper.events.AsyncDialogueEndEvent;
import com.typewritermc.engine.paper.events.AsyncDialogueStartEvent;
import net.momirealms.customnameplates.api.AbstractCNPlayer;
import net.momirealms.customnameplates.api.ConfigManager;
import net.momirealms.customnameplates.api.CustomNameplates;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class TypeWriterListener implements Listener {
private final CustomNameplates plugin;
public TypeWriterListener(CustomNameplates plugin) {
this.plugin = plugin;
}
@EventHandler(ignoreCancelled = true)
public void onDialogueStart(AsyncDialogueStartEvent event) {
if (!ConfigManager.twDialogue()) return;
Player player = event.getPlayer();
AbstractCNPlayer cnPlayer = (AbstractCNPlayer) plugin.getPlayer(player.getUniqueId());
cnPlayer.acquireActionBar("TWDialogue");
}
@EventHandler(ignoreCancelled = true)
public void onDialogueEnd(AsyncDialogueEndEvent event) {
if (!ConfigManager.twDialogue()) return;
Player player = event.getPlayer();
AbstractCNPlayer cnPlayer = (AbstractCNPlayer) plugin.getPlayer(player.getUniqueId());
cnPlayer.releaseActionBar("TWDialogue");
}
@EventHandler(ignoreCancelled = true)
public void onCinematicStart(AsyncCinematicStartEvent event) {
if (!ConfigManager.twCinematic()) return;
Player player = event.getPlayer();
AbstractCNPlayer cnPlayer = (AbstractCNPlayer) plugin.getPlayer(player.getUniqueId());
cnPlayer.acquireActionBar("TWCinematic");
}
@EventHandler(ignoreCancelled = true)
public void onCinematicEnd(AsyncCinematicEndEvent event) {
if (!ConfigManager.twCinematic()) return;
Player player = event.getPlayer();
AbstractCNPlayer cnPlayer = (AbstractCNPlayer) plugin.getPlayer(player.getUniqueId());
cnPlayer.releaseActionBar("TWCinematic");
}
}
@@ -18,13 +18,11 @@
package net.momirealms.customnameplates.bukkit;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.common.plugin.NameplatesPlugin;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitBootstrap extends JavaPlugin {
private CustomNameplates nameplates;
private NameplatesPlugin plugin;
private CustomNameplates plugin;
@Override
public void onLoad() {
@@ -80,7 +80,7 @@ public class BukkitCNPlayer extends AbstractCNPlayer {
@Override
public Vector3 position() {
Location location = player().getLocation();
return new Vector3(location.x(), location.y(), location.z());
return new Vector3(location.getX(), location.getY(), location.getZ());
}
@Override
@@ -51,6 +51,12 @@ public class BukkitChatManager extends AbstractChatManager {
} else if (ConfigManager.chatEss() && Bukkit.getPluginManager().isPluginEnabled("EssentialsChat")) {
this.chatProvider = new EssentialsChatProvider(plugin, this);
plugin.getPluginLogger().info("EssentialsChat hooked!");
} else if (ConfigManager.chatChatControlRed() && Bukkit.getPluginManager().isPluginEnabled("ChatControlRed")) {
this.chatProvider = new ChatControlRedProvider(plugin, this);
plugin.getPluginLogger().info("ChatControlRed hooked!");
} else if (ConfigManager.chatChatty() && Bukkit.getPluginManager().isPluginEnabled("Chatty")) {
this.chatProvider = new ChattyProvider(plugin, this);
plugin.getPluginLogger().info("Chatty hooked!");
} else {
this.chatProvider = new AsyncChatProvider(plugin, this);
}
@@ -40,6 +40,7 @@ import net.momirealms.customnameplates.bukkit.command.BukkitCommandManager;
import net.momirealms.customnameplates.bukkit.compatibility.NameplatesExpansion;
import net.momirealms.customnameplates.bukkit.compatibility.NameplatesExtraExpansion;
import net.momirealms.customnameplates.bukkit.compatibility.cosmetic.MagicCosmeticsHook;
import net.momirealms.customnameplates.bukkit.compatibility.quest.TypeWriterListener;
import net.momirealms.customnameplates.bukkit.compatibility.region.WorldGuardRegion;
import net.momirealms.customnameplates.bukkit.requirement.BukkitRequirementManager;
import net.momirealms.customnameplates.bukkit.scheduler.BukkitSchedulerAdapter;
@@ -94,14 +95,6 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
private boolean loaded = false;
private String buildByBit = "%%__BUILTBYBIT__%%";
private String polymart = "%%__POLYMART__%%";
private String time = "%%__TIMESTAMP__%%";
private String user = "%%__USER__%%";
private String username = "%%__USERNAME__%%";
private boolean isLatest = false;
public BukkitCustomNameplates(JavaPlugin bootstrap) {
this.bootstrap = bootstrap;
VersionHelper.init(getServerVersion());
@@ -211,28 +204,9 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
} catch (Exception ignore) {
}
}
boolean downloadFromPolymart = polymart.equals("1");
boolean downloadFromBBB = buildByBit.equals("true");
if (ConfigManager.checkUpdate()) {
VersionHelper.UPDATE_CHECKER.apply(this).thenAccept(result -> {
String link;
if (downloadFromPolymart) {
link = "https://polymart.org/resource/2543/";
} else if (downloadFromBBB) {
link = "https://builtbybit.com/resources/36359/";
} else {
link = "https://github.com/Xiao-MoMi/Custom-Nameplates/";
}
if (!result) {
this.getPluginLogger().info("You are using the latest version.");
isLatest = true;
} else {
this.getPluginLogger().warn("Update is available: " + link);
isLatest = false;
}
});
if (Bukkit.getPluginManager().isPluginEnabled("Typewriter")) {
TypeWriterListener listener = new TypeWriterListener(this);
Bukkit.getPluginManager().registerEvents(listener, this.getBootstrap());
}
if (VersionHelper.isFolia()) {
@@ -264,6 +238,8 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
}
}, 200, 200, TimeUnit.MILLISECONDS);
}
super.enable();
}
@Override
@@ -284,7 +260,11 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
if (nameplateManager != null) this.nameplateManager.disable();
if (imageManager != null) this.imageManager.disable();
if (chatManager != null) this.chatManager.disable();
if (commandManager != null) this.commandManager.unregisterFeatures();
if (commandManager != null) {
if (!Bukkit.getServer().isStopping()) {
this.commandManager.unregisterFeatures();
}
}
this.joinQuitListeners.clear();
this.playerListeners.clear();
this.networkManager.shutdown();
@@ -313,6 +293,7 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
this.requirementManager.reload();
// load basics
this.configManager.reload();
this.debugger = ConfigManager.debug() ? (s) -> getPluginLogger().info("[DEBUG] " + s.get()) : (s) -> {};
this.storageManager.reload();
this.translationManager.reload();
// prepare resources
@@ -334,11 +315,6 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
this.scheduledMainTask = getScheduler().asyncRepeating(mainTask, 50, 50, TimeUnit.MILLISECONDS);
}
@Override
public boolean isUpToDate() {
return isLatest;
}
@Override
public InputStream getResourceStream(String filePath) {
return getBootstrap().getResource(filePath.replace("\\", "/"));
@@ -19,6 +19,8 @@ package net.momirealms.customnameplates.bukkit;
import it.unimi.dsi.fastutil.ints.IntList;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.ConfigManager;
import net.momirealms.customnameplates.api.CustomNameplates;
@@ -49,7 +51,7 @@ import java.util.regex.Pattern;
public class BukkitPlatform implements Platform {
private static final Pattern LANG_PATTERN = Pattern.compile("<lang:[a-zA-Z0-9._/]+>");
private static final Pattern LANG_PATTERN = Pattern.compile("<lang:[a-zA-Z0-9._/':-]+/?>");
private final CustomNameplates plugin;
private final boolean placeholderAPI;
@@ -98,9 +100,14 @@ public class BukkitPlatform implements Platform {
registerPacketConsumer((player, event, packet) -> {
if (!ConfigManager.actionbarModule()) return;
if (!ConfigManager.catchOtherActionBar()) return;
if (!player.shouldCNTakeOverActionBar()) return;
try {
Object component = Reflections.field$ClientboundSetActionBarTextPacket$text.get(packet);
// some plugins would send null to clear the actionbar, what a bad solution
Object component = Optional.ofNullable(Reflections.field$ClientboundSetActionBarTextPacket$text.get(packet)).orElse(Reflections.instance$Component$empty);
Object contents = Reflections.method$Component$getContents.invoke(component);
if (contents == null) {
return;
}
if (Reflections.clazz$ScoreContents.isAssignableFrom(contents.getClass())) {
//String name = scoreContentNameFunction.apply(Reflections.field$ScoreContents$name.get(contents));
String objective = (String) Reflections.field$ScoreContents$objective.get(contents);
@@ -118,6 +125,7 @@ public class BukkitPlatform implements Platform {
registerPacketConsumer((player, event, packet) -> {
if (!ConfigManager.actionbarModule()) return;
if (!ConfigManager.catchOtherActionBar()) return;
if (!player.shouldCNTakeOverActionBar()) return;
try {
boolean actionBar = (boolean) Reflections.field$ClientboundSystemChatPacket$overlay.get(packet);
if (actionBar) {
@@ -302,15 +310,46 @@ public class BukkitPlatform implements Platform {
Object attributeHolder = Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$attribute.get(attributeSnapshot);
Object attribute = Reflections.method$Holder$value.invoke(attributeHolder);
String id = (String) Reflections.field$Attribute$id.get(attribute);
if (id.equals("attribute.name.generic.scale")) {
if (id.endsWith("scale")) {
double baseValue = (double) Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$base.get(attributeSnapshot);
@SuppressWarnings("unchecked")
Collection<Object> modifiers = (Collection<Object>) Reflections.field$ClientboundUpdateAttributesPacket$AttributeSnapshot$modifiers.get(attributeSnapshot);
for (Object modifier : modifiers) {
double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier);
baseValue += amount;
int left = modifiers.size();
if (left > 0) {
for (Object modifier : modifiers) {
Object operation = Reflections.field$AttributeModifier$operation.get(modifier);
if (operation == Reflections.instance$AttributeModifier$Operation$ADD_VALUE) {
double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier);
baseValue += amount;
left--;
if (left == 0) break;
}
}
}
CustomNameplates.getInstance().getUnlimitedTagManager().onPlayerAttributeSet(another, player, baseValue);
double finalValue = baseValue;
if (left > 0) {
for (Object modifier : modifiers) {
Object operation = Reflections.field$AttributeModifier$operation.get(modifier);
if (operation == Reflections.instance$AttributeModifier$Operation$ADD_MULTIPLIED_BASE) {
double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier);
finalValue += amount * baseValue;
left--;
if (left == 0) break;
}
}
}
if (left > 0) {
for (Object modifier : modifiers) {
Object operation = Reflections.field$AttributeModifier$operation.get(modifier);
if (operation == Reflections.instance$AttributeModifier$Operation$ADD_MULTIPLIED_TOTAL) {
double amount = (double) Reflections.field$AttributeModifier$amount.get(modifier);
finalValue *= 1.0 + amount;
left--;
if (left == 0) break;
}
}
}
CustomNameplates.getInstance().getUnlimitedTagManager().onPlayerAttributeSet(another, player, finalValue);
return;
}
}
@@ -81,11 +81,11 @@ public class BubblesEquipCommand extends BukkitCommandFeature<CommandSender> {
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_EQUIP_FAILURE_PERMISSION);
return;
}
if (player.equippedBubble().equals(bubbleId)) {
if (player.currentBubble().equals(bubbleId)) {
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_EQUIP_FAILURE_NO_CHANGE);
return;
}
player.equippedBubble(bubbleId);
player.setBubbleData(bubbleId);
player.save();
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_EQUIP_SUCCESS, Component.text(bubbleId), AdventureHelper.miniMessage(bubble.displayName()));
});
@@ -73,7 +73,7 @@ public class BubblesForceEquipCommand extends BukkitCommandFeature<CommandSender
plugin.getPluginLogger().warn("Player " + player.name() + " tried to equip a bubble when data not loaded");
return;
}
player.equippedBubble(bubbleId);
player.setBubbleData(bubbleId);
player.save();
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_FORCE_EQUIP_SUCCESS, Component.text(bukkitPlayer.getName()), Component.text(bubbleId), AdventureHelper.miniMessage(bubble.displayName()));
});
@@ -51,7 +51,7 @@ public class BubblesForceUnEquipCommand extends BukkitCommandFeature<CommandSend
plugin.getPluginLogger().warn("Player " + player.name() + " tried to equip a bubble when data not loaded");
return;
}
player.equippedBubble("none");
player.setBubbleData("none");
player.save();
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_FORCE_UNEQUIP_SUCCESS, Component.text(bukkitPlayer.getName()));
});
@@ -48,11 +48,11 @@ public class BubblesUnEquipCommand extends BukkitCommandFeature<CommandSender> {
plugin.getPluginLogger().warn("Player " + player.name() + " tried to unequip a bubble when data not loaded");
return;
}
if (player.equippedBubble().equals("none")) {
if (player.bubbleData().equals("none")) {
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_UNEQUIP_FAILURE_NOT_EQUIP);
return;
}
player.equippedBubble("none");
player.setBubbleData("none");
player.save();
handleFeedback(context, MessageConstants.COMMAND_BUBBLES_UNEQUIP_SUCCESS);
});
@@ -81,11 +81,11 @@ public class NameplatesEquipCommand extends BukkitCommandFeature<CommandSender>
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_EQUIP_FAILURE_PERMISSION);
return;
}
if (player.equippedNameplate().equals(nameplateId)) {
if (player.currentNameplate().equals(nameplateId)) {
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_EQUIP_FAILURE_NO_CHANGE);
return;
}
player.equippedNameplate(nameplateId);
player.setNameplateData(nameplateId);
player.save();
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_EQUIP_SUCCESS, Component.text(nameplateId), AdventureHelper.miniMessage(nameplate.displayName()));
});
@@ -73,7 +73,7 @@ public class NameplatesForceEquipCommand extends BukkitCommandFeature<CommandSen
plugin.getPluginLogger().warn("Player " + player.name() + " tried to equip a nameplate when data not loaded");
return;
}
player.equippedNameplate(nameplateId);
player.setNameplateData(nameplateId);
player.save();
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_FORCE_EQUIP_SUCCESS, Component.text(bukkitPlayer.getName()), Component.text(nameplateId), AdventureHelper.miniMessage(nameplate.displayName()));
});
@@ -74,9 +74,9 @@ public class NameplatesForcePreviewCommand extends BukkitCommandFeature<CommandS
int time = (int) context.optional("time").orElse(plugin.getUnlimitedTagManager().previewDuration());
String previousNameplate = player.equippedNameplate();
String previousNameplate = player.currentNameplate();
if (specified) {
player.equippedNameplate(optionalNameplate.get());
player.setCurrentNameplate(optionalNameplate.get());
}
if (!player.isTempPreviewing())
@@ -92,7 +92,7 @@ public class NameplatesForcePreviewCommand extends BukkitCommandFeature<CommandS
}
if (specified) {
player.equippedNameplate(previousNameplate);
player.setCurrentNameplate(previousNameplate);
}
}, time, TimeUnit.SECONDS);
@@ -51,7 +51,7 @@ public class NameplatesForceUnEquipCommand extends BukkitCommandFeature<CommandS
plugin.getPluginLogger().warn("Player " + player.name() + " tried to equip a nameplate when data not loaded");
return;
}
player.equippedNameplate("none");
player.setNameplateData("none");
player.save();
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_FORCE_UNEQUIP_SUCCESS, Component.text(bukkitPlayer.getName()));
});
@@ -48,11 +48,11 @@ public class NameplatesUnEquipCommand extends BukkitCommandFeature<CommandSender
plugin.getPluginLogger().warn("Player " + player.name() + " tried to unequip a nameplate when data not loaded");
return;
}
if (player.equippedNameplate().equals("none")) {
if (player.nameplateData().equals("none")) {
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_UNEQUIP_FAILURE_NOT_EQUIP);
return;
}
player.equippedNameplate("none");
player.setNameplateData("none");
player.save();
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_UNEQUIP_SUCCESS);
});
Loaded 100 of 146 files, more files were not shown because too many files have changed in this diff. Show more