9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-23 08:59:20 +00:00

Compare commits

..

28 Commits

Author SHA1 Message Date
LoJoSho
35260d4abb Merge remote-tracking branch 'origin/remapped' into remapped 2024-04-27 09:06:34 -05:00
LoJoSho
2d44435d53 fix: hmccolor dye menu not processing through minimessage 2024-04-27 09:06:21 -05:00
LoJoSho
3d785bd157 version bump (2.7.3-DEV) 2024-04-27 09:04:39 -05:00
lucian929
c33cfbd302 fix: update default config to use proper input slots for color 2024-04-25 15:24:22 -04:00
LoJoSho
f5ed39e02c Merge remote-tracking branch 'origin/remapped' into remapped 2024-04-25 14:09:44 -05:00
LoJoSho
0c3af0e0cd version bump (2.7.2) 2024-04-25 14:09:22 -05:00
lucian929
f5a1a67e1e chore: remove emotes from defaultmenu 2024-04-25 14:13:47 -04:00
LoJoSho
ddc0a504fd fix: disabled worlds not checked if player teleports through portals 2024-04-25 12:12:27 -05:00
LoJoSho
de108753d5 clean: ignore cancelled teleportations 2024-04-02 22:04:40 -05:00
LoJoSho
b31e8b7a4b chore: more documentation for CosmeticUsers class 2024-04-02 22:02:51 -05:00
LoJoSho
383fdfa7f6 fix: no entity + backpack spawning causing NPE 2024-03-16 12:13:07 -05:00
LoJoSho
54e867ab0b Merge pull request #131 from HibiscusMC/allow-flight
fix: wardrobe kicking player if allowFlight not enabled in server.pro…
2024-03-11 08:40:46 -05:00
LoJoSho
068ed3eb70 fix: backpacks not reattaching after teleporting 2024-03-05 22:26:10 -06:00
LoJoSho
a203c60df1 fix: backpacks turning black when under blocks 2024-03-05 10:58:12 -06:00
LoJoSho
e13c3fccb4 fix: hidden flags being added async causing error 2024-02-25 17:51:06 -06:00
LoJoSho
add72e66c9 feat: hidden reasons now in lists, add disableall command (hides all players cosmetics) 2024-02-25 15:20:32 -06:00
LoJoSho
0e587feff0 fix: multiple schedulers when player has multiple loaded cosmetics 2024-02-21 12:42:57 -06:00
LoJoSho
27be86c419 fix: clean resources after sql usage 2024-02-20 13:53:10 -06:00
Boy
3d940d8468 fix: wardrobe kicking player if allowFlight not enabled in server.properties 2024-02-10 13:20:36 +01:00
LoJoSho
7515cdd137 refactor: getHidden to isHidden in CosmeticUser class, deprecate old method 2024-02-04 20:07:01 -06:00
LoJoSho
8e92f3e689 fix: hidden reasons for gamemodes + world not working, spawning entity cosmetics while hidden 2024-02-04 20:04:33 -06:00
LoJoSho
7c4b833d80 fix: tab autocomplete checks attempted before user loading causing NPE 2024-02-04 19:20:37 -06:00
LoJoSho
b291dc4c9f Merge remote-tracking branch 'origin/remapped' into remapped 2024-01-28 10:57:30 -06:00
LoJoSho
60b91df843 fix: balloons with head models pitch being affected by player 2024-01-28 10:56:49 -06:00
LoJoSho
56f380025d fix: equipped armor not showing after exiting wardrobe 2024-01-17 13:07:01 -06:00
LoJoSho
b3e0acbcbd feat: add config options to prevent damage while in the wardrobe 2024-01-17 12:45:04 -06:00
LoJoSho
e2d334db9d version bump (2.7.2-DEV) 2024-01-17 12:25:03 -06:00
LoJoSho
dffcf6213b fix: check if player is not null before running end wardrobe 2024-01-17 12:24:41 -06:00
27 changed files with 366 additions and 147 deletions

View File

@@ -8,7 +8,7 @@ plugins {
} }
group = "com.hibiscusmc" group = "com.hibiscusmc"
version = "2.7.1" version = "2.7.3-DEV"
allprojects { allprojects {
apply(plugin = "java") apply(plugin = "java")
@@ -244,6 +244,15 @@ bukkit {
register("hmccosmetics.unapplydeath.bypass") { register("hmccosmetics.unapplydeath.bypass") {
default = BukkitPluginDescription.Permission.Default.OP default = BukkitPluginDescription.Permission.Default.OP
} }
register("hmccosmetics.cmd.disableall") {
default = BukkitPluginDescription.Permission.Default.OP
}
register("hmccosmetics.cmd.hiddenreasons") {
default = BukkitPluginDescription.Permission.Default.OP
}
register("hmccosmetics.cmd.clearhiddenreasons") {
default = BukkitPluginDescription.Permission.Default.OP
}
} }
} }

View File

@@ -427,7 +427,7 @@ public class CosmeticCommand implements CommandExecutor {
CosmeticUser user = CosmeticUsers.getUser(player); CosmeticUser user = CosmeticUsers.getUser(player);
if (!silent) MessagesUtil.sendMessage(sender, "show-cosmetic"); if (!silent) MessagesUtil.sendMessage(sender, "show-cosmetic");
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.COMMAND);
return true; return true;
} }
case ("debug") -> { case ("debug") -> {
@@ -496,6 +496,63 @@ public class CosmeticCommand implements CommandExecutor {
user.getUserEmoteManager().playEmote(args[1]); user.getUserEmoteManager().playEmote(args[1]);
return true; return true;
} }
case "disableall" -> {
if (!sender.hasPermission("hmccosmetics.cmd.disableall")) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length == 1) {
if (!silent) MessagesUtil.sendMessage(player, "not-enough-args");
return true;
}
if (args[1].equalsIgnoreCase("true")) {
Settings.setAllPlayersHidden(true);
for (CosmeticUser user : CosmeticUsers.values()) user.hideCosmetics(CosmeticUser.HiddenReason.DISABLED);
if (!silent) MessagesUtil.sendMessage(sender, "disabled-all");
} else if (args[1].equalsIgnoreCase("false")) {
Settings.setAllPlayersHidden(false);
for (CosmeticUser user : CosmeticUsers.values()) user.showCosmetics(CosmeticUser.HiddenReason.DISABLED);
if (!silent) MessagesUtil.sendMessage(sender, "enabled-all");
} else {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-args");
}
return true;
}
case "hiddenreasons" -> {
if (!sender.hasPermission("hmccosmetics.cmd.hiddenreasons")) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length >= 2) {
player = Bukkit.getPlayer(args[1]);
}
if (player == null) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
sender.sendMessage(user.getHiddenReasons().toString());
return true;
}
case "clearhiddenreasons" -> {
if (!sender.hasPermission("hmccosmetics.cmd.clearhiddenreasons")) {
if (!silent) MessagesUtil.sendMessage(sender, "no-permission");
return true;
}
if (args.length >= 2) {
player = Bukkit.getPlayer(args[1]);
}
if (player == null) {
if (!silent) MessagesUtil.sendMessage(sender, "invalid-player");
return true;
}
CosmeticUser user = CosmeticUsers.getUser(player);
user.clearHiddenReasons();
return true;
}
} }
return true; return true;
} }

View File

