diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java index 59ffc421..8b05df77 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java @@ -19,6 +19,7 @@ import io.github.fisher2911.hmccosmetics.user.UserManager; import me.mattstudios.mf.base.CommandManager; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; +import org.bukkit.Color; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; @@ -71,14 +72,10 @@ public class HMCCosmetics extends JavaPlugin { this.saveTask = Bukkit.getScheduler().runTaskTimerAsynchronously( this, - () -> { - for (final Player player : Bukkit.getOnlinePlayers()) { - this.userManager.get(player.getUniqueId()).ifPresent( - this.database::saveUser - ); - } - }, - 20, + () -> Threads.getInstance().execute( + () -> this.database.saveAll() + ), + 20 * 60, 20 * 60 ); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/concurrent/Threads.java b/src/main/java/io/github/fisher2911/hmccosmetics/concurrent/Threads.java index 54cf18fa..07b8a8f4 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/concurrent/Threads.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/concurrent/Threads.java @@ -16,20 +16,13 @@ public class Threads { } private final ExecutorService service; - private boolean running; private Threads() { - this.service = Executors.newCachedThreadPool(); + this.service = Executors.newFixedThreadPool(1); } - public void submit(final Runnable runnable) { - this.service.submit(() -> { - try { - runnable.run(); - } catch (final Exception exception) { - exception.printStackTrace(); - } - }); + public void execute(final Runnable runnable) { + this.service.execute(runnable); } public void onDisable() { diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/cosmetic/CosmeticManager.java b/src/main/java/io/github/fisher2911/hmccosmetics/cosmetic/CosmeticManager.java index 399fe652..af2dfa52 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/cosmetic/CosmeticManager.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/cosmetic/CosmeticManager.java @@ -27,4 +27,8 @@ public class CosmeticManager { public Collection getAll() { return this.armorItemMap.values(); } + + public Map getArmorItemMap() { + return armorItemMap; + } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java index b6207b49..cf7bca21 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java @@ -1,14 +1,7 @@ package io.github.fisher2911.hmccosmetics.database; -import com.j256.ormlite.dao.BaseForeignCollection; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; -import com.j256.ormlite.dao.ForeignCollection; -import com.j256.ormlite.logger.ConsoleLogBackend; -import com.j256.ormlite.logger.Level; -import com.j256.ormlite.logger.Logger; -import com.j256.ormlite.stmt.UpdateBuilder; -import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; import io.github.fisher2911.hmccosmetics.HMCCosmetics; @@ -21,14 +14,10 @@ import io.github.fisher2911.hmccosmetics.user.User; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import java.sql.Connection; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; public class Database { @@ -66,12 +55,11 @@ public class Database { this.userDao = DaoManager.createDao(this.dataSource, UserDAO.class); this.armorItemDao = DaoManager.createDao(this.dataSource, ArmorItemDAO.class); this.databaseType = databaseType; - Logger.setGlobalLogLevel(Level.DEBUG); } public void load() { - Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> new DatabaseConverter(this.plugin, this).convert()); + Threads.getInstance().execute(() -> new DatabaseConverter(this.plugin, this).convert()); } protected void createTables() { @@ -85,7 +73,7 @@ public class Database { public void loadUser(final UUID uuid) { final int armorStandId = ARMOR_STAND_ID.getAndDecrement(); - Threads.getInstance().submit( + Threads.getInstance().execute( () -> { try { UserDAO user = this.userDao.queryForId(uuid); @@ -130,10 +118,8 @@ public class Database { } public void saveAll() { - for (final Player player : Bukkit.getOnlinePlayers()) { - this.plugin.getUserManager().get(player.getUniqueId()).ifPresent( - this::saveUser - ); + for (final User user : this.plugin.getUserManager().getAll()) { + this.saveUser(user); } } @@ -160,10 +146,4 @@ public class Database { public Dao getArmorItemDao() { return armorItemDao; } - - // public abstract void close(); -// -// public abstract String getSaveStatement(); -// -// public abstract String getLoadStatement(); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java index aa380154..a99b4db0 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java @@ -6,6 +6,7 @@ import io.github.fisher2911.hmccosmetics.gui.ArmorItem; import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; import io.github.fisher2911.hmccosmetics.user.User; import org.bukkit.Bukkit; +import org.bukkit.Color; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; @@ -15,8 +16,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; public class DatabaseConverter { @@ -40,15 +43,18 @@ public class DatabaseConverter { FILE_NAME ).toFile(); + final boolean fileExists = file.exists(); if (!file.exists()) { this.plugin.saveResource("database" + File.separator + FILE_NAME, true); } final YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - final int version = config.getInt("version"); + final int version = fileExists ? config.getInt("version") : 1; - this.convert(version, this.database::saveUser); + final Set users = new HashSet<>(); + + this.convert(version, users::add); try { config.set("version", CURRENT_VERSION); @@ -58,6 +64,8 @@ public class DatabaseConverter { } this.database.createTables(); + + for (final User user : users) database.saveUser(user); } private void convert(final int version, final Consumer consumer) { @@ -69,46 +77,44 @@ public class DatabaseConverter { private void convertVersionOne(final Consumer consumer) { final String query = "SELECT * from user"; - final CosmeticManager cosmeticManager = this.plugin.getCosmeticManager(); - try (final PreparedStatement statement = this.database.getDataSource().getReadOnlyConnection("user"). - getUnderlyingConnection().prepareStatement(query); - final PreparedStatement dropStatement = this.database.getDataSource().getReadWriteConnection("user"). - getUnderlyingConnection().prepareStatement("DROP TABLE user")) { + getUnderlyingConnection().prepareStatement(query)) { final ResultSet results = statement.executeQuery(); - Bukkit.getScheduler().runTask(this.plugin, () -> { + try { - }); - Bukkit.getScheduler().runTask(this.plugin, () -> { - try { - while (results.next()) { - final PlayerArmor playerArmor = PlayerArmor.empty(); - final User user = new User - (UUID.fromString(results.getString(1)), - playerArmor, - this.database.ARMOR_STAND_ID.getAndDecrement() - ); - final String backpackId = results.getString(2); - final String hatId = results.getString(3); - final int hatDye = results.getInt(4); + final Map armorItems = new ConcurrentHashMap<>(this.plugin.getCosmeticManager().getArmorItemMap()); - final ArmorItem backpack = cosmeticManager.getArmorItem(backpackId); - final ArmorItem hat = cosmeticManager.getArmorItem(hatId); - if (backpack != null) playerArmor.setItem(backpack); - if (hat != null) { - hat.setDye(hatDye); - playerArmor.setItem(hat); - } + while (results.next()) { + final PlayerArmor playerArmor = PlayerArmor.empty(); + final User user = new User + (UUID.fromString(results.getString(1)), + playerArmor, + this.database.ARMOR_STAND_ID.getAndDecrement() + ); + final String backpackId = results.getString(2); + final String hatId = results.getString(3); + final int hatDye = results.getInt(4); - consumer.accept(user); + final ArmorItem backpack = armorItems.get(backpackId); + final ArmorItem hat = armorItems.get(hatId); + if (backpack != null) playerArmor.setItem(backpack); + if (hat != null) { + hat.setDye(hatDye); + playerArmor.setItem(hat); } - } catch (final SQLException exception) { - exception.printStackTrace(); + + consumer.accept(user); } - }); + } catch (final SQLException exception) { + exception.printStackTrace(); + } + } catch (final SQLException exception) { + exception.printStackTrace(); + } + try (final PreparedStatement dropStatement = this.database.getDataSource().getReadWriteConnection("user"). + getUnderlyingConnection().prepareStatement("DROP TABLE user")) { dropStatement.executeUpdate(); - } catch (final SQLException exception) { exception.printStackTrace(); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java b/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java index 068e814b..ec1530cd 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java @@ -1,6 +1,5 @@ package io.github.fisher2911.hmccosmetics.gui; -import com.j256.ormlite.table.DatabaseTable; import dev.triumphteam.gui.components.GuiAction; import dev.triumphteam.gui.guis.GuiItem; import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder; @@ -8,7 +7,6 @@ import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,12 +15,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -@DatabaseTable(tableName = "armor_item") public class ArmorItem extends GuiItem { private final String id; private final List lockedLore; - private final GuiAction action; + private GuiAction action; private final String permission; private final Type type; private boolean dyeable; @@ -256,6 +253,12 @@ public class ArmorItem extends GuiItem { return this.getItemStack().getType() == Material.AIR; } + @Override + public void setAction(final GuiAction action) { + super.setAction(action); + this.action = action; + } + public enum Type { HAT, 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 ac062fec..7337fc10 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java @@ -12,7 +12,6 @@ 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; -import org.bukkit.Bukkit; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; @@ -136,35 +135,12 @@ public class CosmeticGui { if (guiItem instanceof final ArmorItem armorItem) { - final Map placeholders = new HashMap<>(); - - final PlayerArmor playerArmor = user.getPlayerArmor(); - - final ArmorItem.Type type = armorItem.getType(); - - final String id = playerArmor.getItem(type).getId(); - - placeholders.put( - Placeholder.ENABLED, - String.valueOf(id.equals(armorItem.getId())). - toLowerCase(Locale.ROOT)); - final String permission = armorItem.getPermission() == null ? "" : armorItem.getPermission(); final boolean hasPermission = permission.isBlank() || player.hasPermission(permission); - placeholders.put( - Placeholder.ALLOWED, - String.valueOf(hasPermission). - toLowerCase(Locale.ROOT)); - return new GuiItem( - ItemBuilder.from( - armorItem.getItemStack(hasPermission) - ).namePlaceholders(placeholders). - lorePlaceholders(placeholders). - papiPlaceholders(player). - build(), + this.applyPlaceholders(user, player, armorItem, hasPermission), event -> { if (!hasPermission) { this.messageHandler.sendMessage( @@ -174,11 +150,50 @@ public class CosmeticGui { return; } - this.setUserArmor(player, user, new ArmorItem(armorItem), event, armorItem.getAction()); + final ArmorItem cosmeticItem = this.plugin.getCosmeticManager().getArmorItem(armorItem.getId()); + + if (cosmeticItem == null) return; + + this.setUserArmor(player, user, cosmeticItem, event, armorItem.getAction()); } ); } return guiItem; } + + protected ItemStack applyPlaceholders(final User user, final Player player, final ArmorItem armorItem, final boolean hasPermission) { + final Map placeholders = new HashMap<>(); + + final PlayerArmor playerArmor = user.getPlayerArmor(); + + final ArmorItem.Type type = armorItem.getType(); + + final String id = playerArmor.getItem(type).getId(); + + placeholders.put( + Placeholder.ENABLED, + String.valueOf(id.equals(armorItem.getId())). + toLowerCase(Locale.ROOT)); + + placeholders.put( + Placeholder.ALLOWED, + String.valueOf(hasPermission). + toLowerCase(Locale.ROOT)); + + final ItemStack itemStack; + + if (!hasPermission) { + itemStack = armorItem.getItemStack(false); + } else { + itemStack = armorItem.getColored(); + } + + return ItemBuilder.from( + itemStack + ).namePlaceholders(placeholders). + lorePlaceholders(placeholders). + papiPlaceholders(player). + build(); + } } \ No newline at end of file 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 d7bc5a19..d44668fb 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java @@ -131,7 +131,9 @@ public class CosmeticsMenu { for (final GuiItem guiItem : gui.guiItemMap.values()) { if (guiItem instanceof final ArmorItem item) { - this.cosmeticManager.addArmorItem(item); + final ArmorItem copy = new ArmorItem(item); + copy.setAction(null); + this.cosmeticManager.addArmorItem(copy); } } 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 555aff0f..c11b5f81 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java @@ -10,6 +10,7 @@ import io.github.fisher2911.hmccosmetics.user.User; import io.github.fisher2911.hmccosmetics.util.StringUtils; import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import net.kyori.adventure.text.Component; +import org.bukkit.Material; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -54,7 +55,17 @@ public class DyeSelectorGui extends CosmeticGui { } for (final var entry : this.cosmeticsSlots.entrySet()) { - gui.setItem(entry.getKey(), user.getPlayerArmor().getItem(entry.getValue())); + gui.setItem( + entry.getKey(), + new GuiItem( + this.applyPlaceholders( + user, + player, + user.getPlayerArmor().getItem(entry.getValue()), + true + ) + ) + ); } for (final var entry : this.guiItemMap.entrySet()) { @@ -74,15 +85,15 @@ public class DyeSelectorGui extends CosmeticGui { final PlayerArmor playerArmor = user.getPlayerArmor(); - final ArmorItem armorItem = playerArmor.getItem( - this.cosmeticsSlots.get(this.selectedCosmetic) - ); - - this.select(this.selectedCosmetic); + this.select(this.selectedCosmetic, user, player); gui.setDefaultClickAction(event -> { event.setCancelled(true); + final ArmorItem armorItem = playerArmor.getItem( + this.cosmeticsSlots.get(this.selectedCosmetic) + ); + if (armorItem == null) { return; } @@ -93,16 +104,16 @@ public class DyeSelectorGui extends CosmeticGui { return; } - if (!armorItem.isDyeable()) { - return; - } - final int slot = event.getSlot(); final ArmorItem.Type clickedType = this.cosmeticsSlots.get(slot); if (clickedType != null) { - this.select(slot); + this.select(slot, user, player); + return; + } + + if (!armorItem.isDyeable()) { return; } @@ -115,30 +126,48 @@ public class DyeSelectorGui extends CosmeticGui { armorItem.setDye(colorItem.getColor().asRGB()); this.plugin.getUserManager().setItem(user, armorItem); + this.updateSelected(user, player); }); return gui; } - private void select(final int slot) { - ItemStack itemStack = this.itemStackMap.get(slot); - ItemStack previous = this.itemStackMap.get(this.selectedCosmetic); + private void select(final int slot, final User user, final Player player) { - if (itemStack == null) return; + final PlayerArmor playerArmor = user.getPlayerArmor(); - itemStack = - dev.triumphteam.gui.builder.item.ItemBuilder.from( - itemStack).glow().build(); + final ItemStack previous = this.applyPlaceholders( + user, + player, + playerArmor.getItem(this.cosmeticsSlots.get(this.selectedCosmetic)), + true + ); - if (previous != null && this.selectedCosmetic != slot) { - previous = dev.triumphteam.gui.builder.item.ItemBuilder.from( - previous).glow(false).build(); - this.gui.updateItem(this.selectedCosmetic, previous); + if (previous != null && previous.getType() != Material.AIR) { + final ItemStack previousItem = dev.triumphteam.gui.builder.item.ItemBuilder.from( + previous + ).glow(false).build(); + + this.gui.updateItem(this.selectedCosmetic, previousItem); } - this.gui.updateItem(slot, itemStack); - this.selectedCosmetic = slot; + + this.updateSelected(user, player); + } + + private void updateSelected(final User user, final Player player) { + final ArmorItem.Type type = this.cosmeticsSlots.get(this.selectedCosmetic); + + if (type == null) return; + + this.gui.updateItem(this.selectedCosmetic, + + ItemBuilder.from( + this.applyPlaceholders( + user, player, user.getPlayerArmor().getItem(type), true + ) + ).glow(true).build()); } @Override diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java b/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java index ea974fa7..4d590cf5 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java @@ -32,19 +32,24 @@ public class PlayerArmor { } public ArmorItem getHat() { - return this.armorItems.get(ArmorItem.Type.HAT); + return this.getItem(ArmorItem.Type.HAT); } public ArmorItem getBackpack() { - return this.armorItems.get(ArmorItem.Type.BACKPACK); + return this.getItem(ArmorItem.Type.BACKPACK); } public ArmorItem getOffHand() { - return this.armorItems.get(ArmorItem.Type.OFF_HAND); + return this.getItem(ArmorItem.Type.OFF_HAND); } public ArmorItem getItem(final ArmorItem.Type type) { - return this.armorItems.get(type); + ArmorItem armorItem = this.armorItems.get(type); + if (armorItem == null) { + armorItem = ArmorItem.empty(type); + this.armorItems.put(type, armorItem); + } + return armorItem; } public ArmorItem setItem(final ArmorItem armorItem) { 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 81edd4a9..293f6c3d 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java @@ -1,5 +1,6 @@ package io.github.fisher2911.hmccosmetics.listener; +import com.comphenix.protocol.wrappers.EnumWrappers; import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import io.github.fisher2911.hmccosmetics.user.User; @@ -65,18 +66,6 @@ public class ClickListener implements Listener { this.doRunnable(optionalUser.get()); } - @EventHandler - public void onRightClick(final PlayerInteractEvent event) { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - final Player player = event.getPlayer(); - - final ItemStack mainHand = event.getPlayer().getInventory().getItemInMainHand(); - - if (mainHand.getType().isBlock() && mainHand.getAmount() > 0) - - this.userManager.updateCosmetics(player.getUniqueId(), true); - } - private void fixInventory(final Player player, final Set slotsClicked, final Inventory inventory) { final Optional optionalUser = this.userManager.get(player.getUniqueId()); @@ -95,7 +84,7 @@ public class ClickListener implements Listener { } private void doRunnable(final User user) { - Bukkit.getScheduler().runTaskLater( + Bukkit.getScheduler().runTaskLaterAsynchronously( this.plugin, () -> this.userManager.updateCosmetics(user), 1); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/CosmeticFixListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/CosmeticFixListener.java index c9c2dcab..dccc5ad0 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/CosmeticFixListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/CosmeticFixListener.java @@ -8,9 +8,13 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.spigotmc.event.entity.EntityMountEvent; @@ -38,8 +42,29 @@ public class CosmeticFixListener implements Listener { this.fixCosmetics(event.getPlayer()); } + @EventHandler + public void onRightClick(final PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getHand() != EquipmentSlot.OFF_HAND) return; + final Player player = event.getPlayer(); + + final ItemStack mainHand = event.getPlayer().getInventory().getItemInMainHand(); + + if (mainHand.getType().isBlock() && mainHand.getAmount() > 0) return; + this.userManager.updateCosmetics(player.getUniqueId(), true); + } + + @EventHandler(ignoreCancelled = true) + public void onBlockPlace(final BlockPlaceEvent event) { + if (event.getHand() != EquipmentSlot.OFF_HAND) return; + final ItemStack itemStack = event.getItemInHand(); + + if (itemStack.getAmount() > 1) return; + + this.fixCosmetics(event.getPlayer()); + } + private void fixCosmetics(final Player player) { - Bukkit.getScheduler().runTaskLater(this.plugin, + Bukkit.getScheduler().runTaskLaterAsynchronously(this.plugin, () -> this.userManager.updateCosmetics(player.getUniqueId(), true), 2); } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java index 5d684926..402a3e0e 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java @@ -3,6 +3,7 @@ package io.github.fisher2911.hmccosmetics.listener; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import io.github.fisher2911.hmccosmetics.database.Database; import io.github.fisher2911.hmccosmetics.user.UserManager; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -26,12 +27,12 @@ public class JoinListener implements Listener { final Player player = event.getPlayer(); this.database.loadUser(player.getUniqueId()); - this.userManager.resendCosmetics(player); + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, + () -> this.userManager.resendCosmetics(player)); } @EventHandler public void onQuit(final PlayerQuitEvent event) { - final Player player = event.getPlayer(); this.userManager.remove(player.getUniqueId()); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/RespawnListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/RespawnListener.java index f093cee2..4e122aa2 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/RespawnListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/RespawnListener.java @@ -23,7 +23,7 @@ public class RespawnListener implements Listener { @EventHandler public void onPlayerRespawn(final PlayerRespawnEvent event) { - Bukkit.getScheduler().runTaskLater(this.plugin, () -> { + Bukkit.getScheduler().runTaskLaterAsynchronously(this.plugin, () -> { final Player player = event.getPlayer(); final Optional optionalUser = this.userManager.get(player.getUniqueId()); optionalUser.ifPresent(user -> { 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 d643557c..b7f2307b 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java @@ -7,10 +7,9 @@ import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.Pair; 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 io.github.fisher2911.hmccosmetics.message.Placeholder; -import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import it.unimi.dsi.fastutil.ints.IntArrayList; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -22,7 +21,6 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.UUID; public class User { @@ -107,15 +105,8 @@ public class User { packet.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND); - final PacketContainer ridingPacket = new PacketContainer(PacketType.Play.Server.MOUNT); - ridingPacket. - getIntegers(). - write(0, player.getEntityId()); - ridingPacket.getIntegerArrays().write(0, new int[]{this.armorStandId}); - try { protocolManager.sendServerPacket(other, packet); - protocolManager.sendServerPacket(other, ridingPacket); } catch (final InvocationTargetException exception) { exception.printStackTrace(); } @@ -146,14 +137,8 @@ public class User { final List> equipmentList = new ArrayList<>(); - final Map placeholders = Map.of(Placeholder.ALLOWED, "true", - Placeholder.ENABLED, "true"); - equipmentList.add(new Pair<>(EnumWrappers.ItemSlot.HEAD, - ItemBuilder.from(this.playerArmor.getBackpack().getItemStack()). - namePlaceholders(placeholders). - lorePlaceholders(placeholders). - build() + this.playerArmor.getBackpack().getColored() )); final PacketContainer armorPacket = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); @@ -165,8 +150,11 @@ public class User { final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); WrappedDataWatcher metaData = new WrappedDataWatcher(); - metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) (0x20)); - metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) (0x10)); + + final Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class); + + 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); @@ -176,6 +164,12 @@ public class User { 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 { @@ -183,6 +177,7 @@ public class User { protocolManager.sendServerPacket(p, armorPacket); protocolManager.sendServerPacket(p, metaContainer); protocolManager.sendServerPacket(p, rotationPacket); + protocolManager.sendServerPacket(p, ridingPacket); } } catch (final InvocationTargetException exception) { exception.printStackTrace(); 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 6d7a8901..3bf03b30 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java @@ -1,6 +1,7 @@ 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; @@ -8,36 +9,32 @@ 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.google.common.xml.XmlEscapers; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import io.github.fisher2911.hmccosmetics.concurrent.Threads; -import io.github.fisher2911.hmccosmetics.database.dao.UserDAO; 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.Messages; import io.github.fisher2911.hmccosmetics.message.Placeholder; import io.github.fisher2911.hmccosmetics.util.Keys; import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftEntityEquipment; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitTask; -import java.awt.*; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; -import java.util.function.Consumer; public class UserManager { @@ -65,6 +62,10 @@ public class UserManager { return Optional.ofNullable(this.userMap.get(uuid)); } + public Collection getAll() { + return this.userMap.values(); + } + public void remove(final UUID uuid) { final User user = this.userMap.remove(uuid); @@ -80,11 +81,13 @@ public class UserManager { user.setPlayerArmor(copy); - Threads.getInstance().submit(() -> this.plugin.getDatabase().saveUser(user)); + Threads.getInstance().execute(() -> this.plugin.getDatabase().saveUser(user)); } public void startTeleportTask() { - this.teleportTask = Bukkit.getScheduler().runTaskTimer( + // throws an error on first load of registry if this isn't here + WrappedDataWatcher.Registry.get(Byte.class); + this.teleportTask = Bukkit.getScheduler().runTaskTimerAsynchronously( this.plugin, () -> this.userMap.values().forEach(User::updateArmorStand), 1, @@ -95,6 +98,7 @@ public class UserManager { public void resendCosmetics(final Player player) { for (final User user : this.userMap.values()) { user.spawnArmorStand(player); + this.updateCosmetics(user, false, player); } } @@ -159,6 +163,12 @@ public class UserManager { } public void updateCosmetics(final User user, final boolean ignoreRestrictions) { + for (final Player player : Bukkit.getOnlinePlayers()) { + this.updateCosmetics(user, ignoreRestrictions, player); + } + } + + public void updateCosmetics(final User user, final boolean ignoreRestrictions, final Player other) { final Player player = user.getPlayer(); if (player == null) { @@ -180,12 +190,10 @@ public class UserManager { fake.getIntegers().write(0, player.getEntityId()); fake.getSlotStackPairLists().write(0, equipmentList); - for (final Player p : Bukkit.getOnlinePlayers()) { - try { - this.plugin.getProtocolManager().sendServerPacket(p, fake); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } + try { + this.plugin.getProtocolManager().sendServerPacket(other, fake); + } catch (InvocationTargetException e) { + e.printStackTrace(); } } @@ -228,7 +236,6 @@ public class UserManager { } /** - * * @param user * @param armorItem * @param removeMessage diff --git a/src/main/resources/database.yml b/src/main/resources/database.yml index 363d95aa..140ea512 100644 --- a/src/main/resources/database.yml +++ b/src/main/resources/database.yml @@ -1,4 +1,4 @@ -# SQLite or MySQL (case-insensitive) + # SQLite or MySQL (case-insensitive) type: "sqlite" # The rest of these are only required for MySQL name: "name" diff --git a/src/main/resources/database/info.yml b/src/main/resources/database/info.yml index c78688b0..ea428f79 100644 --- a/src/main/resources/database/info.yml +++ b/src/main/resources/database/info.yml @@ -1 +1 @@ -version: 1.0 \ No newline at end of file +version: 2 \ No newline at end of file