This commit is contained in:
XiaoMoMi committed 2024-10-08 22:26:48 +08:00
1 parent 6b2bbea6e1
commit a387cf5127
30 files changed
+567 -78

No files matched your search

@@ -39,7 +39,8 @@ public abstract class AbstractCNPlayer implements CNPlayer {
private boolean isLoaded = false;
private boolean isPreviewing = false;
private boolean tempPreviewing = false;
private boolean toggleablePreviewing = false;
private String equippedNameplate;
private String equippedBubble;
@@ -179,13 +180,22 @@ public abstract class AbstractCNPlayer implements CNPlayer {
isLoaded = loaded;
}
public void setPreviewing(boolean previewing) {
isPreviewing = previewing;
public void setTempPreviewing(boolean previewing) {
this.tempPreviewing = previewing;
}
@Override
public boolean isPreviewing() {
return isPreviewing;
public boolean isTempPreviewing() {
return tempPreviewing;
}
public void setToggleablePreviewing(boolean previewing) {
this.toggleablePreviewing = previewing;
}
@Override
public boolean isToggleablePreviewing() {
return toggleablePreviewing;
}
@Override
@@ -468,6 +478,7 @@ public abstract class AbstractCNPlayer implements CNPlayer {
.uuid(uuid())
.nameplate(equippedNameplate())
.bubble(equippedBubble())
.previewTags(isToggleablePreviewing())
.build(), plugin.getScheduler().async());
}
@@ -115,7 +115,14 @@ public interface CNPlayer {
*
* @return true if the player is previewing, false otherwise
*/
boolean isPreviewing();
boolean isTempPreviewing();
/**
* Checks if the player has turned their nameplate on
*
* @return true if the player has turned their nameplate on, false otherwise
*/
boolean isToggleablePreviewing();
/**
* Checks if the player has the specified permission.
@@ -70,6 +70,7 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected int defaultConditionRefreshInterval;
protected int delaySend;
protected boolean catchOtherActionBar;
protected int otherActionBarStayTime;
protected String namespace;
protected String font;
@@ -213,6 +214,7 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
defaultPlaceholderRefreshInterval = config.getInt("other-settings.default-placeholder-refresh-interval", 1);
defaultConditionRefreshInterval = config.getInt("other-settings.ddefault-condition-refresh-interval", 1);
catchOtherActionBar = config.getBoolean("other-settings.catch-other-plugin-actionbar", true);
otherActionBarStayTime = config.getInt("other-settings.other-actionbar-stay-time", 3000);
}
@Override
@@ -336,6 +338,10 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.defaultConditionRefreshInterval;
}
public static int otherActionBarStayTime() {
return instance.otherActionBarStayTime;
}
public static boolean enableShader() {
return instance.enableShader;
}
@@ -79,6 +79,7 @@ public abstract class CustomNameplates implements NameplatesPlugin {
protected ImageManager imageManager;
protected NameplateManager nameplateManager;
protected ResourcePackManager resourcePackManager;
protected CustomNameplatesAPI api;
protected CustomNameplates() {
instance = this;
@@ -262,6 +263,15 @@ public abstract class CustomNameplates implements NameplatesPlugin {
return resourcePackManager;
}
/**
* Get the API class
*
* @return api
*/
public CustomNameplatesAPI getAPI() {
return api;
}
/**
* Returns the platform object for accessing platform-specific functionality.
*
@@ -0,0 +1,167 @@
/*
* 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;
import net.momirealms.customnameplates.api.feature.AdaptiveImage;
import net.momirealms.customnameplates.api.feature.OffsetFont;
import net.momirealms.customnameplates.api.feature.background.Background;
import net.momirealms.customnameplates.api.feature.bubble.Bubble;
import net.momirealms.customnameplates.api.feature.nameplate.Nameplate;
import net.momirealms.customnameplates.api.helper.AdventureHelper;
import net.momirealms.customnameplates.api.placeholder.internal.StaticPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
public record CustomNameplatesAPI(CustomNameplates plugin) {
private static CustomNameplatesAPI instance;
public CustomNameplatesAPI(CustomNameplates plugin) {
this.plugin = plugin;
instance = this;
}
/**
* Gets the CustomNameplates plugin instance.
*
* @return the CustomNameplates plugin
*/
@Override
public CustomNameplates plugin() {
return plugin;
}
/**
* Retrieves a player by their UUID.
*
* @param uuid the player's UUID
* @return the CNPlayer object if found, otherwise null
*/
@Nullable
public CNPlayer getPlayer(UUID uuid) {
return plugin.getPlayer(uuid);
}
/**
* Retrieves a Background by its ID.
*
* @param id the background ID
* @return an Optional containing the Background if found, or empty if not
*/
@NotNull
public Optional<Background> getBackground(@NotNull String id) {
return Optional.ofNullable(plugin.getBackgroundManager().backgroundById(id));
}
/**
* Retrieves a Nameplate by its ID.
*
* @param id the nameplate ID
* @return an Optional containing the Nameplate if found, or empty if not
*/
@NotNull
public Optional<Nameplate> getNameplate(@NotNull String id) {
return Optional.ofNullable(plugin.getNameplateManager().nameplateById(id));
}
/**
* Retrieves a Bubble by its ID.
*
* @param id the bubble ID
* @return an Optional containing the Bubble if found, or empty if not
*/
@NotNull
public Optional<Bubble> getBubble(@NotNull String id) {
return Optional.ofNullable(plugin.getBubbleManager().bubbleById(id));
}
/**
* Creates a text string with an image, applying margins around the image.
*
* @param text the text to be displayed
* @param adaptiveImage the image to insert with the text
* @param leftMargin the margin to apply on the left of the image
* @param rightMargin the margin to apply on the right of the image
* @return the resulting string with the image and margins
*/
@NotNull
public String createTextWithImage(@NotNull String text, @NotNull AdaptiveImage adaptiveImage, float leftMargin, float rightMargin) {
if (AdventureHelper.legacySupport) {
text = AdventureHelper.legacyToMiniMessage(text);
}
float advance = plugin.getAdvanceManager().getLineAdvance(text);
return adaptiveImage.createImagePrefix(advance, leftMargin, rightMargin) + text + adaptiveImage.createImageSuffix(advance, leftMargin, rightMargin);
}
/**
* Gets the width advance (text length in visual representation) for a given text.
*
* @param text the text to measure
* @return the advance width of the text
*/
public float getTextAdvance(@NotNull String text) {
return plugin.getAdvanceManager().getLineAdvance(text);
}
/**
* Creates a statically positioned text, aligning it to the left, right, or middle
* of the specified width.
*
* @param text the text to be positioned
* @param width the total width for the text positioning
* @param position the desired static position (LEFT, RIGHT, MIDDLE)
* @return the resulting string with the appropriate positioning
*/
@NotNull
public String createStaticText(@NotNull String text, int width, @NotNull StaticPosition position) {
float parsedWidth = CustomNameplates.getInstance().getAdvanceManager().getLineAdvance(text);
switch (position) {
case LEFT -> {
return text + AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth));
}
case RIGHT -> {
return AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth)) + text;
}
case MIDDLE -> {
int half = (int) ((width - parsedWidth) / 2);
String left = AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(half));
String right = AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth - half));
return left + text + right;
}
default -> {
return "";
}
}
}
/**
* Returns the singleton instance of CustomNameplatesAPI.
* Throws an exception if the API has not been initialized.
*
* @return the CustomNameplatesAPI instance
*/
public static CustomNameplatesAPI getInstance() {
if (instance == null) {
throw new RuntimeException("Nameplates API has not been initialized yet.");
}
return instance;
}
}
@@ -0,0 +1,33 @@
/*
* 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.feature;
import net.momirealms.customnameplates.api.CNPlayer;
/**
* Listener for handling player respawn
*/
public interface RespawnListener {
/**
* Called when a player respawns
*
* @param player the player who respawns
*/
void onRespawn(CNPlayer player);
}
@@ -0,0 +1,33 @@
/*
* 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.feature;
import net.momirealms.customnameplates.api.CNPlayer;
/**
* Listener for handling player change worlds
*/
public interface WorldChangeListener {
/**
* Called when a player changes the world
*
* @param player the player who changes the world
*/
void onChangeWorld(CNPlayer player);
}
@@ -57,7 +57,15 @@ public interface UnlimitedTagManager extends Reloadable {
* @param player the player to update
* @param preview true to enable preview mode, false to disable
*/
void setPreviewing(CNPlayer player, boolean preview);
void setTempPreviewing(CNPlayer player, boolean preview);
/**
* Sets whether a player can always see their tags
*
* @param player the player to update
* @param preview true to enable preview mode, false to disable
*/
void togglePreviewing(CNPlayer player, boolean preview);
/**
* Returns the duration (in ticks) for which a tag preview is shown.
@@ -19,6 +19,7 @@ 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.OffsetFont;
import net.momirealms.customnameplates.api.feature.PreParsedDynamicText;
import net.momirealms.customnameplates.api.helper.AdventureHelper;
@@ -62,23 +63,6 @@ public class StaticText {
}
public String create(String text) {
float parsedWidth = CustomNameplates.getInstance().getAdvanceManager().getLineAdvance(text);
switch (position) {
case LEFT -> {
return text + AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth));
}
case RIGHT -> {
return AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth)) + text;
}
case MIDDLE -> {
int half = (int) ((width - parsedWidth) / 2);
String left = AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(half));
String right = AdventureHelper.surroundWithNameplatesFont(OffsetFont.createOffsets(width - parsedWidth - half));
return left + text + right;
}
default -> {
return "";
}
}
return CustomNameplatesAPI.getInstance().createStaticText(text, width, position);
}
}
@@ -32,6 +32,9 @@ public class JsonData {
@SerializedName("bubble")
private String bubble;
@SerializedName("flags")
private int flags;
/**
* Constructs a new {@link JsonData} instance.
*
@@ -41,6 +44,27 @@ public class JsonData {
public JsonData(String nameplate, String bubble) {
this.nameplate = nameplate;
this.bubble = bubble;
this.flags = 0;
}
public JsonData(String nameplate, String bubble, int flags) {
this.nameplate = nameplate;
this.bubble = bubble;
this.flags = flags;
}
public JsonData(String nameplate, String bubble, boolean previewState) {
this.nameplate = nameplate;
this.bubble = bubble;
this.flags = encodeFlags(previewState);
}
public static int encodeFlags(boolean previewState) {
return previewState ? 1 : 0;
}
public static boolean decodePreviewState(int flags) {
return (flags & 1) == 1;
}
/**
@@ -61,6 +85,15 @@ public class JsonData {
return bubble;
}
/**
* Returns the flags
*
* @return flags
*/
public int getFlags() {
return flags;
}
/**
* Converts this JSON data back into a {@link PlayerData} instance.
*
@@ -72,6 +105,7 @@ public class JsonData {
.uuid(uuid)
.nameplate(nameplate)
.bubble(bubble)
.previewTags(decodePreviewState(flags))
.build();
}
}
@@ -41,6 +41,13 @@ public interface PlayerData {
*/
String bubble();
/**
* Returns if the tag should always be shown to the owner
*
* @return if the tag should always be shown to the owner
*/
boolean previewTags();
/**
* Returns the UUID of the player.
*
@@ -100,6 +107,14 @@ public interface PlayerData {
*/
Builder uuid(UUID uuid);
/**
* Sets whether to preview state for the {@link PlayerData}.
*
* @param previewTags the state
* @return the builder instance
*/
Builder previewTags(boolean previewTags);
/**
* Builds and returns the {@link PlayerData} instance.
*
@@ -114,6 +129,6 @@ public interface PlayerData {
* @return a {@link JsonData} object containing the nameplate and bubble data
*/
default JsonData toJsonData() {
return new JsonData(nameplate(), bubble());
return new JsonData(nameplate(), bubble(), previewTags());
}
}
@@ -28,11 +28,13 @@ public class PlayerDataImpl implements PlayerData {
protected UUID uuid;
protected String nameplate;
protected String bubble;
protected boolean previewTags;
public PlayerDataImpl(UUID uuid, String nameplate, String bubble) {
public PlayerDataImpl(UUID uuid, String nameplate, String bubble, boolean previewTags) {
this.uuid = uuid;
this.nameplate = nameplate;
this.bubble = bubble;
this.previewTags = previewTags;
}
@Override
@@ -45,6 +47,11 @@ public class PlayerDataImpl implements PlayerData {
return bubble;
}
@Override
public boolean previewTags() {
return previewTags;
}
@Override
public UUID uuid() {
return uuid;
@@ -57,6 +64,7 @@ public class PlayerDataImpl implements PlayerData {
private String nameplate;
private String bubble;
private boolean previewTags;
private UUID uuid;
@Override
@@ -77,9 +85,15 @@ public class PlayerDataImpl implements PlayerData {
return this;
}
@Override
public Builder previewTags(boolean previewTags) {
this.previewTags = previewTags;
return this;
}
@Override
public PlayerData build() {
return new PlayerDataImpl(uuid, nameplate, bubble);
return new PlayerDataImpl(uuid, nameplate, bubble, previewTags);
}
}
}
@@ -18,6 +18,7 @@
package net.momirealms.customnameplates.backend.feature.actionbar;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.ConfigManager;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.api.feature.CarouselText;
import net.momirealms.customnameplates.api.feature.DynamicText;
@@ -146,6 +147,10 @@ public class ActionBarSender implements Feature {
}
public void refresh() {
if (currentActionBar == null) {
latestContent = "";
return;
}
latestContent = this.currentActionBar.render(owner);
textChangeFlag = false;
}
@@ -181,8 +186,11 @@ public class ActionBarSender implements Feature {
@Override
public void notifyPlaceholderUpdates(CNPlayer player, boolean force) {
refresh();
sendLatestActionBar();
// The actionbar should be visible before updating
if (currentActionBar != null) {
refresh();
sendLatestActionBar();
}
}
public void updateLastUpdateTime() {
@@ -204,6 +212,6 @@ public class ActionBarSender implements Feature {
public void externalActionBar(@NotNull String externalActionBar) {
requireNonNull(externalActionBar);
this.externalActionBar = externalActionBar;
this.externalExpireTime = System.currentTimeMillis() + 3000;
this.externalExpireTime = System.currentTimeMillis() + ConfigManager.otherActionBarStayTime();
}
}
@@ -143,12 +143,12 @@ public class BossBarSender implements Feature, BossBar {
}
public void show() {
isShown = true;
if (latestContent == null) {
refresh();
if (this.latestContent == null) {
this.refresh();
}
Object packet = CustomNameplates.getInstance().getPlatform().createBossBarPacket(uuid, AdventureHelper.miniMessageToMinecraftComponent(latestContent), progress(), overlay(), color());
Object packet = CustomNameplates.getInstance().getPlatform().createBossBarPacket(uuid, AdventureHelper.miniMessageToMinecraftComponent(this.latestContent), progress(), overlay(), color());
CustomNameplates.getInstance().getPacketSender().sendPacket(owner, packet);
isShown = true;
}
public boolean isShown() {
@@ -172,18 +172,22 @@ public class BossBarSender implements Feature, BossBar {
@Override
public void notifyPlaceholderUpdates(CNPlayer p1, boolean force) {
refresh();
if (isShown()) {
refresh();
sendLatestBossBarName();
}
}
public void refresh() {
latestContent = this.currentBossBar.render(owner);
if (this.currentBossBar == null) {
this.latestContent = "";
return;
}
this.latestContent = this.currentBossBar.render(owner);
}
public void sendLatestBossBarName() {
if (latestContent != null && isShown()) {
if (this.latestContent != null && isShown()) {
Object packet = CustomNameplates.getInstance().getPlatform().updateBossBarNamePacket(uuid, AdventureHelper.miniMessageToMinecraftComponent(latestContent));
CustomNameplates.getInstance().getPacketSender().sendPacket(owner, packet);
}
@@ -69,19 +69,21 @@ public class ResourcePackManagerImpl implements ResourcePackManager {
// save unicodes
this.saveLegacyUnicodes();
if (!VersionHelper.isVersionNewerThan1_20_5()) {
this.generateShaders("ResourcePack" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, false);
this.generateShaders("ResourcePack" + File.separator + "overlay_1_20_5" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, true);
} else {
this.generateShaders("ResourcePack" + File.separator + "overlay_1_20_5" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, true);
try {
FileUtils.copyDirectory(
new File(plugin.getDataFolder(), "ResourcePack" + File.separator + "overlay_1_20_5"),
new File(plugin.getDataFolder(), "ResourcePack")
);
FileUtils.deleteDirectory(new File(plugin.getDataFolder(), "ResourcePack" + File.separator + "overlay_1_20_5"));
} catch (IOException e) {
throw new RuntimeException(e);
if (ConfigManager.enableShader()) {
if (!VersionHelper.isVersionNewerThan1_20_5()) {
this.generateShaders("ResourcePack" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, false);
this.generateShaders("ResourcePack" + File.separator + "overlay_1_20_5" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, true);
} else {
this.generateShaders("ResourcePack" + File.separator + "overlay_1_20_5" + File.separator + "assets" + File.separator + "minecraft" + File.separator + "shaders" + File.separator + "core" + File.separator, true);
try {
FileUtils.copyDirectory(
new File(plugin.getDataFolder(), "ResourcePack" + File.separator + "overlay_1_20_5"),
new File(plugin.getDataFolder(), "ResourcePack")
);
FileUtils.deleteDirectory(new File(plugin.getDataFolder(), "ResourcePack" + File.separator + "overlay_1_20_5"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -433,7 +435,6 @@ public class ResourcePackManagerImpl implements ResourcePackManager {
}
private void generateShaders(String path, boolean v1_20_5) {
if (!ConfigManager.enableShader()) return;
plugin.getConfigManager().saveResource(path + "rendertype_text.fsh");
plugin.getConfigManager().saveResource(path + "rendertype_text.json");
@@ -131,16 +131,19 @@ public class NameTag extends AbstractTag implements RelationalFeature {
}
public void refresh() {
if (!isShown()) return;
for (CNPlayer viewer : viewerArray) {
refresh(viewer);
}
}
public void refresh(CNPlayer viewer) {
String newName = currentText.render(viewer);
Object component = AdventureHelper.miniMessageToMinecraftComponent(newName);
Object packet = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(entityID, List.of(CustomNameplates.getInstance().getPlatform().createTextComponentModifier(component)));
CustomNameplates.getInstance().getPacketSender().sendPacket(viewer, packet);
if (isShown(viewer)) {
String newName = currentText.render(viewer);
Object component = AdventureHelper.miniMessageToMinecraftComponent(newName);
Object packet = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(entityID, List.of(CustomNameplates.getInstance().getPlatform().createTextComponentModifier(component)));
CustomNameplates.getInstance().getPacketSender().sendPacket(viewer, packet);
}
}
@Override
@@ -24,7 +24,9 @@ import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.ConfigManager;
import net.momirealms.customnameplates.api.CustomNameplates;
import net.momirealms.customnameplates.api.feature.CarouselText;
import net.momirealms.customnameplates.api.feature.RespawnListener;
import net.momirealms.customnameplates.api.feature.JoinQuitListener;
import net.momirealms.customnameplates.api.feature.WorldChangeListener;
import net.momirealms.customnameplates.api.feature.tag.NameTagConfig;
import net.momirealms.customnameplates.api.feature.tag.TagRenderer;
import net.momirealms.customnameplates.api.feature.tag.UnlimitedTagManager;
@@ -40,8 +42,9 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitListener {
public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitListener, WorldChangeListener, RespawnListener {
private final CustomNameplates plugin;
private final LinkedHashMap<String, NameTagConfig> configs = new LinkedHashMap<>();
@@ -55,24 +58,61 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitLis
}
@Override
public void setPreviewing(CNPlayer player, boolean preview) {
boolean isPreviewing = player.isPreviewing();
public void setTempPreviewing(CNPlayer player, boolean preview) {
boolean isPreviewing = player.isTempPreviewing();
if (isPreviewing) {
if (preview) return;
plugin.getUnlimitedTagManager().onRemovePlayer(player, player);
onRemovePlayer(player, player);
player.removePlayerFromTracker(player);
((AbstractCNPlayer) player).setPreviewing(false);
((AbstractCNPlayer) player).setTempPreviewing(false);
} else {
if (!preview) return;
Tracker tracker = player.addPlayerToTracker(player);
tracker.setScale(player.scale());
tracker.setCrouching(player.isCrouching());
tracker.setSpectator(player.isSpectator());
plugin.getUnlimitedTagManager().onAddPlayer(player, player);
((AbstractCNPlayer) player).setPreviewing(true);
onAddPlayer(player, player);
((AbstractCNPlayer) player).setTempPreviewing(true);
}
}
@Override
public void togglePreviewing(CNPlayer player, boolean preview) {
boolean isPreviewing = player.isToggleablePreviewing();
if (isPreviewing) {
if (preview) return;
onRemovePlayer(player, player);
player.removePlayerFromTracker(player);
((AbstractCNPlayer) player).setToggleablePreviewing(false);
} else {
if (!preview) return;
Tracker tracker = player.addPlayerToTracker(player);
tracker.setScale(player.scale());
tracker.setCrouching(player.isCrouching());
tracker.setSpectator(player.isSpectator());
onAddPlayer(player, player);
((AbstractCNPlayer) player).setToggleablePreviewing(true);
}
}
@Override
public void onChangeWorld(CNPlayer player) {
if (player.isTempPreviewing() || player.isToggleablePreviewing()) {
onRemovePlayer(player, player);
onAddPlayer(player, player);
}
}
@Override
public void onRespawn(CNPlayer player) {
plugin.getScheduler().asyncLater(() -> {
if (player.isOnline() && (player.isTempPreviewing() || player.isToggleablePreviewing())) {
onRemovePlayer(player, player);
onAddPlayer(player, player);
}
}, 50, TimeUnit.MILLISECONDS);
}
@Override
public int previewDuration() {
return previewDuration;
@@ -86,7 +126,9 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitLis
if (previous != null) {
previous.destroy();
}
setPreviewing(player, isAlwaysShow());
if (isAlwaysShow()) {
setTempPreviewing(player, isAlwaysShow());
}
}
@Override
@@ -95,6 +95,7 @@ public class StorageManagerImpl implements StorageManager, JoinQuitListener {
private void handleDataLoad(CNPlayer player, PlayerData data) {
player.equippedBubble(data.bubble());
player.equippedNameplate(data.nameplate());
plugin.getUnlimitedTagManager().togglePreviewing(player, data.previewTags());
}
@Override
+2 -1
View File
@@ -58,8 +58,9 @@ 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: 0 # Set actionbar/bossbar send delay
send-delay: 20 # Set actionbar/bossbar send delay (ticks)
catch-other-plugin-actionbar: true # Capture actionbars from other plugins
other-actionbar-stay-time: 3000 # How long does other actionsbars stay (ms)
unsafe-chat-event: false # Listen for canceled(unsafe) chat events from unknown plugins
default-condition-refresh-interval: 1 # Set default condition refresh interval
default-placeholder-refresh-interval: 1 # Set default placeholder refresh interval
@@ -20,7 +20,9 @@ package net.momirealms.customnameplates.bukkit;
import net.momirealms.customnameplates.api.*;
import net.momirealms.customnameplates.api.event.NameplatesReloadEvent;
import net.momirealms.customnameplates.api.feature.ChatListener;
import net.momirealms.customnameplates.api.feature.RespawnListener;
import net.momirealms.customnameplates.api.feature.JoinQuitListener;
import net.momirealms.customnameplates.api.feature.WorldChangeListener;
import net.momirealms.customnameplates.api.helper.VersionHelper;
import net.momirealms.customnameplates.backend.feature.actionbar.ActionBarManagerImpl;
import net.momirealms.customnameplates.backend.feature.advance.AdvanceManagerImpl;
@@ -54,8 +56,11 @@ import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.InputStream;
@@ -78,6 +83,8 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
private final JavaPlugin bootstrap;
private final List<JoinQuitListener> joinQuitListeners = new ArrayList<>();
private final List<WorldChangeListener> worldChangeListeners = new ArrayList<>();
private final List<RespawnListener> respawnListeners = new ArrayList<>();
private boolean loaded = false;
@@ -154,11 +161,14 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
this.chatManager = new BukkitChatManager(this);
this.resourcePackManager = new ResourcePackManagerImpl(this);
this.eventManager = EventManager.create(this);
this.api = new CustomNameplatesAPI(this);
this.registerJoinQuitListener((JoinQuitListener) storageManager);
this.registerJoinQuitListener((JoinQuitListener) actionBarManager);
this.registerJoinQuitListener((JoinQuitListener) bossBarManager);
this.registerJoinQuitListener((JoinQuitListener) unlimitedTagManager);
this.joinQuitListeners.add((JoinQuitListener) storageManager);
this.joinQuitListeners.add((JoinQuitListener) actionBarManager);
this.joinQuitListeners.add((JoinQuitListener) bossBarManager);
this.joinQuitListeners.add((JoinQuitListener) unlimitedTagManager);
this.worldChangeListeners.add((WorldChangeListener) unlimitedTagManager);
this.respawnListeners.add((RespawnListener) unlimitedTagManager);
this.chatManager.registerListener((ChatListener) bubbleManager);
Bukkit.getPluginManager().registerEvents(this, getBootstrap());
@@ -349,6 +359,26 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
}
}
@EventHandler(ignoreCancelled = true)
public void onChangeWorld(PlayerChangedWorldEvent event) {
CNPlayer cnPlayer = getPlayer(event.getPlayer().getUniqueId());
if (cnPlayer != null) {
for (WorldChangeListener listener : worldChangeListeners) {
listener.onChangeWorld(cnPlayer);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onRespawn(PlayerRespawnEvent event) {
CNPlayer cnPlayer = getPlayer(event.getPlayer().getUniqueId());
if (cnPlayer != null) {
for (RespawnListener listener : respawnListeners) {
listener.onRespawn(cnPlayer);
}
}
}
public BukkitSenderFactory getSenderFactory() {
return senderFactory;
}
@@ -211,7 +211,7 @@ public class BukkitPlatform implements Platform {
int vehicle = (int) Reflections.field$ClientboundSetPassengersPacket$vehicle.get(packet);
CNPlayer another = CustomNameplates.getInstance().getPlayer(vehicle);
if (another != null) {
Set<Integer> otherEntities = player.getTrackedPassengerIds(another);
Set<Integer> otherEntities = another.getTrackedPassengerIds(player);
for (int passenger : passengers) {
otherEntities.add(passenger);
}
@@ -57,6 +57,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new NameplatesForceUnEquipCommand(this, plugin),
new NameplatesForcePreviewCommand(this, plugin),
new NameplatesForceEquipCommand(this, plugin),
new NameplatesToggleCommand(this, plugin),
new BubblesForceUnEquipCommand(this, plugin),
new BubblesListCommand(this, plugin),
new BubblesUnEquipCommand(this, plugin),
@@ -79,8 +79,8 @@ public class NameplatesForcePreviewCommand extends BukkitCommandFeature<CommandS
player.equippedNameplate(optionalNameplate.get());
}
if (!player.isPreviewing())
plugin.getUnlimitedTagManager().setPreviewing(player, true);
if (!player.isTempPreviewing())
plugin.getUnlimitedTagManager().setTempPreviewing(player, true);
SchedulerTask task = plugin.getScheduler().asyncLater(() -> {
if (!player.isOnline()) {
@@ -88,7 +88,7 @@ public class NameplatesForcePreviewCommand extends BukkitCommandFeature<CommandS
}
if (!plugin.getUnlimitedTagManager().isAlwaysShow()) {
plugin.getUnlimitedTagManager().setPreviewing(player, false);
plugin.getUnlimitedTagManager().setTempPreviewing(player, false);
}
if (specified) {
@@ -52,17 +52,17 @@ public class NameplatesPreviewCommand extends BukkitCommandFeature<CommandSender
if (plugin.getUnlimitedTagManager().isAlwaysShow()) {
return;
}
if (player.isPreviewing()) {
if (player.isTempPreviewing()) {
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_PREVIEW_FAILURE_COOLDOWN);
return;
}
plugin.getUnlimitedTagManager().setPreviewing(player, true);
plugin.getUnlimitedTagManager().setTempPreviewing(player, true);
SchedulerTask task = plugin.getScheduler().asyncLater(() -> {
if (!player.isOnline()) {
return;
}
plugin.getUnlimitedTagManager().setPreviewing(player, false);
plugin.getUnlimitedTagManager().setTempPreviewing(player, false);
}, plugin.getUnlimitedTagManager().previewDuration(), TimeUnit.SECONDS);
PreviewTasks.delayedTasks.put(player.uuid(), task);
@@ -0,0 +1,60 @@
/*
* 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.command.feature;
import net.momirealms.customnameplates.api.CNPlayer;
import net.momirealms.customnameplates.api.ConfigManager;
import net.momirealms.customnameplates.bukkit.BukkitCustomNameplates;
import net.momirealms.customnameplates.bukkit.command.BukkitCommandFeature;
import net.momirealms.customnameplates.common.command.CustomNameplatesCommandManager;
import net.momirealms.customnameplates.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
public class NameplatesToggleCommand extends BukkitCommandFeature<CommandSender> {
public NameplatesToggleCommand(CustomNameplatesCommandManager<CommandSender> commandManager, BukkitCustomNameplates plugin) {
super(commandManager, plugin);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.senderType(Player.class)
.handler(context -> {
if (!ConfigManager.nameplateModule()) return;
CNPlayer player = plugin.getPlayer(context.sender().getUniqueId());
if (player == null || !player.isLoaded()) return;
boolean isPreviewing = player.isToggleablePreviewing();
plugin.getUnlimitedTagManager().togglePreviewing(player, !isPreviewing);
player.save();
if (!isPreviewing) {
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_TOGGLE_ON);
} else {
handleFeedback(context, MessageConstants.COMMAND_NAMEPLATES_TOGGLE_OFF);
}
});
}
@Override
public String getFeatureID() {
return "nameplates_toggle";
}
}
+10
View File
@@ -87,6 +87,16 @@ nameplates_preview:
usage:
- /nameplates preview
# A command to toggle the nameplate previewing
# This command conflicts with `/nameplates preview`
# You should never enable both of them at the same time
# Usage: [COMMAND]
nameplates_toggle:
enable: false
permission: nameplates.command.toggle
usage:
- /nameplates toggle
# A command to view the available nameplates
# Usage: [COMMAND]
nameplates_list:
@@ -38,6 +38,8 @@ public interface MessageConstants {
TranslatableComponent.Builder COMMAND_NAMEPLATES_LIST_FAILURE_NONE = Component.translatable().key("command.nameplates.list.failure.none");
TranslatableComponent.Builder COMMAND_NAMEPLATES_LIST_SUCCESS = Component.translatable().key("command.nameplates.list.success");
TranslatableComponent.Builder COMMAND_NAMEPLATES_LIST_DELIMITER = Component.translatable().key("command.nameplates.list.delimiter");
TranslatableComponent.Builder COMMAND_NAMEPLATES_TOGGLE_ON = Component.translatable().key("command.nameplates.toggle.on");
TranslatableComponent.Builder COMMAND_NAMEPLATES_TOGGLE_OFF = Component.translatable().key("command.nameplates.toggle.off");
TranslatableComponent.Builder COMMAND_NAMEPLATES_FORCE_EQUIP_SUCCESS = Component.translatable().key("command.nameplates.force_equip.success");
TranslatableComponent.Builder COMMAND_NAMEPLATES_FORCE_EQUIP_FAILURE_NOT_EXISTS = Component.translatable().key("command.nameplates.force_equip.failure.not_exists");
@@ -60,6 +60,8 @@ command.nameplates.force_equip.failure.not_exists: "<red>Failed to equip namepla
command.nameplates.force_equip.success: "<white>Forced <arg:0> to equip <arg:1></white>" # use <arg:2> for display name
command.nameplates.force_unequip.success: "<white>Removed <arg:0>'s nameplate</white>"
command.nameplates.force_preview.success: "<white>Forced <arg:0> to preview nameplates</white>"
command.nameplates.toggle.on: "<white>You're now showing your tags (Go to third person to view)</white>"
command.nameplates.toggle.off: "<white>Your tags have been hidden</white>"
command.bubbles.equip.failure.not_exists: "<red><arg:0> doesn't exist</red>"
command.bubbles.equip.failure.permission: "<red>You don't have permission to use this bubble</red>"
command.bubbles.equip.failure.no_change: "<red>Nothing changed as you have already equipped this bubble</red>"
@@ -60,6 +60,8 @@ command.nameplates.force_equip.failure.not_exists: "<red>由于 <arg:1> 不存
command.nameplates.force_equip.success: "<white>强制 <arg:0> 佩戴了铭牌 <arg:1></white>"
command.nameplates.force_unequip.success: "<white>移除了 <arg:0> 的铭牌</white>"
command.nameplates.force_preview.success: "<white>强制 <arg:0> 预览他的铭牌</white>"
command.nameplates.toggle.on: "<white>你正在显示你的铭牌 (前往第三人称查看)</white>"
command.nameplates.toggle.off: "<white>你关闭了铭牌显示</white>"
command.bubbles.equip.failure.not_exists: "<red>气泡 <arg:0> 不存在</red>"
command.bubbles.equip.failure.permission: "<red>你尚未解锁这个气泡</red>"
command.bubbles.equip.failure.no_change: "<red>你已经应用这个气泡了</red>"
+2 -2
View File
@@ -1,7 +1,7 @@
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=3.0.0-beta-2
config_version=36
project_version=3.0.0-beta-3
config_version=37
project_group=net.momirealms
# Dependency settings