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

Added SQLite and MySQL support

This commit is contained in:
HeroBrineGoat
2022-01-17 14:12:45 -05:00
parent a6c5761636
commit 3e609dac93
17 changed files with 481 additions and 60 deletions

View File

@@ -5,6 +5,8 @@ import com.comphenix.protocol.ProtocolManager;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.database.Database;
import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
@@ -34,6 +36,7 @@ public class HMCCosmetics extends JavaPlugin {
private CosmeticsMenu cosmeticsMenu;
private CommandManager commandManager;
private boolean papiEnabled;
private Database database;
@Override
public void onEnable() {
@@ -47,12 +50,16 @@ public class HMCCosmetics extends JavaPlugin {
this.cosmeticsMenu = new CosmeticsMenu(this);
this.messageHandler.load();
this.cosmeticsMenu.load();
this.registerCommands();
this.registerListeners();
this.userManager.startTeleportTask();
this.database = DatabaseFactory.create(this);
this.database.load();
this.papiEnabled = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
this.registerCommands();
this.registerListeners();
}
@Override
@@ -116,6 +123,10 @@ public class HMCCosmetics extends JavaPlugin {
return protocolManager;
}
public Database getDatabase() {
return database;
}
public boolean isPapiEnabled() {
return papiEnabled;
}

View File

@@ -125,7 +125,7 @@ public class CosmeticsCommand extends CommandBase {
switch (armorItem.getType()) {
case BACKPACK -> {
user.setBackpack(armorItem);
user.setBackpack(armorItem, this.plugin);
this.messageHandler.sendMessage(
player,
Messages.SET_BACKPACK
@@ -138,7 +138,7 @@ public class CosmeticsCommand extends CommandBase {
);
}
case HAT -> {
user.setHat(armorItem, this.userManager);
user.setHat(armorItem, this.plugin);
this.messageHandler.sendMessage(
player,
Messages.SET_HAT
@@ -173,7 +173,7 @@ public class CosmeticsCommand extends CommandBase {
switch (type) {
case HAT -> {
user.removeHat(this.userManager);
user.removeHat(this.plugin);
this.messageHandler.sendMessage(
player,
Messages.REMOVED_HAT
@@ -186,7 +186,7 @@ public class CosmeticsCommand extends CommandBase {
);
}
case BACKPACK -> {
user.removeBackpack();
user.removeBackpack(this.plugin);
this.messageHandler.sendMessage(
player,
Messages.REMOVED_BACKPACK

View File

@@ -0,0 +1,126 @@
package io.github.fisher2911.hmccosmetics.database;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class Database {
AtomicInteger ARMOR_STAND_ID = new AtomicInteger(Integer.MAX_VALUE);
String TABLE_NAME = "user";
String PLAYER_UUID_COLUMN = "uuid";
String BACKPACK_COLUMN = "backpack";
String HAT_COLUMN = "hat";
String DYE_COLOR_COLUMN = "dye";
String CREATE_TABLE_STATEMENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
PLAYER_UUID_COLUMN + " CHAR(36), " +
BACKPACK_COLUMN + " VARCHAR, " +
HAT_COLUMN + " VARCHAR, " +
DYE_COLOR_COLUMN + " SMALLINT, " +
"UNIQUE (" +
PLAYER_UUID_COLUMN +
"))";
protected final HMCCosmetics plugin;
public Database(final HMCCosmetics plugin) {
this.plugin = plugin;
}
public abstract Connection getConnection();
public void load() {
try (final PreparedStatement statement = this.getConnection().prepareStatement(CREATE_TABLE_STATEMENT)) {
statement.executeUpdate();
} 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();
final int dye = user.getDye();
statement.setString(1, user.getUuid().toString());
statement.setString(2, backpack);
statement.setString(3, hat);
statement.setInt(4, dye);
statement.setString(5, backpack);
statement.setString(6, hat);
statement.setInt(7, dye);
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;
}
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,
dye
),
armorStandId
);
} catch (final SQLException exception) {
exception.printStackTrace();
return blankUser;
}
}
public abstract void close();
public abstract String getSaveStatement();
public abstract String getLoadStatement();
}

View File

@@ -0,0 +1,69 @@
package io.github.fisher2911.hmccosmetics.database;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.nio.file.Path;
import java.util.logging.Logger;
public class DatabaseFactory {
private static final String FILE_NAME = "database.yml";
private static final String TYPE_PATH = "type";
private static final String NAME_PATH = "name";
private static final String USERNAME_PATH = "username";
private static final String PASSWORD_PATH = "password";
private static final String IP_PATH = "ip";
private static final String PORT_PATH = "port";
public static Database create(final HMCCosmetics plugin) {
final File file = Path.of(plugin.getDataFolder().getPath(), FILE_NAME).toFile();
if (!file.exists()) {
plugin.saveResource(FILE_NAME, false);
}
final FileConfiguration config = YamlConfiguration.loadConfiguration(file);
final String type = config.getString(TYPE_PATH);
final Logger logger = plugin.getLogger();
if (type == null) {
Bukkit.getPluginManager().disablePlugin(plugin);
throw new NullPointerException();
}
final Database database = switch (type.toLowerCase()) {
case "mysql" -> {
final String name = config.getString(NAME_PATH);
final String username = config.getString(USERNAME_PATH);
final String password = config.getString(PASSWORD_PATH);
final String ip = config.getString(IP_PATH);
final String port = config.getString(PORT_PATH);
yield new MySQLDatabase(
plugin,
name,
username,
password,
ip,
port
);
}
case "sqlite" -> new SQLiteDatabase(plugin);
default -> null;
};
if (database == null) {
logger.severe("Error loading database, type " + type + " is invalid!");
Bukkit.getPluginManager().disablePlugin(plugin);
}
return database;
}
}

View File

@@ -0,0 +1,76 @@
package io.github.fisher2911.hmccosmetics.database;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import java.sql.Connection;
import java.sql.SQLException;
public class MySQLDatabase extends Database {
String SAVE_STATEMENT =
"INSERT INTO " + TABLE_NAME + "(" +
PLAYER_UUID_COLUMN + ", " +
BACKPACK_COLUMN + ", " +
HAT_COLUMN + ", " +
DYE_COLOR_COLUMN + ", " +
"VALUES (?,?,?) " +
"ON DUPLICATE KEY UPDATE " +
BACKPACK_COLUMN + "=?, " +
HAT_COLUMN + "=?, " +
DYE_COLOR_COLUMN + "=?";
String LOAD_STATEMENT =
"SELECT " +
BACKPACK_COLUMN + ", " +
HAT_COLUMN + ", " +
DYE_COLOR_COLUMN + ", " +
"FROM " + TABLE_NAME + " " +
"WHERE " +
PLAYER_UUID_COLUMN + "=?";
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);
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;
}
}
@Override
public void close() {
this.dataSource.close();
}
@Override
public String getSaveStatement() {
return SAVE_STATEMENT;
}
@Override
public String getLoadStatement() {
return LOAD_STATEMENT;
}
}

View File

@@ -0,0 +1,91 @@
package io.github.fisher2911.hmccosmetics.database;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.User;
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) {
super(plugin);
}
String SAVE_STATEMENT =
"INSERT INTO " + TABLE_NAME + "(" +
PLAYER_UUID_COLUMN + ", " +
BACKPACK_COLUMN + ", " +
HAT_COLUMN + ", " +
DYE_COLOR_COLUMN +
") " +
"VALUES (?,?,?,?) " +
"ON CONFLICT (" +
PLAYER_UUID_COLUMN + ") " +
"DO UPDATE SET " +
BACKPACK_COLUMN + "=?," +
HAT_COLUMN + "=?, " +
DYE_COLOR_COLUMN + "=?";
String LOAD_STATEMENT =
"SELECT " +
BACKPACK_COLUMN + ", " +
HAT_COLUMN + ", " +
DYE_COLOR_COLUMN + " " +
"FROM " + TABLE_NAME + " " +
"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 {
this.conn.close();
} catch (final SQLException exception) {
exception.printStackTrace();
}
}
@Override
public String getSaveStatement() {
return SAVE_STATEMENT;
}
@Override
public String getLoadStatement() {
return LOAD_STATEMENT;
}
}

View File

@@ -142,13 +142,13 @@ public class CosmeticGui {
switch (type) {
case HAT -> {
final boolean set = user.setOrUnsetHat(armorItem, this.messageHandler, this.plugin.getUserManager());
final boolean set = user.setOrUnsetHat(armorItem, this.messageHandler, this.plugin);
if (set) {
actionIfSet.execute(event);
}
}
case BACKPACK -> {
final boolean set = user.setOrUnsetBackpack(armorItem, this.messageHandler);
final boolean set = user.setOrUnsetBackpack(armorItem, this.messageHandler, this.plugin);
if (set) {
actionIfSet.execute(event);
}

View File

@@ -120,8 +120,7 @@ public class CosmeticsMenu {
final ConfigurationNode source = loader.load();
if (id.equals(DYE_MENU)) {
this.guiMap.put(id, DyeGuiSerializer.INSTANCE.deserialize(DyeSelectorGui.class,
source));
this.guiMap.put(id, DyeGuiSerializer.INSTANCE.deserialize(DyeSelectorGui.class, source));
this.plugin.getLogger().info("Loaded dye gui: " + id);
continue;
}

View File

@@ -94,9 +94,6 @@ public class DyeSelectorGui extends CosmeticGui {
return;
}
final ColorBuilder colorBuilder =
ColorBuilder.from(itemStack);
final GuiItem guiItem = this.guiItemMap.get(event.getSlot());
if (!(guiItem instanceof final ColorItem colorItem)) {
@@ -104,22 +101,11 @@ public class DyeSelectorGui extends CosmeticGui {
}
final Color color = colorItem.getColor();
colorBuilder.color(color);
final ArmorItem newArmorItem = new ArmorItem(
colorBuilder.build(),
armorItem.getAction(),
armorItem.getId(),
armorItem.getLockedLore(),
armorItem.getPermission(),
armorItem.getType(),
armorItem.isDyeable()
);
user.setDye(color.asRGB());
switch (type) {
case HAT -> user.setHat(newArmorItem, plugin.getUserManager());
case BACKPACK -> user.setBackpack(newArmorItem);
case HAT -> user.setHat(armorItem, this.plugin);
case BACKPACK -> user.setBackpack(armorItem, this.plugin);
}
});

View File

@@ -1,6 +1,8 @@
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;
@@ -10,9 +12,11 @@ public class PlayerArmor {
private ArmorItem hat;
private ArmorItem backpack;
private int dye;
public PlayerArmor(final ArmorItem hat, final ArmorItem backpack) {
this.hat = hat;
public PlayerArmor(ArmorItem hat, final ArmorItem backpack, final int dye) {
this.dye = dye;
this.setHat(hat);
this.backpack = backpack;
}
@@ -31,7 +35,8 @@ public class PlayerArmor {
new ArrayList<>(),
"",
ArmorItem.Type.BACKPACK
));
),
-1);
}
public ArmorItem getHat() {
@@ -39,7 +44,23 @@ public class PlayerArmor {
}
public void setHat(final ArmorItem hat) {
this.hat = hat;
if (dye == -1 || !ColorBuilder.canBeColored(hat.getItemStack())) {
this.hat = hat;
return;
}
final ColorBuilder colorBuilder =
ColorBuilder.from(hat.getItemStack()).
color(Color.fromRGB(this.dye));
this.hat = new ArmorItem(
colorBuilder.build(),
hat.getAction(),
hat.getId(),
hat.getLockedLore(),
hat.getPermission(),
hat.getType(),
hat.isDyeable()
);
}
public ArmorItem getBackpack() {
@@ -49,4 +70,12 @@ public class PlayerArmor {
public void setBackpack(final ArmorItem backpack) {
this.backpack = backpack;
}
public int getDye() {
return this.dye;
}
public void setDye(final int dye) {
this.dye = dye;
}
}

View File

@@ -1,9 +1,12 @@
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;
import org.bukkit.event.player.PlayerJoinEvent;
@@ -12,16 +15,25 @@ import org.bukkit.event.player.PlayerQuitEvent;
public class JoinListener implements Listener {
private final HMCCosmetics plugin;
private final Database database;
private final UserManager userManager;
public JoinListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.database = this.plugin.getDatabase();
this.userManager = this.plugin.getUserManager();
}
@EventHandler
public void onJoin(final PlayerJoinEvent event) {
this.userManager.add(event.getPlayer());
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.userManager.resendCosmetics(player);
}
@EventHandler

View File

@@ -27,7 +27,7 @@ public class RespawnListener implements Listener {
final Player player = event.getPlayer();
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
optionalUser.ifPresent(user -> user.setHat(user.getPlayerArmor().getHat(), this.userManager));
optionalUser.ifPresent(user -> user.setHat(user.getPlayerArmor().getHat(), this.plugin));
}, 1);
}
}

View File

@@ -7,14 +7,17 @@ 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 io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
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.builder.ColorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
@@ -41,6 +44,7 @@ public class User {
this.uuid = uuid;
this.playerArmor = playerArmor;
this.armorStandId = armorStandId;
this.lastSetItem = playerArmor.getHat();
}
public @Nullable Player getPlayer() {
@@ -64,27 +68,30 @@ public class User {
this.setPlayerArmor(PlayerArmor.empty());
}
public void removeHat(final UserManager userManager) {
this.setHat(ArmorItem.empty(ArmorItem.Type.HAT), userManager);
public void removeHat(final HMCCosmetics plugin) {
this.setHat(ArmorItem.empty(ArmorItem.Type.HAT), plugin);
}
public void removeBackpack() {
this.setBackpack(ArmorItem.empty(ArmorItem.Type.BACKPACK));
public void removeBackpack(final HMCCosmetics plugin) {
this.setBackpack(ArmorItem.empty(ArmorItem.Type.BACKPACK), plugin);
}
public int getArmorStandId() {
return armorStandId;
}
public void setBackpack(final ArmorItem backpack) {
public void setBackpack(final ArmorItem backpack, final HMCCosmetics plugin) {
this.playerArmor.setBackpack(backpack);
this.lastSetItem = backpack;
Bukkit.getScheduler().runTaskAsynchronously(plugin,
() -> plugin.getDatabase().saveUser(this));
}
// return true if backpack was set
public boolean setOrUnsetBackpack(
final ArmorItem backpack,
final MessageHandler messageHandler) {
final MessageHandler messageHandler,
final HMCCosmetics plugin) {
final Player player = this.getPlayer();
@@ -93,7 +100,7 @@ public class User {
}
if (backpack.getId().equals(this.playerArmor.getBackpack().getId())) {
this.setBackpack(ArmorItem.empty(ArmorItem.Type.BACKPACK));
this.setBackpack(ArmorItem.empty(ArmorItem.Type.BACKPACK), plugin);
messageHandler.sendMessage(
player,
@@ -103,7 +110,7 @@ public class User {
return false;
}
this.setBackpack(backpack);
this.setBackpack(backpack, plugin);
messageHandler.sendMessage(
player,
Messages.SET_BACKPACK
@@ -113,17 +120,19 @@ public class User {
}
public void setHat(final ArmorItem hat, final UserManager userManager) {
public void setHat(ArmorItem hat, final HMCCosmetics plugin) {
this.playerArmor.setHat(hat);
this.lastSetItem = hat;
userManager.updateHat(this);
plugin.getUserManager().updateHat(this);
Bukkit.getScheduler().runTaskAsynchronously(plugin,
() -> plugin.getDatabase().saveUser(this));
}
// return true if hat was set
public boolean setOrUnsetHat(
final ArmorItem hat,
final MessageHandler messageHandler,
final UserManager userManager) {
final HMCCosmetics plugin) {
final Player player = this.getPlayer();
@@ -132,7 +141,7 @@ public class User {
}
if (hat.getId().equals(this.playerArmor.getHat().getId())) {
this.setHat(ArmorItem.empty(ArmorItem.Type.BACKPACK), userManager);
this.setHat(ArmorItem.empty(ArmorItem.Type.BACKPACK), plugin);
messageHandler.sendMessage(
player,
@@ -142,7 +151,7 @@ public class User {
return false;
}
this.setHat(hat, userManager);
this.setHat(hat, plugin);
messageHandler.sendMessage(
player,
Messages.SET_HAT
@@ -291,4 +300,12 @@ public class User {
public ArmorItem getLastSetItem() {
return lastSetItem;
}
public int getDye() {
return this.playerArmor.getDye();
}
public void setDye(final int dye) {
this.playerArmor.setDye(dye);
}
}

View File

@@ -30,11 +30,9 @@ import java.util.UUID;
public class UserManager {
private int currentArmorStandId = Integer.MAX_VALUE;
private final HMCCosmetics plugin;
private final Map<UUID, User> userMap = new HashMap<>();
private final Map<Integer, User> armorStandIdMap = new HashMap<>();
private BukkitTask teleportTask;
@@ -43,16 +41,9 @@ public class UserManager {
this.registerPacketListener();
}
public void add(final Player player) {
final UUID uuid = player.getUniqueId();
final int armorStandId = this.currentArmorStandId;
final User user = new User(
uuid,
PlayerArmor.empty(),
armorStandId);
this.userMap.put(uuid, user);
this.armorStandIdMap.put(armorStandId, user);
this.currentArmorStandId--;
public void add(final User user) {
this.userMap.put(user.getUuid(), user);
this.setFakeHelmet(user);
}
public Optional<User> get(final UUID uuid) {
@@ -71,8 +62,6 @@ public class UserManager {
user.removeAllCosmetics();
this.setFakeHelmet(user);
user.despawnAttached();
this.armorStandIdMap.remove(user.getArmorStandId());
}
public void startTeleportTask() {