@@ -46,12 +46,16 @@ public class CosmeticCommandTabComplete implements TabCompleter {
if (hasPermission(sender, "hmccosmetics.cmd.debug")) completions.add("debug"); if (hasPermission(sender, "hmccosmetics.cmd.debug")) completions.add("debug");
if (hasPermission(sender, "hmccosmetics.cmd.emote")) completions.add("emote"); if (hasPermission(sender, "hmccosmetics.cmd.emote")) completions.add("emote");
if (hasPermission(sender, "hmccosmetics.cmd.playemote")) completions.add("playemote"); if (hasPermission(sender, "hmccosmetics.cmd.playemote")) completions.add("playemote");
if (hasPermission(sender, "hmccosmetics.cmd.disableall")) completions.add("disableall");
if (hasPermission(sender, "hmccosmetics.cmd.hiddenreasons")) completions.add("hiddenreasons");
if (hasPermission(sender, "hmccosmetics.cmd.clearhiddenreasons")) completions.add("clearhiddenreasons");
StringUtil.copyPartialMatches(args[0], completions, finalCompletions); StringUtil.copyPartialMatches(args[0], completions, finalCompletions);
} }
if (!(sender instanceof Player)) return completions; if (!(sender instanceof Player)) return completions;
CosmeticUser user = CosmeticUsers.getUser(((Player) sender).getUniqueId()); CosmeticUser user = CosmeticUsers.getUser(((Player) sender).getUniqueId());
if (user == null) return completions; // User hasn't loaded in yet, can't do proper checks
if (args.length == 2) { if (args.length == 2) {
String subcommand = args[0].toLowerCase(); String subcommand = args[0].toLowerCase();
@@ -70,11 +74,15 @@ public class CosmeticCommandTabComplete implements TabCompleter {
if (menu.canOpen(user.getPlayer())) completions.add(menu.getId()); if (menu.canOpen(user.getPlayer())) completions.add(menu.getId());
} }
} }
case "dataclear", "hide", "show", "emote" -> { case "dataclear", "hide", "show", "emote", "hiddenreasons", "clearhiddenreasons" -> {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
completions.add(player.getName()); completions.add(player.getName());
} }
} }
case "disableall" -> {
completions.add("true");
completions.add("false");
}
case "wardrobe" -> { case "wardrobe" -> {
for (Wardrobe wardrobe : WardrobeSettings.getWardrobes()) { for (Wardrobe wardrobe : WardrobeSettings.getWardrobes()) {
if (wardrobe.hasPermission()) { if (wardrobe.hasPermission()) {

View File

@@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.config;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@@ -53,6 +54,7 @@ public class Settings {
private static final String COSMETIC_ADD_ENCHANTS_LEGGINGS_PATH = "leggings-add-enchantments"; private static final String COSMETIC_ADD_ENCHANTS_LEGGINGS_PATH = "leggings-add-enchantments";
private static final String COSMETIC_ADD_ENCHANTS_BOOTS_PATH = "boots-add-enchantments"; private static final String COSMETIC_ADD_ENCHANTS_BOOTS_PATH = "boots-add-enchantments";
private static final String COSMETIC_DESTROY_LOOSE_COSMETIC_PATH = "destroy-loose-cosmetics"; private static final String COSMETIC_DESTROY_LOOSE_COSMETIC_PATH = "destroy-loose-cosmetics";
private static final String COSMETIC_BALLOON_HEAD_FORWARD_PATH = "balloon-head-forward";
private static final String MENU_SETTINGS_PATH = "menu-settings"; private static final String MENU_SETTINGS_PATH = "menu-settings";
private static final String COSMETIC_TYPE_SETTINGS_PATH = "cosmetic-type"; private static final String COSMETIC_TYPE_SETTINGS_PATH = "cosmetic-type";
private static final String EQUIP_CLICK_TYPE = "equip-click"; private static final String EQUIP_CLICK_TYPE = "equip-click";
@@ -117,6 +119,8 @@ public class Settings {
@Getter @Getter
private static boolean disabledGamemodesEnabled; private static boolean disabledGamemodesEnabled;
@Getter @Getter
private static boolean balloonHeadForward;
@Getter
private static List<String> disabledGamemodes; private static List<String> disabledGamemodes;
@Getter @Getter
private static List<String> disabledWorlds; private static List<String> disabledWorlds;
@@ -156,6 +160,8 @@ public class Settings {
private static boolean emoteCameraEnabled; private static boolean emoteCameraEnabled;
@Getter @Getter
private static boolean emoteMoveCheck; private static boolean emoteMoveCheck;
@Getter @Setter
private static boolean allPlayersHidden;
public static void load(ConfigurationNode source) { public static void load(ConfigurationNode source) {
@@ -206,6 +212,7 @@ public class Settings {
emoteMoveCheck = cosmeticSettings.node(COSMETIC_EMOTE_MOVE_CHECK_PATH).getBoolean(false); emoteMoveCheck = cosmeticSettings.node(COSMETIC_EMOTE_MOVE_CHECK_PATH).getBoolean(false);
packetEntityTeleportCooldown = cosmeticSettings.node(COSMETIC_PACKET_ENTITY_TELEPORT_COOLDOWN_PATH).getInt(-1); packetEntityTeleportCooldown = cosmeticSettings.node(COSMETIC_PACKET_ENTITY_TELEPORT_COOLDOWN_PATH).getInt(-1);
cosmeticForceOffhandCosmeticShow = cosmeticSettings.node(COSMETIC_FORCE_OFFHAND_COSMETIC_SHOW_PATH).getBoolean(false); cosmeticForceOffhandCosmeticShow = cosmeticSettings.node(COSMETIC_FORCE_OFFHAND_COSMETIC_SHOW_PATH).getBoolean(false);
balloonHeadForward = cosmeticSettings.node(COSMETIC_BALLOON_HEAD_FORWARD_PATH).getBoolean(false);
ConfigurationNode menuSettings = source.node(MENU_SETTINGS_PATH); ConfigurationNode menuSettings = source.node(MENU_SETTINGS_PATH);

View File

@@ -33,6 +33,8 @@ public class WardrobeSettings {
private static final String EQUIP_PUMPKIN_WARDROBE = "equip-pumpkin"; private static final String EQUIP_PUMPKIN_WARDROBE = "equip-pumpkin";
private static final String TRY_COSMETICS_WARDROBE = "unchecked-wardrobe-cosmetics"; private static final String TRY_COSMETICS_WARDROBE = "unchecked-wardrobe-cosmetics";
private static final String RETURN_LAST_LOCATION = "return-last-location"; private static final String RETURN_LAST_LOCATION = "return-last-location";
private static final String DAMAGE_KICK_PATH = "damage-kicked";
private static final String PREVENT_DAMAGE_PATH = "prevent-damage";
private static final String WARDROBE_MENU_OPTIONS = "menu-options"; private static final String WARDROBE_MENU_OPTIONS = "menu-options";
private static final String WARDROBE_ENTER_OPEN_MENU_PATH = "enter-open-menu"; private static final String WARDROBE_ENTER_OPEN_MENU_PATH = "enter-open-menu";
@@ -87,6 +89,10 @@ public class WardrobeSettings {
@Getter @Getter
private static boolean forceExitGamemode; private static boolean forceExitGamemode;
@Getter @Getter
private static boolean damagedKicked;
@Getter
private static boolean preventDamage;
@Getter
private static GameMode exitGamemode; private static GameMode exitGamemode;
private static HashMap<String, Wardrobe> wardrobes; private static HashMap<String, Wardrobe> wardrobes;
@Getter @Getter
@@ -121,6 +127,8 @@ public class WardrobeSettings {
equipPumpkin = source.node(EQUIP_PUMPKIN_WARDROBE).getBoolean(); equipPumpkin = source.node(EQUIP_PUMPKIN_WARDROBE).getBoolean();
returnLastLocation = source.node(RETURN_LAST_LOCATION).getBoolean(false); returnLastLocation = source.node(RETURN_LAST_LOCATION).getBoolean(false);
tryCosmeticsInWardrobe = source.node(TRY_COSMETICS_WARDROBE).getBoolean(false); tryCosmeticsInWardrobe = source.node(TRY_COSMETICS_WARDROBE).getBoolean(false);
damagedKicked = source.node(DAMAGE_KICK_PATH).getBoolean(false);
preventDamage = source.node(PREVENT_DAMAGE_PATH).getBoolean(true);
ConfigurationNode menuOptionsNode = source.node(WARDROBE_MENU_OPTIONS); ConfigurationNode menuOptionsNode = source.node(WARDROBE_MENU_OPTIONS);
enterOpenMenu = menuOptionsNode.node(WARDROBE_ENTER_OPEN_MENU_PATH).getBoolean(false); enterOpenMenu = menuOptionsNode.node(WARDROBE_ENTER_OPEN_MENU_PATH).getBoolean(false);

View File

@@ -74,7 +74,7 @@ public class CosmeticBackpackType extends Cosmetic {
} }
} }
HMCCPacketManager.sendRidingPacket(particleCloud.get(particleCloud.size() - 1), user.getUserBackpackManager().getFirstArmorStandId(), owner); HMCCPacketManager.sendRidingPacket(particleCloud.get(particleCloud.size() - 1), user.getUserBackpackManager().getFirstArmorStandId(), owner);
if (!user.getHidden()) { if (!user.isHidden()) {
//if (loc.getPitch() < -70) NMSHandlers.getHandler().equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, new ItemStack(Material.AIR), owner); //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); //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(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(this, firstPersonBackpack), owner);

View File

@@ -68,6 +68,7 @@ public class CosmeticBalloonType extends Cosmetic {
Location newLocation = entity.getLocation(); Location newLocation = entity.getLocation();
Location currentLocation = user.getBalloonManager().getLocation(); Location currentLocation = user.getBalloonManager().getLocation();
newLocation = newLocation.clone().add(getBalloonOffset()); newLocation = newLocation.clone().add(getBalloonOffset());
if (Settings.isBalloonHeadForward()) newLocation.setPitch(0);
List<Player> viewer = HMCCPacketManager.getViewers(entity.getLocation()); List<Player> viewer = HMCCPacketManager.getViewers(entity.getLocation());
@@ -83,11 +84,11 @@ public class CosmeticBalloonType extends Cosmetic {
HMCCPacketManager.sendTeleportPacket(userBalloonManager.getPufferfishBalloonId(), newLocation, false, viewer); HMCCPacketManager.sendTeleportPacket(userBalloonManager.getPufferfishBalloonId(), newLocation, false, viewer);
HMCCPacketManager.sendLeashPacket(userBalloonManager.getPufferfishBalloonId(), entity.getEntityId(), viewer); HMCCPacketManager.sendLeashPacket(userBalloonManager.getPufferfishBalloonId(), entity.getEntityId(), viewer);
if (user.getHidden()) { if (user.isHidden()) {
userBalloonManager.getPufferfish().hidePufferfish(); userBalloonManager.getPufferfish().hidePufferfish();
return; return;
} }
if (!user.getHidden() && showLead) { if (!user.isHidden() && showLead) {
List<Player> sendTo = userBalloonManager.getPufferfish().refreshViewers(newLocation); List<Player> sendTo = userBalloonManager.getPufferfish().refreshViewers(newLocation);
if (sendTo.isEmpty()) return; if (sendTo.isEmpty()) return;
user.getBalloonManager().getPufferfish().spawnPufferfish(newLocation, sendTo); user.getBalloonManager().getPufferfish().spawnPufferfish(newLocation, sendTo);

View File

@@ -13,9 +13,7 @@ import org.bukkit.Color;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.UUID;
public abstract class Data { public abstract class Data {
@@ -32,9 +30,9 @@ public abstract class Data {
@NotNull @NotNull
public final String serializeData(@NotNull CosmeticUser user) { public final String serializeData(@NotNull CosmeticUser user) {
StringBuilder data = new StringBuilder(); StringBuilder data = new StringBuilder();
if (user.getHidden()) { if (user.isHidden()) {
if (shouldHiddenSave(user.getHiddenReason())) { for (CosmeticUser.HiddenReason reason : user.getHiddenReasons()) {
data.append("HIDDEN=").append(user.getHiddenReason()); if (shouldHiddenSave(reason)) data.append("HIDDEN=").append(reason);
} }
} }
for (Cosmetic cosmetic : user.getCosmetics()) { for (Cosmetic cosmetic : user.getCosmetics()) {
@@ -59,6 +57,7 @@ public abstract class Data {
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = new HashMap<>(); Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = new HashMap<>();
String[] rawData = raw.split(","); String[] rawData = raw.split(",");
ArrayList<CosmeticUser.HiddenReason> hiddenReason = new ArrayList<>();
for (String a : rawData) { for (String a : rawData) {
if (a == null || a.isEmpty()) continue; if (a == null || a.isEmpty()) continue;
String[] splitData = a.split("="); String[] splitData = a.split("=");
@@ -68,9 +67,7 @@ public abstract class Data {
if (splitData[0].equalsIgnoreCase("HIDDEN")) { if (splitData[0].equalsIgnoreCase("HIDDEN")) {
if (EnumUtils.isValidEnum(CosmeticUser.HiddenReason.class, splitData[1])) { if (EnumUtils.isValidEnum(CosmeticUser.HiddenReason.class, splitData[1])) {
if (Settings.isForceShowOnJoin()) continue; if (Settings.isForceShowOnJoin()) continue;
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> { hiddenReason.add(CosmeticUser.HiddenReason.valueOf(splitData[1]));
user.hideCosmetics(CosmeticUser.HiddenReason.valueOf(splitData[1]));
});
} }
continue; continue;
} }
@@ -98,12 +95,46 @@ public abstract class Data {
cosmetics.put(slot, cosmeticColorHashMap); cosmetics.put(slot, cosmeticColorHashMap);
} }
} }
MessagesUtil.sendDebugMessages("Hidden Reason: " + hiddenReason);
// if else this, if else that, if else I got to deal with this anymore i'll lose my mind
if (!hiddenReason.isEmpty()) {
for (CosmeticUser.HiddenReason reason : hiddenReason) user.silentlyAddHideFlag(reason);
} else {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
// Handle gamemode check
if (user.getPlayer() != null && Settings.getDisabledGamemodes().contains(user.getPlayer().getGameMode().toString())) {
MessagesUtil.sendDebugMessages("Hiding Cosmetics due to gamemode");
user.hideCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
return;
} else {
if (user.isHidden(CosmeticUser.HiddenReason.GAMEMODE)) {
MessagesUtil.sendDebugMessages("Join Gamemode Check: Showing Cosmetics");
user.showCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
return;
}
}
// Handle world check
if (Settings.getDisabledWorlds().contains(user.getPlayer().getWorld().getName())) {
MessagesUtil.sendDebugMessages("Hiding Cosmetics due to world");
user.hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else {
if (user.isHidden(CosmeticUser.HiddenReason.WORLD)) {
MessagesUtil.sendDebugMessages("Join World Check: Showing Cosmetics");
user.showCosmetics(CosmeticUser.HiddenReason.WORLD);
}
}
if (Settings.isAllPlayersHidden()) {
user.hideCosmetics(CosmeticUser.HiddenReason.DISABLED);
}
});
}
return cosmetics; return cosmetics;
} }
private boolean shouldHiddenSave(CosmeticUser.HiddenReason reason) { private boolean shouldHiddenSave(CosmeticUser.HiddenReason reason) {
switch (reason) { switch (reason) {
case EMOTE, NONE, GAMEMODE, WORLD -> { case EMOTE, NONE, GAMEMODE, WORLD, DISABLED -> {
return false; return false;
} }
default -> { default -> {

View File

@@ -59,12 +59,17 @@ public class MySQLData extends SQLData {
@Override @Override
public void clear(UUID uniqueId) { public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null;
try { try {
PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;"); preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, uniqueId.toString()); preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}); });
} }

View File

@@ -10,6 +10,7 @@ import org.bukkit.Color;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@@ -20,24 +21,35 @@ public abstract class SQLData extends Data {
CosmeticUser user = new CosmeticUser(uniqueId); CosmeticUser user = new CosmeticUser(uniqueId);
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedStatement = null;
try { try {
PreparedStatement preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;"); preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;");
preparedStatement.setString(1, uniqueId.toString()); preparedStatement.setString(1, uniqueId.toString());
ResultSet rs = preparedStatement.executeQuery(); ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) { if (rs.next()) {
String rawData = rs.getString("COSMETICS"); String rawData = rs.getString("COSMETICS");
Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = deserializeData(user, rawData); Map<CosmeticSlot, Map<Cosmetic, Color>> cosmetics = deserializeData(user, rawData);
// Load cosmetics, put them into the addedCosmetic hashmap
HashMap<Cosmetic, Color> addedCosmetics = new HashMap<>();
for (Map<Cosmetic, Color> cosmeticColors : cosmetics.values()) { for (Map<Cosmetic, Color> cosmeticColors : cosmetics.values()) {
for (Cosmetic cosmetic : cosmeticColors.keySet()) { for (Cosmetic cosmetic : cosmeticColors.keySet()) {
addedCosmetics.put(cosmetic, cosmeticColors.get(cosmetic));
}
}
// Run a task on the main thread, adding the cosmetics to the player
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
// This can not be async. // This can not be async.
user.addPlayerCosmetic(cosmetic, cosmeticColors.get(cosmetic)); for (Cosmetic cosmetic : addedCosmetics.keySet()) {
user.addPlayerCosmetic(cosmetic, addedCosmetics.get(cosmetic));
}
}); });
} }
}
}
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedStatement != null) preparedStatement.close();
} catch (SQLException e) {}
} }
}); });
@@ -48,13 +60,18 @@ public abstract class SQLData extends Data {
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void save(CosmeticUser user) { public void save(CosmeticUser user) {
Runnable run = () -> { Runnable run = () -> {
PreparedStatement preparedSt = null;
try { try {
PreparedStatement preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);"); preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);");
preparedSt.setString(1, user.getUniqueId().toString()); preparedSt.setString(1, user.getUniqueId().toString());
preparedSt.setString(2, serializeData(user)); preparedSt.setString(2, serializeData(user));
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}; };
if (!HMCCosmeticsPlugin.getInstance().isDisabled()) { if (!HMCCosmeticsPlugin.getInstance().isDisabled()) {

View File

@@ -48,12 +48,17 @@ public class SQLiteData extends SQLData {
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void clear(UUID uniqueId) { public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null;
try { try {
PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;"); preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, uniqueId.toString()); preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}); });
} }

View File

@@ -12,7 +12,7 @@ public class ActionCosmeticHide extends Action {
@Override @Override
public void run(@NotNull CosmeticUser user, String raw) { public void run(@NotNull CosmeticUser user, String raw) {
if (user.getHidden()) return; if (user.isHidden()) return;
user.hideCosmetics(CosmeticUser.HiddenReason.ACTION); user.hideCosmetics(CosmeticUser.HiddenReason.ACTION);
} }
} }

View File

@@ -12,10 +12,10 @@ public class ActionCosmeticShow extends Action {
@Override @Override
public void run(@NotNull CosmeticUser user, String raw) { public void run(@NotNull CosmeticUser user, String raw) {
if (!user.getHidden()) return; if (!user.isHidden()) return;
// Do not hide if it's already off for WG // Do not hide if it's already off for WG
if (user.getHiddenReason() != CosmeticUser.HiddenReason.ACTION && user.getHiddenReason() != CosmeticUser.HiddenReason.COMMAND) return; if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return;
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.ACTION);
} }
} }

View File

@@ -12,9 +12,9 @@ public class ActionCosmeticToggle extends Action {
@Override @Override
public void run(@NotNull CosmeticUser user, String raw) { public void run(@NotNull CosmeticUser user, String raw) {
if (user.getHidden()) { if (user.isHidden()) {
if (user.getHiddenReason() != CosmeticUser.HiddenReason.ACTION && user.getHiddenReason() != CosmeticUser.HiddenReason.COMMAND) return; if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return;
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.ACTION);
return; return;
} }

View File

@@ -8,6 +8,7 @@ import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.hibiscuscommons.hooks.Hooks; import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.util.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.Material; import org.bukkit.Material;
@@ -32,7 +33,7 @@ public class DyeMenu {
if (originalItem == null || !cosmetic.isDyable()) return; if (originalItem == null || !cosmetic.isDyable()) return;
Gui gui = HMCColorApi.createColorMenu(player); Gui gui = HMCColorApi.createColorMenu(player);
gui.updateTitle(Hooks.processPlaceholders(player, Settings.getDyeMenuName())); gui.updateTitle(Hooks.processPlaceholders(player, StringUtils.parseStringToString(Settings.getDyeMenuName())));
gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem)); gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem));
gui.setDefaultTopClickAction(event -> { gui.setDefaultTopClickAction(event -> {
if (event.getSlot() == Settings.getDyeMenuOutputSlot()) { if (event.getSlot() == Settings.getDyeMenuOutputSlot()) {

View File

@@ -30,15 +30,15 @@ public class WGListener implements Listener {
if (user == null) return; if (user == null) return;
Location location = event.getPlayer().getLocation(); Location location = event.getPlayer().getLocation();
ApplicableRegionSet set = getRegions(location); ApplicableRegionSet set = getRegions(location);
if (user.getHidden()) { if (user.isHidden()) {
if (user.getHiddenReason() == CosmeticUser.HiddenReason.WORLDGUARD && set.getRegions().isEmpty()) { if (set.getRegions().isEmpty()) {
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
} }
} }
for (ProtectedRegion protectedRegion : set.getRegions()) { for (ProtectedRegion protectedRegion : set.getRegions()) {
if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticEnableFlag())) { if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticEnableFlag())) {
if (protectedRegion.getFlags().get(WGHook.getCosmeticEnableFlag()).toString().equalsIgnoreCase("ALLOW")) { if (protectedRegion.getFlags().get(WGHook.getCosmeticEnableFlag()).toString().equalsIgnoreCase("ALLOW")) {
if (user.getHiddenReason() == CosmeticUser.HiddenReason.WORLDGUARD) user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
return; return;
} }
user.hideCosmetics(CosmeticUser.HiddenReason.WORLDGUARD); user.hideCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
@@ -58,15 +58,15 @@ public class WGListener implements Listener {
if (user == null) return; if (user == null) return;
Location location = event.getTo(); Location location = event.getTo();
ApplicableRegionSet set = getRegions(location); ApplicableRegionSet set = getRegions(location);
if (user.getHidden()) { if (user.isHidden()) {
if (user.getHiddenReason() == CosmeticUser.HiddenReason.WORLDGUARD && set.getRegions().isEmpty()) { if (set.getRegions().isEmpty()) {
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
} }
} }
for (ProtectedRegion protectedRegion : set.getRegions()) { for (ProtectedRegion protectedRegion : set.getRegions()) {
if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticEnableFlag())) { if (protectedRegion.getFlags().containsKey(WGHook.getCosmeticEnableFlag())) {
if (protectedRegion.getFlags().get(WGHook.getCosmeticEnableFlag()).toString().equalsIgnoreCase("ALLOW")) { if (protectedRegion.getFlags().get(WGHook.getCosmeticEnableFlag()).toString().equalsIgnoreCase("ALLOW")) {
if (user.getHiddenReason() == CosmeticUser.HiddenReason.WORLDGUARD) user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);
return; return;
} }
user.hideCosmetics(CosmeticUser.HiddenReason.WORLDGUARD); user.hideCosmetics(CosmeticUser.HiddenReason.WORLDGUARD);

View File

@@ -38,22 +38,6 @@ public class PlayerConnectionListener implements Listener {
CosmeticUsers.addUser(user); CosmeticUsers.addUser(user);
MessagesUtil.sendDebugMessages("Run User Join"); MessagesUtil.sendDebugMessages("Run User Join");
// Handle gamemode check
if (Settings.getDisabledGamemodes().contains(user.getPlayer().getGameMode().toString())) {
user.hideCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
} else {
if (user.getHiddenReason() != null && user.getHiddenReason().equals(CosmeticUser.HiddenReason.GAMEMODE)) {
user.showCosmetics();
}
}
// Handle world check
if (Settings.getDisabledWorlds().contains(user.getPlayer().getWorld().getName())) {
user.hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else {
if (user.getHiddenReason() != null && user.getHiddenReason().equals(CosmeticUser.HiddenReason.WORLD)) {
user.showCosmetics();
}
}
// And finally, launch an update for the cosmetics they have. // And finally, launch an update for the cosmetics they have.
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
if (user.getPlayer() == null) return; if (user.getPlayer() == null) return;

View File

@@ -11,6 +11,7 @@ import com.comphenix.protocol.wrappers.Pair;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.api.events.PlayerCosmeticPostEquipEvent; import com.hibiscusmc.hmccosmetics.api.events.PlayerCosmeticPostEquipEvent;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.config.WardrobeSettings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
@@ -115,7 +116,7 @@ public class PlayerGameListener implements Listener {
user.leaveWardrobe(); user.leaveWardrobe();
} }
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) { public void onPlayerTeleport(PlayerTeleportEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId()); CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
@@ -134,9 +135,7 @@ public class PlayerGameListener implements Listener {
if (Settings.getDisabledWorlds().contains(user.getEntity().getLocation().getWorld().getName())) { if (Settings.getDisabledWorlds().contains(user.getEntity().getLocation().getWorld().getName())) {
user.hideCosmetics(CosmeticUser.HiddenReason.WORLD); user.hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else { } else {
if (user.getHiddenReason() != null && user.getHiddenReason().equals(CosmeticUser.HiddenReason.WORLD)) { user.showCosmetics(CosmeticUser.HiddenReason.WORLD);
user.showCosmetics();
}
} }
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK) && user.getUserBackpackManager() != null) { if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK) && user.getUserBackpackManager() != null) {
user.respawnBackpack(); user.respawnBackpack();
@@ -145,7 +144,7 @@ public class PlayerGameListener implements Listener {
user.respawnBalloon(); user.respawnBalloon();
} }
user.updateCosmetic(); user.updateCosmetic();
}, 1); }, 2);
if (event.getCause().equals(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) || event.getCause().equals(PlayerTeleportEvent.TeleportCause.END_PORTAL)) return; if (event.getCause().equals(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) || event.getCause().equals(PlayerTeleportEvent.TeleportCause.END_PORTAL)) return;
if (user.getUserEmoteManager().isPlayingEmote()) { if (user.getUserEmoteManager().isPlayingEmote()) {
@@ -153,7 +152,7 @@ public class PlayerGameListener implements Listener {
} }
} }
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPortalTeleport(PlayerPortalEvent event) { public void onPortalTeleport(PlayerPortalEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId()); CosmeticUser user = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
@@ -163,6 +162,12 @@ public class PlayerGameListener implements Listener {
return; return;
} }
if (Settings.getDisabledWorlds().contains(user.getEntity().getLocation().getWorld().getName())) {
user.hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else {
user.showCosmetics(CosmeticUser.HiddenReason.WORLD);
}
if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) { if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
user.despawnBalloon(); user.despawnBalloon();
@@ -195,7 +200,11 @@ public class PlayerGameListener implements Listener {
} }
} }
if (user.isInWardrobe()) { if (user.isInWardrobe()) {
user.leaveWardrobe(); if (WardrobeSettings.isPreventDamage()) {
event.setCancelled(true);
return;
}
if (WardrobeSettings.isDamagedKicked()) user.leaveWardrobe();
} }
} }
@@ -306,7 +315,7 @@ public class PlayerGameListener implements Listener {
return; return;
} }
if (event.getAction().equals(EntityPotionEffectEvent.Action.CLEARED) || event.getAction().equals(EntityPotionEffectEvent.Action.REMOVED)) { if (event.getAction().equals(EntityPotionEffectEvent.Action.CLEARED) || event.getAction().equals(EntityPotionEffectEvent.Action.REMOVED)) {
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.POTION);
return; return;
} }
} }
@@ -353,9 +362,7 @@ public class PlayerGameListener implements Listener {
if (Settings.getDisabledGamemodes().contains(event.getNewGameMode().toString())) { if (Settings.getDisabledGamemodes().contains(event.getNewGameMode().toString())) {
user.hideCosmetics(CosmeticUser.HiddenReason.GAMEMODE); user.hideCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
} else { } else {
if (user.getHiddenReason() != null && user.getHiddenReason().equals(CosmeticUser.HiddenReason.GAMEMODE)) { user.showCosmetics(CosmeticUser.HiddenReason.GAMEMODE);
user.showCosmetics();
}
} }
} }
@@ -414,8 +421,8 @@ public class PlayerGameListener implements Listener {
public void onPlayerUnVanish(HibiscusPlayerUnVanishEvent event) { public void onPlayerUnVanish(HibiscusPlayerUnVanishEvent event) {
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer()); CosmeticUser user = CosmeticUsers.getUser(event.getPlayer());
if (user == null) return; if (user == null) return;
if (!user.getHidden()) return; if (!user.isHidden()) return;
if (user.getHiddenReason().equals(CosmeticUser.HiddenReason.PLUGIN)) user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.PLUGIN);
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@@ -54,9 +54,7 @@ public class CosmeticUser {
private final UserEmoteManager userEmoteManager; private final UserEmoteManager userEmoteManager;
// Cosmetic Settings/Toggles // Cosmetic Settings/Toggles
private boolean hideCosmetics; private final ArrayList<HiddenReason> hiddenReason = new ArrayList<>();
@Getter
private HiddenReason hiddenReason;
private final HashMap<CosmeticSlot, Color> colors = new HashMap<>(); private final HashMap<CosmeticSlot, Color> colors = new HashMap<>();
public CosmeticUser(UUID uuid) { public CosmeticUser(UUID uuid) {
@@ -70,7 +68,7 @@ public class CosmeticUser {
Runnable run = () -> { Runnable run = () -> {
MessagesUtil.sendDebugMessages("Tick[uuid=" + uniqueId + "]", Level.INFO); MessagesUtil.sendDebugMessages("Tick[uuid=" + uniqueId + "]", Level.INFO);
updateCosmetic(); updateCosmetic();
if (getHidden() && !getUserEmoteManager().isPlayingEmote()) MessagesUtil.sendActionBar(getPlayer(), "hidden-cosmetics"); if (isHidden() && !getUserEmoteManager().isPlayingEmote()) MessagesUtil.sendActionBar(getPlayer(), "hidden-cosmetics");
}; };
int tickPeriod = Settings.getTickPeriod(); int tickPeriod = Settings.getTickPeriod();
@@ -114,6 +112,7 @@ public class CosmeticUser {
playerCosmetics.put(cosmetic.getSlot(), cosmetic); playerCosmetics.put(cosmetic.getSlot(), cosmetic);
if (color != null) colors.put(cosmetic.getSlot(), color); if (color != null) colors.put(cosmetic.getSlot(), color);
MessagesUtil.sendDebugMessages("addPlayerCosmetic[id=" + cosmetic.getId() + "]"); MessagesUtil.sendDebugMessages("addPlayerCosmetic[id=" + cosmetic.getId() + "]");
if (!isHidden()) {
if (cosmetic.getSlot() == CosmeticSlot.BACKPACK) { if (cosmetic.getSlot() == CosmeticSlot.BACKPACK) {
CosmeticBackpackType backpackType = (CosmeticBackpackType) cosmetic; CosmeticBackpackType backpackType = (CosmeticBackpackType) cosmetic;
spawnBackpack(backpackType); spawnBackpack(backpackType);
@@ -123,6 +122,7 @@ public class CosmeticUser {
CosmeticBalloonType balloonType = (CosmeticBalloonType) cosmetic; CosmeticBalloonType balloonType = (CosmeticBalloonType) cosmetic;
spawnBalloon(balloonType); spawnBalloon(balloonType);
} }
}
// API // API
PlayerCosmeticPostEquipEvent postEquipEvent = new PlayerCosmeticPostEquipEvent(this, cosmetic); PlayerCosmeticPostEquipEvent postEquipEvent = new PlayerCosmeticPostEquipEvent(this, cosmetic);
Bukkit.getPluginManager().callEvent(postEquipEvent); Bukkit.getPluginManager().callEvent(postEquipEvent);
@@ -216,7 +216,7 @@ public class CosmeticUser {
public ItemStack getUserCosmeticItem(Cosmetic cosmetic) { public ItemStack getUserCosmeticItem(Cosmetic cosmetic) {
ItemStack item = null; ItemStack item = null;
if (hideCosmetics) { if (!hiddenReason.isEmpty()) {
if (cosmetic instanceof CosmeticBackpackType || cosmetic instanceof CosmeticBalloonType) return new ItemStack(Material.AIR); if (cosmetic instanceof CosmeticBackpackType || cosmetic instanceof CosmeticBalloonType) return new ItemStack(Material.AIR);
return getPlayer().getInventory().getItem(HMCCInventoryUtils.getEquipmentSlot(cosmetic.getSlot())); return getPlayer().getInventory().getItem(HMCCInventoryUtils.getEquipmentSlot(cosmetic.getSlot()));
} }
@@ -419,7 +419,7 @@ public class CosmeticUser {
if (!hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return; if (!hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return;
final Cosmetic cosmetic = getCosmetic(CosmeticSlot.BACKPACK); final Cosmetic cosmetic = getCosmetic(CosmeticSlot.BACKPACK);
despawnBackpack(); despawnBackpack();
if (hideCosmetics) return; if (!hiddenReason.isEmpty()) return;
spawnBackpack((CosmeticBackpackType) cosmetic); spawnBackpack((CosmeticBackpackType) cosmetic);
MessagesUtil.sendDebugMessages("Respawned Backpack for " + getEntity().getName()); MessagesUtil.sendDebugMessages("Respawned Backpack for " + getEntity().getName());
} }
@@ -428,7 +428,7 @@ public class CosmeticUser {
if (!hasCosmeticInSlot(CosmeticSlot.BALLOON)) return; if (!hasCosmeticInSlot(CosmeticSlot.BALLOON)) return;
final Cosmetic cosmetic = getCosmetic(CosmeticSlot.BALLOON); final Cosmetic cosmetic = getCosmetic(CosmeticSlot.BALLOON);
despawnBalloon(); despawnBalloon();
if (hideCosmetics) return; if (!hiddenReason.isEmpty()) return;
spawnBalloon((CosmeticBalloonType) cosmetic); spawnBalloon((CosmeticBalloonType) cosmetic);
MessagesUtil.sendDebugMessages("Respawned Balloon for " + getEntity().getName()); MessagesUtil.sendDebugMessages("Respawned Balloon for " + getEntity().getName());
} }
@@ -506,15 +506,13 @@ public class CosmeticUser {
} }
public void hideCosmetics(HiddenReason reason) { public void hideCosmetics(HiddenReason reason) {
if (hideCosmetics) return;
PlayerCosmeticHideEvent event = new PlayerCosmeticHideEvent(this, reason); PlayerCosmeticHideEvent event = new PlayerCosmeticHideEvent(this, reason);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
} }
hideCosmetics = true; if (!hiddenReason.contains(reason)) hiddenReason.add(reason);
hiddenReason = reason;
if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) { if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
despawnBalloon(); despawnBalloon();
//getBalloonManager().removePlayerFromModel(getPlayer()); //getBalloonManager().removePlayerFromModel(getPlayer());
@@ -527,8 +525,16 @@ public class CosmeticUser {
MessagesUtil.sendDebugMessages("HideCosmetics"); MessagesUtil.sendDebugMessages("HideCosmetics");
} }
public void showCosmetics() { /**
if (!hideCosmetics) return; * This is used to silently add a hidden flag to the user. This will not trigger any events or checks, nor do anything else
* @param reason
*/
public void silentlyAddHideFlag(HiddenReason reason) {
if (!hiddenReason.contains(reason)) hiddenReason.add(reason);
}
public void showCosmetics(HiddenReason reason) {
if (hiddenReason.isEmpty()) return;
PlayerCosmeticShowEvent event = new PlayerCosmeticShowEvent(this); PlayerCosmeticShowEvent event = new PlayerCosmeticShowEvent(this);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
@@ -536,8 +542,8 @@ public class CosmeticUser {
return; return;
} }
hideCosmetics = false; hiddenReason.remove(reason);
hiddenReason = HiddenReason.NONE; if (isHidden()) return;
if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) { if (hasCosmeticInSlot(CosmeticSlot.BALLOON)) {
if (!isBalloonSpawned()) respawnBalloon(); if (!isBalloonSpawned()) respawnBalloon();
CosmeticBalloonType balloonType = (CosmeticBalloonType) getCosmetic(CosmeticSlot.BALLOON); CosmeticBalloonType balloonType = (CosmeticBalloonType) getCosmetic(CosmeticSlot.BALLOON);
@@ -555,8 +561,30 @@ public class CosmeticUser {
MessagesUtil.sendDebugMessages("ShowCosmetics"); MessagesUtil.sendDebugMessages("ShowCosmetics");
} }
/**
* This method is deprecated and will be removed in the future. Use {@link #isHidden()} instead.
* @return
*/
@Deprecated(since = "2.7.2-DEV", forRemoval = true)
public boolean getHidden() { public boolean getHidden() {
return this.hideCosmetics; return !hiddenReason.isEmpty();
}
public boolean isHidden() {
return !hiddenReason.isEmpty();
}
public boolean isHidden(HiddenReason reason) {
return hiddenReason.contains(reason);
}
public List<HiddenReason> getHiddenReasons() {
return hiddenReason;
}
public void clearHiddenReasons() {
hiddenReason.clear();
} }
public enum HiddenReason { public enum HiddenReason {
@@ -568,6 +596,7 @@ public class CosmeticUser {
COMMAND, COMMAND,
EMOTE, EMOTE,
GAMEMODE, GAMEMODE,
WORLD WORLD,
DISABLED
} }
} }

View File

@@ -4,6 +4,7 @@ import com.google.common.collect.HashBiMap;
import com.hibiscusmc.hmccosmetics.util.HMCCServerUtils; import com.hibiscusmc.hmccosmetics.util.HMCCServerUtils;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Set; import java.util.Set;
@@ -11,31 +12,58 @@ import java.util.UUID;
public class CosmeticUsers { public class CosmeticUsers {
private static HashBiMap<UUID, CosmeticUser> COSMETIC_USERS = HashBiMap.create(); private static final HashBiMap<UUID, CosmeticUser> COSMETIC_USERS = HashBiMap.create();
public static void addUser(CosmeticUser user) { /**
* Adds a user to the Hashmap of stored CosmeticUsers. This will not override an entry if it already exists. If you need to override, delete then add.
* @param user The user to add to the HashMap.
*/
public static void addUser(@NotNull CosmeticUser user) {
if (COSMETIC_USERS.containsKey(user.getUniqueId())) return; // do not add if already exists if (COSMETIC_USERS.containsKey(user.getUniqueId())) return; // do not add if already exists
COSMETIC_USERS.put(user.getUniqueId(), user); COSMETIC_USERS.put(user.getUniqueId(), user);
} }
/**
* Removes a CosmeticUser from the Hashmap
* @param uuid The UUID to remove.
*/
public static void removeUser(UUID uuid) { public static void removeUser(UUID uuid) {
COSMETIC_USERS.remove(uuid); COSMETIC_USERS.remove(uuid);
} }
public static void removeUser(CosmeticUser user) { /**
COSMETIC_USERS.remove(user); * Removes a CosmeticUser from the hashmap by their CosmeticUser method
* @param user The user to be removed (will get their UUID from this class)
*/
public static void removeUser(@NotNull CosmeticUser user) {
COSMETIC_USERS.remove(user.getUniqueId());
} }
/**
* This method allows you to get a CosmeticUser from their UUID. If you are using not internally, HIGHLY recommend to use the API implementation of this.
* @param uuid The UUID of the user that you wish to lookup.
* @return Returns the user if there is a valid user, returns null if not.
*/
@Nullable @Nullable
public static CosmeticUser getUser(UUID uuid) { public static CosmeticUser getUser(UUID uuid) {
return COSMETIC_USERS.get(uuid); return COSMETIC_USERS.get(uuid);
} }
/**
* This method allows you to get a CosmeticUser from just using the player class. This just allows you to have a bit less boilerplate.
* @param player The player to lookup (will take their UUID from the class)
* @return Returns the user if there is a vlaid user, returns null if not.
*/
@Nullable @Nullable
public static CosmeticUser getUser(Player player) { public static CosmeticUser getUser(@NotNull Player player) {
return COSMETIC_USERS.get(player.getUniqueId()); return COSMETIC_USERS.get(player.getUniqueId());
} }
/**
* This method gets the CosmeticUser from an entity id (said entity must be a player). This is not ideal, as it requires the plugin to go through all entities, but it's a possibility.
* @param entityId The entity ID in an integer.
* @return The cosmetic user if there is an entity id associated with that.
*/
@Nullable @Nullable
public static CosmeticUser getUser(int entityId) { public static CosmeticUser getUser(int entityId) {
Entity entity = HMCCServerUtils.getEntity(entityId); Entity entity = HMCCServerUtils.getEntity(entityId);
@@ -44,6 +72,11 @@ public class CosmeticUsers {
return COSMETIC_USERS.get(player.getUniqueId()); return COSMETIC_USERS.get(player.getUniqueId());
} }
/**
* Gets all the values for CosmeticUsers to allow you to iterate over everyone.
* @return CosmeticUsers in a set. This will never be null, but might be empty.
*/
@NotNull
public static Set<CosmeticUser> values() { public static Set<CosmeticUser> values() {
return COSMETIC_USERS.values(); return COSMETIC_USERS.values();
} }

View File

@@ -39,7 +39,7 @@ public class UserBackpackManager {
this.backpackHidden = false; this.backpackHidden = false;
this.invisibleArmorStand = ServerUtils.getNextEntityId(); this.invisibleArmorStand = ServerUtils.getNextEntityId();
this.entityManager = new UserEntity(user.getUniqueId()); this.entityManager = new UserEntity(user.getUniqueId());
this.entityManager.refreshViewers(user.getEntity().getLocation()); if (user.getEntity() != null) this.entityManager.refreshViewers(user.getEntity().getLocation()); // Fixes an issue where a player, who somehow removes their potions, but doesn't have an entity produces an NPE (it's dumb)
} }
public int getFirstArmorStandId() { public int getFirstArmorStandId() {
@@ -85,7 +85,7 @@ public class UserBackpackManager {
else HMCCPacketManager.sendRidingPacket(particleCloud.get(i - 1), particleCloud.get(i) , owner); else 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), user.getUserBackpackManager().getFirstArmorStandId(), owner);
if (!user.getHidden()) PacketManager.equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(cosmeticBackpackType, cosmeticBackpackType.getFirstPersonBackpack()), owner); if (!user.isHidden()) PacketManager.equipmentSlotUpdate(user.getUserBackpackManager().getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(cosmeticBackpackType, cosmeticBackpackType.getFirstPersonBackpack()), owner);
} }
PacketManager.equipmentSlotUpdate(getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(cosmeticBackpackType), outsideViewers); PacketManager.equipmentSlotUpdate(getFirstArmorStandId(), EquipmentSlot.HEAD, user.getUserCosmeticItem(cosmeticBackpackType), outsideViewers);
HMCCPacketManager.sendRidingPacket(entity.getEntityId(), passengerIDs, outsideViewers); HMCCPacketManager.sendRidingPacket(entity.getEntityId(), passengerIDs, outsideViewers);
@@ -118,7 +118,7 @@ public class UserBackpackManager {
} }
public void hideBackpack() { public void hideBackpack() {
if (user.getHidden()) return; if (user.isHidden()) return;
//getArmorStand().getEquipment().clear(); //getArmorStand().getEquipment().clear();
backpackHidden = true; backpackHidden = true;
} }

View File

@@ -205,7 +205,7 @@ public class UserBalloonManager {
CosmeticUser viewer = CosmeticUsers.getUser(player.getUniqueId()); CosmeticUser viewer = CosmeticUsers.getUser(player.getUniqueId());
if (user.getPlayer() == player) { if (user.getPlayer() == player) {
return (!user.getHidden()); return (!user.isHidden());
} else { } else {
if (user.isInWardrobe()) return false; if (user.isInWardrobe()) return false;
MessagesUtil.sendDebugMessages("playerCheck - Not Same Player"); MessagesUtil.sendDebugMessages("playerCheck - Not Same Player");
@@ -214,6 +214,6 @@ public class UserBalloonManager {
return false; return false;
} }
} }
return (!user.getHidden()); return (!user.isHidden());
} }
} }

View File

@@ -124,7 +124,7 @@ public class UserEmoteModel extends PlayerModel {
if (user.getPlayer() != null) player.setInvisible(false); if (user.getPlayer() != null) player.setInvisible(false);
user.getUserEmoteManager().despawnTextEntity(); user.getUserEmoteManager().despawnTextEntity();
user.showPlayer(); user.showPlayer();
user.showCosmetics(); user.showCosmetics(CosmeticUser.HiddenReason.EMOTE);
}); });
} }

View File

@@ -31,10 +31,7 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class UserWardrobeManager { public class UserWardrobeManager {
@@ -94,6 +91,7 @@ public class UserWardrobeManager {
} }
user.hidePlayer(); user.hidePlayer();
if (!Bukkit.getServer().getAllowFlight()) player.setAllowFlight(true);
List<Player> viewer = Collections.singletonList(player); List<Player> viewer = Collections.singletonList(player);
List<Player> outsideViewers = HMCCPacketManager.getViewers(viewingLocation); List<Player> outsideViewers = HMCCPacketManager.getViewers(viewingLocation);
outsideViewers.remove(player); outsideViewers.remove(player);
@@ -202,7 +200,9 @@ public class UserWardrobeManager {
List<Player> outsideViewers = HMCCPacketManager.getViewers(viewingLocation); List<Player> outsideViewers = HMCCPacketManager.getViewers(viewingLocation);
outsideViewers.remove(player); outsideViewers.remove(player);
if (player != null) MessagesUtil.sendMessage(player, "closed-wardrobe"); if (player == null) return;
if (!Bukkit.getServer().getAllowFlight()) player.setAllowFlight(false);
MessagesUtil.sendMessage(player, "closed-wardrobe");
Runnable run = () -> { Runnable run = () -> {
this.active = false; this.active = false;
@@ -252,9 +252,17 @@ public class UserWardrobeManager {
player.teleport(Objects.requireNonNullElseGet(exitLocation, () -> player.getWorld().getSpawnLocation()), PlayerTeleportEvent.TeleportCause.PLUGIN); player.teleport(Objects.requireNonNullElseGet(exitLocation, () -> player.getWorld().getSpawnLocation()), PlayerTeleportEvent.TeleportCause.PLUGIN);
if (WardrobeSettings.isEquipPumpkin()) { HashMap<EquipmentSlot, ItemStack> items = new HashMap<>();
PacketManager.equipmentSlotUpdate(user.getPlayer().getEntityId(), EquipmentSlot.HEAD, player.getInventory().getHelmet(), viewer); for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack item = player.getInventory().getItem(slot);
items.put(slot, item);
} }
/*
if (WardrobeSettings.isEquipPumpkin()) {
items.put(EquipmentSlot.HEAD, player.getInventory().getHelmet());
}
*/
HMCCPacketManager.equipmentSlotUpdate(player.getEntityId(), items, viewer);
if (WardrobeSettings.isEnabledBossbar()) { if (WardrobeSettings.isEnabledBossbar()) {
Audience target = BukkitAudiences.create(HMCCosmeticsPlugin.getInstance()).player(player); Audience target = BukkitAudiences.create(HMCCosmeticsPlugin.getInstance()).player(player);

View File

@@ -106,12 +106,13 @@ public class HMCCPacketManager extends PacketManager {
WrappedDataWatcher wrapper = new WrappedDataWatcher(); WrappedDataWatcher wrapper = new WrappedDataWatcher();
if (HMCCosmeticsAPI.getNMSVersion().contains("v1_18_R2") || HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R1")) { if (HMCCosmeticsAPI.getNMSVersion().contains("v1_18_R2") || HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R1")) {
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20); wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x21);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10); wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects()); packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
} else { } else {
final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList(); final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
wrappedDataValueList.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x20)); // 0x21 = Invisible + Fire (Aka, burns to make it not take the light of the block its in, avoiding turning it black)
wrappedDataValueList.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x21));
wrappedDataValueList.add(new WrappedDataValue(15, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x10)); wrappedDataValueList.add(new WrappedDataValue(15, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x10));
packet.getDataValueCollectionModifier().write(0, wrappedDataValueList); packet.getDataValueCollectionModifier().write(0, wrappedDataValueList);
} }

View File

@@ -67,6 +67,9 @@ cosmetic-settings:
# setting this to lower than the server player view distance should fix the # setting this to lower than the server player view distance should fix the
# bug where players see random backpacks. Put -1 to ignore and send packets to everyone. # bug where players see random backpacks. Put -1 to ignore and send packets to everyone.
view-distance: 32 view-distance: 32
# If the plugin should set the pitch of balloons to always be 0, to prevent players looking up affecting the balloon.
# This only applies to models that have a "head" section to them. THIS DOES NOT IMPACT THE REST OF THE ENTITY.
balloon-head-unmoving: false
# how the balloon should be positioned relative to the player # how the balloon should be positioned relative to the player
balloon-offset: balloon-offset:
x: 0.5 x: 0.5
@@ -92,11 +95,11 @@ menu-settings:
equip-click: "ANY" # ANY or ClickType, https://jd.papermc.io/paper/1.20/org/bukkit/event/inventory/ClickType.html equip-click: "ANY" # ANY or ClickType, https://jd.papermc.io/paper/1.20/org/bukkit/event/inventory/ClickType.html
unequip-click: "ANY" # ANY or ClickType, https://jd.papermc.io/paper/1.20/org/bukkit/event/inventory/ClickType.html unequip-click: "ANY" # ANY or ClickType, https://jd.papermc.io/paper/1.20/org/bukkit/event/inventory/ClickType.html
dye-menu: dye-menu:
# If you use ItemsAdder, set this to "§f:offset_-8::dye_menu:" # If you use ItemsAdder, set this to "<white>:img_offset_-8::img_dye_menu:"
# If you use Oraxen, set this to "<glyph:neg_shift_8><glyph:dye_menu>" # If you use Oraxen, set this to "<white><s:-8><g:dye_menu>"
title: "§f" title: "<white>"
input-slot: 19 input-slot: 10
output-slot: 25 output-slot: 16
hook-settings: hook-settings:
itemsadder: itemsadder:
# This causes the plugin to reload itself after any ItemsAdder change. This keeps the plugin fully up to date with IA, but # This causes the plugin to reload itself after any ItemsAdder change. This keeps the plugin fully up to date with IA, but
@@ -115,6 +118,10 @@ wardrobe:
return-last-location: false return-last-location: false
# If players in wardrobes should be able to equip any cosmetic, regardless of permission (Cosmetics they do not have access to will be removed when they leave the wardrobe) # If players in wardrobes should be able to equip any cosmetic, regardless of permission (Cosmetics they do not have access to will be removed when they leave the wardrobe)
unchecked-wardrobe-cosmetics: false unchecked-wardrobe-cosmetics: false
# If HMCC should prevent a player from being damaged while being in the wardrobe
prevent-damage: true
# If a player is damaged in a wardrobe, and if it's set to true, it'll kick them from the wardrobe (prevent-damage must be false)
damage-kicked: false
menu-options: menu-options:
enter-open-menu: false # If the menu should open when a player enters a wardrobe enter-open-menu: false # If the menu should open when a player enters a wardrobe

View File

@@ -134,33 +134,34 @@ items:
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_kite%" - "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_kite%"
type: cosmetic type: cosmetic
cosmetic: kite cosmetic: kite
handstand: # EMOTES DO NOT WORK IN RECENT HMCCOSMETICS VERSIONS.
slots: # handstand:
- 12 # slots:
item: # - 12
material: PAPER # item:
name: "<blue>Handstand Emote" # material: PAPER
type: cosmetic # name: "<blue>Handstand Emote"
cosmetic: handstand # type: cosmetic
meditate: # cosmetic: handstand
slots: # meditate:
- 13 # slots:
item: # - 13
material: PAPER # item:
name: "<blue>Meditate Emote" # material: PAPER
type: cosmetic # name: "<blue>Meditate Emote"
cosmetic: meditate # type: cosmetic
thinking: # cosmetic: meditate
slots: # thinking:
- 14 # slots:
item: # - 14
material: PAPER # item:
name: "<blue>Thinking Emote" # material: PAPER
type: cosmetic # name: "<blue>Thinking Emote"
cosmetic: thinking # type: cosmetic
# cosmetic: thinking
explorer_backpack: explorer_backpack:
slots: slots:
- 15 - 12
item: item:
material: hmccosmetics:explorer_backpack material: hmccosmetics:explorer_backpack
lore: lore:
@@ -171,7 +172,7 @@ items:
cosmetic: explorer_backpack cosmetic: explorer_backpack
garbage_truck_balloon: garbage_truck_balloon:
slots: slots:
- 16 - 13
item: item:
material: hmccosmetics:garbage_truck_balloon material: hmccosmetics:garbage_truck_balloon
lore: lore:
@@ -182,7 +183,7 @@ items:
cosmetic: garbage_truck_balloon cosmetic: garbage_truck_balloon
earth_day_grabber: earth_day_grabber:
slots: slots:
- 17 - 14
item: item:
material: hmccosmetics:earth_day_grabber material: hmccosmetics:earth_day_grabber
lore: lore:
@@ -193,7 +194,7 @@ items:
cosmetic: earth_day_grabber cosmetic: earth_day_grabber
hibiscus_flower: hibiscus_flower:
slots: slots:
- 18 - 15
item: item:
material: hmccosmetics:hibiscus_flower material: hmccosmetics:hibiscus_flower
lore: lore: