commit
c8f19125f8
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -46,4 +46,7 @@ out/
|
||||||
# Linux temp files
|
# Linux temp files
|
||||||
*~
|
*~
|
||||||
|
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
/run1/
|
||||||
|
/lib/
|
||||||
|
/run/
|
||||||
|
|
|
||||||
131
build.gradle.kts
131
build.gradle.kts
|
|
@ -1,37 +1,53 @@
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.net.URL
|
||||||
|
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("java")
|
id("java")
|
||||||
id("net.minecrell.plugin-yml.bukkit") version "0.5.1"
|
id("net.minecrell.plugin-yml.bukkit") version "0.5.1"
|
||||||
id("com.github.johnrengelman.shadow") version "7.1.0"
|
// id("com.github.johnrengelman.shadow") version "7.1.0"
|
||||||
|
id("xyz.jpenilla.run-paper") version "1.0.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
group = "com.alttd.playershops"
|
||||||
group = "com.alttd.playershops"
|
version = "1.0-SNAPSHOT"
|
||||||
version = "1.0-SNAPSHOT"
|
description = "Player Shop plugin for Altitude."
|
||||||
description = "Player Shop plugin for Altitude."
|
|
||||||
|
|
||||||
apply<JavaLibraryPlugin>()
|
apply<JavaLibraryPlugin>()
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion.set(JavaLanguageVersion.of(17))
|
languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
withType<JavaCompile> {
|
|
||||||
options.encoding = Charsets.UTF_8.name()
|
|
||||||
}
|
|
||||||
|
|
||||||
withType<Javadoc> {
|
|
||||||
options.encoding = Charsets.UTF_8.name()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
withType<JavaCompile> {
|
||||||
|
options.encoding = Charsets.UTF_8.name()
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<Javadoc> {
|
||||||
|
options.encoding = Charsets.UTF_8.name()
|
||||||
|
}
|
||||||
|
|
||||||
|
runServer {
|
||||||
|
val fileName = "./run/galaxy.jar"
|
||||||
|
var file = File(fileName)
|
||||||
|
if (!file.parentFile.exists()) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
}
|
||||||
|
if (!file.exists()) {
|
||||||
|
download("https://repo.destro.xyz/snapshots/com/alttd/Galaxy-Server/Galaxy-paperclip-1.19.2-R0.1-SNAPSHOT-reobf.jar", fileName)
|
||||||
|
}
|
||||||
|
serverJar(file)
|
||||||
|
minecraftVersion("1.19.2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("com.alttd:Galaxy-API:1.18.2-R0.1-SNAPSHOT")
|
compileOnly("com.alttd:Galaxy-API:1.19.2-R0.1-SNAPSHOT")
|
||||||
compileOnly("com.github.milkbowl:VaultAPI:1.7") {
|
compileOnly("com.github.milkbowl:VaultAPI:1.7") {
|
||||||
exclude("org.bukkit","bukkit")
|
exclude("org.bukkit","bukkit")
|
||||||
}
|
}
|
||||||
|
|
@ -50,11 +66,82 @@ fun gitCommit(): String {
|
||||||
return String(os.toByteArray()).trim()
|
return String(os.toByteArray()).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun download(link: String, path: String) {
|
||||||
|
URL(link).openStream().use { input ->
|
||||||
|
FileOutputStream(File(path)).use { output ->
|
||||||
|
input.copyTo(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bukkit {
|
bukkit {
|
||||||
name = rootProject.name
|
name = rootProject.name
|
||||||
main = "$group.${rootProject.name}"
|
main = "$group.${rootProject.name}"
|
||||||
version = "${rootProject.version}-${gitCommit()}"
|
version = "${rootProject.version}-${gitCommit()}"
|
||||||
apiVersion = "1.18"
|
apiVersion = "1.19"
|
||||||
authors = listOf("destro174")
|
authors = listOf("destro174")
|
||||||
depend = listOf("Vault")
|
depend = listOf("Vault")
|
||||||
|
|
||||||
|
commands {
|
||||||
|
register("playershop") {
|
||||||
|
description = "This is a test command!"
|
||||||
|
aliases = listOf("shop")
|
||||||
|
permission = "playershops.command.playershop"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions {
|
||||||
|
register("playershops.admin") {
|
||||||
|
description = "Admin permission for the ${rootProject.name} plugin."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
children = listOf(
|
||||||
|
"playershops.shop.create",
|
||||||
|
"playershops.shop.break.other",
|
||||||
|
"playershops.shop.use",
|
||||||
|
"playershops.shop.use.buy",
|
||||||
|
"playershops.shop.use.sell",
|
||||||
|
"playershops.shop.use.gamble"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
register("playershops.shoplimit") {
|
||||||
|
description = "Base permission to allow per player shop limits."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
register("playershops.shop.create") {
|
||||||
|
description = "Allows players to create shops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
register("playershops.shop.break") {
|
||||||
|
description = "Allows players to break shops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
register("playershops.shop.break.other") {
|
||||||
|
description = "Allows players to break other players shops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
children = listOf(
|
||||||
|
"playershops.shop.break",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
register("playershops.shop.use") {
|
||||||
|
description = "Allows players to use all playershops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
children = listOf(
|
||||||
|
"playershops.shop.use.buy",
|
||||||
|
"playershops.shop.use.sell",
|
||||||
|
"playershops.shop.use.gamble"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
register("playershops.shop.use.buy") {
|
||||||
|
description = "Allows players to use buying playershops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
register("playershops.shop.use.sell") {
|
||||||
|
description = "Allows players to use selling playershops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
register("playershops.shop.use.gamble") {
|
||||||
|
description = "Allows players to use gamble playershops."
|
||||||
|
default = BukkitPluginDescription.Permission.Default.FALSE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
rootProject.name = "PlayerShops"
|
rootProject.name = "PlayerShops"
|
||||||
|
|
||||||
include(":api")
|
|
||||||
include(":plugin")
|
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package com.alttd.playershops;
|
package com.alttd.playershops;
|
||||||
|
|
||||||
|
import com.alttd.playershops.commands.ShopCommand;
|
||||||
import com.alttd.playershops.config.Config;
|
import com.alttd.playershops.config.Config;
|
||||||
|
import com.alttd.playershops.config.DatabaseConfig;
|
||||||
import com.alttd.playershops.config.MessageConfig;
|
import com.alttd.playershops.config.MessageConfig;
|
||||||
|
import com.alttd.playershops.gui.GuiIcon;
|
||||||
import com.alttd.playershops.handler.ShopHandler;
|
import com.alttd.playershops.handler.ShopHandler;
|
||||||
import com.alttd.playershops.listener.PlayerListener;
|
import com.alttd.playershops.listener.*;
|
||||||
import com.alttd.playershops.listener.ShopListener;
|
import com.alttd.playershops.shop.ShopType;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseManager;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseHelper;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import net.milkbowl.vault.economy.Economy;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
@ -19,9 +24,14 @@ public class PlayerShops extends JavaPlugin {
|
||||||
private Economy econ = null;
|
private Economy econ = null;
|
||||||
@Getter
|
@Getter
|
||||||
private ShopHandler shopHandler;
|
private ShopHandler shopHandler;
|
||||||
|
@Getter
|
||||||
|
private DatabaseManager databaseManager;
|
||||||
|
@Getter
|
||||||
|
private DatabaseHelper databaseHelper;
|
||||||
private ShopListener shopListener;
|
private ShopListener shopListener;
|
||||||
private PlayerListener playerListener;
|
private PlayerListener playerListener;
|
||||||
|
private TransactionListener transactionListener;
|
||||||
|
private InventoryListener inventoryListener;
|
||||||
|
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
@ -32,11 +42,24 @@ public class PlayerShops extends JavaPlugin {
|
||||||
}
|
}
|
||||||
Bukkit.getLogger().info("Hooked into Vault economy provided by " + econ.getName());
|
Bukkit.getLogger().info("Hooked into Vault economy provided by " + econ.getName());
|
||||||
reloadConfigs();
|
reloadConfigs();
|
||||||
|
if(!setupDatabase()) {
|
||||||
|
Bukkit.getLogger().warning("Error setting up database connection.\n Disabling plugin");
|
||||||
|
this.setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shopHandler = new ShopHandler(instance);
|
||||||
|
|
||||||
registerListeners();
|
registerListeners();
|
||||||
registerCommands();
|
registerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
shopHandler = new ShopHandler(instance);
|
public void onDisable() {
|
||||||
|
shopHandler.unloadShops();
|
||||||
|
unRegisterListeners();
|
||||||
|
Bukkit.getScheduler().cancelTasks(this);
|
||||||
|
|
||||||
|
databaseManager.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setupEconomy() {
|
private boolean setupEconomy() {
|
||||||
|
|
@ -51,6 +74,13 @@ public class PlayerShops extends JavaPlugin {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean setupDatabase() {
|
||||||
|
this.databaseManager = new DatabaseManager(this);
|
||||||
|
this.databaseHelper = new DatabaseHelper(this, this.databaseManager);
|
||||||
|
this.databaseHelper.init();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public Economy getEconomy() {
|
public Economy getEconomy() {
|
||||||
if(econ == null)
|
if(econ == null)
|
||||||
setupEconomy();
|
setupEconomy();
|
||||||
|
|
@ -60,22 +90,32 @@ public class PlayerShops extends JavaPlugin {
|
||||||
private void registerListeners() {
|
private void registerListeners() {
|
||||||
shopListener = new ShopListener(this);
|
shopListener = new ShopListener(this);
|
||||||
playerListener = new PlayerListener(this);
|
playerListener = new PlayerListener(this);
|
||||||
|
transactionListener = new TransactionListener(this);
|
||||||
|
inventoryListener = new InventoryListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UnregisterListeners() {
|
private void unRegisterListeners() {
|
||||||
shopListener.unregister();
|
shopListener.unregister();
|
||||||
playerListener.unregister();
|
playerListener.unregister();
|
||||||
|
transactionListener.unregister();
|
||||||
|
inventoryListener.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
// for(String command : this.getDescription().getCommands().keySet()) {
|
getCommand("playershop").setExecutor(new ShopCommand());
|
||||||
// getCommand(command).setExecutor();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadConfigs() {
|
public void reloadConfigs() {
|
||||||
Config.reload();
|
Config.reload();
|
||||||
MessageConfig.reload();
|
MessageConfig.reload();
|
||||||
|
DatabaseConfig.reload();
|
||||||
|
|
||||||
|
for (ShopType shopType : ShopType.values()) {
|
||||||
|
// preload ShopType to get the configs active
|
||||||
|
}
|
||||||
|
for (GuiIcon guiIcon : GuiIcon.values()) {
|
||||||
|
// preload to get config values generated
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.alttd.playershops.commands;
|
||||||
|
|
||||||
|
import com.alttd.playershops.gui.HomeGui;
|
||||||
|
import com.alttd.playershops.gui.ShopManagementGui;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
// expose brig in Galaxy?
|
||||||
|
public class ShopCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
if (!(sender instanceof Player player)) return true;
|
||||||
|
if (args.length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (args[0].toLowerCase()) {
|
||||||
|
case "reload":
|
||||||
|
break;
|
||||||
|
case "open":
|
||||||
|
HomeGui gui = new HomeGui(player.getUniqueId());
|
||||||
|
gui.open();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sender.sendMessage("invalid command useage");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||||
|
if (args.length == 1) {
|
||||||
|
return Stream.of("reload", "open")
|
||||||
|
.filter(arg -> arg.startsWith(args[0].toLowerCase()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,19 @@
|
||||||
package com.alttd.playershops.config;
|
package com.alttd.playershops.config;
|
||||||
|
|
||||||
import com.alttd.galaxy.configuration.AbstractConfiguration;
|
import com.alttd.galaxy.configuration.AbstractConfiguration;
|
||||||
import com.alttd.playershops.shop.ShopType;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class Config extends AbstractConfiguration {
|
public class Config extends AbstractConfiguration {
|
||||||
|
|
||||||
public static File configPath = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "com/alttd/playershops");
|
public static File configPath = new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "playershops");
|
||||||
private Config() {
|
private Config() {
|
||||||
super(Config.configPath, "config");
|
super(Config.configPath, "config");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Config config;
|
static Config config;
|
||||||
static int version;
|
static int version;
|
||||||
static HashMap<ShopType, ShopTypeConfig> shopTypeConfigs;
|
|
||||||
|
|
||||||
public static void reload() {
|
public static void reload() {
|
||||||
config = new Config();
|
config = new Config();
|
||||||
|
|
@ -25,27 +22,18 @@ public class Config extends AbstractConfiguration {
|
||||||
config.set("config-version", 1);
|
config.set("config-version", 1);
|
||||||
|
|
||||||
config.readConfig(Config.class, null);
|
config.readConfig(Config.class, null);
|
||||||
|
|
||||||
shopTypeConfigs = new HashMap<>();
|
|
||||||
for (ShopType shopType : ShopType.values()) {
|
|
||||||
shopTypeConfigs.put(shopType, new ShopTypeConfig(shopType.toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int shopLimit = 100;
|
public static int shopLimit = 100;
|
||||||
public static boolean usePermissionShopLimit = false;
|
public static boolean usePermissionShopLimit = false;
|
||||||
public static String shopCreationWord = "[SHOP]";
|
public static String shopCreationWord = "[SHOP]";
|
||||||
|
public static double shopCreationBalance = 2500; // minimum amount of balance to create a shop, this is to cover the cost to manage shops and upkeep
|
||||||
private static void shopSettings() {
|
private static void shopSettings() {
|
||||||
String path = "shop-settings.";
|
String path = "shop-settings.";
|
||||||
shopLimit = config.getInt(path + "player-shop-limit", shopLimit);
|
shopLimit = config.getInt(path + "default-shop-limit", shopLimit);
|
||||||
usePermissionShopLimit = config.getBoolean(path + "use-permission-based-shop-limit", usePermissionShopLimit);
|
usePermissionShopLimit = config.getBoolean(path + "use-permission-based-shop-limit", usePermissionShopLimit);
|
||||||
shopCreationWord = config.getString(path + "creation-word", shopCreationWord);
|
shopCreationWord = config.getString(path + "creation-word", shopCreationWord);
|
||||||
}
|
shopCreationBalance = config.getDouble(path + "creation-balance", shopCreationBalance);
|
||||||
|
|
||||||
public static String shopLimitPermission = "shop.buildlimit";
|
|
||||||
private static void permissionSettings() {
|
|
||||||
String path = "permission.";
|
|
||||||
shopLimitPermission = config.getString(path + "build-limit", shopLimitPermission);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class DatabaseConfig extends AbstractConfiguration {
|
||||||
public static String DRIVER = "mysql";
|
public static String DRIVER = "mysql";
|
||||||
public static String IP = "localhost";
|
public static String IP = "localhost";
|
||||||
public static String PORT = "3306";
|
public static String PORT = "3306";
|
||||||
public static String DATABASE_NAME = "AltitudeQuests";
|
public static String DATABASE_NAME = "PlayerShops";
|
||||||
public static String USERNAME = "root";
|
public static String USERNAME = "root";
|
||||||
public static String PASSWORD = "root";
|
public static String PASSWORD = "root";
|
||||||
|
|
||||||
|
|
@ -38,4 +38,12 @@ public class DatabaseConfig extends AbstractConfiguration {
|
||||||
USERNAME = config.getString("database.username", USERNAME);
|
USERNAME = config.getString("database.username", USERNAME);
|
||||||
PASSWORD = config.getString("database.password", PASSWORD);
|
PASSWORD = config.getString("database.password", PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time in seconds between database tasks
|
||||||
|
public static int queueDelay = 5;
|
||||||
|
public static int maxDatabaseConnections = 10;
|
||||||
|
private static void databaseSettings() {
|
||||||
|
queueDelay = config.getInt("database.queue.delay" , queueDelay);
|
||||||
|
maxDatabaseConnections = config.getInt("database.maximum-connections" , maxDatabaseConnections);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.alttd.playershops.config;
|
||||||
|
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class GuiIconConfig {
|
||||||
|
|
||||||
|
|
||||||
|
private final String icon;
|
||||||
|
private final String configPath;
|
||||||
|
private final String defaultPath;
|
||||||
|
public GuiIconConfig(String icon) {
|
||||||
|
this.icon = icon;
|
||||||
|
this.configPath = "gui-icon." + this.icon + ".";
|
||||||
|
this.defaultPath = "gui-icon.divider.";
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int version;
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
Config.config.readConfig(GuiIconConfig.class, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void set(String path, Object def) {
|
||||||
|
Config.config.set(path, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(String path, String def) {
|
||||||
|
set(defaultPath + path, def);
|
||||||
|
return Config.config.getNode(configPath + path).getString(
|
||||||
|
Config.config.getNode(defaultPath + path).getString(def));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInt(String path, int def) {
|
||||||
|
set(defaultPath + path, def);
|
||||||
|
return Config.config.getNode(configPath + path).getInt(
|
||||||
|
Config.config.getNode(defaultPath + path).getInt(def));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getStringList(String path, List<String> def) {
|
||||||
|
try {
|
||||||
|
set(defaultPath + path, def);
|
||||||
|
return Config.config.getNode(configPath + path).getList(TypeToken.get(String.class),
|
||||||
|
Config.config.getNode(defaultPath + path).getList(TypeToken.get(String.class), def));
|
||||||
|
} catch(SerializationException ignore) {}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int slot = 0;
|
||||||
|
public String displayName = "Default";
|
||||||
|
public String material = "dirt";
|
||||||
|
public List<String> lore = new ArrayList<>();
|
||||||
|
private void guiItems() {
|
||||||
|
slot = getInt("slot", slot);
|
||||||
|
material = getString("material", material);
|
||||||
|
displayName = getString("display-name", displayName);
|
||||||
|
lore = getStringList("lore", lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
package com.alttd.playershops.config;
|
package com.alttd.playershops.config;
|
||||||
|
|
||||||
import com.alttd.galaxy.configuration.AbstractConfiguration;
|
import com.alttd.galaxy.configuration.AbstractConfiguration;
|
||||||
import com.alttd.playershops.shop.ShopType;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
public class MessageConfig extends AbstractConfiguration {
|
public class MessageConfig extends AbstractConfiguration {
|
||||||
|
|
||||||
|
|
@ -13,7 +10,6 @@ public class MessageConfig extends AbstractConfiguration {
|
||||||
|
|
||||||
static MessageConfig config;
|
static MessageConfig config;
|
||||||
static int version;
|
static int version;
|
||||||
static HashMap<ShopType, ShopTypeConfig> shopTypeConfigs;
|
|
||||||
|
|
||||||
public static void reload() {
|
public static void reload() {
|
||||||
config = new MessageConfig();
|
config = new MessageConfig();
|
||||||
|
|
@ -22,11 +18,6 @@ public class MessageConfig extends AbstractConfiguration {
|
||||||
config.set("config-version", 1);
|
config.set("config-version", 1);
|
||||||
|
|
||||||
config.readConfig(Config.class, null);
|
config.readConfig(Config.class, null);
|
||||||
|
|
||||||
shopTypeConfigs = new HashMap<>();
|
|
||||||
for (ShopType shopType : ShopType.values()) {
|
|
||||||
shopTypeConfigs.put(shopType, new ShopTypeConfig(shopType.toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String SHOP_ALREADY_EXISTS = "<red>This block is already a Shop</red>";
|
public static String SHOP_ALREADY_EXISTS = "<red>This block is already a Shop</red>";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
package com.alttd.playershops.config;
|
package com.alttd.playershops.config;
|
||||||
|
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ShopTypeConfig {
|
public class ShopTypeConfig {
|
||||||
|
|
||||||
private final String shopType;
|
private final String shopType;
|
||||||
|
|
@ -27,4 +33,41 @@ public class ShopTypeConfig {
|
||||||
Config.config.getNode(defaultPath + path).getString(def));
|
Config.config.getNode(defaultPath + path).getString(def));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> getStringList(String path, List<String> def) {
|
||||||
|
try {
|
||||||
|
set(defaultPath + path, def);
|
||||||
|
return Config.config.getNode(configPath + path).getList(TypeToken.get(String.class),
|
||||||
|
Config.config.getNode(defaultPath + path).getList(TypeToken.get(String.class), def));
|
||||||
|
} catch(SerializationException ignore) {}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> activeSignLines = List.of("<green>[Shop]", "", "", "");
|
||||||
|
public List<String> inActiveSignLines = List.of("<green>[Shop]", "right click", "to manage", "<ownername>");
|
||||||
|
public List<String> expiredSignLines = List.of("[Shop]", "expired", "", "<ownername>");
|
||||||
|
public List<String> deletedSignLines = List.of("[Shop]", "deleted", "", "<ownername>");
|
||||||
|
private void signSettings() {
|
||||||
|
activeSignLines = getStringList("sign.active-lines", activeSignLines);
|
||||||
|
inActiveSignLines = getStringList("sign.inactive-lines", inActiveSignLines);
|
||||||
|
expiredSignLines = getStringList("sign.expired-lines", expiredSignLines);
|
||||||
|
deletedSignLines = getStringList("sign.deleted-lines", deletedSignLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String playerInventoryFull = "<red>You do not have enough space in your inventory to buy from this shop.";
|
||||||
|
public String playerNoFunds = "<red>You do not have sufficient funds to trade with this shop.";
|
||||||
|
public String playerBought = "<white>You bought <amount> <item>(s) from <ownername> for <price>.";
|
||||||
|
public String shopSold = "<white><user> bought <amount> <item>(s) from you for <price>.";
|
||||||
|
public String shopInventoryFull = "<red>This shop does not have enough space in its inventory.";
|
||||||
|
public String shopNoStock = "<red>This shop is out of stock.";
|
||||||
|
public String yourShopNoFunds = "<red>Your <item> shop at <location> is out of funds";
|
||||||
|
public String yourShopNoStock = "<red>Your <item> shop at <location> is out of stock";
|
||||||
|
private void transactionMessages() {
|
||||||
|
playerInventoryFull = getString("transaction.player-inventory-full", playerInventoryFull);
|
||||||
|
playerNoFunds = getString("transaction.player-no-funds", playerNoFunds);
|
||||||
|
shopInventoryFull = getString("transaction.shop-inventory-full", shopInventoryFull);
|
||||||
|
shopNoStock = getString("transaction.shop-no-stock", shopNoStock);
|
||||||
|
yourShopNoFunds = getString("transaction.your-shop-no-funds", yourShopNoFunds);
|
||||||
|
yourShopNoStock = getString("transaction.your-shop-no-stock", yourShopNoStock);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
package com.alttd.playershops.conversation;
|
||||||
|
|
||||||
|
import com.alttd.playershops.gui.ShopManagementGui;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.shop.ShopType;
|
||||||
|
import com.alttd.playershops.utils.EconomyUtils;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import org.bukkit.conversations.*;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ConversationManager implements ConversationAbandonedListener {
|
||||||
|
|
||||||
|
PlayerShop playerShop;
|
||||||
|
Player player;
|
||||||
|
Conversation conversation;
|
||||||
|
|
||||||
|
public ConversationManager(JavaPlugin plugin, Player player, ConversationType conversationType, PlayerShop playerShop) {
|
||||||
|
if (player.isConversing()) return;
|
||||||
|
this.player = player;
|
||||||
|
this.playerShop = playerShop;
|
||||||
|
ConversationFactory conversationFactory = new ConversationFactory(plugin)
|
||||||
|
.withModality(true)
|
||||||
|
.withFirstPrompt(getPrompt(conversationType))
|
||||||
|
.addConversationAbandonedListener(this)
|
||||||
|
.withEscapeSequence("cancel");
|
||||||
|
conversation = conversationFactory.buildConversation(player);
|
||||||
|
conversation.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Prompt getPrompt(ConversationType conversationType) {
|
||||||
|
switch (conversationType) {
|
||||||
|
case CHANGE_ITEM -> {
|
||||||
|
return new ChangeItemPrompt();
|
||||||
|
}
|
||||||
|
case CHANGE_AMOUNT -> {
|
||||||
|
return new ChangeAmountPrompt();
|
||||||
|
}
|
||||||
|
case CHANGE_TYPE -> {
|
||||||
|
return new ChangeTypePrompt();
|
||||||
|
}
|
||||||
|
case WITHDRAW_BALANCE -> {
|
||||||
|
return new WithdrawBalancePrompt();
|
||||||
|
}
|
||||||
|
case ADD_BALANCE -> {
|
||||||
|
return new AddBalancePrompt();
|
||||||
|
}
|
||||||
|
case CHANGE_PRICE -> {
|
||||||
|
return new ChangePricePrompt();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openGui() {
|
||||||
|
player.abandonConversation(conversation);
|
||||||
|
ShopManagementGui shopManagementGui = new ShopManagementGui(player.getUniqueId(), playerShop);
|
||||||
|
shopManagementGui.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void conversationAbandoned(@NotNull ConversationAbandonedEvent abandonedEvent) {
|
||||||
|
// abandonedEvent.getContext().getForWhom().sendRawMessage("Conversation ended.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChangeTypePrompt extends FixedSetPrompt {
|
||||||
|
|
||||||
|
public ChangeTypePrompt() {
|
||||||
|
super("buy", "sell", "none"); // todo can this be automated shoptype.values()
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "What shoptype would you like to use: " + Joiner.on(", ").join(fixedSet) + " Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, String input) {
|
||||||
|
ShopType newType = ShopType.fromString(input);
|
||||||
|
if (playerShop.getType() == newType) {
|
||||||
|
context.getForWhom().sendRawMessage("Shoptype was already set to " + newType.toString() + " Type cancel to cancel this action.");
|
||||||
|
return new ChangeTypePrompt();
|
||||||
|
}
|
||||||
|
playerShop.setShopType(newType);
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChangePricePrompt extends NumericPrompt {
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "What should the price be? Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNumberValid(ConversationContext context, Number input) {
|
||||||
|
return input.doubleValue() >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFailedValidationText(ConversationContext context, Number invalidInput) {
|
||||||
|
return "Input must 0 or higher. Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, Number number) {
|
||||||
|
playerShop.setPrice(number.doubleValue());
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChangeAmountPrompt extends NumericPrompt {
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "How many items would you like to sell? Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNumberValid(ConversationContext context, Number input) {
|
||||||
|
return input.intValue() > 0 && input.intValue() <= 3456;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFailedValidationText(ConversationContext context, Number invalidInput) {
|
||||||
|
return "Input must be between 1 and 3456. Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, Number number) {
|
||||||
|
playerShop.setAmount(number.intValue());
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AddBalancePrompt extends NumericPrompt {
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "How much money would you like to add? Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNumberValid(ConversationContext context, Number input) {
|
||||||
|
if (input.doubleValue() < 0)
|
||||||
|
return false;
|
||||||
|
return EconomyUtils.hasSufficientFunds(player, input.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFailedValidationText(ConversationContext context, Number invalidInput) {
|
||||||
|
return "You do not have enough balance to deposit this amount. Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, Number number) {
|
||||||
|
playerShop.addBalance(number.doubleValue());
|
||||||
|
EconomyUtils.removeFunds(player, number.doubleValue());
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WithdrawBalancePrompt extends NumericPrompt {
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "How much money would you like to withdraw? Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNumberValid(ConversationContext context, Number input) {
|
||||||
|
if (input.doubleValue() < 0)
|
||||||
|
return false;
|
||||||
|
return EconomyUtils.hasSufficientFunds(playerShop, input.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFailedValidationText(ConversationContext context, Number invalidInput) {
|
||||||
|
return "Your shop does not have enough balance to withdraw this amount. Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, Number number) {
|
||||||
|
playerShop.removeBalance(number.doubleValue());
|
||||||
|
EconomyUtils.addFunds(player, number.doubleValue());
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChangeItemPrompt extends FixedSetPrompt {
|
||||||
|
|
||||||
|
ChangeItemPrompt() {
|
||||||
|
super("continue");
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull String getPromptText(ConversationContext context) {
|
||||||
|
return "Hold the item you would like to sell and type continue? Type cancel to cancel this action.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Prompt acceptValidatedInput(ConversationContext context, String input) {
|
||||||
|
playerShop.setItemStack(player.getInventory().getItemInMainHand().clone());
|
||||||
|
openGui();
|
||||||
|
return END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.alttd.playershops.conversation;
|
||||||
|
|
||||||
|
public enum ConversationType {
|
||||||
|
CHANGE_ITEM,
|
||||||
|
CHANGE_AMOUNT,
|
||||||
|
CHANGE_TYPE,
|
||||||
|
CHANGE_PRICE,
|
||||||
|
WITHDRAW_BALANCE,
|
||||||
|
ADD_BALANCE;
|
||||||
|
}
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
package com.alttd.playershops.database;
|
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
|
||||||
import com.alttd.playershops.shop.ShopType;
|
|
||||||
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 AbstractShop 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<AbstractShop> loadShops() {
|
|
||||||
String sql = "SELECT * FROM shops";
|
|
||||||
ArrayList<AbstractShop> shops = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
|
||||||
|
|
||||||
ResultSet resultSet = statement.executeQuery();
|
|
||||||
while (resultSet.next()) {
|
|
||||||
AbstractShop 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 AbstractShop 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -9,7 +9,7 @@ public class PlayerCreateShopEvent extends ShopEvent {
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private final Player player;
|
private final Player player;
|
||||||
|
|
||||||
public PlayerCreateShopEvent(Player player, AbstractShop shop) {
|
public PlayerCreateShopEvent(Player player, PlayerShop shop) {
|
||||||
super(shop);
|
super(shop);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -10,7 +10,7 @@ public class PlayerDestroyShopEvent extends ShopEvent {
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private final Player player;
|
private final Player player;
|
||||||
|
|
||||||
public PlayerDestroyShopEvent(Player player, AbstractShop shop) {
|
public PlayerDestroyShopEvent(Player player, PlayerShop shop) {
|
||||||
super(shop);
|
super(shop);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -10,7 +10,7 @@ public class PlayerExchangeShopEvent extends ShopEvent {
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private final Player player;
|
private final Player player;
|
||||||
|
|
||||||
public PlayerExchangeShopEvent(Player player, AbstractShop shop) {
|
public PlayerExchangeShopEvent(Player player, PlayerShop shop) {
|
||||||
super(shop);
|
super(shop);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -10,7 +10,7 @@ public class PlayerInitializeShopEvent extends ShopEvent {
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private final Player player;
|
private final Player player;
|
||||||
|
|
||||||
public PlayerInitializeShopEvent(Player player, AbstractShop shop) {
|
public PlayerInitializeShopEvent(Player player, PlayerShop shop) {
|
||||||
super(shop);
|
super(shop);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ public class ShopBalanceChangeEvent extends ShopEvent {
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private final ChangeReason changeReason;
|
private final ChangeReason changeReason;
|
||||||
|
|
||||||
public ShopBalanceChangeEvent(AbstractShop shop, ChangeReason reason) {
|
public ShopBalanceChangeEvent(PlayerShop shop, ChangeReason reason) {
|
||||||
super(shop);
|
super(shop);
|
||||||
this.changeReason = reason;
|
this.changeReason = reason;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ public class ShopBalanceChangeEvent extends ShopEvent {
|
||||||
public enum ChangeReason {
|
public enum ChangeReason {
|
||||||
|
|
||||||
DEPOSIT,
|
DEPOSIT,
|
||||||
WIDRAW,
|
WITHDRAW,
|
||||||
SELL,
|
SELL,
|
||||||
BUY,
|
BUY,
|
||||||
UPKEEP
|
UPKEEP
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
package com.alttd.playershops.events;
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
|
|
||||||
public abstract class ShopEvent extends Event implements Cancellable {
|
public abstract class ShopEvent extends Event implements Cancellable {
|
||||||
|
|
||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
private final AbstractShop shop;
|
private final PlayerShop shop;
|
||||||
|
|
||||||
public ShopEvent(AbstractShop shop) {
|
public ShopEvent(PlayerShop shop) {
|
||||||
this.shop = shop;
|
this.shop = shop;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractShop getShop() {
|
public PlayerShop getShop() {
|
||||||
return shop;
|
return shop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ShopItemAmountChangeEvent extends ShopEvent {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private final int newAmount;
|
||||||
|
|
||||||
|
public ShopItemAmountChangeEvent(PlayerShop shop, int newAmount) {
|
||||||
|
super(shop);
|
||||||
|
this.newAmount = newAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNewAmount() {
|
||||||
|
return newAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ShopItemChangeEvent extends ShopEvent {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private final ItemStack newItem;
|
||||||
|
|
||||||
|
public ShopItemChangeEvent(PlayerShop shop, ItemStack newItem) {
|
||||||
|
super(shop);
|
||||||
|
this.newItem = newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getNewItem() {
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ShopPriceChangeEvent extends ShopEvent {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private final double newPrice;
|
||||||
|
|
||||||
|
public ShopPriceChangeEvent(PlayerShop shop, double newPrice) {
|
||||||
|
super(shop);
|
||||||
|
this.newPrice = newPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getNewPrice() {
|
||||||
|
return newPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.alttd.playershops.events;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.shop.ShopType;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ShopTypeChangeEvent extends ShopEvent {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private final ShopType shopType;
|
||||||
|
|
||||||
|
public ShopTypeChangeEvent(PlayerShop shop, ShopType shopType) {
|
||||||
|
super(shop);
|
||||||
|
this.shopType = shopType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShopType getShopType() {
|
||||||
|
return shopType;
|
||||||
|
}
|
||||||
|
}
|
||||||
158
src/main/java/com/alttd/playershops/gui/AbstractGui.java
Normal file
158
src/main/java/com/alttd/playershops/gui/AbstractGui.java
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public abstract class AbstractGui implements InventoryHolder {
|
||||||
|
|
||||||
|
Inventory inventory;
|
||||||
|
protected final int INV_SIZE = 54;
|
||||||
|
int currentSlot;
|
||||||
|
UUID uuid;
|
||||||
|
int pageIndex;
|
||||||
|
AbstractGui lastGui;
|
||||||
|
|
||||||
|
|
||||||
|
AbstractGui(UUID uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.currentSlot = 0;
|
||||||
|
this.lastGui = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
Player player = getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean close() {
|
||||||
|
Player player = getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
player.closeInventory();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scrollPageNext() {
|
||||||
|
ItemStack nextPageIcon = inventory.getItem(GuiIcon.MENUBAR_NEXT_PAGE.getSlot());
|
||||||
|
if (nextPageIcon != null && nextPageIcon.equals(getNextPageIcon())) {
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_NEXT_PAGE.getSlot(), getPrevPageIcon());
|
||||||
|
++pageIndex;
|
||||||
|
initInvContents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scrollPagePrev() {
|
||||||
|
ItemStack prevPageIcon = inventory.getItem(GuiIcon.MENUBAR_PREV_PAGE.getSlot());
|
||||||
|
if (prevPageIcon != null && prevPageIcon.equals(getPrevPageIcon())) {
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_PREV_PAGE.getSlot(), getNextPageIcon());
|
||||||
|
--pageIndex;
|
||||||
|
if (pageIndex == 0) {
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_PREV_PAGE.getSlot(), null);
|
||||||
|
}
|
||||||
|
initInvContents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean addItem(int slot, ItemStack icon) {
|
||||||
|
currentSlot = slot;
|
||||||
|
return addItem(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean addItem(ItemStack icon) {
|
||||||
|
if (currentSlot == inventory.getSize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
inventory.setItem(currentSlot, icon);
|
||||||
|
currentSlot++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initInvContents() {
|
||||||
|
clearInvBody();
|
||||||
|
currentSlot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void clearInvBody() {
|
||||||
|
for (int i = 0; i < inventory.getSize() - 9; ++i) {
|
||||||
|
// inventory.setItem(i, null);
|
||||||
|
inventory.setItem(i, getDivider());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeMenuBar() {
|
||||||
|
for (int i = inventory.getSize() - 9; i < inventory.getSize(); ++i) {
|
||||||
|
inventory.setItem(i, getDivider());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player getPlayer() {
|
||||||
|
return Bukkit.getPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Inventory getInventory() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack getPrevPageIcon() {
|
||||||
|
return GuiIcon.MENUBAR_PREV_PAGE.getItemStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack getNextPageIcon() {
|
||||||
|
return GuiIcon.MENUBAR_NEXT_PAGE.getItemStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack getExitIcon() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack getDivider() {
|
||||||
|
return GuiIcon.DIVIDER.getItemStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(int slot, ItemStack item) {
|
||||||
|
// TODO a better way to do this.
|
||||||
|
// check all menu actions here
|
||||||
|
if (slot == GuiIcon.MENUBAR_BACK.getSlot() && GuiIcon.MENUBAR_BACK.getItemStack().equals(item)) {
|
||||||
|
if (hasLastGui())
|
||||||
|
lastGui.open();
|
||||||
|
} else if (slot == GuiIcon.MENUBAR_EXIT.getSlot() && GuiIcon.MENUBAR_EXIT.getItemStack().equals(item)) {
|
||||||
|
getPlayer().closeInventory();
|
||||||
|
} else if (slot == GuiIcon.MENUBAR_SEARCH.getSlot() && GuiIcon.MENUBAR_SEARCH.getItemStack().equals(item)) {
|
||||||
|
// TODO
|
||||||
|
} else if (slot == GuiIcon.MENUBAR_PREV_PAGE.getSlot() && GuiIcon.MENUBAR_PREV_PAGE.getItemStack().equals(item)) {
|
||||||
|
scrollPagePrev();
|
||||||
|
} else if (slot == GuiIcon.MENUBAR_NEXT_PAGE.getSlot() && GuiIcon.MENUBAR_NEXT_PAGE.getItemStack().equals(item)) {
|
||||||
|
scrollPageNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastGui(AbstractGui lastGui) {
|
||||||
|
this.lastGui = lastGui;
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_BACK.getSlot(), GuiIcon.MENUBAR_BACK.getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasLastGui() {
|
||||||
|
return lastGui != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPrevPageItem() {
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_PREV_PAGE.getSlot(), GuiIcon.MENUBAR_PREV_PAGE.getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addNextPageItem() {
|
||||||
|
inventory.setItem(GuiIcon.MENUBAR_NEXT_PAGE.getSlot(), GuiIcon.MENUBAR_NEXT_PAGE.getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
79
src/main/java/com/alttd/playershops/gui/GuiIcon.java
Normal file
79
src/main/java/com/alttd/playershops/gui/GuiIcon.java
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import com.alttd.playershops.config.GuiIconConfig;
|
||||||
|
import com.alttd.playershops.config.ShopTypeConfig;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemFlag;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum GuiIcon {
|
||||||
|
DIVIDER,
|
||||||
|
MENUBAR_BACK,
|
||||||
|
MENUBAR_EXIT,
|
||||||
|
MENUBAR_SEARCH,
|
||||||
|
MENUBAR_PREV_PAGE,
|
||||||
|
MENUBAR_NEXT_PAGE,
|
||||||
|
|
||||||
|
MANAGE_SHOP,
|
||||||
|
MANAGE_SHOP_BALANCE_ADD,
|
||||||
|
MANAGE_SHOP_BALANCE_REMOVE,
|
||||||
|
MANAGE_SHOP_SALES,
|
||||||
|
MANAGE_SHOP_ITEM,
|
||||||
|
MANAGE_SHOP_TYPE,
|
||||||
|
MANAGE_SHOP_AMOUNT,
|
||||||
|
MANAGE_SHOP_PRICE,
|
||||||
|
|
||||||
|
HOME_LIST_OWN_SHOPS,
|
||||||
|
HOME_LIST_PLAYERS,
|
||||||
|
HOME_SETTINGS,
|
||||||
|
LIST_SHOP,
|
||||||
|
LIST_PLAYER,
|
||||||
|
LIST_PLAYER_ADMIN,
|
||||||
|
EMPTY_SHOP;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final int slot;
|
||||||
|
@Getter
|
||||||
|
private final ItemStack itemStack;
|
||||||
|
|
||||||
|
GuiIcon() {
|
||||||
|
GuiIconConfig config = new GuiIconConfig(this.toString());
|
||||||
|
this.slot = config.slot;
|
||||||
|
this.itemStack = createItem(config.material, config.displayName, config.lore);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack createItem(String materialString, String displayName, List<String> itemlore) {
|
||||||
|
Material material = Material.getMaterial(materialString);
|
||||||
|
if (material == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ItemStack item = new ItemStack(material);
|
||||||
|
ItemMeta itemMeta = item.getItemMeta();
|
||||||
|
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
|
||||||
|
itemMeta.displayName(format(displayName));
|
||||||
|
List<Component> lore = new ArrayList<>();
|
||||||
|
for (String line : itemlore) {
|
||||||
|
lore.add(format(line));
|
||||||
|
}
|
||||||
|
itemMeta.lore(lore);
|
||||||
|
item.setItemMeta(itemMeta);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component format(String s) {
|
||||||
|
return Util.parseMiniMessage(s, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name().toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/java/com/alttd/playershops/gui/HomeGui.java
Normal file
41
src/main/java/com/alttd/playershops/gui/HomeGui.java
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class HomeGui extends AbstractGui {
|
||||||
|
|
||||||
|
public HomeGui(UUID uuid) {
|
||||||
|
super(uuid);
|
||||||
|
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.home-title", null));
|
||||||
|
initInvContents();
|
||||||
|
makeMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initInvContents() {
|
||||||
|
super.initInvContents();
|
||||||
|
inventory.setItem(GuiIcon.HOME_LIST_OWN_SHOPS.getSlot(), GuiIcon.HOME_LIST_OWN_SHOPS.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.HOME_LIST_PLAYERS.getSlot(), GuiIcon.HOME_LIST_PLAYERS.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.HOME_SETTINGS.getSlot(), GuiIcon.HOME_SETTINGS.getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(int slot, ItemStack item) {
|
||||||
|
super.onClick(slot, item);
|
||||||
|
if (slot == GuiIcon.HOME_LIST_OWN_SHOPS.getSlot() && GuiIcon.HOME_LIST_OWN_SHOPS.getItemStack().equals(item)) {
|
||||||
|
ListShopsGui listShopsGui = new ListShopsGui(uuid, uuid);
|
||||||
|
listShopsGui.setLastGui(this);
|
||||||
|
listShopsGui.open();
|
||||||
|
} else if (slot == GuiIcon.HOME_LIST_PLAYERS.getSlot() && GuiIcon.HOME_LIST_PLAYERS.getItemStack().equals(item)) {
|
||||||
|
ListPlayersGui listPlayersGui = new ListPlayersGui(uuid);
|
||||||
|
listPlayersGui.setLastGui(this);
|
||||||
|
listPlayersGui.open();
|
||||||
|
} else if (slot == GuiIcon.HOME_SETTINGS.getSlot() && GuiIcon.HOME_SETTINGS.getItemStack().equals(item)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/main/java/com/alttd/playershops/gui/ListPlayersGui.java
Normal file
56
src/main/java/com/alttd/playershops/gui/ListPlayersGui.java
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ListPlayersGui extends AbstractGui {
|
||||||
|
|
||||||
|
private List<UUID> owners;
|
||||||
|
public ListPlayersGui(UUID uuid) {
|
||||||
|
super(uuid);
|
||||||
|
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.list-players-title", null));
|
||||||
|
initInvContents();
|
||||||
|
makeMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initInvContents() {
|
||||||
|
super.initInvContents();
|
||||||
|
|
||||||
|
owners = PlayerShops.getInstance().getShopHandler().getShopOwners();
|
||||||
|
int startIndex = pageIndex * 45;
|
||||||
|
ItemStack item;
|
||||||
|
for (int i = startIndex; i < owners.size(); i++) {
|
||||||
|
item = ShopUtil.getPlayerHead(owners.get(i));
|
||||||
|
|
||||||
|
if (!addItem(item)) {
|
||||||
|
addNextPageItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(int slot, ItemStack item) {
|
||||||
|
super.onClick(slot, item);
|
||||||
|
|
||||||
|
if (item.getType() != Material.PLAYER_HEAD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int index = pageIndex * 45 + slot;
|
||||||
|
if (index > owners.size())
|
||||||
|
return;
|
||||||
|
UUID playerToList = owners.get(index);
|
||||||
|
|
||||||
|
ListShopsGui listShopGUI = new ListShopsGui(uuid, playerToList);
|
||||||
|
listShopGUI.setLastGui(this);
|
||||||
|
listShopGUI.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/main/java/com/alttd/playershops/gui/ListShopsGui.java
Normal file
80
src/main/java/com/alttd/playershops/gui/ListShopsGui.java
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ListShopsGui extends AbstractGui {
|
||||||
|
|
||||||
|
private UUID playerToList;
|
||||||
|
List<PlayerShop> shops;
|
||||||
|
|
||||||
|
public ListShopsGui(UUID uuid, UUID playerToList) {
|
||||||
|
super(uuid);
|
||||||
|
this.playerToList = playerToList;
|
||||||
|
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerToList);
|
||||||
|
|
||||||
|
TagResolver placeholders = TagResolver.resolver(
|
||||||
|
Placeholder.unparsed("name", offlinePlayer.hasPlayedBefore() ? offlinePlayer.getName() : "error")
|
||||||
|
);
|
||||||
|
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.list-shops-title", placeholders));
|
||||||
|
initInvContents();
|
||||||
|
makeMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initInvContents() {
|
||||||
|
super.initInvContents();
|
||||||
|
|
||||||
|
shops = PlayerShops.getInstance().getShopHandler().getShops(playerToList);
|
||||||
|
// Todo add option to sort shops?
|
||||||
|
|
||||||
|
int startIndex = pageIndex * 45;
|
||||||
|
for (int i = startIndex; i < shops.size(); i++) {
|
||||||
|
PlayerShop shop = shops.get(i);
|
||||||
|
ItemStack item = shop.getItemStack();
|
||||||
|
if (!shop.isInitialized())
|
||||||
|
item = GuiIcon.EMPTY_SHOP.getItemStack();
|
||||||
|
|
||||||
|
if (!this.addItem(item)) {
|
||||||
|
addNextPageItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(int slot, ItemStack item) {
|
||||||
|
super.onClick(slot, item);
|
||||||
|
|
||||||
|
Player player = getPlayer();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int index = pageIndex * 45 + slot;
|
||||||
|
if (index > shops.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop playerShop = shops.get(index);
|
||||||
|
if (playerShop == null) return;
|
||||||
|
|
||||||
|
if (!ShopUtil.canManageShop(player, playerShop))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ShopManagementGui shopManagementGui = new ShopManagementGui(player.getUniqueId(), playerShop);
|
||||||
|
shopManagementGui.setLastGui(this);
|
||||||
|
shopManagementGui.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
108
src/main/java/com/alttd/playershops/gui/ShopManagementGui.java
Normal file
108
src/main/java/com/alttd/playershops/gui/ShopManagementGui.java
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.conversation.ConversationManager;
|
||||||
|
import com.alttd.playershops.conversation.ConversationType;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.utils.EconomyUtils;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ShopManagementGui extends AbstractGui {
|
||||||
|
|
||||||
|
PlayerShop shop;
|
||||||
|
|
||||||
|
public ShopManagementGui(UUID uuid, PlayerShop shop) {
|
||||||
|
super(uuid);
|
||||||
|
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.management-title", null));
|
||||||
|
this.shop = shop;
|
||||||
|
initInvContents();
|
||||||
|
makeMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initInvContents() {
|
||||||
|
super.initInvContents();
|
||||||
|
|
||||||
|
ItemStack shopIcon = GuiIcon.MANAGE_SHOP.getItemStack();
|
||||||
|
ItemMeta meta = shopIcon.getItemMeta();
|
||||||
|
List<Component> lore = new ArrayList<>();
|
||||||
|
TagResolver placeholders = TagResolver.resolver(
|
||||||
|
Placeholder.unparsed("balance", shop.getBalance() + ""),
|
||||||
|
Placeholder.unparsed("price", shop.getPrice() + ""),
|
||||||
|
Placeholder.unparsed("amount", shop.getAmount() + ""),
|
||||||
|
Placeholder.unparsed("shoptype", shop.getType().toString()),
|
||||||
|
Placeholder.component("itemname", ShopUtil.itemNameComponent(shop.getItemStack()))
|
||||||
|
);
|
||||||
|
lore.add(Util.parseMiniMessage("Balance: <balance>", placeholders));
|
||||||
|
lore.add(Util.parseMiniMessage("item: <itemname>", placeholders));
|
||||||
|
lore.add(Util.parseMiniMessage("amount: <amount>", placeholders));
|
||||||
|
lore.add(Util.parseMiniMessage("Type: <shoptype>", placeholders));
|
||||||
|
lore.add(Util.parseMiniMessage("Price: <price>", placeholders));
|
||||||
|
|
||||||
|
meta.lore(lore);
|
||||||
|
shopIcon.setItemMeta(meta);
|
||||||
|
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP.getSlot(), shopIcon);
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_BALANCE_ADD.getSlot(), GuiIcon.MANAGE_SHOP_BALANCE_ADD.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_BALANCE_REMOVE.getSlot(), GuiIcon.MANAGE_SHOP_BALANCE_REMOVE.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_SALES.getSlot(), GuiIcon.MANAGE_SHOP_SALES.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_ITEM.getSlot(), GuiIcon.MANAGE_SHOP_ITEM.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_TYPE.getSlot(), GuiIcon.MANAGE_SHOP_TYPE.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_AMOUNT.getSlot(), GuiIcon.MANAGE_SHOP_AMOUNT.getItemStack());
|
||||||
|
inventory.setItem(GuiIcon.MANAGE_SHOP_PRICE.getSlot(), GuiIcon.MANAGE_SHOP_PRICE.getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void makeMenuBar() {
|
||||||
|
super.makeMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(int slot, ItemStack item) {
|
||||||
|
super.onClick(slot, item);
|
||||||
|
if (slot == GuiIcon.MANAGE_SHOP.getSlot() && GuiIcon.MANAGE_SHOP.getItemStack().equals(item)) {
|
||||||
|
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_BALANCE_ADD.getSlot() && GuiIcon.MANAGE_SHOP_BALANCE_ADD.getItemStack().equals(item)) {
|
||||||
|
if (EconomyUtils.getFunds(getPlayer()) > 0) {
|
||||||
|
openChangePrompt(ConversationType.ADD_BALANCE);
|
||||||
|
} else {
|
||||||
|
getPlayer().sendMiniMessage("<red>You do not have money to add to this shop", null);
|
||||||
|
}
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_BALANCE_REMOVE.getSlot() && GuiIcon.MANAGE_SHOP_BALANCE_REMOVE.getItemStack().equals(item)) {
|
||||||
|
if (shop.getBalance() > 0) {
|
||||||
|
openChangePrompt(ConversationType.WITHDRAW_BALANCE);
|
||||||
|
} else {
|
||||||
|
getPlayer().sendMiniMessage("<red>You can't widraw money from this shop", null);
|
||||||
|
}
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_SALES.getSlot() && GuiIcon.MANAGE_SHOP_SALES.getItemStack().equals(item)) {
|
||||||
|
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_ITEM.getSlot() && GuiIcon.MANAGE_SHOP_ITEM.getItemStack().equals(item)) {
|
||||||
|
openChangePrompt(ConversationType.CHANGE_ITEM);
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_TYPE.getSlot() && GuiIcon.MANAGE_SHOP_TYPE.getItemStack().equals(item)) {
|
||||||
|
openChangePrompt(ConversationType.CHANGE_TYPE);
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_AMOUNT.getSlot() && GuiIcon.MANAGE_SHOP_AMOUNT.getItemStack().equals(item)) {
|
||||||
|
openChangePrompt(ConversationType.CHANGE_AMOUNT);
|
||||||
|
} else if (slot == GuiIcon.MANAGE_SHOP_PRICE.getSlot() && GuiIcon.MANAGE_SHOP_PRICE.getItemStack().equals(item)) {
|
||||||
|
openChangePrompt(ConversationType.CHANGE_PRICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openChangePrompt(ConversationType conversationType) {
|
||||||
|
Player player = getPlayer();
|
||||||
|
player.closeInventory();
|
||||||
|
new ConversationManager(PlayerShops.getInstance(), player, conversationType, shop);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ package com.alttd.playershops.handler;
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
import com.alttd.playershops.PlayerShops;
|
||||||
import com.alttd.playershops.config.Config;
|
import com.alttd.playershops.config.Config;
|
||||||
import com.alttd.playershops.events.PlayerCreateShopEvent;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.storage.database.DatabaseHelper;
|
||||||
import com.alttd.playershops.shop.ShopType;
|
import com.alttd.playershops.utils.Logger;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
@ -13,8 +13,12 @@ import org.bukkit.Material;
|
||||||
import org.bukkit.Tag;
|
import org.bukkit.Tag;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.DoubleChest;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -24,19 +28,41 @@ public class ShopHandler {
|
||||||
@Getter
|
@Getter
|
||||||
private final Object2IntMap<UUID> shopBuildLimits;
|
private final Object2IntMap<UUID> shopBuildLimits;
|
||||||
@Getter
|
@Getter
|
||||||
private final Map<Location, AbstractShop> shopLocation;
|
private final Map<Location, PlayerShop> shopLocation;
|
||||||
|
private final Map<Location, PlayerShop> shopSignLocation;
|
||||||
@Getter
|
@Getter
|
||||||
private final ArrayList<Material> shopMaterials;
|
private final ArrayList<Material> shopMaterials;
|
||||||
|
|
||||||
public ShopHandler(PlayerShops instance) {
|
public ShopHandler(PlayerShops instance) {
|
||||||
plugin = instance;
|
plugin = instance;
|
||||||
shopLocation = new ConcurrentHashMap<>();
|
shopLocation = new ConcurrentHashMap<>();
|
||||||
|
shopSignLocation = new ConcurrentHashMap<>();
|
||||||
shopBuildLimits = new Object2IntOpenHashMap<>();
|
shopBuildLimits = new Object2IntOpenHashMap<>();
|
||||||
shopBuildLimits.defaultReturnValue(Config.shopLimit);
|
shopBuildLimits.defaultReturnValue(Config.shopLimit);
|
||||||
shopMaterials = new ArrayList<>(); // TODO move into parent method where materials are loaded in.
|
shopMaterials = new ArrayList<>(); // TODO move into parent method where materials are loaded in.
|
||||||
|
shopMaterials.add(Material.BARREL);
|
||||||
|
|
||||||
|
loadShops();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractShop getShop(Location location) {
|
void loadShops() {
|
||||||
|
Logger.info("Loading all shops from database...");
|
||||||
|
// TODO add a timer to test performance
|
||||||
|
DatabaseHelper databaseHelper = plugin.getDatabaseHelper();
|
||||||
|
try (ResultSet resultSet = databaseHelper.selectAllShops()) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
PlayerShop playerShop = databaseHelper.shopFromResultSet(resultSet);
|
||||||
|
if (playerShop == null) continue;
|
||||||
|
|
||||||
|
addShop(playerShop);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error("Error loading shops\n" + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerShop getShop(Location location) {
|
||||||
Location newLocation = new Location(location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
Location newLocation = new Location(location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
|
|
||||||
return shopLocation.get(newLocation);
|
return shopLocation.get(newLocation);
|
||||||
|
|
@ -46,10 +72,14 @@ public class ShopHandler {
|
||||||
return getShop(location) != null;
|
return getShop(location) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<AbstractShop> getShops() {
|
public Collection<PlayerShop> getShops() {
|
||||||
return Collections.unmodifiableCollection(shopLocation.values());
|
return Collections.unmodifiableCollection(shopLocation.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<UUID> getShopOwners() {
|
||||||
|
return shopLocation.values().stream().map(PlayerShop::getOwnerUUID).distinct().toList();
|
||||||
|
}
|
||||||
|
|
||||||
public void addPlayerLimit(UUID uuid, int limit) {
|
public void addPlayerLimit(UUID uuid, int limit) {
|
||||||
shopBuildLimits.put(uuid, limit);
|
shopBuildLimits.put(uuid, limit);
|
||||||
}
|
}
|
||||||
|
|
@ -58,55 +88,70 @@ public class ShopHandler {
|
||||||
return shopBuildLimits.getInt(uuid);
|
return shopBuildLimits.getInt(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeShops() {
|
public void unloadShops() {
|
||||||
|
for (PlayerShop shop : shopLocation.values()) {
|
||||||
|
if (shop.isDirty())
|
||||||
|
plugin.getDatabaseHelper().updateShop(shop, true);
|
||||||
|
}
|
||||||
shopLocation.clear();
|
shopLocation.clear();
|
||||||
|
shopSignLocation.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShopMaterial(Block block) {
|
public boolean isShopMaterial(Block block) {
|
||||||
if (Tag.SHULKER_BOXES.isTagged(block.getType())) {
|
// if (Tag.SHULKER_BOXES.isTagged(block.getType())) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
return shopMaterials.contains(block.getType());
|
// return shopMaterials.contains(block.getType());
|
||||||
|
// TODO make a cache of this somehow?
|
||||||
|
return block.getState() instanceof InventoryHolder inventoryHolder && !(inventoryHolder.getInventory().getHolder() instanceof DoubleChest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AbstractShop> getShops(UUID uuid) {
|
public List<PlayerShop> getShops(UUID uuid) {
|
||||||
List<AbstractShop> shops = new ArrayList<>();
|
List<PlayerShop> shops = new ArrayList<>();
|
||||||
for (AbstractShop shop : shopLocation.values()) {
|
for (PlayerShop shop : shopLocation.values()) {
|
||||||
if (shop.getOwnerUUID().equals(uuid))
|
if (shop.getOwnerUUID().equals(uuid))
|
||||||
shops.add(shop);
|
shops.add(shop);
|
||||||
}
|
}
|
||||||
return shops;
|
return shops;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractShop getShopBySignLocation(Location signLocation) {
|
public PlayerShop getShopBySignLocation(Location signLocation) {
|
||||||
for (AbstractShop shop : shopLocation.values()) {
|
Location newLocation = new Location(signLocation.getWorld(), signLocation.getBlockX(), signLocation.getBlockY(), signLocation.getBlockZ());
|
||||||
if (shop.getSignLocation().equals(signLocation))
|
|
||||||
return shop;
|
return shopSignLocation.get(newLocation);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractShop getShopNearBlock(Block block) {
|
public PlayerShop getShopsNear(Block block) {
|
||||||
BlockFace[] faces = {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST};
|
BlockFace[] faces = {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST};
|
||||||
for (BlockFace face : faces) {
|
for (BlockFace face : faces) {
|
||||||
if (this.isShopMaterial(block.getRelative(face))) {
|
if (this.isShopMaterial(block.getRelative(face))) {
|
||||||
Block blockRelative = block.getRelative(face);
|
Block shopChest = block.getRelative(face);
|
||||||
if (isShop(blockRelative.getLocation()))
|
PlayerShop shop = getShop(shopChest.getLocation());
|
||||||
return getShop(blockRelative.getLocation());
|
if (shop != null)
|
||||||
|
return shop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractShop createShop(Location signLocation, Player player, double price, int amount, ShopType shopType) {
|
public void addShop(PlayerShop shop) {
|
||||||
AbstractShop shop = AbstractShop.create(signLocation, player.getUniqueId(), price, amount, shopType);
|
shopLocation.put(shop.getShopLocation(), shop);
|
||||||
|
shopSignLocation.put(shop.getSignLocation(), shop);
|
||||||
|
}
|
||||||
|
|
||||||
PlayerCreateShopEvent playerCreateShopEvent = new PlayerCreateShopEvent(player, shop);
|
public void removeShop(PlayerShop shop) {
|
||||||
plugin.getServer().getPluginManager().callEvent(playerCreateShopEvent);
|
shopLocation.remove(shop.getShopLocation());
|
||||||
|
shopSignLocation.remove(shop.getSignLocation());
|
||||||
|
plugin.getDatabaseHelper().removeShop(shop);
|
||||||
|
}
|
||||||
|
|
||||||
if(playerCreateShopEvent.isCancelled())
|
public boolean canPlayerBreakShop(Player player, PlayerShop shop) { // TODO move to util?
|
||||||
return null;
|
if (player.getUniqueId().equals(shop.getOwnerUUID()) && player.hasPermission("playershops.shop.break"))
|
||||||
|
return true;
|
||||||
|
|
||||||
return shop;
|
if (player.hasPermission("playershops.shop.break.other"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/main/java/com/alttd/playershops/hook/WorldGuardHook.java
Normal file
11
src/main/java/com/alttd/playershops/hook/WorldGuardHook.java
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.alttd.playershops.hook;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class WorldGuardHook {
|
||||||
|
|
||||||
|
public static boolean canUseShopInRegion(Player player, Location location) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,39 +1,45 @@
|
||||||
package com.alttd.playershops.listener;
|
package com.alttd.playershops.listener;
|
||||||
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.gui.AbstractGui;
|
||||||
|
import com.alttd.playershops.gui.ShopManagementGui;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
|
|
||||||
public class InventoryListener extends EventListener {
|
public class InventoryListener extends EventListener {
|
||||||
|
|
||||||
protected final Inventory inventory;
|
private final PlayerShops plugin;
|
||||||
protected boolean cancelCloseUnregister = false;
|
public InventoryListener(PlayerShops plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
public InventoryListener(Inventory inv) {
|
this.register(this.plugin);
|
||||||
this.inventory = inv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler
|
||||||
public void unregisterOnClose(InventoryCloseEvent event) {
|
public void onInventoryClickEvent(InventoryClickEvent event) {
|
||||||
if (event.getView().getTopInventory().equals(inventory) && !cancelCloseUnregister) unregister();
|
if (!(event.getWhoClicked() instanceof Player player))
|
||||||
}
|
return;
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
if (!(event.getView().getTopInventory().getHolder() instanceof AbstractGui gui))
|
||||||
public void unregisterOnLeaveEvent(PlayerQuitEvent event) {
|
return;
|
||||||
if ((inventory.getHolder() instanceof OfflinePlayer) && event.getPlayer().getUniqueId().equals(((OfflinePlayer) inventory.getHolder()).getUniqueId()))
|
|
||||||
unregister();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
if ((event.getView().getBottomInventory().equals(event.getClickedInventory())))
|
||||||
public void onInventoryDrag(InventoryDragEvent event) {
|
return;
|
||||||
if (event.getView().getTopInventory().equals(inventory)) for (int slot : event.getRawSlots()) if (slot < inventory.getSize()) {
|
|
||||||
|
if (event.getClick() == ClickType.NUMBER_KEY) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemStack clicked = event.getCurrentItem();
|
||||||
|
if (!(clicked != null && clicked.getType() != Material.AIR))
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
gui.onClick(event.getRawSlot(), clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,16 @@ import com.alttd.playershops.PlayerShops;
|
||||||
import com.alttd.playershops.config.Config;
|
import com.alttd.playershops.config.Config;
|
||||||
import com.alttd.playershops.config.MessageConfig;
|
import com.alttd.playershops.config.MessageConfig;
|
||||||
import com.alttd.playershops.handler.ShopHandler;
|
import com.alttd.playershops.handler.ShopHandler;
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.utils.EconomyUtils;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Tag;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.Chest;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.Directional;
|
import org.bukkit.block.data.Directional;
|
||||||
|
|
@ -18,29 +22,37 @@ import org.bukkit.block.data.type.WallSign;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.event.block.SignChangeEvent;
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class to listen to player events
|
||||||
|
*/
|
||||||
public class PlayerListener extends EventListener {
|
public class PlayerListener extends EventListener {
|
||||||
|
|
||||||
private final PlayerShops plugin;
|
private final PlayerShops plugin;
|
||||||
|
ShopHandler shopHandler;
|
||||||
|
|
||||||
public PlayerListener(PlayerShops plugin) {
|
public PlayerListener(PlayerShops plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.register(this.plugin);
|
this.register(this.plugin);
|
||||||
|
shopHandler = plugin.getShopHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void PlayerJoinEvent(PlayerJoinEvent event) {
|
||||||
if(!this.isRegistered || !Config.usePermissionShopLimit) return;
|
if(!this.isRegistered || !Config.usePermissionShopLimit) return;
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
if (!player.hasPermission(Config.shopLimitPermission)) return;
|
if (!player.hasPermission("playershops.shoplimit")) return;
|
||||||
|
|
||||||
ShopHandler shopHandler = plugin.getShopHandler();
|
|
||||||
UUID uuid = player.getUniqueId();
|
UUID uuid = player.getUniqueId();
|
||||||
|
|
||||||
// early return to not check this all the time, if this changes by rankup etc handle it in another event
|
// early return to not check this all the time, if this changes by rankup etc handle it in another event
|
||||||
|
|
@ -62,22 +74,13 @@ public class PlayerListener extends EventListener {
|
||||||
shopHandler.addPlayerLimit(player.getUniqueId(), buildPermissionNumber);
|
shopHandler.addPlayerLimit(player.getUniqueId(), buildPermissionNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
|
||||||
public void onSignChange(SignChangeEvent event) {
|
|
||||||
Block block = event.getBlock();
|
|
||||||
|
|
||||||
if (!(block.getState() instanceof Sign)) return;
|
|
||||||
|
|
||||||
AbstractShop shop = plugin.getShopHandler().getShop(block.getLocation());
|
|
||||||
if(shop == null) return;
|
|
||||||
|
|
||||||
if(shop.isInitialized()) event.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
public void onShopCreation(SignChangeEvent event) {
|
public void onShopCreation(SignChangeEvent event) {
|
||||||
Block b = event.getBlock();
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block b = event.getBlock();
|
||||||
|
Player player = event.getPlayer();
|
||||||
if (!(b.getState() instanceof Sign))
|
if (!(b.getState() instanceof Sign))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -90,19 +93,19 @@ public class PlayerListener extends EventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
Block bRelative = b.getRelative(facing.getOppositeFace());
|
Block bRelative = b.getRelative(facing.getOppositeFace());
|
||||||
ShopHandler shopHandler = plugin.getShopHandler();
|
|
||||||
|
|
||||||
if (shopHandler.isShopMaterial(bRelative)) {
|
if (shopHandler.isShopMaterial(bRelative)) {
|
||||||
Sign signBlock = (Sign) b.getState();
|
Sign signBlock = (Sign) b.getState();
|
||||||
Component signLine = event.line(0);
|
Component signLine = event.line(0);
|
||||||
if (signLine == null)
|
if (signLine == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String signLineString = PlainTextComponentSerializer.plainText().serialize(signLine);
|
String signLineString = PlainTextComponentSerializer.plainText().serialize(signLine);
|
||||||
if (!signLineString.equalsIgnoreCase(Config.shopCreationWord))
|
if (!signLineString.equalsIgnoreCase(Config.shopCreationWord))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AbstractShop shop = shopHandler.getShop(bRelative.getLocation());
|
PlayerShop shop = shopHandler.getShop(bRelative.getLocation());
|
||||||
Player player = event.getPlayer();
|
// Player player = event.getPlayer();
|
||||||
if(shop != null) {
|
if(shop != null) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.sendMiniMessage(MessageConfig.SHOP_ALREADY_EXISTS, null);
|
player.sendMiniMessage(MessageConfig.SHOP_ALREADY_EXISTS, null);
|
||||||
|
|
@ -110,7 +113,7 @@ public class PlayerListener extends EventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID playerUUID = player.getUniqueId();
|
UUID playerUUID = player.getUniqueId();
|
||||||
if (!player.hasPermission("shop.create")) {
|
if (!player.hasPermission("playershops.shop.create")) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.sendMiniMessage(MessageConfig.NO_SHOP_CREATE_PERMISSION, null);
|
player.sendMiniMessage(MessageConfig.NO_SHOP_CREATE_PERMISSION, null);
|
||||||
return;
|
return;
|
||||||
|
|
@ -125,9 +128,61 @@ public class PlayerListener extends EventListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO instance shopCreationManagement
|
if (!EconomyUtils.hasSufficientFunds(player, Config.shopCreationBalance)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerShop playerShop = new PlayerShop(bRelative.getLocation(), signBlock.getLocation(), player);
|
||||||
|
playerShop.addBalance(Config.shopCreationBalance);
|
||||||
|
EconomyUtils.removeFunds(player, Config.shopCreationBalance);
|
||||||
|
shopHandler.addShop(playerShop);
|
||||||
|
PlayerShops.getInstance().getDatabaseHelper().createShop(playerShop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onDoubleChestPlace(BlockPlaceEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getBlock();
|
||||||
|
if (!(block.getState() instanceof Chest))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop playerShop = shopHandler.getShopsNear(block);
|
||||||
|
if (playerShop == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// As net.minecraft.world.level.block.state.properties.ChestType
|
||||||
|
// is not exposed in the api this is the shit we need to do to ensure these chests do not connect.
|
||||||
|
BlockData blockData = block.getState().getBlockData();
|
||||||
|
Material material = blockData.getMaterial();
|
||||||
|
BlockData newBlockData = material.createBlockData();
|
||||||
|
BlockFace facing = ((Directional) blockData).getFacing();
|
||||||
|
((Directional) newBlockData).setFacing(facing);
|
||||||
|
block.getLocation().getBlock().setBlockData(newBlockData, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onShopBlockInteraction(PlayerInteractEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getClickedBlock();
|
||||||
|
if (block == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop playerShop = shopHandler.getShop(block.getLocation());
|
||||||
|
if (playerShop == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// todo add bypass permission to open shop containers?
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player.getUniqueId().equals(playerShop.getOwnerUUID()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
// We could send some info here eg remaining inventory, item details
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,62 @@
|
||||||
package com.alttd.playershops.listener;
|
package com.alttd.playershops.listener;
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
import com.alttd.playershops.PlayerShops;
|
||||||
import com.alttd.playershops.shop.AbstractShop;
|
import com.alttd.playershops.handler.ShopHandler;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Tag;
|
import org.bukkit.Tag;
|
||||||
|
import org.bukkit.TreeType;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.Directional;
|
||||||
|
import org.bukkit.block.data.Rotatable;
|
||||||
|
import org.bukkit.block.data.type.WallSign;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||||
|
import org.bukkit.event.world.StructureGrowEvent;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class to listen to events related to shops.
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class ShopListener extends EventListener {
|
public class ShopListener extends EventListener {
|
||||||
|
|
||||||
private final PlayerShops plugin;
|
private final PlayerShops plugin;
|
||||||
|
ShopHandler shopHandler;
|
||||||
|
|
||||||
public ShopListener(PlayerShops plugin) {
|
public ShopListener(PlayerShops plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.register(this.plugin);
|
this.register(this.plugin);
|
||||||
|
shopHandler = plugin.getShopHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
public void onEntityExplosion(EntityExplodeEvent event) {
|
public void onEntityExplosion(EntityExplodeEvent event) {
|
||||||
if(!this.isRegistered) return;
|
if(!this.isRegistered)
|
||||||
// This might be heavy when tnt is chained, would it be better to expand the unbreakable block api in galaxy and use that?
|
return;
|
||||||
// No need for slow bukkit events eating up cpu and memory
|
|
||||||
|
// This might be heavy when tnt is chained
|
||||||
Iterator<Block> blockIterator = event.blockList().iterator();
|
Iterator<Block> blockIterator = event.blockList().iterator();
|
||||||
AbstractShop shop = null;
|
PlayerShop shop = null;
|
||||||
while (blockIterator.hasNext()) {
|
while (blockIterator.hasNext()) {
|
||||||
|
|
||||||
Block block = blockIterator.next();
|
Block block = blockIterator.next();
|
||||||
Location location = block.getLocation();
|
Location location = block.getLocation();
|
||||||
if (Tag.WALL_SIGNS.isTagged(block.getType())) {
|
if (Tag.WALL_SIGNS.isTagged(block.getType())) {
|
||||||
shop = plugin.getShopHandler().getShopBySignLocation(location);
|
shop = shopHandler.getShopBySignLocation(location);
|
||||||
} else if (plugin.getShopHandler().isShopMaterial(block)) {
|
} else if (shopHandler.isShopMaterial(block)) {
|
||||||
shop = plugin.getShopHandler().getShop(location);
|
shop = shopHandler.getShop(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shop != null) {
|
if (shop != null) {
|
||||||
|
|
@ -41,4 +64,138 @@ public class ShopListener extends EventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onBlockPhysics(BlockPhysicsEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getBlock();
|
||||||
|
if (!Tag.WALL_SIGNS.isTagged(block.getType())) return;
|
||||||
|
|
||||||
|
|
||||||
|
if (shopHandler.getShopBySignLocation(block.getLocation()) != null)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onInventoryHolderBlockBreak(BlockBreakEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getBlock();
|
||||||
|
|
||||||
|
if (!(block.getState() instanceof InventoryHolder))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop shop = shopHandler.getShop(block.getLocation());
|
||||||
|
if (shop == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Shop sign must be broken in order to remove the shop?
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onSignBlockBreak(BlockBreakEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
// this is going to be heavy, add a cache shopsignlocation <-> Shop?
|
||||||
|
Block block = event.getBlock();
|
||||||
|
|
||||||
|
if (!(block.getState() instanceof Sign))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockFace facing;
|
||||||
|
BlockData data = block.getState().getBlockData();
|
||||||
|
if (data instanceof WallSign) {
|
||||||
|
facing = ((Directional) data).getFacing();
|
||||||
|
} else {
|
||||||
|
facing = ((Rotatable) data).getRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
Block relativeBlock = block.getRelative(facing.getOppositeFace());
|
||||||
|
PlayerShop shop = shopHandler.getShop(relativeBlock.getLocation());
|
||||||
|
if (shop == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shopHandler.removeShop(shop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onBucketEmptyAtSign(PlayerBucketEmptyEvent event) {
|
||||||
|
if (!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getBlock();
|
||||||
|
if (!Tag.WALL_SIGNS.isTagged(block.getType()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop playerShop = shopHandler.getShopBySignLocation(block.getLocation());
|
||||||
|
if (playerShop != null)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onBucketEmptyOnBlock(PlayerBucketEmptyEvent event) {
|
||||||
|
if (!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getBlock();
|
||||||
|
|
||||||
|
PlayerShop playerShop = shopHandler.getShop(block.getLocation());
|
||||||
|
if (playerShop != null)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mushrooms can replace blocks anywhere in the world w/o a check, this needs to be fixed in Galaxy or upstreams but is a pita
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onTreeGrow(StructureGrowEvent event) {
|
||||||
|
if (!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// as mushrooms only grow from bonemeal we can cut off early
|
||||||
|
if (!event.isFromBonemeal())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Only continue with mushrooms
|
||||||
|
TreeType treeType = event.getSpecies();
|
||||||
|
if (treeType != TreeType.RED_MUSHROOM && treeType != TreeType.BROWN_MUSHROOM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// we can either cancel the event or remove the blocks from the event.
|
||||||
|
// as canceling would mean we get back here on the next attempt I opt to remove the blocks
|
||||||
|
for (int i = 0; i < event.getBlocks().size(); i++) {
|
||||||
|
BlockState block = event.getBlocks().get(i);
|
||||||
|
PlayerShop playerShop;
|
||||||
|
if (block instanceof Sign sign) { // does not work?
|
||||||
|
playerShop = shopHandler.getShopBySignLocation(sign.getLocation());
|
||||||
|
System.out.println(block.getBlock());
|
||||||
|
} else {
|
||||||
|
playerShop = shopHandler.getShop(block.getLocation());
|
||||||
|
}
|
||||||
|
if (playerShop != null) {
|
||||||
|
event.getBlocks().remove(i--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
|
public void onSignChange(SignChangeEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(event.getBlock().getState() instanceof Sign sign)) return;
|
||||||
|
|
||||||
|
PlayerShop shop = shopHandler.getShopBySignLocation(sign.getLocation());
|
||||||
|
if(shop == null) return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
package com.alttd.playershops.listener;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.gui.ShopManagementGui;
|
||||||
|
import com.alttd.playershops.handler.ShopHandler;
|
||||||
|
import com.alttd.playershops.hook.WorldGuardHook;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.shop.TransactionError;
|
||||||
|
import com.alttd.playershops.utils.Logger;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Tag;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dedicated class to listen to transactions for shops.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TransactionListener extends EventListener {
|
||||||
|
|
||||||
|
private final PlayerShops plugin;
|
||||||
|
|
||||||
|
public TransactionListener(PlayerShops plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.register(this.plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onShopSignClick(PlayerInteractEvent event) {
|
||||||
|
if(!this.isRegistered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.getHand() == EquipmentSlot.OFF_HAND)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = event.getClickedBlock();
|
||||||
|
if (block == null || !Tag.WALL_SIGNS.isTagged(block.getType()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PlayerShop playerShop = plugin.getShopHandler().getShopBySignLocation(block.getLocation());
|
||||||
|
if (playerShop == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if we ever need worldguard support add it to the hook
|
||||||
|
if (!WorldGuardHook.canUseShopInRegion(player, block.getLocation())) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.hasPermission("playershops.shop.use." + playerShop.getType().toString())) {
|
||||||
|
player.sendMiniMessage("<red>You do not have permission to use " + playerShop.getType().toString() + " shops.", null); // TODO config
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShopHandler shopHandler = plugin.getShopHandler();
|
||||||
|
|
||||||
|
// Failsafe. If we have a shopsign but no block cancel the event, log error save and unload the shop
|
||||||
|
if (!shopHandler.isShopMaterial(playerShop.getShopLocation().getBlock())) {
|
||||||
|
Logger.error("We have a shop here but no connected container");
|
||||||
|
event.setCancelled(true);
|
||||||
|
// TODO LOG THIS ERROR
|
||||||
|
shopHandler.removeShop(playerShop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShopUtil.canManageShop(player, playerShop)) {
|
||||||
|
if (player.isSneaking())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ShopManagementGui gui = new ShopManagementGui(player.getUniqueId(), playerShop);
|
||||||
|
gui.open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playerShop.isInitialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
executeTransaction(player, playerShop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeTransaction(Player player, PlayerShop shop) {
|
||||||
|
if (shop == null || shop.getItemStack() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int orders = 1;
|
||||||
|
|
||||||
|
if (player.isSneaking())
|
||||||
|
orders = shop.getItemStack().getMaxStackSize();
|
||||||
|
TransactionError transactionError = shop.executeTransaction(orders, player);
|
||||||
|
|
||||||
|
// TODO minimessage placeholders
|
||||||
|
TagResolver placeholders = TagResolver.resolver(
|
||||||
|
Placeholder.unparsed("ownername", shop.getOwnerName()),
|
||||||
|
Placeholder.unparsed("price", shop.getPrice() + ""),
|
||||||
|
Placeholder.unparsed("amount", shop.getAmount() + ""),
|
||||||
|
Placeholder.component("item", ShopUtil.itemNameComponent(shop.getItemStack())),
|
||||||
|
Placeholder.unparsed("location", formatLocation(shop.getShopLocation()))
|
||||||
|
);
|
||||||
|
if (transactionError != TransactionError.NONE) {
|
||||||
|
switch (transactionError) {
|
||||||
|
case INSUFFICIENT_FUNDS_SHOP -> {
|
||||||
|
Player shopOwner = Bukkit.getPlayer(shop.getOwnerUUID());
|
||||||
|
if (shopOwner != null && notifyOwner(shop)) {
|
||||||
|
// TODO notify shopowner in game if not on cooldown and once per day on discord if linked and enabled
|
||||||
|
shopOwner.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().yourShopNoFunds, placeholders));
|
||||||
|
}
|
||||||
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().shopNoStock, placeholders);
|
||||||
|
}
|
||||||
|
case INSUFFICIENT_FUNDS_PLAYER -> {
|
||||||
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerNoFunds, placeholders);
|
||||||
|
}
|
||||||
|
case INVENTORY_FULL_SHOP -> {
|
||||||
|
Player shopOwner = Bukkit.getPlayer(shop.getOwnerUUID());
|
||||||
|
if (shopOwner != null && notifyOwner(shop)) {
|
||||||
|
shopOwner.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().yourShopNoStock, placeholders));
|
||||||
|
// TODO notify shopowner in game if not on cooldown and once per day on discord if linked and enabled
|
||||||
|
}
|
||||||
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().shopInventoryFull, placeholders);
|
||||||
|
}
|
||||||
|
case INVENTORY_FULL_PLAYER -> {
|
||||||
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerInventoryFull, placeholders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().playerBought, placeholders));
|
||||||
|
plugin.getDatabaseHelper().logTransaction(player, shop, orders);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatLocation(Location location) {
|
||||||
|
return Util.capitalize(location.getWorld().getName()) + ": " +
|
||||||
|
" " + (int) location.getX() +
|
||||||
|
", " + (int) location.getY() +
|
||||||
|
", " + (int) location.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean notifyOwner(PlayerShop playerShop) {
|
||||||
|
// TODO notify shopowner in game if not on cooldown and once per day on discord if linked and enabled
|
||||||
|
return playerShop.isNotifiedOwner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.data.Directional;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class AbstractShop {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private int id;
|
|
||||||
private String ownerName;
|
|
||||||
@Getter
|
|
||||||
private UUID ownerUUID;
|
|
||||||
@Getter @Setter
|
|
||||||
private ShopType type;
|
|
||||||
@Getter
|
|
||||||
private Location signLocation;
|
|
||||||
@Getter
|
|
||||||
private Location containerLocation;
|
|
||||||
@Getter
|
|
||||||
private String server;
|
|
||||||
@Getter @Setter
|
|
||||||
private double price;
|
|
||||||
@Getter @Setter
|
|
||||||
private int amount;
|
|
||||||
@Getter @Setter
|
|
||||||
private double balance;
|
|
||||||
@Getter @Setter
|
|
||||||
private ItemStack itemStack;
|
|
||||||
@Getter @Setter
|
|
||||||
private ItemStack secondaryItem;
|
|
||||||
@Getter @Setter
|
|
||||||
private long lastTransaction;
|
|
||||||
|
|
||||||
protected boolean initialized;
|
|
||||||
|
|
||||||
AbstractShop(Location signLocation, UUID uuid, double price, int amount) {
|
|
||||||
this.signLocation = signLocation;
|
|
||||||
if (signLocation != null) {
|
|
||||||
Directional sign = (Directional) signLocation.getBlock().getState().getBlockData();
|
|
||||||
this.containerLocation = signLocation.getBlock().getRelative(sign.getFacing().getOppositeFace()).getLocation();
|
|
||||||
}
|
|
||||||
this.ownerUUID = uuid;
|
|
||||||
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) {
|
|
||||||
return switch (shopType) {
|
|
||||||
case SELL -> new SellShop(signLocation, player, price, amount);
|
|
||||||
case BUY -> new BuyShop(signLocation, player, price, amount);
|
|
||||||
case GAMBLE -> new GambleShop(signLocation, player, price, amount);
|
|
||||||
case BARTER -> new BarterShop(signLocation, player, price, amount);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
ownerName = Bukkit.getOfflinePlayer(this.getOwnerUUID()).getName();
|
|
||||||
return ownerName;
|
|
||||||
}
|
|
||||||
return ChatColor.RED + "[CLOSED]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInitialized() {
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class BarterShop extends AbstractShop {
|
|
||||||
|
|
||||||
public BarterShop(Location location, UUID player, double price, int amount) {
|
|
||||||
super(location, player, price, amount);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class BuyShop extends AbstractShop {
|
|
||||||
|
|
||||||
public BuyShop(Location location, UUID player, double price, int amount) {
|
|
||||||
super(location, player, price, amount);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class GambleShop extends AbstractShop {
|
|
||||||
|
|
||||||
private ItemStack gambleItem;
|
|
||||||
|
|
||||||
public GambleShop(Location location, UUID player, double price, int amount) {
|
|
||||||
super(location, player, price, amount);
|
|
||||||
|
|
||||||
this.setType(ShopType.GAMBLE);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
351
src/main/java/com/alttd/playershops/shop/PlayerShop.java
Normal file
351
src/main/java/com/alttd/playershops/shop/PlayerShop.java
Normal file
|
|
@ -0,0 +1,351 @@
|
||||||
|
package com.alttd.playershops.shop;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.events.*;
|
||||||
|
import com.alttd.playershops.utils.EconomyUtils;
|
||||||
|
import com.alttd.playershops.utils.InventoryUtils;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PlayerShop {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private UUID shopID;
|
||||||
|
@Getter @Setter // TODO a way to check if the player changed name and update if needed
|
||||||
|
private String ownerName;
|
||||||
|
@Getter
|
||||||
|
private UUID ownerUUID;
|
||||||
|
@Getter
|
||||||
|
private ShopType type = ShopType.NONE;
|
||||||
|
@Getter
|
||||||
|
private final Location signLocation;
|
||||||
|
@Getter
|
||||||
|
private final Location shopLocation;
|
||||||
|
@Getter
|
||||||
|
private String server;
|
||||||
|
@Getter
|
||||||
|
private double price;
|
||||||
|
@Getter
|
||||||
|
private int amount;
|
||||||
|
@Getter
|
||||||
|
private double balance;
|
||||||
|
@Getter
|
||||||
|
private ItemStack itemStack;
|
||||||
|
@Getter @Setter
|
||||||
|
private long lastTransaction;
|
||||||
|
@Getter @Setter
|
||||||
|
private boolean notifiedOwner = false;
|
||||||
|
@Getter @Setter
|
||||||
|
private boolean dirty;
|
||||||
|
|
||||||
|
public PlayerShop(Location shopLocation, Location signLocation, Player player) {
|
||||||
|
this(shopLocation, signLocation, player.getUniqueId(), player.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerShop(Location shopLocation, Location signLocation, UUID uuid, String playerName) {
|
||||||
|
this.shopID = UUID.randomUUID();
|
||||||
|
this.shopLocation = new Location(shopLocation.getWorld(), shopLocation.getBlockX(), shopLocation.getBlockY(), shopLocation.getBlockZ());
|
||||||
|
this.signLocation = new Location(signLocation.getWorld(), signLocation.getBlockX(), signLocation.getBlockY(), signLocation.getBlockZ());
|
||||||
|
this.ownerUUID = uuid;
|
||||||
|
this.ownerName = playerName;
|
||||||
|
this.server = Bukkit.getServerName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerShop load(UUID shopID, String ownerName, UUID ownerUUID, ShopType shopType, String server,
|
||||||
|
Location shopLocation, Location signLocation, double price, int amount,
|
||||||
|
double balance, ItemStack item, long lastTransaction) {
|
||||||
|
PlayerShop playerShop = new PlayerShop(shopLocation, signLocation, ownerUUID, ownerName);
|
||||||
|
|
||||||
|
playerShop.shopID = shopID;
|
||||||
|
playerShop.type = shopType;
|
||||||
|
playerShop.server = server;
|
||||||
|
playerShop.price = price;
|
||||||
|
playerShop.amount = amount;
|
||||||
|
playerShop.balance = balance;
|
||||||
|
playerShop.itemStack = item;
|
||||||
|
playerShop.lastTransaction = lastTransaction;
|
||||||
|
|
||||||
|
return playerShop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRemainingStock() {
|
||||||
|
return InventoryUtils.countItems(getInventory(), getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRemainingSpace() {
|
||||||
|
return ShopUtil.countSpace(getInventory(), getItemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(ItemStack item) {
|
||||||
|
return ShopUtil.matches(getItemStack(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(ItemStack item, int amount) {
|
||||||
|
Inventory inv = getInventory();
|
||||||
|
int remains = amount;
|
||||||
|
while (remains > 0) {
|
||||||
|
int stackSize = Math.min(remains, item.getMaxStackSize());
|
||||||
|
item.setAmount(stackSize);
|
||||||
|
inv.removeItem(item);
|
||||||
|
remains = remains - stackSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ItemStack item, int amount) {
|
||||||
|
Inventory inv = getInventory();
|
||||||
|
int remains = amount;
|
||||||
|
while (remains > 0) {
|
||||||
|
int stackSize = Math.min(remains, item.getMaxStackSize());
|
||||||
|
item.setAmount(stackSize);
|
||||||
|
inv.addItem(item);
|
||||||
|
remains = remains - stackSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(Player player) {
|
||||||
|
ownerUUID = player.getUniqueId();
|
||||||
|
ownerName = player.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getInventory() {
|
||||||
|
// Could use a check if the block is still an InventoryHolder.
|
||||||
|
InventoryHolder container = (InventoryHolder) shopLocation.getBlock().getState();
|
||||||
|
return container.getInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return type != ShopType.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSign() {
|
||||||
|
if (!isInitialized()) {
|
||||||
|
setSignLines(type.getShopTypeConfig().inActiveSignLines);
|
||||||
|
} else {
|
||||||
|
setSignLines(type.getShopTypeConfig().activeSignLines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSignLines() {
|
||||||
|
setSignLines(type.getShopTypeConfig().activeSignLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSignLines(List<String> signLines) {
|
||||||
|
new BukkitRunnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!(signLocation.getBlock().getState() instanceof Sign signBlock)) return;
|
||||||
|
MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||||
|
TagResolver tagResolver = TagResolver.resolver(
|
||||||
|
Placeholder.unparsed("ownername", getOwnerName()),
|
||||||
|
Placeholder.unparsed("price", String.valueOf(getPrice())),
|
||||||
|
Placeholder.unparsed("amount", String.valueOf(getAmount())),
|
||||||
|
Placeholder.component("itemname", ShopUtil.itemNameComponent(getItemStack()))
|
||||||
|
);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
signBlock.line(i, miniMessage.deserialize(signLines.get(i), tagResolver));
|
||||||
|
}
|
||||||
|
signBlock.update(true);
|
||||||
|
}
|
||||||
|
}.runTaskLater(PlayerShops.getInstance(), 2L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPricePerItem() {
|
||||||
|
return this.getPrice() / this.getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeBalance(double amount) {
|
||||||
|
ShopBalanceChangeEvent shopBalanceChangeEvent = new ShopBalanceChangeEvent(this, ShopBalanceChangeEvent.ChangeReason.WITHDRAW);
|
||||||
|
if (Util.callCancellableEvent(shopBalanceChangeEvent))
|
||||||
|
return false; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
this.balance -= amount;
|
||||||
|
this.setLastTransaction(System.currentTimeMillis());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addBalance(double amount) {
|
||||||
|
ShopBalanceChangeEvent shopBalanceChangeEvent = new ShopBalanceChangeEvent(this, ShopBalanceChangeEvent.ChangeReason.DEPOSIT);
|
||||||
|
if (Util.callCancellableEvent(shopBalanceChangeEvent))
|
||||||
|
return false; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
this.balance += amount;
|
||||||
|
this.setLastTransaction(System.currentTimeMillis());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TransactionError executeTransaction(int orders, Player player) {
|
||||||
|
return switch (getType()) {
|
||||||
|
case SELL -> executeSellTransaction(orders, player);
|
||||||
|
case BUY -> executeBuyTransaction(orders, player);
|
||||||
|
case GAMBLE -> executeGambleTransaction(orders, player);
|
||||||
|
default -> TransactionError.NONE; // This should not happen
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransactionError executeSellTransaction(int orders, Player player) {
|
||||||
|
ItemStack itemStack = getItemStack().clone();
|
||||||
|
double price = getPrice();
|
||||||
|
if (orders == itemStack.getMaxStackSize()) {
|
||||||
|
itemStack.setAmount(orders);
|
||||||
|
price = getPricePerItem() * orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shopItems = InventoryUtils.countItems(getInventory(), itemStack);
|
||||||
|
if (shopItems < itemStack.getAmount())
|
||||||
|
return TransactionError.INSUFFICIENT_FUNDS_SHOP;
|
||||||
|
|
||||||
|
boolean hasFunds = EconomyUtils.hasSufficientFunds(player, price);
|
||||||
|
if (!hasFunds)
|
||||||
|
return TransactionError.INSUFFICIENT_FUNDS_PLAYER;
|
||||||
|
|
||||||
|
boolean hasRoom = EconomyUtils.canAcceptFunds(this, price);
|
||||||
|
if (!hasRoom)
|
||||||
|
return TransactionError.INVENTORY_FULL_SHOP;
|
||||||
|
|
||||||
|
boolean playerHasRoom = InventoryUtils.hasRoom(player.getInventory(), itemStack);
|
||||||
|
if (!playerHasRoom)
|
||||||
|
return TransactionError.INVENTORY_FULL_PLAYER;
|
||||||
|
|
||||||
|
PlayerExchangeShopEvent playerExchangeShopEvent = new PlayerExchangeShopEvent(player, this);
|
||||||
|
if (Util.callCancellableEvent(playerExchangeShopEvent)) {
|
||||||
|
return TransactionError.CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addBalance(price))
|
||||||
|
return TransactionError.CANCELLED;
|
||||||
|
|
||||||
|
InventoryUtils.removeItem(getInventory(), itemStack);
|
||||||
|
EconomyUtils.removeFunds(player, price);
|
||||||
|
InventoryUtils.addItem(player.getInventory(), itemStack);
|
||||||
|
player.updateInventory();
|
||||||
|
|
||||||
|
return TransactionError.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransactionError executeBuyTransaction(int orders, Player player) {
|
||||||
|
ItemStack itemStack = getItemStack().clone();
|
||||||
|
double price = getPrice();
|
||||||
|
if (orders == itemStack.getMaxStackSize()) {
|
||||||
|
itemStack.setAmount(orders);
|
||||||
|
price = getPricePerItem() * orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
int playerItems = InventoryUtils.countItems(player.getInventory(), itemStack);
|
||||||
|
if (playerItems < itemStack.getAmount())
|
||||||
|
return TransactionError.INSUFFICIENT_FUNDS_PLAYER;
|
||||||
|
|
||||||
|
boolean hasFunds = EconomyUtils.hasSufficientFunds(this, price);
|
||||||
|
if (!hasFunds)
|
||||||
|
return TransactionError.INSUFFICIENT_FUNDS_SHOP;
|
||||||
|
|
||||||
|
boolean hasRoom = EconomyUtils.canAcceptFunds(player, price);
|
||||||
|
if (!hasRoom)
|
||||||
|
return TransactionError.INVENTORY_FULL_PLAYER;
|
||||||
|
|
||||||
|
boolean shopHasRoom = InventoryUtils.hasRoom(getInventory(), itemStack);
|
||||||
|
if (!shopHasRoom)
|
||||||
|
return TransactionError.INVENTORY_FULL_SHOP;
|
||||||
|
|
||||||
|
PlayerExchangeShopEvent playerExchangeShopEvent = new PlayerExchangeShopEvent(player, this);
|
||||||
|
if (Util.callCancellableEvent(playerExchangeShopEvent)) {
|
||||||
|
return TransactionError.CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removeBalance(price))
|
||||||
|
return TransactionError.CANCELLED;
|
||||||
|
|
||||||
|
InventoryUtils.removeItem(player.getInventory(), itemStack);
|
||||||
|
EconomyUtils.addFunds(player, price);
|
||||||
|
InventoryUtils.addItem(getInventory(), itemStack);
|
||||||
|
player.updateInventory();
|
||||||
|
|
||||||
|
return TransactionError.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransactionError executeGambleTransaction(int orders, Player player) {
|
||||||
|
return TransactionError.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemStack(ItemStack itemStack) {
|
||||||
|
if (this.itemStack != null && this.itemStack.equals(itemStack))
|
||||||
|
return; // no changes have been made.
|
||||||
|
ShopItemChangeEvent shopItemChangeEvent = new ShopItemChangeEvent(this, itemStack);
|
||||||
|
if (Util.callCancellableEvent(shopItemChangeEvent))
|
||||||
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
this.itemStack.setAmount(this.amount != 0 ? this.amount : 1);
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrice(double price) {
|
||||||
|
if (this.price == price)
|
||||||
|
return; // no changes have been made.
|
||||||
|
ShopPriceChangeEvent shopPriceChangeEvent = new ShopPriceChangeEvent(this, price);
|
||||||
|
if (Util.callCancellableEvent(shopPriceChangeEvent))
|
||||||
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
this.price = price;
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(int amount) {
|
||||||
|
if (this.amount == amount)
|
||||||
|
return; // no changes have been made.
|
||||||
|
ShopItemAmountChangeEvent ShopItemAmountChangeEvent = new ShopItemAmountChangeEvent(this, amount);
|
||||||
|
if (Util.callCancellableEvent(ShopItemAmountChangeEvent))
|
||||||
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
this.amount = amount;
|
||||||
|
if (this.itemStack != null)
|
||||||
|
this.itemStack.setAmount(this.amount);
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShopType(ShopType shopType) {
|
||||||
|
if (this.type == shopType)
|
||||||
|
return; // no changes have been made.
|
||||||
|
ShopTypeChangeEvent shopTypeChangeEvent = new ShopTypeChangeEvent(this, shopType);
|
||||||
|
if (Util.callCancellableEvent(shopTypeChangeEvent))
|
||||||
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
|
this.type = shopType;
|
||||||
|
setDirty(true);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates and saves the PlayerShop in the database
|
||||||
|
*/
|
||||||
|
private void update() {
|
||||||
|
PlayerShops.getInstance().getDatabaseHelper().updateShop(this, false);
|
||||||
|
if (!ShopUtil.isLoaded(signLocation))
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateSign();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class SellShop extends AbstractShop {
|
|
||||||
|
|
||||||
public SellShop(Location location, UUID player, double price, int amount) {
|
|
||||||
super(location, player, price, amount);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
8
src/main/java/com/alttd/playershops/shop/ShopAction.java
Normal file
8
src/main/java/com/alttd/playershops/shop/ShopAction.java
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.alttd.playershops.shop;
|
||||||
|
|
||||||
|
public enum ShopAction {
|
||||||
|
BUY,
|
||||||
|
SELL,
|
||||||
|
CREATE,
|
||||||
|
CANCELLED;
|
||||||
|
}
|
||||||
4
src/main/java/com/alttd/playershops/shop/ShopInfo.java
Normal file
4
src/main/java/com/alttd/playershops/shop/ShopInfo.java
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
package com.alttd.playershops.shop;
|
||||||
|
|
||||||
|
public class ShopInfo {
|
||||||
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package com.alttd.playershops.shop;
|
|
||||||
|
|
||||||
public class ShopTransaction {
|
|
||||||
|
|
||||||
public enum ShopTransactionError {
|
|
||||||
CANCELLED,
|
|
||||||
INSUFFICIENT_FUNDS_SHOP,
|
|
||||||
INSUFFICIENT_FUNDS_PLAYER,
|
|
||||||
INVENTORY_FULL_SHOP,
|
|
||||||
INVENTORY_FULL_PLAYER,
|
|
||||||
NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,34 @@
|
||||||
package com.alttd.playershops.shop;
|
package com.alttd.playershops.shop;
|
||||||
|
|
||||||
|
import com.alttd.playershops.config.ShopTypeConfig;
|
||||||
|
|
||||||
public enum ShopType {
|
public enum ShopType {
|
||||||
SELL,
|
|
||||||
BUY,
|
NONE(),
|
||||||
GAMBLE,
|
SELL(),
|
||||||
BARTER;
|
BUY(),
|
||||||
|
GAMBLE();
|
||||||
|
|
||||||
|
private ShopTypeConfig shopTypeConfig;
|
||||||
|
ShopType() {
|
||||||
|
this.shopTypeConfig = new ShopTypeConfig(this.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShopTypeConfig getShopTypeConfig() {
|
||||||
|
return shopTypeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShopType fromString(String name) {
|
||||||
|
if (name == null)
|
||||||
|
return ShopType.NONE;
|
||||||
|
|
||||||
|
for (ShopType shopType : ShopType.values()) {
|
||||||
|
if (name.equalsIgnoreCase(shopType.toString()))
|
||||||
|
return shopType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShopType.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package com.alttd.playershops.shop;
|
package com.alttd.playershops.shop;
|
||||||
|
|
||||||
public enum ShopTransactionError {
|
public enum TransactionError {
|
||||||
CANCELLED,
|
CANCELLED,
|
||||||
INSUFFICIENT_FUNDS_SHOP,
|
INSUFFICIENT_FUNDS_SHOP,
|
||||||
INSUFFICIENT_FUNDS_PLAYER,
|
INSUFFICIENT_FUNDS_PLAYER,
|
||||||
INVENTORY_FULL_SHOP,
|
INVENTORY_FULL_SHOP,
|
||||||
INVENTORY_FULL_PLAYER,
|
INVENTORY_FULL_PLAYER,
|
||||||
|
PLAYER_OFFLINE,
|
||||||
NONE;
|
NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
package com.alttd.playershops.storage.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, " +
|
||||||
|
// "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());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import com.alttd.playershops.config.DatabaseConfig;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class DatabaseConnection implements AutoCloseable {
|
||||||
|
private Connection connection;
|
||||||
|
private volatile boolean isActive;
|
||||||
|
|
||||||
|
public DatabaseConnection() {
|
||||||
|
try {
|
||||||
|
openConnection();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized 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",
|
||||||
|
DatabaseConfig.USERNAME, DatabaseConfig.PASSWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Connection get() {
|
||||||
|
try {
|
||||||
|
openConnection();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isValid() {
|
||||||
|
try {
|
||||||
|
return !connection.isClosed() && connection.isValid(8000);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void setActive(boolean active) {
|
||||||
|
isActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isActive() {
|
||||||
|
return isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void close() {
|
||||||
|
try {
|
||||||
|
if (!connection.isClosed()) {
|
||||||
|
if (!connection.getAutoCommit()) {
|
||||||
|
connection.commit();
|
||||||
|
}
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.shop.ShopType;
|
||||||
|
import com.alttd.playershops.utils.Logger;
|
||||||
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util class to predefine sql queries that need to run.
|
||||||
|
*/
|
||||||
|
public record DatabaseHelper(PlayerShops plugin, DatabaseManager databaseManager) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all the tables are present, if not create them.
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
Logger.info("Checking required tables");
|
||||||
|
if (!databaseManager().hasTable("shops"))
|
||||||
|
createShopTable();
|
||||||
|
|
||||||
|
if (databaseManager().hasTable("transactions"))
|
||||||
|
createTransactionsTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void createShopTable() {
|
||||||
|
Logger.info("Creating shops table");
|
||||||
|
String sql = "CREATE TABLE IF NOT EXISTS shops(" +
|
||||||
|
"id VARCHAR(36) NOT NULL, " +
|
||||||
|
"owner_name VARCHAR(16) NOT NULL, " +
|
||||||
|
"owner_uuid VARCHAR(36) NOT NULL, " +
|
||||||
|
"shop_type VARCHAR(36), " +
|
||||||
|
"server VARCHAR(16) NOT NULL, " +
|
||||||
|
"container_location VARCHAR(256), " +
|
||||||
|
"sign_location VARCHAR(256), " +
|
||||||
|
"price DOUBLE, " +
|
||||||
|
"amount INT, " +
|
||||||
|
"balance DOUBLE, " +
|
||||||
|
"item BLOB, " +
|
||||||
|
"last_transaction BIGINT, " +
|
||||||
|
"PRIMARY KEY (id)" +
|
||||||
|
")";
|
||||||
|
databaseManager().addDatabaseQuery(new DatabaseQuery(sql), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createTransactionsTable() {
|
||||||
|
Logger.info("Creating transactions table");
|
||||||
|
String sql = "CREATE TABLE IF NOT EXISTS transactions(" +
|
||||||
|
"id INT NOT NULL AUTO INCREMENT, " +
|
||||||
|
"shop_id VARCHAR(36) NOT NULL, " +
|
||||||
|
"actor_name VARCHAR(16) NOT NULL, " +
|
||||||
|
"actor_uuid VARCHAR(36) NOT NULL, " +
|
||||||
|
"server VARCHAR(16) NOT NULL, " +
|
||||||
|
"action VARCHAR(36) NOT NULL, " +
|
||||||
|
"time BIGINT NOT NULL, " +
|
||||||
|
"price DOUBLE, " +
|
||||||
|
"amount INT, " +
|
||||||
|
"item BLOB, " +
|
||||||
|
"PRIMARY KEY (id)" +
|
||||||
|
")";
|
||||||
|
databaseManager().addDatabaseQuery(new DatabaseQuery(sql), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet selectTable(String tableName) throws SQLException {
|
||||||
|
String sql = "SELECT * FROM " + tableName;
|
||||||
|
return databaseManager().getDatabaseConnection().get().prepareStatement(sql).executeQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSet selectAllShops() throws SQLException {
|
||||||
|
return selectTable("shops");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createShop(PlayerShop shop) {
|
||||||
|
String sql = "INSERT INTO shops " +
|
||||||
|
"(id, owner_name, owner_uuid, server, container_location, sign_location)" +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, ?)";
|
||||||
|
databaseManager().addDatabaseQuery(
|
||||||
|
new DatabaseQuery(sql, new DatabaseQuery.DatabaseTask() {
|
||||||
|
@Override
|
||||||
|
public void edit(PreparedStatement ps) throws SQLException {
|
||||||
|
ps.setString(1, shop.getShopID().toString());
|
||||||
|
ps.setString(2, shop.getOwnerName());
|
||||||
|
ps.setString(3, shop.getOwnerUUID().toString());
|
||||||
|
ps.setString(4, Bukkit.getServerName());
|
||||||
|
ps.setString(5, ShopUtil.locationToString(shop.getShopLocation()));
|
||||||
|
ps.setString(6, ShopUtil.locationToString(shop.getSignLocation()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
shop.updateSign();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(SQLException e) {
|
||||||
|
Logger.error("Could not save shop for " + shop.getOwnerName() + " at " + shop.getShopLocation() + " to the database.\n" + e);
|
||||||
|
}
|
||||||
|
}), false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeShop(PlayerShop shop) {
|
||||||
|
String sql = "DELETE FROM shops WHERE id = ?";
|
||||||
|
databaseManager().addDatabaseQuery(
|
||||||
|
new DatabaseQuery(sql, new DatabaseQuery.DatabaseTask() {
|
||||||
|
@Override
|
||||||
|
public void edit(PreparedStatement ps) throws SQLException {
|
||||||
|
ps.setString(1, shop.getShopID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
shop.removeSignLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(SQLException e) {
|
||||||
|
Logger.error("Could not remove shop for " + shop.getOwnerName() + " at " + shop.getShopLocation() + " to the database.\n" + e);
|
||||||
|
}
|
||||||
|
}), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public PlayerShop shopFromResultSet(ResultSet resultSet) throws SQLException {
|
||||||
|
UUID id = UUID.fromString(resultSet.getString("id"));
|
||||||
|
String ownerName = resultSet.getString("owner_name");
|
||||||
|
UUID ownerUuid = UUID.fromString(resultSet.getString("owner_uuid"));
|
||||||
|
ShopType shopType = ShopType.fromString(resultSet.getString("shop_type"));
|
||||||
|
String server = resultSet.getString("server");
|
||||||
|
Location containerLocation = ShopUtil.stringToLocation(resultSet.getString("container_location"));
|
||||||
|
Location signLocation = ShopUtil.stringToLocation(resultSet.getString("sign_location"));
|
||||||
|
double price = resultSet.getDouble("price");
|
||||||
|
int amount = resultSet.getInt("amount");
|
||||||
|
double balance = resultSet.getDouble("balance");
|
||||||
|
byte[] itemstackbytes = resultSet.getBytes("item");
|
||||||
|
ItemStack itemStack = null;
|
||||||
|
if (itemstackbytes != null) {
|
||||||
|
itemStack = ItemStack.deserializeBytes(resultSet.getBytes("item"));
|
||||||
|
}
|
||||||
|
long lastTransaction = resultSet.getLong("last_transaction");
|
||||||
|
|
||||||
|
if (containerLocation == null || signLocation == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return PlayerShop.load(id, ownerName, ownerUuid, shopType, server, containerLocation, signLocation,
|
||||||
|
price, amount, balance, itemStack, lastTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates and saves the PlayerShop in the database
|
||||||
|
*/
|
||||||
|
public void updateShop(PlayerShop shop, boolean queue) {
|
||||||
|
String query = "UPDATE shops SET owner_name = ?, owner_uuid = ?, shop_type = ?, server = ?, " +
|
||||||
|
"container_location = ?, sign_location = ?, price = ?, amount = ?, balance = ?, " +
|
||||||
|
"item = ?, last_transaction = ? WHERE id = ?";
|
||||||
|
databaseManager().addDatabaseQuery(
|
||||||
|
new DatabaseQuery(query, ps -> {
|
||||||
|
ps.setString(1, shop.getOwnerName());
|
||||||
|
ps.setString(2, shop.getOwnerUUID().toString());
|
||||||
|
ps.setString(3, shop.getType().toString());
|
||||||
|
ps.setString(4, shop.getServer());
|
||||||
|
ps.setString(5, ShopUtil.locationToString(shop.getShopLocation()));
|
||||||
|
ps.setString(6, ShopUtil.locationToString(shop.getSignLocation()));
|
||||||
|
ps.setDouble(7, shop.getPrice());
|
||||||
|
ps.setInt(8, shop.getAmount());
|
||||||
|
ps.setDouble(9, shop.getBalance());
|
||||||
|
ItemStack itemStack = shop.getItemStack();
|
||||||
|
if (itemStack != null && !itemStack.getType().equals(Material.AIR)) {
|
||||||
|
ps.setBytes(10, shop.getItemStack().serializeAsBytes());
|
||||||
|
} else {
|
||||||
|
ps.setBytes(10, null);
|
||||||
|
}
|
||||||
|
ps.setLong(11, shop.getLastTransaction());
|
||||||
|
ps.setString(12, shop.getShopID().toString());
|
||||||
|
}), queue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a transaction with a shop
|
||||||
|
*/
|
||||||
|
public void logTransaction(Player player, PlayerShop shop, int orders) {
|
||||||
|
String query = "INSERT INTO transaction (shop_id, actor_name, actor_uuid, server, action, time, price, amount, item) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
databaseManager().addDatabaseQuery(
|
||||||
|
new DatabaseQuery(query, new DatabaseQuery.DatabaseTask() {
|
||||||
|
@Override
|
||||||
|
public void edit(PreparedStatement ps) throws SQLException {
|
||||||
|
ps.setString(1, shop.getShopID().toString());
|
||||||
|
ps.setString(2, player.getName());
|
||||||
|
ps.setString(3, player.getUniqueId().toString());
|
||||||
|
ps.setString(4, shop.getServer());
|
||||||
|
ps.setString(5, shop.getType().toString());
|
||||||
|
ps.setLong(6, new Date().getTime());
|
||||||
|
ps.setDouble(7, shop.getPrice());
|
||||||
|
ps.setInt(8, orders);
|
||||||
|
ItemStack itemStack = shop.getItemStack();
|
||||||
|
if (itemStack != null && !itemStack.getType().equals(Material.AIR)) {
|
||||||
|
ps.setBytes(9, shop.getItemStack().serializeAsBytes());
|
||||||
|
} else {
|
||||||
|
ps.setBytes(9, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(SQLException e) {
|
||||||
|
Logger.error("Could not log transaction by " + player.getName() + " at " + shop.getShopLocation() + " to the database.\n" + e);
|
||||||
|
}
|
||||||
|
}), true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.config.DatabaseConfig;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseConnection;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseQuery;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseQueue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DatabaseManager {
|
||||||
|
|
||||||
|
DatabaseQueue databaseQueue;
|
||||||
|
private final List<DatabaseConnection> CONNECTIONPOOL = new ArrayList<>();
|
||||||
|
|
||||||
|
public DatabaseManager(PlayerShops playerShops) {
|
||||||
|
databaseQueue = new DatabaseQueue(this);
|
||||||
|
int delay = DatabaseConfig.queueDelay * 20;
|
||||||
|
databaseQueue.runTaskTimerAsynchronously(playerShops, delay, delay);
|
||||||
|
// preload out database connections, TODO FIND A BETTER WAY TO LIMIT THIS
|
||||||
|
for (int i = 1; i < DatabaseConfig.maxDatabaseConnections; i++) {
|
||||||
|
CONNECTIONPOOL.add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseConnection getDatabaseConnection() {
|
||||||
|
for (int i = 0; i < DatabaseConfig.maxDatabaseConnections; i++) {
|
||||||
|
DatabaseConnection connection = CONNECTIONPOOL.get(i);
|
||||||
|
if (connection == null) {
|
||||||
|
return generateDatabaseConnection(i);
|
||||||
|
} else if (!connection.isActive()) {
|
||||||
|
if (connection.isValid()) {
|
||||||
|
return connection;
|
||||||
|
} else {
|
||||||
|
connection.close();
|
||||||
|
return generateDatabaseConnection(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will cause an infinite running loop, throw an exception or wait for a connection to be available?
|
||||||
|
return getDatabaseConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DatabaseConnection generateDatabaseConnection(int index) {
|
||||||
|
DatabaseConnection connection = new DatabaseConnection();
|
||||||
|
CONNECTIONPOOL.set(index, connection);
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeDatabaseConnections() {
|
||||||
|
for (DatabaseConnection connection : CONNECTIONPOOL) {
|
||||||
|
if (connection == null || connection.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!connection.isActive()) {
|
||||||
|
connection.close();
|
||||||
|
} else {
|
||||||
|
while (connection.isActive()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// This should not be interrupted as this is saving all the shops in the background for us.
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unload() {
|
||||||
|
if (databaseQueue != null && !databaseQueue.isCancelled()) {
|
||||||
|
databaseQueue.cancel();
|
||||||
|
databaseQueue.runTaskQueue();
|
||||||
|
}
|
||||||
|
closeDatabaseConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDatabaseQuery(DatabaseQuery databaseQuery, boolean queue) {
|
||||||
|
if (queue) {
|
||||||
|
databaseQueue.getDatabaseQueryQueue().offer(databaseQuery);
|
||||||
|
} else {
|
||||||
|
databaseQuery.execute(getDatabaseConnection().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasTable(String table){
|
||||||
|
DatabaseConnection connection = getDatabaseConnection();
|
||||||
|
boolean match = false;
|
||||||
|
try (ResultSet rs = connection.get().getMetaData().getTables(null, null, table, null)) {
|
||||||
|
while (rs.next()) {
|
||||||
|
if (table.equalsIgnoreCase(rs.getString("TABLE_NAME"))) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class DatabaseQuery {
|
||||||
|
|
||||||
|
private final String statement;
|
||||||
|
private final DatabaseTask databaseTask;
|
||||||
|
|
||||||
|
public DatabaseQuery(String statement, DatabaseTask databaseTask) {
|
||||||
|
this.statement = statement;
|
||||||
|
this.databaseTask = databaseTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseQuery(String statement) {
|
||||||
|
this(statement, ps -> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(Connection connection) {
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(statement)) {
|
||||||
|
databaseTask.edit(preparedStatement);
|
||||||
|
preparedStatement.execute();
|
||||||
|
databaseTask.onSuccess();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
databaseTask.onFailure(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DatabaseTask {
|
||||||
|
|
||||||
|
void edit(PreparedStatement preparedStatement) throws SQLException;
|
||||||
|
|
||||||
|
default void onSuccess() {};
|
||||||
|
|
||||||
|
default void onFailure(SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class DatabaseQueue extends BukkitRunnable {
|
||||||
|
|
||||||
|
private final DatabaseManager databaseManager;
|
||||||
|
|
||||||
|
public DatabaseQueue(DatabaseManager databaseManager) {
|
||||||
|
this.databaseManager = databaseManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final Queue<DatabaseQuery> databaseQueryQueue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
runTaskQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void runTaskQueue() {
|
||||||
|
if (databaseQueryQueue.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DatabaseConnection databaseConnection = databaseManager.getDatabaseConnection();
|
||||||
|
Connection connection = databaseConnection.get();
|
||||||
|
|
||||||
|
try {
|
||||||
|
databaseConnection.setActive(true);
|
||||||
|
connection.setAutoCommit(false);
|
||||||
|
while (!databaseQueryQueue.isEmpty()) {
|
||||||
|
if (!databaseConnection.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DatabaseQuery databaseQuery = databaseQueryQueue.poll();
|
||||||
|
if (databaseQuery == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
databaseQuery.execute(connection);
|
||||||
|
}
|
||||||
|
if (!connection.getAutoCommit()) {
|
||||||
|
connection.commit();
|
||||||
|
connection.setAutoCommit(true);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
databaseConnection.setActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.alttd.playershops.storage.database;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.shop.ShopType;
|
||||||
|
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(PlayerShop 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 = ?, 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.getShopLocation()));
|
||||||
|
// 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.setLong(12, shop.getLastTransaction());
|
||||||
|
// //repeat everything except id for update
|
||||||
|
// statement.setString(13, shop.getOwnerName());
|
||||||
|
// statement.setString(14, shop.getOwnerUUID().toString());
|
||||||
|
// statement.setString(15, shop.getServer());
|
||||||
|
// statement.setString(16, shop.getType().toString());
|
||||||
|
// statement.setString(17, locationToString(shop.getShopLocation()));
|
||||||
|
// statement.setString(18, locationToString(shop.getSignLocation()));
|
||||||
|
// statement.setDouble(19, shop.getPrice());
|
||||||
|
// statement.setInt(20, shop.getAmount());
|
||||||
|
// statement.setDouble(21, shop.getBalance());
|
||||||
|
// statement.setBytes(22, shop.getItemStack().serializeAsBytes());
|
||||||
|
// statement.setLong(23, shop.getLastTransaction());
|
||||||
|
//
|
||||||
|
// return statement.executeUpdate() == 1;
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static PlayerShop 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<PlayerShop> loadShops() {
|
||||||
|
// String sql = "SELECT * FROM shops";
|
||||||
|
// ArrayList<PlayerShop> shops = new ArrayList<>();
|
||||||
|
// try {
|
||||||
|
// PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||||
|
//
|
||||||
|
// ResultSet resultSet = statement.executeQuery();
|
||||||
|
// while (resultSet.next()) {
|
||||||
|
// PlayerShop 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 PlayerShop 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 PlayerShop.create(id, ownerName, ownerUuid, shopType, server, containerLocation, signLocation,
|
||||||
|
// price, amount, balance, itemOne, 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;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
58
src/main/java/com/alttd/playershops/utils/EconomyUtils.java
Normal file
58
src/main/java/com/alttd/playershops/utils/EconomyUtils.java
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import net.milkbowl.vault.economy.EconomyResponse;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
// TODO document
|
||||||
|
public class EconomyUtils {
|
||||||
|
|
||||||
|
//check to see if the player has enough funds to take out [amount]
|
||||||
|
//return false if they do not
|
||||||
|
public static boolean hasSufficientFunds(Player player, double amount) {
|
||||||
|
double balance = PlayerShops.getInstance().getEconomy().getBalance(player);
|
||||||
|
return (balance >= amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasSufficientFunds(PlayerShop shop, double amount) {
|
||||||
|
double balance = shop.getBalance();
|
||||||
|
return (balance >= amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//gets the current funds of the player
|
||||||
|
public static double getFunds(Player player) {
|
||||||
|
return PlayerShops.getInstance().getEconomy().getBalance(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
//removes [amount] of funds from the player
|
||||||
|
//return false if the player did not have sufficient funds or if something went wrong
|
||||||
|
public static boolean removeFunds(Player player, double amount) {
|
||||||
|
EconomyResponse response = PlayerShops.getInstance().getEconomy().withdrawPlayer(player, amount);
|
||||||
|
return response.transactionSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
//adds [amount] of funds to the player
|
||||||
|
//return false if the player is offline
|
||||||
|
public static boolean addFunds(Player player, double amount) {
|
||||||
|
if(player.isOnline()) {
|
||||||
|
EconomyResponse response = PlayerShops.getInstance().getEconomy().depositPlayer(player, amount);
|
||||||
|
return response.transactionSuccess();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
// int temp = PlayerShops.getInstance().Earnings.getInt(player.getUniqueId() + ".earnings");
|
||||||
|
// PlayerShops.getInstance().Earnings.set(player.getUniqueId() + ".earnings", temp + amount);
|
||||||
|
// PlayerShops.getInstance().Earnings.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canAcceptFunds(Player player, double price) {
|
||||||
|
// if we ever need to limit the maximum balance a player can have this is the place
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canAcceptFunds(PlayerShop shop, double price) {
|
||||||
|
// if we ever need to limit the maximum balance a shop can have this is the place
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/main/java/com/alttd/playershops/utils/InventoryUtils.java
Normal file
119
src/main/java/com/alttd/playershops/utils/InventoryUtils.java
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class InventoryUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of items in the given inventory where
|
||||||
|
* Util.matches(inventory item, item) is true.
|
||||||
|
*
|
||||||
|
* @param inv
|
||||||
|
* The inventory to search
|
||||||
|
* @param item
|
||||||
|
* The ItemStack to search for
|
||||||
|
* @return The number of items that match in this inventory.
|
||||||
|
*/
|
||||||
|
public static int countItems(Inventory inv, ItemStack item) {
|
||||||
|
int items = 0;
|
||||||
|
for (ItemStack iStack : inv.getContents()) {
|
||||||
|
if (iStack == null)
|
||||||
|
continue;
|
||||||
|
if (ShopUtil.matches(item, iStack)) {
|
||||||
|
items += iStack.getAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO DOCS
|
||||||
|
//removes itemstack from inventory
|
||||||
|
//returns the amount of items it could not remove
|
||||||
|
public static int removeItem(Inventory inventory, ItemStack itemStack) {
|
||||||
|
if (inventory == null)
|
||||||
|
return itemStack.getAmount();
|
||||||
|
if (itemStack == null || itemStack.getAmount() <= 0)
|
||||||
|
return 0;
|
||||||
|
ItemStack[] contents = inventory.getContents();
|
||||||
|
int amount = itemStack.getAmount();
|
||||||
|
for (ItemStack stack : contents) {
|
||||||
|
if (stack != null) {
|
||||||
|
if (ShopUtil.matches(stack, itemStack)) {
|
||||||
|
if (stack.getAmount() > amount) {
|
||||||
|
stack.setAmount(stack.getAmount() - amount);
|
||||||
|
inventory.setContents(contents);
|
||||||
|
return 0;
|
||||||
|
} else if (stack.getAmount() == amount) {
|
||||||
|
stack.setType(Material.AIR);
|
||||||
|
inventory.setContents(contents);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
amount -= stack.getAmount();
|
||||||
|
stack.setType(Material.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inventory.setContents(contents);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
//takes an ItemStack and splits it up into multiple ItemStacks with correct stack sizes
|
||||||
|
//then adds those items to the given inventory
|
||||||
|
public static int addItem(Inventory inventory, ItemStack itemStack) {
|
||||||
|
if (inventory == null)
|
||||||
|
return itemStack.getAmount();
|
||||||
|
if (itemStack.getAmount() <= 0)
|
||||||
|
return 0;
|
||||||
|
ArrayList<ItemStack> itemStacksAdding = new ArrayList<>();
|
||||||
|
|
||||||
|
//break up the itemstack into multiple ItemStacks with correct stack size
|
||||||
|
int fullStacks = itemStack.getAmount() / itemStack.getMaxStackSize();
|
||||||
|
int partialStack = itemStack.getAmount() % itemStack.getMaxStackSize();
|
||||||
|
for (int i = 0; i < fullStacks; i++) {
|
||||||
|
ItemStack is = itemStack.clone();
|
||||||
|
is.setAmount(is.getMaxStackSize());
|
||||||
|
itemStacksAdding.add(is);
|
||||||
|
}
|
||||||
|
ItemStack is = itemStack.clone();
|
||||||
|
is.setAmount(partialStack);
|
||||||
|
if (partialStack > 0)
|
||||||
|
itemStacksAdding.add(is);
|
||||||
|
|
||||||
|
//try adding all items from itemStacksAdding and return number of ones you couldn't add
|
||||||
|
int amount = 0;
|
||||||
|
for (ItemStack addItem : itemStacksAdding) {
|
||||||
|
HashMap<Integer, ItemStack> noAdd = inventory.addItem(addItem);
|
||||||
|
for (ItemStack noAddItemstack : noAdd.values()) {
|
||||||
|
amount += noAddItemstack.getAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasRoom(Inventory inventory, ItemStack itemStack) {
|
||||||
|
if (inventory == null)
|
||||||
|
return false;
|
||||||
|
if (itemStack.getAmount() <= 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int overflow = addItem(inventory, itemStack);
|
||||||
|
|
||||||
|
//revert back if inventory cannot hold all of the items
|
||||||
|
if (overflow > 0) {
|
||||||
|
ItemStack revert = itemStack.clone();
|
||||||
|
revert.setAmount(revert.getAmount() - overflow);
|
||||||
|
InventoryUtils.removeItem(inventory, revert);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
removeItem(inventory, itemStack);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,43 @@
|
||||||
package com.alttd.playershops.utils;
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import com.alttd.playershops.PlayerShops;
|
||||||
import org.bukkit.Bukkit;
|
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
public class Logger {
|
||||||
|
|
||||||
public class Logger
|
private static ComponentLogger logger;
|
||||||
{
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message on the INFO level
|
||||||
|
*
|
||||||
|
* @param str Message to be logged.
|
||||||
|
*/
|
||||||
public static void info(String str) {
|
public static void info(String str) {
|
||||||
log(Level.INFO,"&e" + str);
|
getLogger().info(Util.parseMiniMessage(str, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message on the WARN level
|
||||||
|
*
|
||||||
|
* @param str Message to be logged.
|
||||||
|
*/
|
||||||
public static void warn(String str) {
|
public static void warn(String str) {
|
||||||
log(Level.SEVERE,"&6" + str);
|
getLogger().warn(Util.parseMiniMessage(str, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void severe(String str) {
|
/**
|
||||||
log(Level.SEVERE,"&c" + str);
|
* Logs a message on the ERROR level
|
||||||
|
*
|
||||||
|
* @param str Message to be logged.
|
||||||
|
*/
|
||||||
|
public static void error(String str) {
|
||||||
|
getLogger().error(Util.parseMiniMessage("<red>" + str, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(Level level, String str) {
|
static ComponentLogger getLogger() {
|
||||||
Bukkit.getLogger().log(level,
|
if (logger == null)
|
||||||
ChatColor.translateAlternateColorCodes('&',
|
logger = PlayerShops.getInstance().getComponentLogger();
|
||||||
"&r " + str));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
196
src/main/java/com/alttd/playershops/utils/ShopUtil.java
Normal file
196
src/main/java/com/alttd/playershops/utils/ShopUtil.java
Normal file
|
|
@ -0,0 +1,196 @@
|
||||||
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ShopUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given location is loaded or not.
|
||||||
|
*
|
||||||
|
* @param loc
|
||||||
|
* The location
|
||||||
|
* @return true if the given location is loaded or not.
|
||||||
|
*/
|
||||||
|
public static boolean isLoaded(Location loc) {
|
||||||
|
if (!loc.isWorldLoaded()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int x = (int) Math.floor((loc.getBlockX()) / 16.0);
|
||||||
|
int z = (int) Math.floor((loc.getBlockZ()) / 16.0);
|
||||||
|
return (loc.getWorld().isChunkLoaded(x, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two items to each other. Returns true if they match.
|
||||||
|
*
|
||||||
|
* @param stack1
|
||||||
|
* The first item stack
|
||||||
|
* @param stack2
|
||||||
|
* The second item stack
|
||||||
|
* @return true if the itemstacks match. (Material, durability, enchants, name)
|
||||||
|
*/
|
||||||
|
public static boolean matches(ItemStack stack1, ItemStack stack2) {
|
||||||
|
if (stack1 == stack2)
|
||||||
|
return true; // Referring to the same thing, or both are null.
|
||||||
|
if (stack1 == null || stack2 == null)
|
||||||
|
return false; // One of them is null (Can't be both, see above)
|
||||||
|
if (stack1.getType() != stack2.getType())
|
||||||
|
return false; // Not the same material
|
||||||
|
if (stack1.getDurability() != stack2.getDurability())
|
||||||
|
return false; // Not the same durability
|
||||||
|
if (!stack1.getEnchantments().equals(stack2.getEnchantments()))
|
||||||
|
return false; // They have the same enchants
|
||||||
|
if (stack1.getItemMeta().hasDisplayName() || stack2.getItemMeta().hasDisplayName()) {
|
||||||
|
if (stack1.getItemMeta().hasDisplayName() && stack2.getItemMeta().hasDisplayName()) {
|
||||||
|
if (!stack1.getItemMeta().getDisplayName().equals(stack2.getItemMeta().getDisplayName())) {
|
||||||
|
return false; // items have different display name
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false; // one of the item stacks have a display name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Class.forName("org.bukkit.inventory.meta.EnchantmentStorageMeta");
|
||||||
|
boolean book1 = stack1.getItemMeta() instanceof EnchantmentStorageMeta;
|
||||||
|
boolean book2 = stack2.getItemMeta() instanceof EnchantmentStorageMeta;
|
||||||
|
if (book1 != book2)
|
||||||
|
return false;// One has enchantment meta, the other does not.
|
||||||
|
if (book1 == true) { // They are the same here (both true or both
|
||||||
|
// false). So if one is true, the other is
|
||||||
|
// true.
|
||||||
|
Map<Enchantment, Integer> ench1 = ((EnchantmentStorageMeta) stack1.getItemMeta()).getStoredEnchants();
|
||||||
|
Map<Enchantment, Integer> ench2 = ((EnchantmentStorageMeta) stack2.getItemMeta()).getStoredEnchants();
|
||||||
|
if (!ench1.equals(ench2))
|
||||||
|
return false; // Enchants aren't the same.
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of items that can be given to the inventory safely.
|
||||||
|
*
|
||||||
|
* @param inv
|
||||||
|
* The inventory to count
|
||||||
|
* @param item
|
||||||
|
* The item. Material, durabiltiy and enchants must
|
||||||
|
* match for 'stackability' to occur.
|
||||||
|
* @return The number of items that can be given to the inventory safely.
|
||||||
|
*/
|
||||||
|
public static int countSpace(Inventory inv, ItemStack item) {
|
||||||
|
int space = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ItemStack[] contents = inv.getContents();
|
||||||
|
for (ItemStack iStack : contents) {
|
||||||
|
if (iStack == null || iStack.getType() == Material.AIR) {
|
||||||
|
space += item.getMaxStackSize();
|
||||||
|
} else if (matches(item, iStack)) {
|
||||||
|
space += item.getMaxStackSize() - iStack.getAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String locationToString(Location location) {
|
||||||
|
return location.getWorld().getName() + ":" +
|
||||||
|
AMath.round(location.getX(), 1) + ":" +
|
||||||
|
AMath.round(location.getY(), 1) + ":" +
|
||||||
|
AMath.round(location.getZ(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack getPlayerHead(UUID uuid) {
|
||||||
|
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
|
||||||
|
|
||||||
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
|
if (player == null) return skull;
|
||||||
|
|
||||||
|
// TODO add skins to skulls and name them.
|
||||||
|
SkullMeta meta = (SkullMeta) skull.getItemMeta();
|
||||||
|
meta.setPlayerProfile(player.getPlayerProfile());
|
||||||
|
skull.setItemMeta(meta);
|
||||||
|
|
||||||
|
return skull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO upgrade this to an util method check if owner/trusted and open management interface
|
||||||
|
public static boolean canManageShop(Player player, PlayerShop playerShop) {
|
||||||
|
if (playerShop.getOwnerUUID().equals(player.getUniqueId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Component itemNameComponent(ItemStack item) {
|
||||||
|
Component component = Component.empty();
|
||||||
|
if(item == null || item.getType().equals(Material.AIR))
|
||||||
|
return Component.text("Nothing");
|
||||||
|
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
|
||||||
|
if(dname) {
|
||||||
|
component = component.append(item.getItemMeta().displayName());
|
||||||
|
} else {
|
||||||
|
component = component.append(Component.text(materialToName(item.getType()), NamedTextColor.WHITE));
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String materialToName(Material m) {
|
||||||
|
if (m.equals(Material.TNT)) {
|
||||||
|
return "TNT";
|
||||||
|
}
|
||||||
|
String orig = m.name().toLowerCase();
|
||||||
|
String[] splits = orig.split("_");
|
||||||
|
StringBuilder sb = new StringBuilder(orig.length());
|
||||||
|
int pos = 0;
|
||||||
|
for (String split : splits) {
|
||||||
|
sb.append(split);
|
||||||
|
int loc = sb.lastIndexOf(split);
|
||||||
|
char charLoc = sb.charAt(loc);
|
||||||
|
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") ||
|
||||||
|
split.equalsIgnoreCase("with") || split.equalsIgnoreCase("on")))
|
||||||
|
sb.setCharAt(loc, Character.toUpperCase(charLoc));
|
||||||
|
if (pos != splits.length - 1)
|
||||||
|
sb.append(' ');
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
82
src/main/java/com/alttd/playershops/utils/Util.java
Normal file
82
src/main/java/com/alttd/playershops/utils/Util.java
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
private static MiniMessage miniMessage = null;
|
||||||
|
|
||||||
|
public static HashMap<String, String> colors;
|
||||||
|
static { // this might be in minimessage already?
|
||||||
|
colors = new HashMap<>();
|
||||||
|
colors.put("&0", "<black>");
|
||||||
|
colors.put("&1", "<dark_blue>");
|
||||||
|
colors.put("&2", "<dark_green>");
|
||||||
|
colors.put("&3", "<dark_aqua>");
|
||||||
|
colors.put("&4", "<dark_red>");
|
||||||
|
colors.put("&5", "<dark_purple>");
|
||||||
|
colors.put("&6", "<gold>");
|
||||||
|
colors.put("&7", "<gray>");
|
||||||
|
colors.put("&8", "<dark_gray>");
|
||||||
|
colors.put("&9", "<blue>");
|
||||||
|
colors.put("&a", "<green>");
|
||||||
|
colors.put("&b", "<aqua>");
|
||||||
|
colors.put("&c", "<red>");
|
||||||
|
colors.put("&d", "<light_purple>");
|
||||||
|
colors.put("&e", "<yellow>");
|
||||||
|
colors.put("&f", "<white>");
|
||||||
|
colors.put("&l", "<bold>");
|
||||||
|
colors.put("&o", "<italic>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String parseColors(String message) {
|
||||||
|
for (String key : colors.keySet()) {
|
||||||
|
if (message.contains(key)) {
|
||||||
|
message = message.replace(key, colors.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MiniMessage miniMessage() {
|
||||||
|
if (miniMessage == null)
|
||||||
|
miniMessage = MiniMessage.miniMessage();
|
||||||
|
return miniMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Component parseMiniMessage(String message, TagResolver tagResolver) {
|
||||||
|
message = parseColors(message);
|
||||||
|
if (tagResolver == null) {
|
||||||
|
return miniMessage().deserialize(message);
|
||||||
|
} else {
|
||||||
|
return miniMessage().deserialize(message, tagResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String capitalize(String string) {
|
||||||
|
if (string.length() <= 1)
|
||||||
|
return string.toUpperCase();
|
||||||
|
return string.substring(0, 1).toUpperCase() + string.toLowerCase().substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call an event and check it is cancelled.
|
||||||
|
*
|
||||||
|
* @param event The event implement the Cancellable interface.
|
||||||
|
* @return The event is cancelled.
|
||||||
|
*/
|
||||||
|
public static boolean callCancellableEvent(Cancellable event) {
|
||||||
|
if (!(event instanceof Event)) {
|
||||||
|
throw new IllegalArgumentException("Cancellable must is event implement");
|
||||||
|
}
|
||||||
|
Bukkit.getPluginManager().callEvent((Event) event);
|
||||||
|
return event.isCancelled();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user