Added loading/saving shops in a database

This commit is contained in:
Teriuihi 2022-08-03 19:11:03 +02:00
parent d4c4163bc4
commit eb8ee00e4a
9 changed files with 389 additions and 0 deletions

View File

@ -0,0 +1,48 @@
package com.alttd.playershops.config;
import com.alttd.galaxy.configuration.AbstractConfiguration;
import com.alttd.playershops.api.ShopType;
import java.io.File;
import java.util.HashMap;
public class DatabaseConfig extends AbstractConfiguration {
private DatabaseConfig() {
super(new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "com/alttd/playershops"), "database");
}
static DatabaseConfig config;
static int version;
static HashMap<ShopType, ShopTypeConfig> shopTypeConfigs;
public static void reload() {
config = new DatabaseConfig();
version = config.getInt("config-version", 1);
config.set("config-version", 1);
config.readConfig(DatabaseConfig.class, null);
shopTypeConfigs = new HashMap<>();
for (ShopType shopType : ShopType.values()) {
shopTypeConfigs.put(shopType, new ShopTypeConfig(shopType.toString()));
}
}
public static String DRIVER = "mysql";
public static String IP = "localhost";
public static String PORT = "3306";
public static String DATABASE_NAME = "AltitudeQuests";
public static String USERNAME = "root";
public static String PASSWORD = "root";
private static void loadDatabase() {
DRIVER = config.getString("database.driver", DRIVER);
IP = config.getString("database.ip", IP);
PORT = config.getString("database.port", PORT);
DATABASE_NAME = config.getString("database.name", DATABASE_NAME);
USERNAME = config.getString("database.username", USERNAME);
PASSWORD = config.getString("database.password", PASSWORD);
}
}

View File

