diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java index 8b05df77..830d3030 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java @@ -5,6 +5,7 @@ import com.comphenix.protocol.ProtocolManager; import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand; import io.github.fisher2911.hmccosmetics.concurrent.Threads; +import io.github.fisher2911.hmccosmetics.config.Settings; import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager; import io.github.fisher2911.hmccosmetics.database.Database; import io.github.fisher2911.hmccosmetics.database.DatabaseFactory; @@ -15,6 +16,7 @@ import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook; import io.github.fisher2911.hmccosmetics.listener.*; import io.github.fisher2911.hmccosmetics.message.MessageHandler; import io.github.fisher2911.hmccosmetics.message.Messages; +import io.github.fisher2911.hmccosmetics.message.Translation; import io.github.fisher2911.hmccosmetics.user.UserManager; import me.mattstudios.mf.base.CommandManager; import org.bstats.bukkit.Metrics; @@ -28,11 +30,13 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; public class HMCCosmetics extends JavaPlugin { private ProtocolManager protocolManager; + private Settings settings; private UserManager userManager; private CosmeticManager cosmeticManager; private MessageHandler messageHandler; @@ -48,6 +52,7 @@ public class HMCCosmetics extends JavaPlugin { final Metrics metrics = new Metrics(this, pluginId); protocolManager = ProtocolLibrary.getProtocolManager(); + this.settings = new Settings(this); this.messageHandler = new MessageHandler(this); this.userManager = new UserManager(this); this.cosmeticManager = new CosmeticManager(new HashMap<>()); @@ -130,12 +135,28 @@ public class HMCCosmetics extends JavaPlugin { public void load() { Bukkit.getScheduler().runTaskAsynchronously(this, () -> { + this.settings.load(); this.messageHandler.load(); this.cosmeticsMenu.load(); + Translation.getInstance().load(); this.database.load(); }); } + public void reload() { + Bukkit.getScheduler().runTaskAsynchronously(this, + () -> { + this.settings.load(); + this.messageHandler.load(); + this.cosmeticsMenu.reload(); + Translation.getInstance().load(); + }); + } + + public Settings getSettings() { + return settings; + } + public MessageHandler getMessageHandler() { return messageHandler; } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java b/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java index f0ad1aa3..d119c0b3 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java @@ -51,8 +51,7 @@ public class CosmeticsCommand extends CommandBase { Bukkit.getScheduler().runTaskAsynchronously( this.plugin, () -> { - this.cosmeticsMenu.reload(); - this.plugin.getMessageHandler().load(); + this.plugin.reload(); this.messageHandler.sendMessage( sender, Messages.RELOADED diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/config/CosmeticSettings.java b/src/main/java/io/github/fisher2911/hmccosmetics/config/CosmeticSettings.java new file mode 100644 index 00000000..c76741d9 --- /dev/null +++ b/src/main/java/io/github/fisher2911/hmccosmetics/config/CosmeticSettings.java @@ -0,0 +1,47 @@ +package io.github.fisher2911.hmccosmetics.config; + +import io.github.fisher2911.hmccosmetics.HMCCosmetics; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.inventory.EquipmentSlot; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.meta.Setting; + +@ConfigSerializable +public class CosmeticSettings { + + private static final transient String COSMETIC_SETTINGS_PATH = "cosmetic-settings"; + private static final transient String REQUIRE_EMPTY_HELMET_PATH = "require-empty-helmet"; + private static final transient String REQUIRE_EMPTY_OFF_HAND_PATH = "require-empty-off-hand"; + + private boolean requireEmptyHelmet; + private boolean requireEmptyOffHand; + + public void load(final FileConfiguration config) { + this.requireEmptyHelmet = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_HELMET_PATH); + this.requireEmptyOffHand = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_OFF_HAND_PATH); + } + + public boolean isRequireEmptyHelmet() { + return requireEmptyHelmet; + } + + public boolean isRequireEmptyOffHand() { + return requireEmptyOffHand; + } + + public void setRequireEmptyHelmet(final boolean requireEmptyHelmet) { + this.requireEmptyHelmet = requireEmptyHelmet; + } + + public void setRequireEmptyOffHand(final boolean requireEmptyOffHand) { + this.requireEmptyOffHand = requireEmptyOffHand; + } + + public boolean requireEmpty(final EquipmentSlot slot) { + return switch (slot) { + case OFF_HAND -> this.isRequireEmptyOffHand(); + case HEAD -> this.isRequireEmptyHelmet(); + default -> false; + }; + } +} diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/config/Settings.java b/src/main/java/io/github/fisher2911/hmccosmetics/config/Settings.java new file mode 100644 index 00000000..c9bd25bd --- /dev/null +++ b/src/main/java/io/github/fisher2911/hmccosmetics/config/Settings.java @@ -0,0 +1,25 @@ +package io.github.fisher2911.hmccosmetics.config; + +import io.github.fisher2911.hmccosmetics.HMCCosmetics; +import org.bukkit.Bukkit; + +public class Settings { + + private final HMCCosmetics plugin; + private final CosmeticSettings settings; + + public Settings(final HMCCosmetics plugin) { + this.plugin = plugin; + this.settings = new CosmeticSettings(); + } + + public void load() { + this.plugin.saveDefaultConfig(); + this.plugin.reloadConfig(); + this.settings.load(this.plugin.getConfig()); + } + + public CosmeticSettings getCosmeticSettings() { + return settings; + } +} diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java index 87def14b..77827232 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java @@ -117,7 +117,7 @@ public class CosmeticGui { final User user = optionalUser.get(); this.gui = Gui.gui(). - title(Adventure.MINI_MESSAGE.parse(StringUtils.applyPapiPlaceholders(user.getPlayer(), this.title))). + title(Adventure.MINI_MESSAGE.parse(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title))). rows(this.rows). create(); diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java index faff70dc..bc8e3f94 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java @@ -50,6 +50,9 @@ public class CosmeticsMenu { } public void reload() { + for (final ArmorItem armorItem : this.cosmeticManager.getAll()) { + Bukkit.getPluginManager().removePermission(new Permission(armorItem.getPermission())); + } this.load(); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java b/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java index fba62f37..14855bc0 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java @@ -7,6 +7,7 @@ import dev.triumphteam.gui.guis.GuiItem; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import io.github.fisher2911.hmccosmetics.database.dao.ArmorItemDAO; import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; +import io.github.fisher2911.hmccosmetics.message.Placeholder; import io.github.fisher2911.hmccosmetics.user.User; import io.github.fisher2911.hmccosmetics.util.StringUtils; import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; @@ -45,7 +46,7 @@ public class DyeSelectorGui extends CosmeticGui { public Gui getGui(final User user, @Nullable final ArmorItem.Type type) { this.gui = Gui.gui(). - title(Component.text(StringUtils.applyPapiPlaceholders(user.getPlayer(), this.title))). + title(Component.text(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title))). rows(rows). create(); diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java index ee3c36ad..4288e84f 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java @@ -8,6 +8,8 @@ import io.github.fisher2911.hmccosmetics.user.UserManager; import io.th0rgal.oraxen.utils.armorequipevent.ArmorEquipEvent; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.CreatureSpawner; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/message/MessageHandler.java b/src/main/java/io/github/fisher2911/hmccosmetics/message/MessageHandler.java index a7a2742e..cc2ec890 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/message/MessageHandler.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/message/MessageHandler.java @@ -48,7 +48,7 @@ public class MessageHandler { public void sendMessage(final CommandSender sender, final Message key, final Map placeholders) { final String message = this.getPapiPlaceholders( sender, - StringUtils.applyPlaceholders(this.getMessage(key), placeholders) + Placeholder.applyPlaceholders(this.getMessage(key), placeholders) ); final Component component = Adventure.MINI_MESSAGE.parse(message); this.adventure.sender(sender).sendMessage(component); @@ -72,7 +72,7 @@ public class MessageHandler { public void sendActionBar(final Player player, final Message key, final Map placeholders) { final String message = this.getPapiPlaceholders( player, - StringUtils.applyPlaceholders(this.getMessage(key), placeholders) + Placeholder.applyPlaceholders(this.getMessage(key), placeholders) ); Component component = Adventure.MINI_MESSAGE.parse(message); this.adventure.player(player).sendActionBar(component); @@ -96,7 +96,7 @@ public class MessageHandler { public void sendTitle(final Player player, final Message key, final Map placeholders) { final String message = this.getPapiPlaceholders( player, - StringUtils.applyPlaceholders(this.getMessage(key), placeholders) + Placeholder.applyPlaceholders(this.getMessage(key), placeholders) ); Component component = Adventure.MINI_MESSAGE.parse(message); this.adventure.player(player).showTitle(Title.title(component, Component.empty())); @@ -158,9 +158,9 @@ public class MessageHandler { private String getPapiPlaceholders(final CommandSender sender, final String message) { if (sender instanceof final Player player) { - return StringUtils.applyPapiPlaceholders(player, message); + return Placeholder.applyPapiPlaceholders(player, message); } - return StringUtils.applyPapiPlaceholders(null, message); + return Placeholder.applyPapiPlaceholders(null, message); } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/message/Placeholder.java b/src/main/java/io/github/fisher2911/hmccosmetics/message/Placeholder.java index 0eb63af2..d331ab81 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/message/Placeholder.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/message/Placeholder.java @@ -1,5 +1,12 @@ package io.github.fisher2911.hmccosmetics.message; +import io.github.fisher2911.hmccosmetics.hook.HookManager; +import io.github.fisher2911.hmccosmetics.hook.PAPIHook; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + public class Placeholder { public static final String PREFIX = "%prefix%"; @@ -11,4 +18,24 @@ public class Placeholder { public static final String ENABLED = "%enabled%"; public static final String ALLOWED = "%allowed%"; + /** + * @param message message being translated + * @param placeholders placeholders applied + * @return message with placeholders applied + */ + + public static String applyPlaceholders(String message, final Map placeholders) { + for (final Map.Entry entry : placeholders.entrySet()) { + message = message.replace(entry.getKey(), Translation.translate(entry.getValue())); + } + return message; + } + + public static String applyPapiPlaceholders(@Nullable final Player player, final String message) { + if (HookManager.getInstance().isEnabled(PAPIHook.class)) { + return HookManager.getInstance().getPapiHook().parse(player, message); + } + + return message; + } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/message/Translation.java b/src/main/java/io/github/fisher2911/hmccosmetics/message/Translation.java new file mode 100644 index 00000000..53d2e25f --- /dev/null +++ b/src/main/java/io/github/fisher2911/hmccosmetics/message/Translation.java @@ -0,0 +1,56 @@ +package io.github.fisher2911.hmccosmetics.message; + +import io.github.fisher2911.hmccosmetics.HMCCosmetics; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class Translation { + + private static final Translation INSTANCE; + + static { + INSTANCE = new Translation(HMCCosmetics.getPlugin(HMCCosmetics.class)); + } + + public static Translation getInstance() { + return INSTANCE; + } + + private final HMCCosmetics plugin; + private final Map translations; + + public Translation(final HMCCosmetics plugin) { + this.translations = new HashMap<>(); + this.plugin = plugin; + } + + private static final String FILE_NAME = "translations.yml"; + private static final String TRANSLATION_PATH = "translations"; + + public void load() { + final File file = new File(this.plugin.getDataFolder(), FILE_NAME); + if (!file.exists()) { + this.plugin.saveResource(FILE_NAME, false); + } + + final FileConfiguration config = YamlConfiguration.loadConfiguration(file); + + final ConfigurationSection section = config.getConfigurationSection(TRANSLATION_PATH); + + if (section == null) return; + + for (final String key : section.getKeys(false)) { + this.translations.put(key, section.getString(key)); + } + } + + public static String translate(final String key) { + return INSTANCE.translations.getOrDefault(key, key); + } + +} diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java b/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java new file mode 100644 index 00000000..d9f027e1 --- /dev/null +++ b/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java @@ -0,0 +1,107 @@ +package io.github.fisher2911.hmccosmetics.packet; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.Pair; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.minecraft.network.protocol.Packet; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class PacketManager { + + private static final ProtocolManager protocolManager; + + static { + protocolManager = ProtocolLibrary.getProtocolManager(); + } + + public static PacketContainer getEntitySpawnPacket(final Location location, final int entityId, final EntityType entityType) { + final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + + final PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY); + + // Entity ID + packet.getIntegers().write(0, entityId); + // Entity Type +// packet.getIntegers().write(6, 78); + // Set yaw pitch + packet.getIntegers().write(4, (int) location.getPitch()); + packet.getIntegers().write(5, (int) location.getYaw()); + // Set location + packet.getDoubles().write(0, location.getX()); + packet.getDoubles().write(1, location.getY()); + packet.getDoubles().write(2, location.getZ()); + // Set UUID + packet.getUUIDs().write(0, UUID.randomUUID()); + + packet.getEntityTypeModifier().write(0, entityType); + + return packet; + } + + public static PacketContainer getEquipmentPacket( + final List> equipmentList, + final int entityId + ) { + + final PacketContainer armorPacket = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); + armorPacket.getIntegers().write(0, entityId); + armorPacket.getSlotStackPairLists().write(0, equipmentList); + + return armorPacket; + } + + public static PacketContainer getRotationPacket(final int entityId, final Location location) { + final PacketContainer rotationPacket = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION); + + rotationPacket.getIntegers().write(0, entityId); + rotationPacket.getBytes().write(0, (byte) (location.getYaw() * 256 / 360)); + + return rotationPacket; + } + + public static PacketContainer getRidingPacket(final int mountId, final int passengerId) { + final PacketContainer ridingPacket = new PacketContainer(PacketType.Play.Server.MOUNT); + ridingPacket. + getIntegers(). + write(0, mountId); + ridingPacket.getIntegerArrays().write(0, new int[]{passengerId}); + + return ridingPacket; + } + + public static PacketContainer getEntityDestroyPacket(final int entityId) { + final PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); + destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId})); + + return destroyPacket; + } + + public static void sendPacket(final Player to, final PacketContainer... packets) { + try { + for (final PacketContainer packet : packets) { + protocolManager.sendServerPacket(to, packet); + } + } catch (final InvocationTargetException exception) { + exception.printStackTrace(); + } + } + + public static void sendPacketToOnline(final PacketContainer... packets) { + for (final Player player : Bukkit.getOnlinePlayers()) { + sendPacket(player, packets); + } + } +} diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java index b7f2307b..ea63ef82 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java @@ -1,8 +1,6 @@ package io.github.fisher2911.hmccosmetics.user; import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.Pair; @@ -10,7 +8,7 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher; import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; import io.github.fisher2911.hmccosmetics.gui.ArmorItem; import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; -import it.unimi.dsi.fastutil.ints.IntArrayList; +import io.github.fisher2911.hmccosmetics.packet.PacketManager; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.EntityType; @@ -18,7 +16,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -76,8 +73,6 @@ public class User { return this.setItem(ArmorItem.empty(type)); } - // return true if backpack was set - public void spawnArmorStand(final Player other) { final Player player = this.getPlayer(); @@ -85,31 +80,9 @@ public class User { final Location location = player.getLocation(); - final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + final PacketContainer packet = PacketManager.getEntitySpawnPacket(location, this.armorStandId, EntityType.ARMOR_STAND); - final PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY); - - // Entity ID - packet.getIntegers().write(0, this.armorStandId); - // Entity Type -// packet.getIntegers().write(6, 78); - // Set yaw pitch - packet.getIntegers().write(4, (int) location.getPitch()); - packet.getIntegers().write(5, (int) location.getYaw()); - // Set location - packet.getDoubles().write(0, location.getX()); - packet.getDoubles().write(1, location.getY()); - packet.getDoubles().write(2, location.getZ()); - // Set UUID - packet.getUUIDs().write(0, UUID.randomUUID()); - - packet.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND); - - try { - protocolManager.sendServerPacket(other, packet); - } catch (final InvocationTargetException exception) { - exception.printStackTrace(); - } + PacketManager.sendPacket(player, packet); } public void spawnArmorStand() { @@ -136,17 +109,16 @@ public class User { if (player == null) return; final List> equipmentList = new ArrayList<>(); - equipmentList.add(new Pair<>(EnumWrappers.ItemSlot.HEAD, this.playerArmor.getBackpack().getColored() )); - final PacketContainer armorPacket = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); - armorPacket.getIntegers().write(0, this.armorStandId); - armorPacket.getSlotStackPairLists().write(0, equipmentList); - final Location location = player.getLocation(); + final PacketContainer armorPacket = PacketManager.getEquipmentPacket(equipmentList, this.armorStandId); + final PacketContainer rotationPacket = PacketManager.getRotationPacket(this.armorStandId, location); + final PacketContainer ridingPacket = PacketManager.getRidingPacket(player.getEntityId(), this.armorStandId); + final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); WrappedDataWatcher metaData = new WrappedDataWatcher(); @@ -156,48 +128,14 @@ public class User { metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20)); metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, byteSerializer), (byte) (0x10)); - final PacketContainer rotationPacket = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION); - - rotationPacket.getIntegers().write(0, this.armorStandId); - rotationPacket.getBytes().write(0, (byte) (location.getYaw() * 256 / 360)); - metaContainer.getIntegers().write(0, this.armorStandId); metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects()); - final PacketContainer ridingPacket = new PacketContainer(PacketType.Play.Server.MOUNT); - ridingPacket. - getIntegers(). - write(0, player.getEntityId()); - ridingPacket.getIntegerArrays().write(0, new int[]{this.armorStandId}); - - final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - - try { - for (final Player p : Bukkit.getOnlinePlayers()) { - protocolManager.sendServerPacket(p, armorPacket); - protocolManager.sendServerPacket(p, metaContainer); - protocolManager.sendServerPacket(p, rotationPacket); - protocolManager.sendServerPacket(p, ridingPacket); - } - } catch (final InvocationTargetException exception) { - exception.printStackTrace(); - } + PacketManager.sendPacketToOnline(armorPacket, metaContainer, rotationPacket, ridingPacket); } public void despawnAttached() { - final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - - final PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); - destroyPacket.getModifier().write(0, new IntArrayList(new int[]{this.armorStandId})); - - for (final Player p : Bukkit.getOnlinePlayers()) { - try { - protocolManager.sendServerPacket(p, destroyPacket); - this.hasArmorStand = false; - } catch (final InvocationTargetException exception) { - exception.printStackTrace(); - } - } + PacketManager.sendPacketToOnline(PacketManager.getEntityDestroyPacket(this.armorStandId)); } public boolean hasArmorStand() { diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java index 2bcd83b7..44553959 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java @@ -1,23 +1,18 @@ package io.github.fisher2911.hmccosmetics.user; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -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.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.Pair; import com.comphenix.protocol.wrappers.WrappedDataWatcher; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import io.github.fisher2911.hmccosmetics.concurrent.Threads; +import io.github.fisher2911.hmccosmetics.config.CosmeticSettings; +import io.github.fisher2911.hmccosmetics.config.Settings; import io.github.fisher2911.hmccosmetics.gui.ArmorItem; import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; import io.github.fisher2911.hmccosmetics.message.Message; import io.github.fisher2911.hmccosmetics.message.MessageHandler; import io.github.fisher2911.hmccosmetics.message.Placeholder; -import io.github.fisher2911.hmccosmetics.util.Keys; +import io.github.fisher2911.hmccosmetics.packet.PacketManager; import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -27,7 +22,6 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitTask; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -35,21 +29,23 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class UserManager { private final HMCCosmetics plugin; + private final Settings settings; private final MessageHandler messageHandler; - private final Map userMap = new HashMap<>(); + private final Map userMap = new ConcurrentHashMap<>(); private final Map armorStandIdMap = new HashMap<>(); private BukkitTask teleportTask; public UserManager(final HMCCosmetics plugin) { this.plugin = plugin; + this.settings = this.plugin.getSettings(); this.messageHandler = this.plugin.getMessageHandler(); - this.registerPacketListener(); } public void add(final User user) { @@ -89,7 +85,11 @@ public class UserManager { WrappedDataWatcher.Registry.get(Byte.class); this.teleportTask = Bukkit.getScheduler().runTaskTimerAsynchronously( this.plugin, - () -> this.userMap.values().forEach(User::updateArmorStand), + () -> { + for (final User user : this.userMap.values()) { + user.updateArmorStand(); + } + }, 1, 1 ); @@ -102,53 +102,6 @@ public class UserManager { } } - private void registerPacketListener() { - final ProtocolManager protocolManager = this.plugin.getProtocolManager(); - protocolManager.addPacketListener(new PacketAdapter( - this.plugin, - ListenerPriority.NORMAL, - PacketType.Play.Server.ENTITY_EQUIPMENT) { - @Override - public void onPacketReceiving(PacketEvent event) { - - } - - @Override - public void onPacketSending(final PacketEvent event) { - if (event.getPacketType() == PacketType.Play.Server.ENTITY_EQUIPMENT) { - final int id = event.getPacket().getIntegers().read(0); - - for (final var entry : event.getPacket().getSlotStackPairLists().getValues().get(0)) { - if (entry.getFirst() != EnumWrappers.ItemSlot.HEAD) { - continue; - } - for (final Player p : Bukkit.getOnlinePlayers()) { - if (p.getEntityId() != id) { - continue; - } - - final User user = userMap.get(p.getUniqueId()); - - if (user == null) { - break; - } - - final ItemStack hat = user.getPlayerArmor().getHat().getItemStack(); - final ItemStack second = entry.getSecond(); - - if (hat != null && hat - .getType() != Material.AIR && - second != null && - !Keys.hasKey(second)) { - event.setCancelled(true); - } - } - } - } - } - }); - } - public void updateCosmetics(final UUID uuid, final boolean ignoreRestrictions) { this.get(uuid).ifPresent(user -> this.updateCosmetics(user, ignoreRestrictions)); @@ -185,16 +138,13 @@ public class UserManager { new Pair<>(EnumWrappers.ItemSlot.OFFHAND, this.getCosmeticItem(player, playerArmor.getOffHand(), EquipmentSlot.OFF_HAND, ignoreRestrictions)) ); - final PacketContainer fake = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); - - fake.getIntegers().write(0, player.getEntityId()); - fake.getSlotStackPairLists().write(0, equipmentList); - - try { - this.plugin.getProtocolManager().sendServerPacket(other, fake); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } + PacketManager.sendPacket( + other, + PacketManager.getEquipmentPacket( + equipmentList, + player.getEntityId() + ) + ); } private ItemStack getCosmeticItem( @@ -202,6 +152,7 @@ public class UserManager { final ArmorItem armorItem, final EquipmentSlot slot, final boolean ignoreRestrictions) { + final CosmeticSettings cosmeticSettings = this.settings.getCosmeticSettings(); final EntityEquipment equipment = player.getEquipment(); final Map placeholders = Map.of(Placeholder.ALLOWED, "true", @@ -212,8 +163,11 @@ public class UserManager { lorePlaceholders(placeholders). build(); - if (itemStack.getType() != Material.AIR && - (slot != EquipmentSlot.OFF_HAND || ignoreRestrictions)) return itemStack; + final boolean isAir = itemStack.getType().isAir(); + final boolean requireEmpty = cosmeticSettings.requireEmpty(slot); + + if (!isAir && (!requireEmpty || ignoreRestrictions)) return itemStack; + if (equipment == null) return itemStack; diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/util/StringUtils.java b/src/main/java/io/github/fisher2911/hmccosmetics/util/StringUtils.java index 88c13ef8..4e33ea34 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/util/StringUtils.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/util/StringUtils.java @@ -19,27 +19,6 @@ public class StringUtils { plugin = HMCCosmetics.getPlugin(HMCCosmetics.class); } - /** - * @param message message being translated - * @param placeholders placeholders applied - * @return message with placeholders applied - */ - - public static String applyPlaceholders(String message, final Map placeholders) { - for (final Map.Entry entry : placeholders.entrySet()) { - message = message.replace(entry.getKey(), entry.getValue()); - } - return message; - } - - public static String applyPapiPlaceholders(@Nullable final Player player, final String message) { - if (HookManager.getInstance().isEnabled(PAPIHook.class)) { - return HookManager.getInstance().getPapiHook().parse(player, message); - } - - return message; - } - /** * @param parsed message to be parsed * @return MiniMessage parsed string diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/util/builder/ItemBuilder.java b/src/main/java/io/github/fisher2911/hmccosmetics/util/builder/ItemBuilder.java index 6d6dde7f..f0abbeec 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/util/builder/ItemBuilder.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/util/builder/ItemBuilder.java @@ -1,6 +1,7 @@ package io.github.fisher2911.hmccosmetics.util.builder; import io.github.fisher2911.hmccosmetics.message.Adventure; +import io.github.fisher2911.hmccosmetics.message.Placeholder; import io.github.fisher2911.hmccosmetics.util.StringUtils; import net.kyori.adventure.text.Component; import net.minecraft.network.PacketListener; @@ -101,7 +102,7 @@ public class ItemBuilder { return this; } - final String name = StringUtils. + final String name = Placeholder. applyPlaceholders(this.itemMeta.getDisplayName(), placeholders); this.itemMeta.setDisplayName(name); return this; @@ -140,7 +141,7 @@ public class ItemBuilder { } for (final String line : previousLore) { - lore.add(StringUtils.applyPlaceholders( + lore.add(Placeholder.applyPlaceholders( line, placeholders )); } @@ -164,7 +165,7 @@ public class ItemBuilder { if (lore == null) return; for (final String line : this.itemMeta.getLore()) { - newLore.add(StringUtils.applyPapiPlaceholders(player, line)); + newLore.add(Placeholder.applyPapiPlaceholders(player, line)); } this.itemMeta.setLore(newLore); @@ -174,7 +175,7 @@ public class ItemBuilder { if (this.itemMeta == null) return; this.itemMeta.setDisplayName( - StringUtils.applyPapiPlaceholders( + Placeholder.applyPapiPlaceholders( player, this.itemMeta.getDisplayName() ) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 00000000..ffa639b5 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,3 @@ +cosmetic-settings: + require-empty-helmet: false + require-empty-off-hand: true \ No newline at end of file diff --git a/src/main/resources/translations.yml b/src/main/resources/translations.yml new file mode 100644 index 00000000..3e6acef5 --- /dev/null +++ b/src/main/resources/translations.yml @@ -0,0 +1,3 @@ +translations: + true: "true" + false: "false" \ No newline at end of file