From 7ea5cdcf4680851a8d2fc92a3fa36ccf2e0cebc6 Mon Sep 17 00:00:00 2001 From: HeroBrineGoat <76707404+MasterOfTheFish@users.noreply.github.com> Date: Fri, 21 Jan 2022 13:29:29 -0500 Subject: [PATCH] Improved database handling, and added selecting which item to dye in menu --- build.gradle | 2 +- .../command/CosmeticsCommand.java | 8 +- .../hmccosmetics/config/DyeGuiSerializer.java | 38 ++++- .../hmccosmetics/database/Database.java | 152 ++++++++---------- .../database/DatabaseFactory.java | 35 ++-- .../hmccosmetics/database/MySQLDatabase.java | 41 +---- .../hmccosmetics/database/SQLiteDatabase.java | 52 +----- .../database/dao/ArmorItemDAO.java | 30 +++- .../hmccosmetics/database/dao/UserDAO.java | 46 +++++- .../hmccosmetics/gui/ArmorItem.java | 24 ++- .../hmccosmetics/gui/CosmeticGui.java | 2 +- .../hmccosmetics/gui/CosmeticsMenu.java | 4 +- .../hmccosmetics/gui/DyeSelectorGui.java | 95 ++++++++--- .../hmccosmetics/inventory/PlayerArmor.java | 17 -- .../hmccosmetics/listener/JoinListener.java | 16 +- .../fisher2911/hmccosmetics/user/User.java | 10 +- .../hmccosmetics/user/UserManager.java | 4 +- src/main/resources/menus/dye-menu.yml | 4 + 18 files changed, 328 insertions(+), 252 deletions(-) diff --git a/build.gradle b/build.gradle index 1146335f..8b90f2d6 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ shadowJar { relocate 'org.spongepowered.configurate', 'io.github.fisher2911.hmccosmetics.configurate' relocate 'org.bstats', 'io.github.fisher2911.hmccosmetics.bstats' relocate 'com.zaxxer.hikaricp', 'io.github.fisher2911.hmccosmetics.hikaricp' - relocate 'com.j256.ormlite', 'io.github.fisher2911.databasetest.ormlite' + relocate 'com.j256.ormlite', 'io.github.fisher2911.hmccosmetics.ormlite' } shadowJar { 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 4ddbcba7..5f0970b7 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java @@ -74,13 +74,7 @@ public class CosmeticsCommand extends CommandBase { final User user = optionalUser.get(); - final ArmorItem armorItem = switch (type) { - case HAT -> user.getPlayerArmor().getHat(); - case BACKPACK -> user.getPlayerArmor().getBackpack(); - case OFF_HAND -> user.getPlayerArmor().getOffHand(); - }; - - this.cosmeticsMenu.openDyeSelectorGui(user, armorItem); + this.cosmeticsMenu.openDyeSelectorGui(user, type); } catch (final IllegalArgumentException exception) { this.messageHandler.sendMessage( player, diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/config/DyeGuiSerializer.java b/src/main/java/io/github/fisher2911/hmccosmetics/config/DyeGuiSerializer.java index f45ee1f7..a34d3c94 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/config/DyeGuiSerializer.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/config/DyeGuiSerializer.java @@ -1,11 +1,15 @@ package io.github.fisher2911.hmccosmetics.config; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import dev.triumphteam.gui.guis.GuiItem; import io.github.fisher2911.hmccosmetics.HMCCosmetics; +import io.github.fisher2911.hmccosmetics.gui.ArmorItem; import io.github.fisher2911.hmccosmetics.gui.ColorItem; import io.github.fisher2911.hmccosmetics.gui.DyeSelectorGui; import io.github.fisher2911.hmccosmetics.message.Adventure; import io.github.fisher2911.hmccosmetics.util.StringUtils; +import io.th0rgal.oraxen.utils.armorequipevent.ArmorType; import org.bukkit.Color; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.configurate.ConfigurationNode; @@ -15,6 +19,8 @@ import org.spongepowered.configurate.serialize.TypeSerializer; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; import java.util.Map; @@ -33,6 +39,7 @@ public class DyeGuiSerializer implements TypeSerializer { private static final String TITLE = "title"; private static final String ROWS = "rows"; private static final String ITEMS = "items"; + private static final String COSMETICS_SLOTS = "cosmetics-slots"; private static final String SET_COLOR = "set-color"; private static final String RED = "red"; private static final String GREEN = "green"; @@ -50,13 +57,15 @@ public class DyeGuiSerializer implements TypeSerializer { final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE); final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS); final ConfigurationNode itemsNode = source.node(ITEMS); + final ConfigurationNode cosmeticSlotsNode = source.node(COSMETICS_SLOTS); final Map guiItemMap = new HashMap<>(); - final var map = itemsNode.childrenMap(); + final var itemMap = itemsNode.childrenMap(); + final var cosmeticSlotsMap = cosmeticSlotsNode.childrenMap(); - for (final var entry : map.entrySet()) { + for (final var entry : itemMap.entrySet()) { if (!(entry.getKey() instanceof final Integer slot)) { continue; } @@ -82,6 +91,27 @@ public class DyeGuiSerializer implements TypeSerializer { guiItemMap.put(slot, new ColorItem(guiItem.getItemStack(), Color.fromRGB(red, green, blue))); } + final BiMap cosmeticSlots = HashBiMap.create(); + int selectedCosmetic = -1; + for (final var entry : cosmeticSlotsMap.entrySet()) { + if (!(entry.getKey() instanceof final Integer slot)) { + continue; + } + + selectedCosmetic = selectedCosmetic == -1 ? slot : selectedCosmetic; + + final var node = entry.getValue(); + + final String typeStr = node.getString(); + + try { + final ArmorItem.Type itemType = ArmorItem.Type.valueOf(typeStr); + cosmeticSlots.put(slot, itemType); + } catch (final IllegalArgumentException | NullPointerException exception) { + plugin.getLogger().severe(typeStr + " is not a valid ArmorItem type in DyeGui!"); + } + } + String title = titleNode.getString(); if (title == null) title = ""; @@ -91,7 +121,9 @@ public class DyeGuiSerializer implements TypeSerializer { Adventure.SERIALIZER.serialize( Adventure.MINI_MESSAGE.parse(title)), rowsNode.getInt(), - guiItemMap); + guiItemMap, + cosmeticSlots, + selectedCosmetic); } @Override 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 c10c9f0c..e5ed9cd4 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java @@ -1,25 +1,27 @@ 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.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; import io.github.fisher2911.hmccosmetics.HMCCosmetics; -import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager; import io.github.fisher2911.hmccosmetics.database.dao.ArmorItemDAO; 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.user.User; +import org.bukkit.Bukkit; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collection; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; -public abstract class Database { +public class Database { AtomicInteger ARMOR_STAND_ID = new AtomicInteger(Integer.MAX_VALUE); @@ -41,17 +43,20 @@ public abstract class Database { protected final HMCCosmetics plugin; private final ConnectionSource dataSource; - public Database(final HMCCosmetics plugin, final ConnectionSource dataSource) { + final Dao userDao; + final Dao armorItemDao; + + public Database(final HMCCosmetics plugin, final ConnectionSource dataSource) throws SQLException { this.plugin = plugin; this.dataSource = dataSource; + this.userDao = DaoManager.createDao(this.dataSource, UserDAO.class); + this.armorItemDao = DaoManager.createDao(this.dataSource, ArmorItemDAO.class); } - public abstract Connection getConnection(); - public void load() { this.createTables(); } - + private void createTables() { try { TableUtils.createTableIfNotExists(this.dataSource, ArmorItemDAO.class); @@ -61,92 +66,67 @@ public abstract class Database { } } - public void saveUser(final User u) { - try { - final UserDAO user = new UserDAO(u.getUuid()); + public void loadUser(final UUID uuid) { + final int armorStandId = ARMOR_STAND_ID.getAndDecrement(); + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, + () -> { + try { + UserDAO user = this.userDao.queryForId(uuid); + + if (user == null) { + user = this.userDao.createIfNotExists(new UserDAO(uuid)); + this.plugin.getLogger().severe("Created New: " + user); + this.userDao.assignEmptyForeignCollection(user, "armorItems"); + this.plugin.getLogger().severe("Initializing Collection: " + user); + } + + final UserDAO finalUser = user; + Bukkit.getScheduler().runTask(this.plugin, + () -> this.plugin.getUserManager().add( + finalUser.toUser(this.plugin.getCosmeticManager(), armorStandId) + ) + ); + + } catch (final SQLException exception) { + exception.printStackTrace(); + } + }); + + this.plugin.getUserManager().add(new User(uuid, PlayerArmor.empty(), armorStandId)); - final Dao userDao = DaoManager.createDao(this.dataSource, UserDAO.class); - userDao.assignEmptyForeignCollection(user, "armorItems"); - for (final ArmorItem armorItem : u.getPlayerArmor().getArmorItems()) { - user.getArmorItems().add(ArmorItemDAO.fromArmorItem(armorItem)); - } - userDao.createOrUpdate(user); - } catch (final SQLException exception) { - exception.printStackTrace(); - } } -// public void saveUser(final User user) { -// -// try (final PreparedStatement statement = this.getConnection().prepareStatement(this.getSaveStatement())) { -// final PlayerArmor playerArmor = user.getPlayerArmor(); -// final String hat = playerArmor.getHat().getId(); -// final String backpack = playerArmor.getBackpack().getId(); -// -// statement.setString(1, user.getUuid().toString()); -// statement.setString(2, backpack); -// statement.setString(3, hat); -// statement.setString(5, backpack); -// statement.setString(6, hat); -// -// statement.executeUpdate(); -// } catch (final SQLException exception) { -// this.plugin.getLogger().severe("There was in issue saving the player!"); -// exception.printStackTrace(); -// } -// } -// - public User loadUser(final UUID uuid) { - final int armorStandId = ARMOR_STAND_ID.getAndDecrement(); - - final User blankUser = new User( - uuid, - PlayerArmor.empty(), - armorStandId - ); - - try (final PreparedStatement statement = this.getConnection().prepareStatement(this.getLoadStatement())) { - statement.setString(1, uuid.toString()); - - final ResultSet results = statement.executeQuery(); - - if (!results.next()) { - return blankUser; + public void saveUser(final User user) { + try { + final UserDAO userDAO = new UserDAO(user.getUuid()); + this.userDao.assignEmptyForeignCollection(userDAO, "armorItems"); + for (final ArmorItem armorItem : user.getPlayerArmor().getArmorItems()) { + final ArmorItemDAO dao = ArmorItemDAO.fromArmorItem(armorItem); + dao.setUser(userDAO); + final ForeignCollection armorItems = userDAO.getArmorItems(); + if (armorItems.contains(dao)) { + armorItems.update(dao); + } else { + armorItems.add(dao); + } } - - final String backpackId = results.getString(1); - final String hatId = results.getString(2); - final int dye = results.getInt(3); - - final CosmeticManager manager = this.plugin.getCosmeticManager(); - - ArmorItem backpack = manager.getArmorItem(backpackId); - ArmorItem hat = manager.getArmorItem(hatId); - - if (backpack == null) backpack = ArmorItem.empty(ArmorItem.Type.BACKPACK); - if (hat == null) hat = ArmorItem.empty(ArmorItem.Type.HAT); - - return new User( - uuid, - new PlayerArmor( - hat, - backpack, - // todo - null - ), - armorStandId - ); - + this.userDao.createOrUpdate(userDAO); } catch (final SQLException exception) { exception.printStackTrace(); - return blankUser; } } + public void close() { + try { + this.dataSource.close(); + } catch (final Exception exception) { + exception.printStackTrace(); + } + } - public abstract void close(); - - public abstract String getSaveStatement(); - - public abstract String getLoadStatement(); +// public abstract void close(); +// +// public abstract String getSaveStatement(); +// +// public abstract String getLoadStatement(); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseFactory.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseFactory.java index 9c8c6db8..25292f69 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseFactory.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseFactory.java @@ -1,5 +1,9 @@ package io.github.fisher2911.hmccosmetics.database; +import com.j256.ormlite.jdbc.DataSourceConnectionSource; +import com.j256.ormlite.jdbc.JdbcPooledConnectionSource; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import io.github.fisher2911.hmccosmetics.HMCCosmetics; import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; @@ -47,21 +51,32 @@ public class DatabaseFactory { final String ip = config.getString(IP_PATH); final String port = config.getString(PORT_PATH); - yield new MySQLDatabase( - plugin, - name, - username, - password, - ip, - port - ); + final HikariConfig hikari = new HikariConfig(); + + final String jdbcUrl = "jdbc:mysql://" + ip + ":" + port + "/" + name; + + hikari.setJdbcUrl(jdbcUrl); + hikari.setUsername(username); + hikari.setPassword(password); + hikari.setConnectionTimeout(1000000000); + + final HikariDataSource source = new HikariDataSource(hikari); + + yield new Database(plugin, new DataSourceConnectionSource(source, jdbcUrl)); + } + case "sqlite" -> { + final File folder = new File(plugin.getDataFolder().getPath(), "database"); + folder.mkdirs(); + yield new Database(plugin, new JdbcPooledConnectionSource("jdbc:sqlite:" + new File( + folder.getPath(), + "users.db" + ).getPath())); } - case "sqlite" -> new SQLiteDatabase(plugin); default -> null; }; if (database == null) { - logger.severe("Error loading database, type " + type + " is invalid!"); + logger.severe("Error loading database, type " + type + " is invalid! Disabling plugin."); Bukkit.getPluginManager().disablePlugin(plugin); } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/MySQLDatabase.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/MySQLDatabase.java index dbabb5b5..0809da2a 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/MySQLDatabase.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/MySQLDatabase.java @@ -1,5 +1,6 @@ package io.github.fisher2911.hmccosmetics.database; +import com.j256.ormlite.support.ConnectionSource; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.github.fisher2911.hmccosmetics.HMCCosmetics; @@ -32,45 +33,15 @@ public class MySQLDatabase extends Database { private final HikariDataSource dataSource; - MySQLDatabase( - final HMCCosmetics plugin, - final String name, - final String username, - final String password, - final String ip, - final String port) { - super(plugin, null); - final HikariConfig config = new HikariConfig(); - - config.setJdbcUrl("jdbc:mysql://" + ip + ":" + port + "/" + name); - config.setUsername(username); - config.setPassword(password); - config.setConnectionTimeout(1000000000); - - this.dataSource = new HikariDataSource(config); - } - - @Override - public Connection getConnection() { - try { - return this.dataSource.getConnection(); - } catch (final SQLException exception) { - return null; - } + public MySQLDatabase(final HMCCosmetics plugin, final ConnectionSource dataSource, final String SAVE_STATEMENT, final String LOAD_STATEMENT, final HikariDataSource dataSource1) throws SQLException { + super(plugin, dataSource); + this.SAVE_STATEMENT = SAVE_STATEMENT; + this.LOAD_STATEMENT = LOAD_STATEMENT; + this.dataSource = dataSource1; } @Override public void close() { this.dataSource.close(); } - - @Override - public String getSaveStatement() { - return SAVE_STATEMENT; - } - - @Override - public String getLoadStatement() { - return LOAD_STATEMENT; - } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/SQLiteDatabase.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/SQLiteDatabase.java index 0e40ef90..337cc794 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/SQLiteDatabase.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/SQLiteDatabase.java @@ -1,28 +1,23 @@ package io.github.fisher2911.hmccosmetics.database; -import com.j256.ormlite.jdbc.JdbcConnectionSource; +import com.j256.ormlite.jdbc.DataSourceConnectionSource; import com.j256.ormlite.jdbc.JdbcPooledConnectionSource; +import com.j256.ormlite.support.ConnectionSource; import io.github.fisher2911.hmccosmetics.HMCCosmetics; -import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; -import io.github.fisher2911.hmccosmetics.user.User; +import javax.sql.DataSource; import java.io.File; import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; -import java.sql.PreparedStatement; import java.sql.SQLException; public class SQLiteDatabase extends Database { private Connection conn; - public SQLiteDatabase(final HMCCosmetics plugin) throws SQLException { - super(plugin, new JdbcPooledConnectionSource("jdbc:sqlite:" + Path.of( - plugin.getDataFolder().getPath(), - "database", - "users.db" - ).toFile().getPath())); + public SQLiteDatabase(final HMCCosmetics plugin, final ConnectionSource connectionSource) throws SQLException { + super(plugin, connectionSource); } String SAVE_STATEMENT = @@ -49,33 +44,6 @@ public class SQLiteDatabase extends Database { "WHERE " + PLAYER_UUID_COLUMN + "=? "; - @Override - public Connection getConnection() { - if (this.conn != null) { - return this.conn; - } - try { - final File folder = Path.of( - this.plugin.getDataFolder().getPath(), - "database" - ).toFile(); - - folder.mkdirs(); - - final File file = Path.of( - folder.getPath(), - "users.db" - ).toFile(); - - this.conn = DriverManager.getConnection("jdbc:sqlite:" + - file.getPath()); - return this.conn; - } catch (final SQLException exception) { - exception.printStackTrace(); - } - return null; - } - @Override public void close() { try { @@ -84,14 +52,4 @@ public class SQLiteDatabase extends Database { exception.printStackTrace(); } } - - @Override - public String getSaveStatement() { - return SAVE_STATEMENT; - } - - @Override - public String getLoadStatement() { - return LOAD_STATEMENT; - } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/ArmorItemDAO.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/ArmorItemDAO.java index 858c8835..146a6fcb 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/ArmorItemDAO.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/ArmorItemDAO.java @@ -2,18 +2,22 @@ package io.github.fisher2911.hmccosmetics.database.dao; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager; import io.github.fisher2911.hmccosmetics.gui.ArmorItem; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; @DatabaseTable(tableName = "armor_item") public class ArmorItemDAO { - @DatabaseField(foreign = true, foreignAutoRefresh = true) + @DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = "user", uniqueCombo = true) private UserDAO user; @DatabaseField private String id; - @DatabaseField + @DatabaseField(id = true, uniqueCombo = true) private String type; @DatabaseField(columnName = "color") @@ -29,6 +33,15 @@ public class ArmorItemDAO { return new ArmorItemDAO(armorItem.getId(), armorItem.getType().toString(), armorItem.getDye()); } + @Nullable + public ArmorItem toArmorItem(final CosmeticManager cosmeticManager) { + final ArmorItem armorItem = cosmeticManager.getArmorItem(this.id); + if (armorItem == null) return null; + final ArmorItem copy = new ArmorItem(armorItem); + copy.setDye(this.rgbDye); + return copy; + } + public ArmorItemDAO() { } @@ -63,4 +76,17 @@ public class ArmorItemDAO { public void setRgbDye(final int rgbDye) { this.rgbDye = rgbDye; } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final ArmorItemDAO that = (ArmorItemDAO) o; + return Objects.equals(getUser(), that.getUser()) && Objects.equals(getType(), that.getType()); + } + + @Override + public int hashCode() { + return Objects.hash(getUser(), getType()); + } } diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java index 2e72eb78..81c649c9 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java @@ -1,13 +1,17 @@ package io.github.fisher2911.hmccosmetics.database.dao; -import com.j256.ormlite.dao.EagerForeignCollection; import com.j256.ormlite.dao.ForeignCollection; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.ForeignCollectionField; import com.j256.ormlite.table.DatabaseTable; +import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager; +import io.github.fisher2911.hmccosmetics.gui.ArmorItem; +import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor; import io.github.fisher2911.hmccosmetics.user.User; -import java.util.List; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Objects; import java.util.UUID; @DatabaseTable(tableName = "user") @@ -22,11 +26,6 @@ public class UserDAO { public UserDAO() { } - public UserDAO(final UUID uuid, final ForeignCollection armorItems) { - this.uuid = uuid; - this.armorItems = armorItems; - } - public void setUuid(final UUID uuid) { this.uuid = uuid; } @@ -42,4 +41,37 @@ public class UserDAO { public void setArmorItems(final ForeignCollection armorItems) { this.armorItems = armorItems; } + + public User toUser(final CosmeticManager cosmeticManager, final int armorStandId) { + final PlayerArmor playerArmor = PlayerArmor.empty(); + + for (final ArmorItemDAO armorItemDao : this.armorItems) { + final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager); + if (armorItem == null) continue; + playerArmor.setItem(armorItem); + } + + return new User(this.uuid, playerArmor, armorStandId); + } + + @Override + public String toString() { + return "UserDAO{" + + "uuid=" + uuid + + ", armorItems=" + armorItems + + '}'; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final UserDAO userDAO = (UserDAO) o; + return Objects.equals(uuid, userDAO.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } } 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 6a3de424..8c051173 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/ArmorItem.java @@ -1,5 +1,6 @@ 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; @@ -13,8 +14,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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; @@ -23,7 +26,7 @@ public class ArmorItem extends GuiItem { private final String permission; private final Type type; private boolean dyeable; - private final int dye; + private int dye; public ArmorItem( @NotNull final ItemStack itemStack, @@ -177,6 +180,18 @@ public class ArmorItem extends GuiItem { ); } + public ArmorItem(final ArmorItem armorItem) { + super(armorItem.getItemStack(), armorItem.getAction()); + this.id = armorItem.getId(); + this.lockedLore = new ArrayList<>(); + Collections.copy(armorItem.getLockedLore(), this.lockedLore); + this.action = armorItem.getAction(); + this.permission = armorItem.getPermission(); + this.type = armorItem.getType(); + this.dyeable = armorItem.isDyeable(); + this.dye = armorItem.getDye(); + } + public String getId() { return id; } @@ -205,8 +220,11 @@ public class ArmorItem extends GuiItem { return dye; } - @Override - public ItemStack getItemStack() { + public void setDye(final int dye) { + this.dye = dye; + } + + public ItemStack getColored() { return this.color(super.getItemStack()); } 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 209c7325..140373a7 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticGui.java @@ -50,7 +50,7 @@ public class CosmeticGui { this.guiItemMap.forEach((key, value) -> itemStackMap.put(key, value.getItemStack())); } - private void setItems(final User user) { + protected void setItems(final User user) { final Player player = user.getPlayer(); 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 83ce8ae6..d7bc5a19 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/CosmeticsMenu.java @@ -51,7 +51,7 @@ public class CosmeticsMenu { public void openDyeSelectorGui( final User user, - final ArmorItem armorItem) { + final ArmorItem.Type type) { final Player player = user.getPlayer(); @@ -62,7 +62,7 @@ public class CosmeticsMenu { final CosmeticGui gui = this.guiMap.get(DYE_MENU); if (gui instanceof final DyeSelectorGui dyeSelectorGui) { - dyeSelectorGui.getGui(user, armorItem).open(player); + dyeSelectorGui.getGui(user, type).open(player); } } 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 234b4ffc..543803d0 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/gui/DyeSelectorGui.java @@ -1,41 +1,62 @@ package io.github.fisher2911.hmccosmetics.gui; +import com.google.common.collect.BiMap; import dev.triumphteam.gui.guis.Gui; 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.user.User; import io.github.fisher2911.hmccosmetics.util.StringUtils; -import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder; import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder; import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; -import org.bukkit.Color; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; -import java.util.HashMap; import java.util.Map; import java.util.Optional; public class DyeSelectorGui extends CosmeticGui { + private final BiMap cosmeticsSlots; + private int selectedCosmetic; + public DyeSelectorGui( final HMCCosmetics plugin, final String title, final int rows, - final Map guiItemMap) { + final Map guiItemMap, + final BiMap cosmeticsSlots, + final int selectedCosmetic + ) { super(plugin, title, rows, guiItemMap); + this.cosmeticsSlots = cosmeticsSlots; + this.selectedCosmetic = selectedCosmetic; } - public Gui getGui(final User user, final ArmorItem armorItem) { - final Gui gui = Gui.gui(). + public Gui getGui(final User user) { + return this.getGui(user, null); + } + + public Gui getGui(final User user, @Nullable final ArmorItem.Type type) { + this.gui = Gui.gui(). title(Component.text(StringUtils.applyPapiPlaceholders(user.getPlayer(), this.title))). rows(rows). create(); final Player player = user.getPlayer(); + player.sendMessage("Getting Gui"); + + if (type != null) { + final Integer selected = this.cosmeticsSlots.inverse().get(type); + this.selectedCosmetic = selected == null ? this.selectedCosmetic : selected; + } + + for (final var entry : this.cosmeticsSlots.entrySet()) { + gui.setItem(entry.getKey(), user.getPlayerArmor().getItem(entry.getValue())); + } for (final var entry : this.guiItemMap.entrySet()) { @@ -52,6 +73,14 @@ public class DyeSelectorGui extends CosmeticGui { gui.setItem(entry.getKey(), guiItem); } + final PlayerArmor playerArmor = user.getPlayerArmor(); + + final ArmorItem armorItem = playerArmor.getItem( + this.cosmeticsSlots.get(this.selectedCosmetic) + ); + + this.select(this.selectedCosmetic); + gui.setDefaultClickAction(event -> { event.setCancelled(true); @@ -59,14 +88,6 @@ public class DyeSelectorGui extends CosmeticGui { return; } - final ArmorItem.Type type = armorItem.getType(); - - final PlayerArmor playerArmor = user.getPlayerArmor(); - - if (playerArmor == null) { - return; - } - final ItemStack itemStack = playerArmor.getItem(type).getItemStack(); if (itemStack == null) { @@ -77,22 +98,58 @@ public class DyeSelectorGui extends CosmeticGui { return; } - final GuiItem guiItem = this.guiItemMap.get(event.getSlot()); + final int slot = event.getSlot(); - if (!(guiItem instanceof ColorItem)) { + final ArmorItem.Type clickedType = this.cosmeticsSlots.get(slot); + + if (clickedType != null) { + this.select(slot); return; } + final GuiItem guiItem = this.guiItemMap.get(slot); + + if (!(guiItem instanceof ColorItem colorItem)) { + return; + } + + armorItem.setDye(colorItem.getColor().asRGB()); + this.userManager.setItem(user, armorItem); }); return gui; } + private void select(final int slot) { + ItemStack itemStack = this.itemStackMap.get(slot); + ItemStack previous = this.itemStackMap.get(this.selectedCosmetic); + + if (itemStack == null) return; + + itemStack = + dev.triumphteam.gui.builder.item.ItemBuilder.from( + itemStack).glow().build(); + + if (previous != null && this.selectedCosmetic != slot) { + previous = dev.triumphteam.gui.builder.item.ItemBuilder.from( + previous).glow(false).build(); + this.gui.updateItem(this.selectedCosmetic, previous); + } + + this.gui.updateItem(slot, itemStack); + + this.selectedCosmetic = slot; + } + @Override public void open(final HumanEntity player) { final Optional optionalUser = this.plugin.getUserManager().get(player.getUniqueId()); - // todo -// optionalUser.ifPresent(user -> this.getGui(user, user.getLastSetItem()).open(player)); + optionalUser.ifPresent(user -> this.getGui(user, user.getLastSetItem().getType()).open(player)); + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); } } 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 84284fa4..c2f6a47c 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/inventory/PlayerArmor.java @@ -1,12 +1,7 @@ package io.github.fisher2911.hmccosmetics.inventory; import io.github.fisher2911.hmccosmetics.gui.ArmorItem; -import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder; -import org.bukkit.Color; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.Map; @@ -34,26 +29,14 @@ public class PlayerArmor { return this.armorItems.get(ArmorItem.Type.HAT); } - public void setHat(final ArmorItem hat) { - this.armorItems.put(ArmorItem.Type.HAT, hat); - } - public ArmorItem getBackpack() { return this.armorItems.get(ArmorItem.Type.BACKPACK); } - public void setBackpack(final ArmorItem backpack) { - this.armorItems.put(ArmorItem.Type.BACKPACK, backpack); - } - public ArmorItem getOffHand() { return this.armorItems.get(ArmorItem.Type.OFF_HAND); } - public void setOffHand(final ArmorItem offHand) { - this.armorItems.put(ArmorItem.Type.OFF_HAND, offHand); - } - public ArmorItem getItem(final ArmorItem.Type type) { return this.armorItems.get(type); } 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 ea8af4c9..c869dc73 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java @@ -2,10 +2,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.User; import io.github.fisher2911.hmccosmetics.user.UserManager; -import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -27,17 +24,18 @@ public class JoinListener implements Listener { @EventHandler public void onJoin(final PlayerJoinEvent event) { final Player player = event.getPlayer(); - Bukkit.getScheduler().runTaskAsynchronously(this.plugin, - () -> { - final User user = this.database.loadUser(player.getUniqueId()); - Bukkit.getScheduler().runTask(this.plugin, - () -> this.userManager.add(user)); - }); + this.database.loadUser(player.getUniqueId()); + this.userManager.resendCosmetics(player); } @EventHandler public void onQuit(final PlayerQuitEvent event) { + this.userManager.remove(event.getPlayer().getUniqueId()); + this.userManager.get(event.getPlayer().getUniqueId()). + ifPresent( + this.database::saveUser + ); } } 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 47e89e4a..784d6c54 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java @@ -30,6 +30,8 @@ public class User { private final UUID uuid; private final PlayerArmor playerArmor; + private ArmorItem lastSetItem = ArmorItem.empty(ArmorItem.Type.HAT); + private boolean hasArmorStand; private final int armorStandId; @@ -52,8 +54,8 @@ public class User { } protected void setPlayerArmor(final PlayerArmor playerArmor) { - this.playerArmor.setBackpack(playerArmor.getBackpack()); - this.playerArmor.setHat(playerArmor.getHat()); + this.playerArmor.setItem(playerArmor.getBackpack()); + this.playerArmor.setItem(playerArmor.getHat()); } protected void removeAllCosmetics() { @@ -67,6 +69,7 @@ public class User { } protected ArmorItem setItem(final ArmorItem armorItem) { + this.lastSetItem = armorItem; return this.playerArmor.setItem(armorItem); } @@ -205,4 +208,7 @@ public class User { return hasArmorStand; } + public ArmorItem getLastSetItem() { + return lastSetItem; + } } 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 62070c5b..6be9b4d1 100644 --- a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java +++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java @@ -10,6 +10,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.Pair; import com.google.common.xml.XmlEscapers; import io.github.fisher2911.hmccosmetics.HMCCosmetics; +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; @@ -32,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.function.Consumer; public class UserManager { @@ -142,7 +144,7 @@ public class UserManager { public void setFakeHelmet(final User user) { - ItemStack hat = user.getPlayerArmor().getHat().getItemStack(); + ItemStack hat = user.getPlayerArmor().getHat().getColored(); final Player player = user.getPlayer(); if (player == null || hat == null) { diff --git a/src/main/resources/menus/dye-menu.yml b/src/main/resources/menus/dye-menu.yml index eab80cbe..5939cf36 100644 --- a/src/main/resources/menus/dye-menu.yml +++ b/src/main/resources/menus/dye-menu.yml @@ -1,5 +1,9 @@ title: "" rows: 4 +cosmetics-slots: + 15: BACKPACK + 16: HAT + 17: OFF_HAND items: 10: material: LEATHER_HORSE_ARMOR