@ -0,0 +1,118 @@
package com.alttd.playershops.database;
import com.alttd.playershops.PlayerShops;
import com.alttd.playershops.config.DatabaseConfig;
import com.alttd.playershops.utils.Logger;
import org.bukkit.Bukkit;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Database {
private static Database instance = null;
private Connection connection = null;
private Database() {}
public static Database getDatabase(){
if (instance == null)
{
instance = new Database();
instance.init();
}
return (instance);
}
protected void init() {
try {
openConnection();
} catch (SQLException e) {
e.printStackTrace();
}
//Run all create table functions
for (Method method : Database.class.getDeclaredMethods()) {
if (Modifier.isPrivate(method.getModifiers())) {
if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
try {
method.setAccessible(true);
method.invoke(instance);
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (Exception ex) {
Logger.severe("Error invoking " + method + ".");
ex.printStackTrace();
}
}
}
}
}
/**
* Opens the connection if it's not already open.
* @throws SQLException If it can't create the connection.
*/
private void openConnection() throws SQLException {
if (connection != null && !connection.isClosed()) {
return;
}
synchronized (this) {
if (connection != null && !connection.isClosed()) {
return;
}
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
connection = DriverManager.getConnection(
"jdbc:mysql://" + DatabaseConfig.IP + ":" + DatabaseConfig.PORT + "/" + DatabaseConfig.DATABASE_NAME +
"?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true",
DatabaseConfig.USERNAME, DatabaseConfig.PASSWORD);
}
}
public Connection getConnection() {
try {
openConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
private static void createShopTable() {
try {
String sql = "CREATE TABLE IF NOT EXISTS shops(" +
"id INT NOT NULL AUTO_INCREMENT, " +
"owner_name VARCHAR(16) NOT NULL, " +
"owner_uuid VARCHAR(36) NOT NULL, " +
"shop_type VARCHAR(36) NOT NULL, " +
"server VARCHAR(16) NOT NULL, " +
"container_location VARCHAR(256), " +
"sign_location VARCHAR(256), " +
"price DOUBLE NOT NULL, " +
"amount INT NOT NULL, " +
"balance DOUBLE NOT NULL, " +
"item_one TEXT, " +
"item_two TEXT, " +
"last_transaction BIGINT, " +
"PRIMARY KEY (id)" +
")";
getDatabase().getConnection().prepareStatement(sql).executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
Logger.severe("Error while trying to create shop table");
Logger.severe("Shutting down PlayerShops");
Bukkit.getPluginManager().disablePlugin(PlayerShops.getInstance());
}
}
}

View File

@ -0,0 +1,152 @@
package com.alttd.playershops.database;
import com.alttd.playershops.api.Shop;
import com.alttd.playershops.api.ShopType;
import com.alttd.playershops.shop.AbstractShop;
import com.alttd.playershops.utils.AMath;
import com.alttd.playershops.utils.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ShopQueries {
public static boolean saveShop(AbstractShop shop) {
String sql = "INSERT INTO shops " +
"(id, owner_name, owner_uuid, shop_type, server, container_location, sign_location, " +
"price, amount, balance, item_one, item_two, last_transaction)" +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
"ON DUPLICATE KEY UPDATE owner_name = ?, owner_uuid = ?, shop_type = ?, server = ?, " +
"container_location = ?, sign_location = ?, price = ?, amount = ?, balance = ?, " +
"item_one = ?, item_two = ?, last_transaction = ?";
try {
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
statement.setInt(1, shop.getId());
statement.setString(2, shop.getOwnerName());
statement.setString(3, shop.getOwnerUUID().toString());
statement.setString(4, shop.getServer());
statement.setString(5, shop.getType().toString());
statement.setString(6, locationToString(shop.getContainerLocation()));
statement.setString(7, locationToString(shop.getSignLocation()));
statement.setDouble(8, shop.getPrice());
statement.setInt(9, shop.getAmount());
statement.setDouble(10, shop.getBalance());
statement.setBytes(11, shop.getItemStack().serializeAsBytes());
statement.setBytes(12, shop.getSecondaryItem().serializeAsBytes());
statement.setLong(13, shop.getLastTransaction());
//repeat everything except id for update
statement.setString(14, shop.getOwnerName());
statement.setString(15, shop.getOwnerUUID().toString());
statement.setString(16, shop.getServer());
statement.setString(17, shop.getType().toString());
statement.setString(18, locationToString(shop.getContainerLocation()));
statement.setString(19, locationToString(shop.getSignLocation()));
statement.setDouble(20, shop.getPrice());
statement.setInt(21, shop.getAmount());
statement.setDouble(22, shop.getBalance());
statement.setBytes(23, shop.getItemStack().serializeAsBytes());
statement.setBytes(24, shop.getSecondaryItem().serializeAsBytes());
statement.setLong(25, shop.getLastTransaction());
return statement.executeUpdate() == 1;
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public static Shop loadShop(int id) {
String sql = "SELECT * FROM shops WHERE id = ?";
try {
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
statement.setInt(1, id);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next())
return shopFromResultSet(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static List<Shop> loadShops() {
String sql = "SELECT * FROM shops";
ArrayList<Shop> shops = new ArrayList<>();
try {
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
Shop shop = shopFromResultSet(resultSet);
if (shop == null) {
Logger.warn("Tried to load a shop but failed [" + resultSet + "]");
continue;
}
shops.add(shop);
}
} catch (SQLException e) {
e.printStackTrace();
}
return shops;
}
/**
* Loads a shop from a result set, does not iterate
* @param resultSet Result set to load from
* @return A shop
* @throws SQLException if data is missing or formatted incorrectly
*/
private static Shop shopFromResultSet(ResultSet resultSet) throws SQLException {
int id = resultSet.getInt("id");
String ownerName = resultSet.getString("owner_name");
UUID ownerUuid = UUID.fromString(resultSet.getString("owner_uuid"));
ShopType shopType = ShopType.valueOf(resultSet.getString("shop_type"));
String server = resultSet.getString("server");
Location containerLocation = stringToLocation(resultSet.getString("container_location"));
Location signLocation = stringToLocation(resultSet.getString("sign_location"));
double price = resultSet.getDouble("price");
int amount = resultSet.getInt("amount");
double balance = resultSet.getDouble("balance");
ItemStack itemOne = ItemStack.deserializeBytes(resultSet.getBytes("item_one"));
ItemStack itemTwo = ItemStack.deserializeBytes(resultSet.getBytes("item_two"));
long lastTransaction = resultSet.getLong("last_transaction");
if (containerLocation == null || signLocation == null)
return null;
return AbstractShop.create(id, ownerName, ownerUuid, shopType, server, containerLocation, signLocation,
price, amount, balance, itemOne, itemTwo, lastTransaction);
}
private static String locationToString(Location location) {
return location.getWorld() + ":" +
AMath.round(location.getX(), 1) + ":" +
AMath.round(location.getY(), 1) + ":" +
AMath.round(location.getZ(), 1);
}
private static Location stringToLocation(String string) {
String[] split = string.split(":");
if (split.length != 4) {
Logger.warn("Unable to load location [" + string + "] due to invalid format");
return null;
}
try {
return new Location(Bukkit.getWorld(split[0]),
Double.parseDouble(split[1]), Double.parseDouble(split[2]), Double.parseDouble(split[3]));
} catch (NumberFormatException e) {
Logger.warn("Unable to load location [" + string + "] due to invalid format");
return null;
}
}
}

View File

@ -52,6 +52,24 @@ public abstract class AbstractShop implements Shop {
ownerName = getOwnerName();
this.price = price;
this.amount = amount;
this.server = Bukkit.getServerName();
}
AbstractShop(int id, String ownerName, UUID ownerUUID, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
this.id = id;
this.ownerName = ownerName;
this.ownerUUID = ownerUUID;
this.server = server;
this.containerLocation = containerLocation;
this.signLocation = signLocation;
this.price = price;
this.amount = amount;
this.balance = balance;
this.itemStack = itemOne;
this.secondaryItem = itemTwo;
this.lastTransaction = lastTransaction;
}
public static AbstractShop create(Location signLocation, UUID player, double price, int amount, ShopType shopType) {
@ -63,6 +81,17 @@ public abstract class AbstractShop implements Shop {
};
}
public static AbstractShop create(int id, String ownerName, UUID ownerUUID, ShopType shopType, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
return switch (shopType) {
case SELL -> new SellShop(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount, balance, itemOne, itemTwo, lastTransaction);
case BUY -> new BuyShop(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount, balance, itemOne, itemTwo, lastTransaction);
case GAMBLE -> new GambleShop(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount, balance, itemOne, itemTwo, lastTransaction);
case BARTER -> new BarterShop(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount, balance, itemOne, itemTwo, lastTransaction);
};
}
public String getOwnerName() {
if(this.ownerName != null) return ownerName;
if (this.getOwnerUUID() != null) {

View File

@ -2,6 +2,7 @@ package com.alttd.playershops.shop;
import com.alttd.playershops.api.ShopType;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import java.util.UUID;
@ -13,4 +14,12 @@ public class BarterShop extends AbstractShop {
this.setType(ShopType.BARTER);
}
public BarterShop(int id, String ownerName, UUID ownerUUID, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
super(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount,
balance, itemOne, itemTwo, lastTransaction);
this.setType(ShopType.BARTER);
}
}

View File

@ -2,6 +2,7 @@ package com.alttd.playershops.shop;
import com.alttd.playershops.api.ShopType;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import java.util.UUID;
@ -13,4 +14,11 @@ public class BuyShop extends AbstractShop {
this.setType(ShopType.BUY);
}
public BuyShop(int id, String ownerName, UUID ownerUUID, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
super(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount,
balance, itemOne, itemTwo, lastTransaction);
this.setType(ShopType.BUY);
}
}

View File

@ -17,4 +17,12 @@ public class GambleShop extends AbstractShop {
this.gambleItem = this.getItemStack();
}
public GambleShop(int id, String ownerName, UUID ownerUUID, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
super(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount,
balance, itemOne, itemTwo, lastTransaction);
this.setType(ShopType.GAMBLE);
}
}

View File

@ -2,6 +2,7 @@ package com.alttd.playershops.shop;
import com.alttd.playershops.api.ShopType;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import java.util.UUID;
@ -13,4 +14,12 @@ public class SellShop extends AbstractShop {
this.setType(ShopType.SELL);
}
public SellShop(int id, String ownerName, UUID ownerUUID, String server,
Location containerLocation, Location signLocation, double price, int amount,
double balance, ItemStack itemOne, ItemStack itemTwo, long lastTransaction) {
super(id, ownerName, ownerUUID, server, containerLocation, signLocation, price, amount,
balance, itemOne, itemTwo, lastTransaction);
this.setType(ShopType.SELL);
}
}

View File

@ -0,0 +1,8 @@
package com.alttd.playershops.utils;
public class AMath {
public static double round (double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) Math.round(value * scale) / scale;
}
}