9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-19 15:09:19 +00:00

Merge branch 'remapped' into display_entities_backpacks

# Conflicts:
#	common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/types/CosmeticBackpackType.java
#	common/src/main/java/com/hibiscusmc/hmccosmetics/user/manager/UserBackpackManager.java
This commit is contained in:
lojosho
2025-04-06 10:42:59 -05:00
42 changed files with 601 additions and 234 deletions

1
.gitignore vendored
View File

@@ -115,3 +115,4 @@ run/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
/qodana.yaml

View File

@@ -8,7 +8,7 @@ plugins {
}
group = "com.hibiscusmc"
version = "2.7.5${getGitCommitHash()}"
version = "2.7.7${getGitCommitHash()}"
allprojects {
apply(plugin = "java")
@@ -18,7 +18,7 @@ allprojects {
mavenCentral()
// Paper Repo
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
// Jitpack
@@ -81,13 +81,16 @@ allprojects {
compileOnly("me.clip:placeholderapi:2.11.6")
compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.6")
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.12")
compileOnly("io.github.toxicity188:BetterHud-standard-api:1.12") //Standard api
compileOnly("io.github.toxicity188:BetterHud-bukkit-api:1.12") //Platform api
compileOnly("io.github.toxicity188:BetterCommand:1.3") //BetterCommand library
//compileOnly("it.unimi.dsi:fastutil:8.5.14")
compileOnly("org.projectlombok:lombok:1.18.34")
compileOnly("me.lojosho:HibiscusCommons:0.6.0-85d65299")
compileOnly("me.lojosho:HibiscusCommons:0.6.2-d21ebed8")
// Handled by Spigot Library Loader
compileOnly("net.kyori:adventure-api:4.18.0")
compileOnly("net.kyori:adventure-text-minimessage:4.18.0")
compileOnly("net.kyori:adventure-api:4.19.0")
compileOnly("net.kyori:adventure-text-minimessage:4.19.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.3.4")
annotationProcessor("org.projectlombok:lombok:1.18.36")
@@ -100,6 +103,14 @@ allprojects {
implementation("com.owen1212055:particlehelper:1.0.0-SNAPSHOT")
implementation("com.ticxo.playeranimator:PlayerAnimator:R1.2.7")
}
tasks {
javadoc {
// javadoc spec has these added.
(options as StandardJavadocDocletOptions)
.tags("apiNote:a:API:", "implSpec:a:Implementation Requirements", "implNote:a:Implementation Note:")
}
}
}
dependencies {
@@ -165,7 +176,7 @@ bukkit {
apiVersion = "1.20"
authors = listOf("LoJoSho")
depend = listOf("HibiscusCommons", "ProtocolLib")
softDepend = listOf("ModelEngine", "Oraxen", "ItemsAdder", "Geary", "HMCColor", "WorldGuard", "MythicMobs", "PlaceholderAPI", "SuperVanish", "PremiumVanish", "LibsDisguises", "Denizen", "MMOItems", "Eco")
softDepend = listOf("BetterHud", "ModelEngine", "Oraxen", "ItemsAdder", "Geary", "HMCColor", "WorldGuard", "MythicMobs", "PlaceholderAPI", "SuperVanish", "PremiumVanish", "LibsDisguises", "Denizen", "MMOItems", "Eco")
version = "${project.version}"
loadBefore = listOf(
"Cosmin" // Fixes an issue with Cosmin loading before and taking /cosmetic, when messing with what we do.
@@ -264,6 +275,9 @@ bukkit {
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
withJavadocJar()
withSourcesJar()
}
fun getGitCommitHash(): String {

View File

@@ -4,8 +4,10 @@ plugins {
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21
))
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
withJavadocJar()
withSourcesJar()
}
publishing {

View File

@@ -14,6 +14,7 @@ import com.hibiscusmc.hmccosmetics.emotes.EmoteManager;
import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.hooks.items.HookHMCCosmetics;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookBetterHud;
import com.hibiscusmc.hmccosmetics.hooks.placeholders.HMCPlaceholderExpansion;
import com.hibiscusmc.hmccosmetics.hooks.worldguard.WGHook;
import com.hibiscusmc.hmccosmetics.hooks.worldguard.WGListener;
@@ -52,6 +53,7 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
public HMCCosmeticsPlugin() {
super(13873, 1879);
new HookHMCCosmetics();
new HookBetterHud();
}
@Override
@@ -66,8 +68,8 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
if (!Path.of(getDataFolder().getPath() + "/cosmetics/").toFile().exists()) saveResource("cosmetics/defaultcosmetics.yml", false);
if (!Path.of(getDataFolder().getPath() + "/menus/").toFile().exists()) saveResource("menus/defaultmenu.yml", false);
// Player Animator
if (HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R3") || HMCCosmeticsAPI.getNMSVersion().contains("v1_20_R1")) PlayerAnimatorImpl.initialize(this); // PlayerAnimator does not support 1.20.2 yet
// Player Animator ~ Do no longer support running this on a version that PlayerAnimator is supported
// if (HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R3") || HMCCosmeticsAPI.getNMSVersion().contains("v1_20_R1")) PlayerAnimatorImpl.initialize(this); // PlayerAnimator does not support 1.20.2 yet
// Configuration Sync
final File configFile = Path.of(getInstance().getDataFolder().getPath(), "config.yml").toFile();
@@ -96,7 +98,7 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
getServer().getPluginManager().registerEvents(new PlayerConnectionListener(), this);
getServer().getPluginManager().registerEvents(new PlayerGameListener(), this);
getServer().getPluginManager().registerEvents(new ServerListener(), this);
// Taken from PaperLib
if (HibiscusCommonsPlugin.isOnPaper()) {
getServer().getPluginManager().registerEvents(new PaperPlayerGameListener(), this);
}
@@ -227,7 +229,7 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
}
}
if (Settings.isEmotesEnabled() && (HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R3") || HMCCosmeticsAPI.getNMSVersion().contains("v1_20_R1"))) EmoteManager.loadEmotes(); // PlayerAnimator does not support 1.20.2 yet
//if (Settings.isEmotesEnabled() && (HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R3") || HMCCosmeticsAPI.getNMSVersion().contains("v1_20_R1"))) EmoteManager.loadEmotes(); // PlayerAnimator does not support 1.20.2 yet
getInstance().getLogger().info("Successfully Enabled HMCCosmetics");
getInstance().getLogger().info(Cosmetics.values().size() + " Cosmetics Successfully Setup");

View File

@@ -10,6 +10,7 @@ import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUserProvider;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import me.lojosho.hibiscuscommons.nms.MinecraftVersion;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.Color;
@@ -95,7 +96,7 @@ public final class HMCCosmeticsAPI {
* customization
*/
public static void equipCosmetic(@NotNull CosmeticUser user, @NotNull Cosmetic cosmetic, @Nullable Color color) {
user.addPlayerCosmetic(cosmetic, color);
user.addCosmetic(cosmetic, color);
}
/**
@@ -200,7 +201,9 @@ public final class HMCCosmeticsAPI {
* @return the NMS version of the server in string format, or {@code null} if setup is not complete.
*/
public static @Nullable String getNMSVersion() {
return NMSHandlers.getVersion();
MinecraftVersion version = NMSHandlers.getVersion();
if (version == null) return null;
return version.toString();
}
/**

View File

@@ -144,6 +144,11 @@ public class CosmeticCommand implements CommandExecutor {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
if (!user.canEquipCosmetic(cosmetic) && !console) {
if (!silent) MessagesUtil.sendMessage(player, "no-cosmetic-permission");
return true;
@@ -156,7 +161,7 @@ public class CosmeticCommand implements CommandExecutor {
if (!silent) MessagesUtil.sendMessage(player, "equip-cosmetic", placeholders);
user.addPlayerCosmetic(cosmetic, color);
user.addCosmetic(cosmetic, color);
user.updateCosmetic(cosmetic.getSlot());
return true;
}
@@ -325,7 +330,7 @@ public class CosmeticCommand implements CommandExecutor {
if (!silent) MessagesUtil.sendMessage(player, "invalid-color");
return true;
}
user.addPlayerCosmetic(cosmetic, color); // #FFFFFF
user.addCosmetic(cosmetic, color); // #FFFFFF
} else {
DyeMenu.openMenu(user, cosmetic);
}

View File

@@ -73,6 +73,8 @@ public class Settings {
private static final String ENABLED_PATH = "enabled";
private static final String SLOT_OPTIONS_PATH = "slot-options";
private static final String BACKPACK_PREVENT_DARKNESS_PATH = "backpack-prevent-darkness";
private static final String BETTER_HUD_PATH = "betterhud";
private static final String BETTER_HUD_HIDE_IN_WARDROBE_PATH = "wardrobe-hide";
@Getter
private static String defaultMenu;
@@ -169,6 +171,8 @@ public class Settings {
private static boolean emoteMoveCheck;
@Getter @Setter
private static boolean allPlayersHidden;
@Getter
private static boolean wardrobeHideHud;
public static void load(ConfigurationNode source) {
@@ -271,6 +275,9 @@ public class Settings {
ConfigurationNode nexoSettings = hookSettings.node(HOOK_NEXO_PATH);
nexoChangeReload = nexoSettings.node(HOOK_RELOAD_CHANGE_PATH).getBoolean(true);
ConfigurationNode betterHudSettings = hookSettings.node(BETTER_HUD_PATH);
wardrobeHideHud = betterHudSettings.node(BETTER_HUD_HIDE_IN_WARDROBE_PATH).getBoolean(true);
ConfigurationNode worldGuardSettings = hookSettings.node(HOOK_WORLDGUARD_PATH);
worldGuardMoveCheck = worldGuardSettings.node(HOOK_WG_MOVE_CHECK_PATH).getBoolean(true);
// I messed up in release 2.2.6 and forgot to change player_move_check to player-move-check.

View File

@@ -0,0 +1,75 @@
package com.hibiscusmc.hmccosmetics.cosmetic;
import com.google.common.collect.ImmutableCollection;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.Color;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* Represents any object that can wear/hold cosmetics,
* users, for example.
*/
public interface CosmeticHolder {
@Nullable Cosmetic getCosmetic(@NotNull CosmeticSlot slot);
@NotNull ImmutableCollection<Cosmetic> getCosmetics();
void addCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color);
default void addCosmetic(@NotNull Cosmetic cosmetic) {
addCosmetic(cosmetic, null);
}
default void removeCosmetics() {
// Small optimization could be made, but Concurrent modification prevents us from both getting and removing
for (CosmeticSlot slot : CosmeticSlot.values().values()) {
removeCosmeticSlot(slot);
}
}
void removeCosmeticSlot(@NotNull CosmeticSlot slot);
default void removeCosmeticSlot(@NotNull Cosmetic cosmetic) {
removeCosmeticSlot(cosmetic.getSlot());
}
default boolean hasCosmeticInSlot(@NotNull CosmeticSlot slot) {
return getCosmetic(slot) != null;
}
default boolean hasCosmeticInSlot(@NotNull Cosmetic cosmetic) {
final var existingCosmetic = getCosmetic(cosmetic.getSlot());
if (existingCosmetic == null) return false;
return Objects.equals(cosmetic.getId(), existingCosmetic.getId());
}
default boolean canEquipCosmetic(@NotNull Cosmetic cosmetic) {
return canEquipCosmetic(cosmetic, false);
}
boolean canEquipCosmetic(@NotNull Cosmetic cosmetic, boolean ignoreWardrobe);
void updateCosmetic(@NotNull CosmeticSlot slot);
/**
* Just for backwards compatibility, ensures that the given viewer and the given cosmetic holder
* represent the same user.
*
* @param viewer the viewer
* @param cosmeticHolder the cosmetic holder
*/
@ApiStatus.Internal
static @NotNull CosmeticUser ensureSingleCosmeticUser(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder) {
if (!(cosmeticHolder instanceof CosmeticUser user) || !user.getUniqueId().equals(viewer.getUniqueId())) {
throw new IllegalStateException("This method does not support having a different viewer than" +
" the same cosmetic holder. Needs to be updated to support the overload that takes a viewer and" +
" a cosmetic holder instead of a single CosmeticUser.");
}
return user;
}
}

View File

@@ -4,6 +4,9 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.user.manager.UserEntity;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import lombok.Getter;
@@ -41,7 +44,7 @@ public class CosmeticBackpackType extends Cosmetic {
@Override
public void update(@NotNull CosmeticUser user) {
Entity entity = Bukkit.getEntity(user.getUniqueId());
Entity entity = user.getEntity();
if (entity == null) return;
if (user.isInWardrobe() || !user.isBackpackSpawned()) return;
@@ -51,8 +54,10 @@ public class CosmeticBackpackType extends Cosmetic {
return;
}
UserBackpackManager backpackManager = user.getUserBackpackManager();
Location loc = entity.getLocation().clone().add(0, 2, 0);
loc.setPitch(0);
List<Player> addedViewers = user.getUserBackpackManager().getEntityManager().refreshViewers(loc);
int entityId = user.getUserBackpackManager().getDisplayEntityId();
ItemStack backpackItem = user.getUserCosmeticItem(CosmeticSlot.BACKPACK);
@@ -69,7 +74,7 @@ public class CosmeticBackpackType extends Cosmetic {
if (!user.isInWardrobe() && isFirstPersonCompadible() && user.getPlayer() != null) {
List<Player> owner = List.of(user.getPlayer());
ArrayList<Integer> particleCloud = user.getUserBackpackManager().getAreaEffectEntityId();
ArrayList<Integer> particleCloud = backpackManager.getAreaEffectEntityId();
for (int i = 0; i < particleCloud.size(); i++) {
if (i == 0) {
HMCCPacketManager.sendRidingPacket(entity.getEntityId(), particleCloud.get(i), owner);
@@ -77,17 +82,17 @@ public class CosmeticBackpackType extends Cosmetic {
HMCCPacketManager.sendRidingPacket(particleCloud.get(i - 1), particleCloud.get(i) , owner);
}
}
HMCCPacketManager.sendRidingPacket(particleCloud.get(particleCloud.size() - 1), user.getUserBackpackManager().getFirstArmorStandId(), owner);
HMCCPacketManager.sendRidingPacket(particleCloud.get(particleCloud.size() - 1), firstArmorStandId, owner);
if (!user.isHidden()) {
//if (loc.getPitch() < -70) NMSHandlers.getHandler().equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, new ItemStack(Material.AIR), owner);
//else NMSHandlers.getHandler().equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, firstPersonBackpack, owner);
PacketManager.equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(this, firstPersonBackpack), owner);
PacketManager.equipmentSlotUpdate(firstArmorStandId, EquipmentSlot.HEAD, user.getUserCosmeticItem(this, firstPersonBackpack), owner);
}
//MessagesUtil.sendDebugMessages("First Person Backpack Update[owner=" + user.getUniqueId() + ",player_location=" + loc + "]!", Level.INFO);
}
*/
user.getUserBackpackManager().showBackpack();
backpackManager.showBackpack();
}
public boolean isFirstPersonCompadible() {

View File

@@ -79,8 +79,8 @@ public class CosmeticBalloonType extends Cosmetic {
}
Vector velocity = newLocation.toVector().subtract(currentLocation.toVector());
userBalloonManager.setVelocity(velocity.multiply(1.1));
userBalloonManager.setLocation(newLocation);
userBalloonManager.setVelocity(velocity.multiply(1.1));
HMCCPacketManager.sendTeleportPacket(userBalloonManager.getPufferfishBalloonId(), newLocation, false, viewer);
HMCCPacketManager.sendLeashPacket(userBalloonManager.getPufferfishBalloonId(), entity.getEntityId(), viewer);

View File

@@ -5,6 +5,7 @@ import com.hibiscusmc.hmccosmetics.api.events.PlayerMenuCloseEvent;
import com.hibiscusmc.hmccosmetics.api.events.PlayerMenuOpenEvent;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.gui.type.Types;
@@ -108,8 +109,7 @@ public class Menu {
int priority = config.node("priority").getInt(1);
Type type = null;
Type type = Types.getDefaultType();
if (!config.node("type").virtual()) {
String typeId = config.node("type").getString("");
if (Types.isType(typeId)) type = Types.getType(typeId);
@@ -123,7 +123,7 @@ public class Menu {
menuItems.sort(priorityCompare);
items.put(slot, menuItems);
} else {
items.put(slot, new ArrayList<>(Arrays.asList(menuItem)));
items.put(slot, new ArrayList<>(List.of(menuItem)));
}
}
}
@@ -136,13 +136,21 @@ public class Menu {
public void openMenu(@NotNull CosmeticUser user, boolean ignorePermission) {
Player player = user.getPlayer();
if (player == null) return;
openMenu(player, user, ignorePermission);
}
public void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder) {
openMenu(viewer, cosmeticHolder, false);
}
public void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, boolean ignorePermission) {
if (!ignorePermission && !permissionNode.isEmpty()) {
if (!player.hasPermission(permissionNode) && !player.isOp()) {
MessagesUtil.sendMessage(player, "no-permission");
if (!viewer.hasPermission(permissionNode) && !viewer.isOp()) {
MessagesUtil.sendMessage(viewer, "no-permission");
return;
}
}
final Component component = AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(player, this.title));
final Component component = AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(viewer, this.title));
Gui gui = Gui.gui()
.title(component)
.type(GuiType.CHEST)
@@ -159,7 +167,7 @@ public class Menu {
Bukkit.getScheduler().cancelTask(taskid.get());
}
updateMenu(user, gui);
updateMenu(viewer, cosmeticHolder, gui);
};
if (refreshRate != -1) {
@@ -170,25 +178,29 @@ public class Menu {
});
gui.setCloseGuiAction(event -> {
PlayerMenuCloseEvent closeEvent = new PlayerMenuCloseEvent(user, this, event.getReason());
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(closeEvent));
if (cosmeticHolder instanceof CosmeticUser user) {
PlayerMenuCloseEvent closeEvent = new PlayerMenuCloseEvent(user, this, event.getReason());
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(closeEvent));
}
if (taskid.get() != -1) Bukkit.getScheduler().cancelTask(taskid.get());
});
// API
PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this);
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(event));
if (event.isCancelled()) return;
if (cosmeticHolder instanceof CosmeticUser user) {
PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this);
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(event));
if (event.isCancelled()) return;
}
// Internal
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
gui.open(player);
updateMenu(user, gui); // fixes shading? I know I do this twice but it's easier than writing a whole new class to deal with this shit
gui.open(viewer);
updateMenu(viewer, cosmeticHolder, gui); // fixes shading? I know I do this twice but it's easier than writing a whole new class to deal with this shit
});
}
private void updateMenu(CosmeticUser user, Gui gui) {
private void updateMenu(Player viewer, CosmeticHolder cosmeticHolder, Gui gui) {
StringBuilder title = new StringBuilder(this.title);
int row = 0;
@@ -212,15 +224,15 @@ public class Menu {
// Handles the items
List<MenuItem> menuItems = items.get(i);
MenuItem item = menuItems.get(0);
updateItem(user, gui, i);
updateItem(viewer, cosmeticHolder, gui, i);
if (item.type() instanceof TypeCosmetic) {
Cosmetic cosmetic = Cosmetics.getCosmetic(item.itemConfig().node("cosmetic").getString(""));
if (cosmetic == null) continue;
if (user.hasCosmeticInSlot(cosmetic)) {
if (cosmeticHolder.hasCosmeticInSlot(cosmetic)) {
title.append(Settings.getEquippedCosmeticColor());
} else {
if (user.canEquipCosmetic(cosmetic, true)) {
if (cosmeticHolder.canEquipCosmetic(cosmetic, true)) {
title.append(Settings.getEquipableCosmeticColor());
} else {
title.append(Settings.getLockedCosmeticColor());
@@ -236,42 +248,42 @@ public class Menu {
}
}
MessagesUtil.sendDebugMessages("Updated menu with title " + title);
gui.updateTitle(StringUtils.parseStringToString(Hooks.processPlaceholders(user.getPlayer(), title.toString())));
gui.updateTitle(StringUtils.parseStringToString(Hooks.processPlaceholders(viewer, title.toString())));
} else {
for (int i = 0; i < gui.getInventory().getSize(); i++) {
if (items.containsKey(i)) {
updateItem(user, gui, i);
updateItem(viewer, cosmeticHolder, gui, i);
}
}
}
}
private void updateItem(CosmeticUser user, Gui gui, int slot) {
private void updateItem(Player viewer, CosmeticHolder cosmeticHolder, Gui gui, int slot) {
if (!items.containsKey(slot)) return;
List<MenuItem> menuItems = items.get(slot);
if (menuItems.isEmpty()) return;
for (MenuItem item : menuItems) {
Type type = item.type();
ItemStack modifiedItem = getMenuItem(user, type, item.itemConfig(), item.item().clone(), slot);
ItemStack modifiedItem = getMenuItem(viewer, cosmeticHolder, type, item.itemConfig(), item.item().clone(), slot);
if (modifiedItem.getType().isAir()) continue;
GuiItem guiItem = ItemBuilder.from(modifiedItem).asGuiItem();
guiItem.setAction(event -> {
UUID uuid = user.getUniqueId();
UUID uuid = viewer.getUniqueId();
if (Settings.isMenuClickCooldown()) {
Long userCooldown = Menus.getCooldown(uuid);
if (userCooldown != 0 && (System.currentTimeMillis() - Menus.getCooldown(uuid) <= getCooldown())) {
MessagesUtil.sendDebugMessages("Cooldown for " + user.getUniqueId() + " System time: " + System.currentTimeMillis() + " Cooldown: " + Menus.getCooldown(user.getUniqueId()) + " Difference: " + (System.currentTimeMillis() - Menus.getCooldown(user.getUniqueId())));
MessagesUtil.sendMessage(user.getPlayer(), "on-click-cooldown");
MessagesUtil.sendDebugMessages("Cooldown for " + viewer.getUniqueId() + " System time: " + System.currentTimeMillis() + " Cooldown: " + Menus.getCooldown(viewer.getUniqueId()) + " Difference: " + (System.currentTimeMillis() - Menus.getCooldown(viewer.getUniqueId())));
MessagesUtil.sendMessage(viewer, "on-click-cooldown");
return;
} else {
Menus.addCooldown(user.getUniqueId(), System.currentTimeMillis());
Menus.addCooldown(uuid, System.currentTimeMillis());
}
}
MessagesUtil.sendDebugMessages("Updated Menu Item in slot number " + slot);
final ClickType clickType = event.getClick();
if (type != null) type.run(user, item.itemConfig(), clickType);
updateMenu(user, gui);
if (type != null) type.run(viewer, cosmeticHolder, item.itemConfig(), clickType);
updateMenu(viewer, cosmeticHolder, gui);
});
MessagesUtil.sendDebugMessages("Set an item in slot " + slot + " in the menu of " + getId());
@@ -306,11 +318,11 @@ public class Menu {
return slots;
}
@Contract("_, _, _, _, _ -> param2")
@Contract("_, _, _, _, _, _ -> param4")
@NotNull
private ItemStack getMenuItem(CosmeticUser user, Type type, ConfigurationNode config, ItemStack itemStack, int slot) {
private ItemStack getMenuItem(Player viewer, CosmeticHolder cosmeticHolder, Type type, ConfigurationNode config, ItemStack itemStack, int slot) {
if (!itemStack.hasItemMeta()) return itemStack;
return type.setItem(user, config, itemStack, slot);
return type.setItem(viewer, cosmeticHolder, config, itemStack, slot);
}
public boolean canOpen(Player player) {

View File

@@ -3,9 +3,10 @@ package com.hibiscusmc.hmccosmetics.gui;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public record MenuItem(List<Integer> slots, ItemStack item, Type type, int priority, ConfigurationNode itemConfig) {
public record MenuItem(@NotNull List<Integer> slots, @NotNull ItemStack item, Type type, int priority, ConfigurationNode itemConfig) {
}

View File

@@ -1,6 +1,8 @@
package com.hibiscusmc.hmccosmetics.gui.action;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public abstract class Action {
@@ -16,5 +18,13 @@ public abstract class Action {
return this.id;
}
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
run(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), raw);
}
/**
* @deprecated Override {@link #run(Player, CosmeticHolder, String)} instead.
*/
@Deprecated
public abstract void run(CosmeticUser user, String raw);
}

View File

@@ -1,9 +1,11 @@
package com.hibiscusmc.hmccosmetics.gui.action;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.actions.*;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
@@ -41,16 +43,20 @@ public class Actions {
actions.put(action.getId().toUpperCase(), action);
}
public static void runActions(CosmeticUser user, @NotNull List<String> raw) {
public static void runActions(Player viewer, CosmeticHolder cosmeticHolder, @NotNull List<String> raw) {
for (String a : raw) {
String id = StringUtils.substringBetween(a, "[", "]").toUpperCase();
String message = StringUtils.substringAfter(a, "] ");
MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message);
if (isAction(id)) {
getAction(id).run(user, message);
getAction(id).run(viewer, cosmeticHolder, message);
} else {
MessagesUtil.sendDebugMessages("Possible ids: " + actions.keySet());
}
}
}
public static void runActions(CosmeticUser user, @NotNull List<String> raw) {
runActions(user.getPlayer(), user, raw);
}
}

View File

@@ -1,7 +1,9 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionCloseMenu extends Action {
@@ -10,8 +12,13 @@ public class ActionCloseMenu extends Action {
super("close");
}
@Override
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
viewer.closeInventory();
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
user.getPlayer().closeInventory();
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,10 +1,12 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionConsoleCommand extends Action {
@@ -13,8 +15,15 @@ public class ActionConsoleCommand extends Action {
super("console-command");
}
@Override
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
// todo: some of these generalizations may require more specific implementations, for example,
// todo: what if we wanted to execute console commands only for the cosmetic holder?
HMCCosmeticsPlugin.getInstance().getServer().dispatchCommand(Bukkit.getConsoleSender(), Hooks.processPlaceholders(viewer, raw));
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
HMCCosmeticsPlugin.getInstance().getServer().dispatchCommand(Bukkit.getConsoleSender(), Hooks.processPlaceholders(user.getPlayer(), raw));
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,7 +1,9 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticHide extends Action {
@@ -11,8 +13,14 @@ public class ActionCosmeticHide extends Action {
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
if (!(cosmeticHolder instanceof CosmeticUser user)) return;
if (user.isHidden()) return;
user.hideCosmetics(CosmeticUser.HiddenReason.ACTION);
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,7 +1,9 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticShow extends Action {
@@ -11,11 +13,17 @@ public class ActionCosmeticShow extends Action {
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
if (!(cosmeticHolder instanceof CosmeticUser user)) return;
if (!user.isHidden()) return;
// Do not hide if it's already off for WG
if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return;
user.showCosmetics(CosmeticUser.HiddenReason.ACTION);
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,7 +1,9 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionCosmeticToggle extends Action {
@@ -11,7 +13,8 @@ public class ActionCosmeticToggle extends Action {
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
if (!(cosmeticHolder instanceof CosmeticUser user)) return;
if (user.isHidden()) {
if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return;
user.showCosmetics(CosmeticUser.HiddenReason.ACTION);
@@ -20,4 +23,9 @@ public class ActionCosmeticToggle extends Action {
user.hideCosmetics(CosmeticUser.HiddenReason.ACTION);
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,9 +1,11 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.entity.Player;
public class ActionEquip extends Action {
@@ -12,10 +14,15 @@ public class ActionEquip extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
Cosmetic cosmetic = Cosmetics.getCosmetic(raw);
if (cosmetic == null) return;
user.addPlayerCosmetic(cosmetic);
cosmeticHolder.addCosmetic(cosmetic);
}
@Override
public void run(CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,10 +1,12 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.entity.Player;
import java.util.logging.Level;
@@ -15,7 +17,7 @@ public class ActionMenu extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
boolean ignorePermission = false;
raw = raw.replaceAll(" ", ""); // Removes all spaces
@@ -32,6 +34,11 @@ public class ActionMenu extends Action {
Menu menu = Menus.getMenu(raw);
MessagesUtil.sendDebugMessages(raw + " | " + ignorePermission);
menu.openMenu(user, ignorePermission);
menu.openMenu(viewer, cosmeticHolder, ignorePermission);
}
@Override
public void run(CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,8 +1,10 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionMessage extends Action {
@@ -11,8 +13,13 @@ public class ActionMessage extends Action {
super("message");
}
@Override
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
MessagesUtil.sendMessageNoKey(viewer, raw);
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
MessagesUtil.sendMessageNoKey(user.getPlayer(), raw);
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,5 +1,6 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -24,7 +25,7 @@ public class ActionParticle extends Action {
@Override
@SuppressWarnings("ConstantConditions")
public void run(CosmeticUser user, @NotNull String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
String[] rawString = raw.split(" ");
ParticleType<?, ?> particleType = Particles.fromKey(NamespacedKey.minecraft(rawString[0].toLowerCase()));
if (particleType == null) {
@@ -43,9 +44,14 @@ public class ActionParticle extends Action {
}
particle = HMCCServerUtils.addParticleValues(particle, rawString);
Location location = user.getPlayer().getLocation();
Location location = viewer.getLocation();
for (Player player : HMCCPacketManager.getViewers(location)) {
particle.compile().send(player, location);
}
}
@Override
public void run(CosmeticUser user, @NotNull String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,9 +1,11 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ActionPlayerCommand extends Action {
@@ -12,8 +14,14 @@ public class ActionPlayerCommand extends Action {
super("player-command");
}
@Override
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
// todo: what if we wanted the cosmetic holder to execute the command instead
viewer.performCommand(MessagesUtil.processStringNoKeyString(viewer, Hooks.processPlaceholders(viewer, raw)));
}
@Override
public void run(@NotNull CosmeticUser user, String raw) {
user.getPlayer().performCommand(MessagesUtil.processStringNoKeyString(user.getPlayer(), Hooks.processPlaceholders(user.getPlayer(), raw)));
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,5 +1,6 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -16,8 +17,7 @@ public class ActionSound extends Action {
}
@Override
public void run(@NotNull CosmeticUser user, @NotNull String raw) {
Player player = user.getPlayer();
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
String[] processedString = raw.split(" ");
String soundName = processedString[0];
@@ -31,6 +31,11 @@ public class ActionSound extends Action {
MessagesUtil.sendDebugMessages("Attempting to play " + soundName, Level.INFO);
player.playSound(player.getLocation(), soundName, volume, pitch);
viewer.playSound(viewer.getLocation(), soundName, volume, pitch);
}
@Override
public void run(@NotNull CosmeticUser user, @NotNull String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -1,9 +1,10 @@
package com.hibiscusmc.hmccosmetics.gui.action.actions;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.gui.action.Action;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.apache.commons.lang3.EnumUtils;
import org.bukkit.entity.Player;
public class ActionUnequip extends Action {
@@ -12,10 +13,15 @@ public class ActionUnequip extends Action {
}
@Override
public void run(CosmeticUser user, String raw) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) {
if (!CosmeticSlot.contains(raw)) return;
CosmeticSlot slot = CosmeticSlot.valueOf(raw);
user.removeCosmeticSlot(slot);
cosmeticHolder.removeCosmeticSlot(slot);
}
@Override
public void run(CosmeticUser user, String raw) {
run(user.getPlayer(), user, raw);
}
}

View File

@@ -6,6 +6,7 @@ import com.hibiscusmc.hmccolor.shaded.gui.guis.GuiItem;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.util.ColorBuilder;
@@ -15,23 +16,19 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import org.jetbrains.annotations.Nullable;
public class DyeMenu {
public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) {
Player player = user.getPlayer();
if (player == null) return;
public static void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, Cosmetic cosmetic) {
if (!Hooks.isActiveHook("HMCColor")) {
addCosmetic(user, cosmetic, null);
addCosmetic(viewer, cosmeticHolder, cosmetic, null);
return;
}
ItemStack originalItem = user.getUserCosmeticItem(cosmetic);
ItemStack originalItem = cosmetic.getItem();
if (originalItem == null || !cosmetic.isDyable()) return;
Gui gui = HMCColorApi.createColorMenu(player);
gui.updateTitle(Hooks.processPlaceholders(player, StringUtils.parseStringToString(Settings.getDyeMenuName())));
Gui gui = HMCColorApi.createColorMenu(viewer);
gui.updateTitle(Hooks.processPlaceholders(viewer, StringUtils.parseStringToString(Settings.getDyeMenuName())));
gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem));
gui.setDefaultTopClickAction(event -> {
if (event.getSlot() == Settings.getDyeMenuOutputSlot()) {
@@ -55,23 +52,28 @@ public class DyeMenu {
}
if (color == null) return;
addCosmetic(user, cosmetic, color);
addCosmetic(viewer, cosmeticHolder, cosmetic, color);
event.setCancelled(true);
} else event.setCancelled(true);
});
gui.setPlayerInventoryAction(event -> event.setCancelled(true));
gui.setCloseGuiAction(event -> {});
gui.open(player);
gui.open(viewer);
}
private static void addCosmetic(@NotNull CosmeticUser user, Cosmetic cosmetic, Color color) {
public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) {
Player player = user.getPlayer();
user.addPlayerCosmetic(cosmetic, color);
player.setItemOnCursor(new ItemStack(Material.AIR));
if (player == null) return;
openMenu(player, user, cosmetic);
}
private static void addCosmetic(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic, @Nullable Color color) {
cosmeticHolder.addCosmetic(cosmetic, color);
viewer.setItemOnCursor(new ItemStack(Material.AIR));
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
player.closeInventory();
user.updateCosmetic(cosmetic.getSlot());
viewer.closeInventory();
cosmeticHolder.updateCosmetic(cosmetic.getSlot());
}, 2);
}
}

View File

@@ -1,7 +1,9 @@
package com.hibiscusmc.hmccosmetics.gui.type;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@@ -18,11 +20,32 @@ public abstract class Type {
return this.id;
}
public void run(CosmeticUser user, ConfigurationNode config) {
run(user, config, null);
public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config) {
run(viewer, cosmeticHolder, config, null);
}
public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ClickType clickType) {
run(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), config, clickType);
}
public void run(CosmeticUser user, ConfigurationNode config) {
final var player = user.getPlayer();
if (player == null) return;
run(player, user, config, null);
}
/**
* @deprecated Override {@link #run(Player, CosmeticHolder, ConfigurationNode, ClickType)} instead.
*/
@Deprecated
public abstract void run(CosmeticUser user, ConfigurationNode config, ClickType clickType);
public ItemStack setItem(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ItemStack itemStack, int slot) {
return setItem(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), config, itemStack, slot);
}
/**
* @deprecated Override {@link #setItem(Player, CosmeticHolder, ConfigurationNode, ItemStack, int)} instead.
*/
public abstract ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot);
}

View File

@@ -10,18 +10,43 @@ public class Types {
private static final HashMap<String, Type> types = new HashMap<>();
private static TypeCosmetic TYPE_COSMETIC = new TypeCosmetic();
private static TypeEmpty TYPE_EMPTY = new TypeEmpty();
private static final TypeCosmetic TYPE_COSMETIC = new TypeCosmetic();
private static final TypeEmpty TYPE_EMPTY = new TypeEmpty();
/**
* Get's a Menu Item type. Add custom menu item types with {@link #addType(Type)}
* @param id A non-case sensitive ID
* @return The type of Menu Item
*/
public static Type getType(@NotNull String id) {
return types.get(id.toUpperCase());
}
/**
* Checks if a type is valid. Add custom menu item types with {@link #addType(Type)}
* @param id A non-case sensitive ID
* @return True if exists, False if not.
*/
public static boolean isType(@NotNull String id) {
return types.containsKey(id.toUpperCase());
}
public static void addType(Type type) {
types.put(type.getId().toUpperCase(), type);
/**
* Adds a Menu Item Type to the types HashMap for reference. Menu Types will automatically be added using this method.
* @param type A non-null {@link Type} that'll be added. ID should be unique; can't be duplicated
*/
public static boolean addType(@NotNull Type type) {
String id = type.getId().toUpperCase();
if (types.containsKey(id)) return false;
types.put(id, type);
return true;
}
/**
* Gets the default menu item; {@link TypeEmpty}
* @return The empty menu type.
*/
public static TypeEmpty getDefaultType() {
return TYPE_EMPTY;
}
}

View File

@@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.gui.type.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.gui.action.Actions;
@@ -38,7 +39,7 @@ public class TypeCosmetic extends Type {
}
@Override
public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ClickType clickType) {
MessagesUtil.sendDebugMessages("Running Cosmetic Click Type");
if (config.node("cosmetic").virtual()) {
MessagesUtil.sendDebugMessages("Cosmetic Config Field Virtual");
@@ -46,21 +47,20 @@ public class TypeCosmetic extends Type {
}
String cosmeticName = config.node("cosmetic").getString();
Cosmetic cosmetic = Cosmetics.getCosmetic(cosmeticName);
Player player = user.getPlayer();
if (cosmetic == null) {
MessagesUtil.sendDebugMessages("No Cosmetic Found");
MessagesUtil.sendMessage(player, "invalid-cosmetic");
MessagesUtil.sendMessage(viewer, "invalid-cosmetic");
return;
}
if (!user.canEquipCosmetic(cosmetic)) {
if (!cosmeticHolder.canEquipCosmetic(cosmetic)) {
MessagesUtil.sendDebugMessages("No Cosmetic Permission");
MessagesUtil.sendMessage(player, "no-cosmetic-permission");
MessagesUtil.sendMessage(viewer, "no-cosmetic-permission");
return;
}
boolean isUnEquippingCosmetic = false;
if (user.getCosmetic(cosmetic.getSlot()) == cosmetic) isUnEquippingCosmetic = true;
if (cosmeticHolder.getCosmetic(cosmetic.getSlot()) == cosmetic) isUnEquippingCosmetic = true;
String requiredClick;
if (isUnEquippingCosmetic) requiredClick = Settings.getCosmeticUnEquipClickType();
@@ -69,7 +69,7 @@ public class TypeCosmetic extends Type {
MessagesUtil.sendDebugMessages("Required click type: " + requiredClick);
MessagesUtil.sendDebugMessages("Click type: " + clickType.name());
if (!requiredClick.equalsIgnoreCase("ANY") && !requiredClick.equalsIgnoreCase(clickType.name())) {
MessagesUtil.sendMessage(user.getPlayer(), "invalid-click-type");
MessagesUtil.sendMessage(viewer.getPlayer(), "invalid-click-type");
return;
}
@@ -99,25 +99,25 @@ public class TypeCosmetic extends Type {
if (isUnEquippingCosmetic) {
if (!actionConfig.node("on-unequip").virtual()) actionStrings.addAll(actionConfig.node("on-unequip").getList(String.class));
MessagesUtil.sendDebugMessages("on-unequip");
user.removeCosmeticSlot(cosmetic);
cosmeticHolder.removeCosmeticSlot(cosmetic);
} else {
if (!actionConfig.node("on-equip").virtual()) actionStrings.addAll(actionConfig.node("on-equip").getList(String.class));
MessagesUtil.sendDebugMessages("on-equip");
// TODO: Redo this
if (cosmetic.isDyable() && Hooks.isActiveHook("HMCColor")) {
DyeMenu.openMenu(user, cosmetic);
DyeMenu.openMenu(viewer, cosmeticHolder, cosmetic);
} else {
user.addPlayerCosmetic(cosmetic);
cosmeticHolder.addCosmetic(cosmetic);
}
}
Actions.runActions(user, actionStrings);
Actions.runActions(viewer, cosmeticHolder, actionStrings);
} catch (SerializationException e) {
e.printStackTrace();
}
// Fixes issue with offhand cosmetics not appearing. Yes, I know this is dumb
Runnable run = () -> user.updateCosmetic(cosmetic.getSlot());
Runnable run = () -> cosmeticHolder.updateCosmetic(cosmetic.getSlot());
if (cosmetic instanceof CosmeticArmorType) {
if (((CosmeticArmorType) cosmetic).getEquipSlot().equals(EquipmentSlot.OFF_HAND)) {
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), run, 1);
@@ -128,8 +128,18 @@ public class TypeCosmetic extends Type {
}
@Override
public ItemStack setItem(@NotNull CosmeticUser user, @NotNull ConfigurationNode config, @NotNull ItemStack itemStack, int slot) {
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta()));
public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) {
run(user.getPlayer(), user, config, clickType);
}
@Override
public ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot) {
return setItem(user.getPlayer(), user, config, itemStack, slot);
}
@Override
public ItemStack setItem(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull ConfigurationNode config, @NotNull ItemStack itemStack, int slot) {
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta()));
else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta?");
if (config.node("cosmetic").virtual()) {
@@ -141,9 +151,9 @@ public class TypeCosmetic extends Type {
return itemStack;
}
if (user.hasCosmeticInSlot(cosmetic) && (!config.node("equipped-item").virtual() || !config.node("locked-equipped-item").virtual())) {
if (cosmeticHolder.hasCosmeticInSlot(cosmetic) && (!config.node("equipped-item").virtual() || !config.node("locked-equipped-item").virtual())) {
MessagesUtil.sendDebugMessages("GUI Equipped Item");
ConfigurationNode equippedItem = config.node(user.canEquipCosmetic(cosmetic, true) && !config.node("equipped-item").virtual() ? "equipped-item" : "locked-equipped-item");
ConfigurationNode equippedItem = config.node(cosmeticHolder.canEquipCosmetic(cosmetic, true) && !config.node("equipped-item").virtual() ? "equipped-item" : "locked-equipped-item");
try {
if (equippedItem.node("material").virtual()) equippedItem.node("material").set(config.node("item", "material").getString());
} catch (SerializationException e) {
@@ -154,12 +164,12 @@ public class TypeCosmetic extends Type {
} catch (SerializationException e) {
throw new RuntimeException(e);
}
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta()));
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta()));
else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta in equipped item?");
return itemStack;
}
if (!user.canEquipCosmetic(cosmetic, true) && !config.node("locked-item").virtual()) {
if (!cosmeticHolder.canEquipCosmetic(cosmetic, true) && !config.node("locked-item").virtual()) {
MessagesUtil.sendDebugMessages("GUI Locked Item");
ConfigurationNode lockedItem = config.node("locked-item");
try {
@@ -172,7 +182,7 @@ public class TypeCosmetic extends Type {
} catch (SerializationException e) {
throw new RuntimeException(e);
}
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta()));
if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta()));
else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta in locked item?");
return itemStack;
}
@@ -182,22 +192,22 @@ public class TypeCosmetic extends Type {
@Contract("_, _ -> param2")
@NotNull
@SuppressWarnings("Duplicates")
private ItemMeta processLoreLines(CosmeticUser user, @NotNull ItemMeta itemMeta) {
private ItemMeta processLoreLines(Player viewer, @NotNull ItemMeta itemMeta) {
List<String> processedLore = new ArrayList<>();
if (itemMeta.hasDisplayName()) {
itemMeta.setDisplayName(Hooks.processPlaceholders(user.getPlayer(), itemMeta.getDisplayName()));
itemMeta.setDisplayName(Hooks.processPlaceholders(viewer, itemMeta.getDisplayName()));
}
if (itemMeta.hasLore()) {
for (String loreLine : itemMeta.getLore()) {
processedLore.add(Hooks.processPlaceholders(user.getPlayer(), loreLine));
processedLore.add(Hooks.processPlaceholders(viewer, loreLine));
}
}
if (itemMeta instanceof SkullMeta skullMeta) {
if (skullMeta.hasOwner() && skullMeta.getOwner() != null) {
skullMeta.setOwner(Hooks.processPlaceholders(user.getPlayer(), skullMeta.getOwner()));
skullMeta.setOwner(Hooks.processPlaceholders(viewer, skullMeta.getOwner()));
}
}
itemMeta.setLore(processedLore);

View File

@@ -1,11 +1,13 @@
package com.hibiscusmc.hmccosmetics.gui.type.types;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.action.Actions;
import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.shaded.configurate.ConfigurationNode;
import me.lojosho.shaded.configurate.serialize.SerializationException;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@@ -23,9 +25,10 @@ public class TypeEmpty extends Type {
// This is an empty type, meaning, when a menu item has a type of "empty" it will run the code in the method run.
}
// This is the code that's run when the item is clicked.
// This is the code that's run when the item is clicked. The item is clicked by the "viewer" player in a menu for the
// given "cosmeticHolder". They're the same player by default, but it's not guaranteed.
@Override
public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) {
public void run(Player viewer, CosmeticHolder cosmeticHolder, @NotNull ConfigurationNode config, ClickType clickType) {
List<String> actionStrings = new ArrayList<>(); // List where we keep the actions the server will execute.
ConfigurationNode actionConfig = config.node("actions"); // Configuration node that actions are under.
@@ -52,31 +55,45 @@ public class TypeEmpty extends Type {
}
// We run the actions once we got the raw strings from the config.
Actions.runActions(user, actionStrings);
Actions.runActions(viewer, cosmeticHolder, actionStrings);
} catch (SerializationException e) {
throw new RuntimeException(e);
}
}
// backward-compatibility method, will not be required in the future
@Override
public void run(CosmeticUser user, ConfigurationNode config, ClickType clickType) {
final var player = user.getPlayer();
if (player == null) return;
run(player, user, config, clickType);
}
// backward-compatibility method, will not be required in the future
@Override
public ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot) {
return setItem(user.getPlayer(), user, config, itemStack, slot);
}
@Override
@SuppressWarnings("Duplicates")
public ItemStack setItem(CosmeticUser user, ConfigurationNode config, @NotNull ItemStack itemStack, int slot) {
public ItemStack setItem(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, @NotNull ItemStack itemStack, int slot) {
List<String> processedLore = new ArrayList<>();
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta.hasDisplayName()) {
itemMeta.setDisplayName(Hooks.processPlaceholders(user.getPlayer(), itemMeta.getDisplayName()));
itemMeta.setDisplayName(Hooks.processPlaceholders(viewer, itemMeta.getDisplayName()));
}
if (itemMeta.hasLore()) {
for (String loreLine : itemMeta.getLore()) {
processedLore.add(Hooks.processPlaceholders(user.getPlayer(), loreLine));
processedLore.add(Hooks.processPlaceholders(viewer, loreLine));
}
}
if (itemMeta instanceof SkullMeta skullMeta) {
if (skullMeta.hasOwner() && skullMeta.getOwner() != null) {
skullMeta.setOwner(Hooks.processPlaceholders(user.getPlayer(), skullMeta.getOwner()));
skullMeta.setOwner(Hooks.processPlaceholders(viewer, skullMeta.getOwner()));
}
}

View File

@@ -0,0 +1,39 @@
package com.hibiscusmc.hmccosmetics.hooks.misc;
import com.hibiscusmc.hmccosmetics.api.events.PlayerWardrobeEnterEvent;
import com.hibiscusmc.hmccosmetics.api.events.PlayerWardrobeLeaveEvent;
import com.hibiscusmc.hmccosmetics.config.Settings;
import kr.toxicity.hud.api.BetterHud;
import kr.toxicity.hud.api.player.HudPlayer;
import me.lojosho.hibiscuscommons.hooks.Hook;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class HookBetterHud extends Hook {
public HookBetterHud() {
super("BetterHUD");
setActive(true);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPlayerEnterWardrobe(@NotNull PlayerWardrobeEnterEvent event) {
if (!Settings.isWardrobeHideHud()) return;
UUID uuid = event.getUniqueId();
HudPlayer hudPlayer = BetterHud.getInstance().getPlayerManager().getHudPlayer(uuid);
if (hudPlayer == null) return;
hudPlayer.setHudEnabled(false);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPlayerLeaveWardrobe(@NotNull PlayerWardrobeLeaveEvent event) {
if (!Settings.isWardrobeHideHud()) return;
UUID uuid = event.getUniqueId();
HudPlayer hudPlayer = BetterHud.getInstance().getPlayerManager().getHudPlayer(uuid);
if (hudPlayer == null) return;
hudPlayer.setHudEnabled(true);
}
}

View File

@@ -55,6 +55,7 @@ public class PlayerConnectionListener implements Listener {
CosmeticUser cosmeticUser = CosmeticUsers.getProvider()
.createCosmeticUser(uuid)
.initialize(userData);
cosmeticUser.startTicking();
CosmeticUsers.addUser(cosmeticUser);
MessagesUtil.sendDebugMessages("Run User Join for " + uuid);

View File

@@ -2,10 +2,7 @@ package com.hibiscusmc.hmccosmetics.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.*;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
@@ -455,7 +452,7 @@ public class PlayerGameListener implements Listener {
}
private void registerInventoryClickListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Client.WINDOW_CLICK) {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, List.of(PacketType.Play.Client.WINDOW_CLICK), ListenerOptions.ASYNC) {
@Override
public void onPacketReceiving(PacketEvent event) {
Player player = event.getPlayer();
@@ -481,7 +478,7 @@ public class PlayerGameListener implements Listener {
}
private void registerMenuChangeListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.WINDOW_ITEMS) {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, List.of(PacketType.Play.Server.WINDOW_ITEMS), ListenerOptions.ASYNC) {
@Override
public void onPacketSending(PacketEvent event) {
MessagesUtil.sendDebugMessages("Menu Initial ");
@@ -515,7 +512,7 @@ public class PlayerGameListener implements Listener {
if ((slot >= 5 && slot <= 8) || slot == 45) {
if (!items.containsKey(slot)) continue;
slotData.set(slot, items.get(slot));
MessagesUtil.sendDebugMessages("Set " + slot + " as " + items.get(slot));
if (Settings.isDebugMode()) MessagesUtil.sendDebugMessages("Set " + slot + " as " + items.get(slot));
}
}
packet.getItemListModifier().write(0, slotData);
@@ -703,7 +700,6 @@ public class PlayerGameListener implements Listener {
for (final EquipmentSlot slot : EquipmentSlot.values()) {
final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
if (armorItems == null) continue;
if (material == null) continue;
if (armorItems.contains(material)) return slot;
}
return null;

View File

@@ -8,6 +8,7 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.config.Wardrobe;
import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
@@ -44,11 +45,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.logging.Level;
public class CosmeticUser {
public class CosmeticUser implements CosmeticHolder {
@Getter
private final UUID uniqueId;
private int taskId;
private int taskId = -1;
private final HashMap<CosmeticSlot, Cosmetic> playerCosmetics = new HashMap<>();
private UserWardrobeManager userWardrobeManager;
private UserBalloonManager userBalloonManager;
@@ -105,7 +105,6 @@ public class CosmeticUser {
this.applyHiddenState(userData.getHiddenReasons());
}
this.startTickTask();
return this;
}
@@ -139,69 +138,88 @@ public class CosmeticUser {
}
Player bukkitPlayer = getPlayer();
if (bukkitPlayer != null && Settings.isDisabledGamemodesEnabled() && Settings.getDisabledGamemodes().contains(bukkitPlayer.getGameMode().toString())) {
MessagesUtil.sendDebugMessages("Hiding cosmetics due to gamemode");
hideCosmetics(HiddenReason.GAMEMODE);
} else if (this.isHidden(HiddenReason.GAMEMODE)) {
MessagesUtil.sendDebugMessages("Showing cosmetics for gamemode");
showCosmetics(HiddenReason.GAMEMODE);
}
if (bukkitPlayer != null && Settings.getDisabledWorlds().contains(getEntity().getLocation().getWorld().getName())) {
MessagesUtil.sendDebugMessages("Hiding Cosmetics due to world");
hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else if (this.isHidden(HiddenReason.WORLD)) {
MessagesUtil.sendDebugMessages("Showing Cosmetics due to world");
showCosmetics(HiddenReason.WORLD);
}
if (Settings.isAllPlayersHidden()) {
hideCosmetics(HiddenReason.DISABLED);
}
for (final HiddenReason reason : hiddenReasons) {
if(bukkitPlayer != null && Settings.isDisabledGamemodesEnabled() && Settings.getDisabledGamemodes().contains(bukkitPlayer.getGameMode().toString())) {
MessagesUtil.sendDebugMessages("Hiding cosmetics due to gamemode");
this.hideCosmetics(HiddenReason.GAMEMODE);
return;
} else if(this.isHidden(HiddenReason.GAMEMODE)) {
MessagesUtil.sendDebugMessages("Showing cosmetics for gamemode");
this.showCosmetics(HiddenReason.GAMEMODE);
}
if(bukkitPlayer != null && Settings.getDisabledGamemodes().contains(bukkitPlayer.getWorld().getName())) {
MessagesUtil.sendDebugMessages("Hiding Cosmetics due to gamemode");
this.hideCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
return;
} else if(this.isHidden(HiddenReason.WORLD)) {
MessagesUtil.sendDebugMessages("Showing Cosmetics due to world");
this.showCosmetics(HiddenReason.WORLD);
return;
}
if(Settings.isAllPlayersHidden()) {
this.hideCosmetics(HiddenReason.DISABLED);
}
this.silentlyAddHideFlag(reason);
}
}
private void startTickTask() {
// Occasionally updates the entity cosmetics
Runnable run = () -> {
MessagesUtil.sendDebugMessages("Tick[uuid=" + uniqueId + "]", Level.INFO);
if (Hooks.isInvisible(uniqueId)) hideCosmetics(HiddenReason.VANISH);
else showCosmetics(HiddenReason.VANISH);
updateCosmetic();
if (isHidden() && !getUserEmoteManager().isPlayingEmote() && !getCosmetics().isEmpty()) MessagesUtil.sendActionBar(getPlayer(), "hidden-cosmetics");
};
/**
* Start ticking against the {@link CosmeticUser}.
* @implNote The tick-rate is determined by the tick period specified in the configuration, if it is less-than or equal to 0
* there will be no {@link BukkitTask} created, and the {@link CosmeticUser#taskId} will be -1
*/
public final void startTicking() {
int tickPeriod = Settings.getTickPeriod();
if (tickPeriod > 0) {
BukkitTask task = Bukkit.getScheduler().runTaskTimer(HMCCosmeticsPlugin.getInstance(), run, 0, tickPeriod);
taskId = task.getTaskId();
if(tickPeriod <= 0) {
MessagesUtil.sendDebugMessages("CosmeticUser tick is disabled.");
return;
}
final BukkitTask task = Bukkit.getScheduler().runTaskTimer(HMCCosmeticsPlugin.getInstance(), this::tick, 0, tickPeriod);
this.taskId = task.getTaskId();
}
/**
* Dispatch an operation to happen against this {@link CosmeticUser}
* at a pre-determined tick-rate.
* The tick-rate is determined by the tick period specified in the configuration.
*/
protected void tick() {
MessagesUtil.sendDebugMessages("Tick[uuid=" + uniqueId + "]", Level.INFO);
if (Hooks.isInvisible(uniqueId)) {
this.hideCosmetics(HiddenReason.VANISH);
} else {
this.showCosmetics(HiddenReason.VANISH);
}
this.updateCosmetic();
if(isHidden() && !getUserEmoteManager().isPlayingEmote() && !playerCosmetics.isEmpty()) {
MessagesUtil.sendActionBar(getPlayer(), "hidden-cosmetics");
}
}
public void destroy() {
Bukkit.getScheduler().cancelTask(taskId);
if(this.taskId != -1) { // ensure we're actually ticking this user.
Bukkit.getScheduler().cancelTask(taskId);
}
despawnBackpack();
despawnBalloon();
}
public Cosmetic getCosmetic(CosmeticSlot slot) {
@Override
public Cosmetic getCosmetic(@NotNull CosmeticSlot slot) {
return playerCosmetics.get(slot);
}
public ImmutableCollection<Cosmetic> getCosmetics() {
@Override
public @NotNull ImmutableCollection<Cosmetic> getCosmetics() {
return ImmutableList.copyOf(playerCosmetics.values());
}
public void addPlayerCosmetic(@NotNull Cosmetic cosmetic) {
addPlayerCosmetic(cosmetic, null);
}
public void addPlayerCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) {
@Override
public void addCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) {
// API
PlayerCosmeticEquipEvent event = new PlayerCosmeticEquipEvent(this, cosmetic);
Bukkit.getPluginManager().callEvent(event);
@@ -233,15 +251,24 @@ public class CosmeticUser {
Bukkit.getPluginManager().callEvent(postEquipEvent);
}
public void removeCosmetics() {
// Small optimization could be made, but Concurrent modification prevents us from both getting and removing
for (CosmeticSlot slot : CosmeticSlot.values().values()) {
removeCosmeticSlot(slot);
}
/**
* @deprecated Use {@link #addCosmetic(Cosmetic)} instead
*/
@Deprecated(since = "2.7.7", forRemoval = true)
public void addPlayerCosmetic(@NotNull Cosmetic cosmetic) {
addCosmetic(cosmetic);
}
/**
* @deprecated Use {@link #addCosmetic(Cosmetic, Color)} instead
*/
@Deprecated(since = "2.7.7", forRemoval = true)
public void addPlayerCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) {
addCosmetic(cosmetic, color);
}
public void removeCosmeticSlot(CosmeticSlot slot) {
@Override
public void removeCosmeticSlot(@NotNull CosmeticSlot slot) {
// API
PlayerCosmeticRemoveEvent event = new PlayerCosmeticRemoveEvent(this, getCosmetic(slot));
Bukkit.getPluginManager().callEvent(event);
@@ -263,30 +290,21 @@ public class CosmeticUser {
removeArmor(slot);
}
public void removeCosmeticSlot(Cosmetic cosmetic) {
removeCosmeticSlot(cosmetic.getSlot());
}
public boolean hasCosmeticInSlot(CosmeticSlot slot) {
@Override
public boolean hasCosmeticInSlot(@NotNull CosmeticSlot slot) {
return playerCosmetics.containsKey(slot);
}
public boolean hasCosmeticInSlot(Cosmetic cosmetic) {
if (getCosmetic(cosmetic.getSlot()) == null) return false;
return Objects.equals(cosmetic.getId(), getCosmetic(cosmetic.getSlot()).getId());
}
public Set<CosmeticSlot> getSlotsWithCosmetics() {
return Set.copyOf(playerCosmetics.keySet());
}
public void updateCosmetic(CosmeticSlot slot) {
if (getCosmetic(slot) == null) {
return;
@Override
public void updateCosmetic(@NotNull CosmeticSlot slot) {
Cosmetic cosmetic = playerCosmetics.get(slot);
if (cosmetic != null) {
cosmetic.update(this);
}
getCosmetic(slot).update(this);
return;
}
public void updateCosmetic(Cosmetic cosmetic) {
@@ -297,7 +315,7 @@ public class CosmeticUser {
MessagesUtil.sendDebugMessages("updateCosmetic (All) - start");
HashMap<EquipmentSlot, ItemStack> items = new HashMap<>();
for (Cosmetic cosmetic : getCosmetics()) {
for (Cosmetic cosmetic : playerCosmetics.values()) {
if (cosmetic instanceof CosmeticArmorType armorType) {
if (getUserEmoteManager().isPlayingEmote() || isInWardrobe()) return;
if (!(getEntity() instanceof HumanEntity humanEntity)) return;
@@ -309,7 +327,7 @@ public class CosmeticUser {
items.put(HMCCInventoryUtils.getEquipmentSlot(armorType.getSlot()), armorType.getItem(this));
} else {
updateCosmetic(cosmetic.getSlot());
cosmetic.update(this);
}
}
if (items.isEmpty() || getEntity() == null) return;
@@ -614,23 +632,20 @@ public class CosmeticUser {
public List<CosmeticSlot> getDyeableSlots() {
ArrayList<CosmeticSlot> dyableSlots = new ArrayList<>();
for (Cosmetic cosmetic : getCosmetics()) {
for (Cosmetic cosmetic : playerCosmetics.values()) {
if (cosmetic.isDyable()) dyableSlots.add(cosmetic.getSlot());
}
return dyableSlots;
}
public boolean canEquipCosmetic(Cosmetic cosmetic) {
return canEquipCosmetic(cosmetic, false);
}
public boolean canEquipCosmetic(Cosmetic cosmetic, boolean ignoreWardrobe) {
@Override
public boolean canEquipCosmetic(@NotNull Cosmetic cosmetic, boolean ignoreWardrobe) {
if (!cosmetic.requiresPermission()) return true;
if (isInWardrobe() && !ignoreWardrobe) {
if (WardrobeSettings.isTryCosmeticsInWardrobe() && userWardrobeManager.getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return true;
}
return getPlayer().hasPermission(cosmetic.getPermission());
return getEntity().hasPermission(cosmetic.getPermission());
}
public void hidePlayer() {

View File

@@ -1,6 +1,5 @@
package com.hibiscusmc.hmccosmetics.user;
import com.google.common.collect.HashBiMap;
import com.hibiscusmc.hmccosmetics.util.HMCCServerUtils;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -9,9 +8,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class CosmeticUsers {
private static final HashBiMap<UUID, CosmeticUser> COSMETIC_USERS = HashBiMap.create();
private static final ConcurrentHashMap<UUID, CosmeticUser> COSMETIC_USERS = new ConcurrentHashMap<>();
private static CosmeticUserProvider PROVIDER = CosmeticUserProvider.Default.INSTANCE;
@@ -104,6 +105,7 @@ public class CosmeticUsers {
*/
@NotNull
public static Set<CosmeticUser> values() {
return COSMETIC_USERS.values();
// fix this later; this is a temporary fix. It was originally a set, now it's a collection
return Set.copyOf(COSMETIC_USERS.values());
}
}

View File

@@ -30,7 +30,7 @@ public class UserBackpackManager {
@Getter
private boolean backpackHidden;
@Getter
private int displayEntityId;
private final int displayEntityId;
private ArrayList<Integer> particleCloud = new ArrayList<>();
@Getter
private final CosmeticUser user;

View File

@@ -180,6 +180,10 @@ public class UserBalloonManager {
this.getModelEntity().teleport(location);
}
public Vector getVelocity() {
return getModelEntity().getVelocity();
}
public void setVelocity(Vector vector) {
this.getModelEntity().setVelocity(vector);
}

View File

@@ -9,6 +9,7 @@ import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@@ -43,7 +44,7 @@ public class UserEntity {
ArrayList<Player> newPlayers = new ArrayList<>();
ArrayList<Player> removePlayers = new ArrayList<>();
List<Player> players = HMCCPacketManager.getViewers(location);
Player ownerPlayer = Bukkit.getPlayer(owner);
Entity ownerPlayer = Bukkit.getEntity(owner);
if (ownerPlayer == null) {
MessagesUtil.sendDebugMessages("Owner is null (refreshViewers), returning empty list");
return List.of();

View File

@@ -109,14 +109,19 @@ public class UserWardrobeManager {
MessagesUtil.sendMessage(player, "opened-wardrobe");
Runnable run = () -> {
if (!player.isOnline()) {
end();
return;
}
// Armorstand
HMCCPacketManager.sendEntitySpawnPacket(viewingLocation, ARMORSTAND_ID, EntityType.ARMOR_STAND, UUID.randomUUID(), viewer);
HMCCPacketManager.sendArmorstandMetadata(ARMORSTAND_ID, viewer);
HMCCPacketManager.sendLookPacket(ARMORSTAND_ID, viewingLocation, viewer);
// Player
user.getPlayer().teleport(viewingLocation, PlayerTeleportEvent.TeleportCause.PLUGIN);
user.getPlayer().setInvisible(true);
player.teleport(viewingLocation, PlayerTeleportEvent.TeleportCause.PLUGIN);
player.setInvisible(true);
HMCCPacketManager.gamemodeChangePacket(player, 3);
HMCCPacketManager.sendCameraPacket(ARMORSTAND_ID, viewer);

View File

@@ -385,13 +385,7 @@ public class HMCCPacketManager extends PacketManager {
*/
@NotNull
public static List<Player> getViewers(@NotNull Location location) {
ArrayList<Player> viewers = new ArrayList<>();
if (Settings.getViewDistance() <= 0) {
viewers.addAll(location.getWorld().getPlayers());
} else {
viewers.addAll(PacketManager.getViewers(location, Settings.getViewDistance()));
}
return viewers;
return PacketManager.getViewers(location, Settings.getViewDistance());
}
public static void sendPacket(Player player, PacketContainer packet) {

View File

@@ -105,13 +105,13 @@ menu-settings:
shading:
# Below is the shading mechanism behind cosmetic items. This is a bit complicated, but it allows for a lot of customization.
# The shading is done through the title and by shifting textures around. This is done by offsets.
# Only Oraxen is support by default. Vanilla can't properly handle it without a lot of unicodes and ItemsAdder adds weird offsets and decolors it. (This is why it is disabled by default)
# Only Nexo is support by default. Vanilla can't properly handle it without a lot of unicodes and ItemsAdder adds weird offsets and decolors it. (This is why it is disabled by default)
enabled: false # Default of menus having shading. This can be toggled individually in menus with "shading: true/false"
first-row-shift: "<s:-169>" # Oraxen: "<s:-169>"
sequent-row-shift: " <s:-169>" # Oraxen: " <s:-169>" (Space is important here!)
individual-column-shift: "<s:-3>" # Oraxen: "<s:-3>"
background: "<g:shade_row_<row>:colorable> " # Oraxen: "<g:shade_row_<row>:colorable>
clear-background: "<g:clear_row_<row>:colorable> " # Oraxen: "<g:clear_row_<row>:colorable> "
first-row-shift: "<shift:-169>" # Nexo: "<shift:-169>"
sequent-row-shift: " <shift:-169>" # Nexo: " <shift:-169>" (Space is important here!)
individual-column-shift: "<shift:-3>" # Nexo: "<shift:-3>"
background: "<glyph:shade_row_<row>:colorable> " # Nexo: "<glyph:shade_row_<row>:colorable>
clear-background: "<glyph:clear_row_<row>:colorable> " # Nexo: "<glyph:clear_row_<row>:colorable> "
#These use MiniMessage for color! https://docs.advntr.dev/minimessage/format.html#color
equipped-cosmetic-color: "<yellow>"
equipable-cosmetic-color: "<green>"
@@ -123,6 +123,7 @@ menu-settings:
dye-menu:
# If you use ItemsAdder, set this to "<white>:img_offset_-8::img_dye_menu:"
# If you use Oraxen, set this to "<white><s:-8><g:dye_menu>"
# If you use Nexo, set this to "<white><shift:-8><glyph:dye_menu>"
title: "<white>"
input-slot: 10
output-slot: 16
@@ -138,6 +139,8 @@ hook-settings:
# Checks worldguard regions for HMCC flags. If set to false, flags will not work properly.
# Requires restart to apply changes.
player-move-check: true
betterhud:
wardrobe-hide: true
wardrobe:
# how much yaw should change per tick, set to 0 for none
rotation-speed: 3
@@ -170,6 +173,7 @@ wardrobe:
enabled: true
# If you use ItemsAdder, set this to "<black>%img_title%
# If you use Oraxen, set this to "<black><glyph:title>"
# If you use Nexo, set this to "<black>%nexo_title%" and use PlaceholderAPI
text: "<black>"
delay: 40
title-fade-in: 1000 # milliseconds