dev/rework
This commit is contained in:
parent
1ae73c5ba8
commit
abf53fbbbe
|
|
@ -97,7 +97,10 @@ bukkit {
|
||||||
children = listOf(
|
children = listOf(
|
||||||
"playershops.shop.create",
|
"playershops.shop.create",
|
||||||
"playershops.shop.break.other",
|
"playershops.shop.break.other",
|
||||||
"playershops.shop.use"
|
"playershops.shop.use",
|
||||||
|
"playershops.shop.use.buy",
|
||||||
|
"playershops.shop.use.sell",
|
||||||
|
"playershops.shop.use.gamble"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
register("playershops.shoplimit") {
|
register("playershops.shoplimit") {
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,10 @@ 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.gui.GuiIcon;
|
||||||
import com.alttd.playershops.handler.ShopHandler;
|
import com.alttd.playershops.handler.ShopHandler;
|
||||||
import com.alttd.playershops.listener.BlockListener;
|
import com.alttd.playershops.listener.*;
|
||||||
import com.alttd.playershops.listener.PlayerListener;
|
|
||||||
import com.alttd.playershops.listener.ShopListener;
|
|
||||||
import com.alttd.playershops.listener.TransactionListener;
|
|
||||||
import com.alttd.playershops.shop.ShopType;
|
import com.alttd.playershops.shop.ShopType;
|
||||||
import com.alttd.playershops.storage.DatabaseManager;
|
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;
|
||||||
|
|
@ -28,11 +26,13 @@ public class PlayerShops extends JavaPlugin {
|
||||||
private ShopHandler shopHandler;
|
private ShopHandler shopHandler;
|
||||||
@Getter
|
@Getter
|
||||||
private DatabaseManager databaseManager;
|
private DatabaseManager databaseManager;
|
||||||
|
@Getter
|
||||||
|
private DatabaseHelper databaseHelper;
|
||||||
private ShopListener shopListener;
|
private ShopListener shopListener;
|
||||||
private PlayerListener playerListener;
|
private PlayerListener playerListener;
|
||||||
private BlockListener blockListener;
|
private BlockListener blockListener;
|
||||||
private TransactionListener transactionListener;
|
private TransactionListener transactionListener;
|
||||||
|
private InventoryListener inventoryListener;
|
||||||
|
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
@ -43,7 +43,12 @@ 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();
|
||||||
databaseManager = new DatabaseManager(instance);
|
if(!setupDatabase()) {
|
||||||
|
Bukkit.getLogger().warning("Error setting up database connection.\n Disabling plugin");
|
||||||
|
this.setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
shopHandler = new ShopHandler(instance);
|
shopHandler = new ShopHandler(instance);
|
||||||
|
|
||||||
registerListeners();
|
registerListeners();
|
||||||
|
|
@ -51,6 +56,7 @@ public class PlayerShops extends JavaPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
shopHandler.unloadShops();
|
||||||
unRegisterListeners();
|
unRegisterListeners();
|
||||||
Bukkit.getScheduler().cancelTasks(this);
|
Bukkit.getScheduler().cancelTasks(this);
|
||||||
|
|
||||||
|
|
@ -69,6 +75,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();
|
||||||
|
|
@ -80,6 +93,7 @@ public class PlayerShops extends JavaPlugin {
|
||||||
playerListener = new PlayerListener(this);
|
playerListener = new PlayerListener(this);
|
||||||
blockListener = new BlockListener(this);
|
blockListener = new BlockListener(this);
|
||||||
transactionListener = new TransactionListener(this);
|
transactionListener = new TransactionListener(this);
|
||||||
|
inventoryListener = new InventoryListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unRegisterListeners() {
|
private void unRegisterListeners() {
|
||||||
|
|
@ -87,6 +101,7 @@ public class PlayerShops extends JavaPlugin {
|
||||||
playerListener.unregister();
|
playerListener.unregister();
|
||||||
blockListener.unregister();
|
blockListener.unregister();
|
||||||
transactionListener.unregister();
|
transactionListener.unregister();
|
||||||
|
inventoryListener.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.alttd.playershops.commands;
|
package com.alttd.playershops.commands;
|
||||||
|
|
||||||
|
import com.alttd.playershops.gui.HomeGui;
|
||||||
import com.alttd.playershops.gui.ShopManagementGui;
|
import com.alttd.playershops.gui.ShopManagementGui;
|
||||||
import com.alttd.playershops.shop.PlayerShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
|
|
@ -25,7 +26,7 @@ public class ShopCommand implements CommandExecutor, TabCompleter {
|
||||||
case "reload":
|
case "reload":
|
||||||
break;
|
break;
|
||||||
case "open":
|
case "open":
|
||||||
ShopManagementGui gui = new ShopManagementGui(player.getUniqueId(), new PlayerShop(player.getLocation(), player.getLocation(), player));
|
HomeGui gui = new HomeGui(player.getUniqueId());
|
||||||
gui.open();
|
gui.open();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,13 @@ public class Config extends AbstractConfiguration {
|
||||||
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 + "default-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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,12 @@ public class ShopTypeConfig {
|
||||||
public List<String> activeSignLines = List.of("<green>[Shop]", "", "", "");
|
public List<String> activeSignLines = List.of("<green>[Shop]", "", "", "");
|
||||||
public List<String> inActiveSignLines = List.of("<green>[Shop]", "right click", "to manage", "<ownername>");
|
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> expiredSignLines = List.of("[Shop]", "expired", "", "<ownername>");
|
||||||
|
public List<String> deletedSignLines = List.of("[Shop]", "deleted", "", "<ownername>");
|
||||||
private void signSettings() {
|
private void signSettings() {
|
||||||
activeSignLines = getStringList("sign.active-lines", activeSignLines);
|
activeSignLines = getStringList("sign.active-lines", activeSignLines);
|
||||||
inActiveSignLines = getStringList("sign.inactive-lines", inActiveSignLines);
|
inActiveSignLines = getStringList("sign.inactive-lines", inActiveSignLines);
|
||||||
expiredSignLines = getStringList("sign.expired-lines", expiredSignLines);
|
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 playerInventoryFull = "<red>You do not have enough space in your inventory to buy from this shop.";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
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) {
|
||||||
|
this.player = player;
|
||||||
|
this.playerShop = playerShop;
|
||||||
|
ConversationFactory conversationFactory = new ConversationFactory(plugin)
|
||||||
|
.withModality(true)
|
||||||
|
.withFirstPrompt(getPrompt(conversationType))
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
@ -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,6 +1,5 @@
|
||||||
package com.alttd.playershops.gui;
|
package com.alttd.playershops.gui;
|
||||||
|
|
||||||
import com.alttd.playershops.config.GuiIconConfig;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
@ -17,10 +16,13 @@ public abstract class AbstractGui implements InventoryHolder {
|
||||||
int currentSlot;
|
int currentSlot;
|
||||||
UUID uuid;
|
UUID uuid;
|
||||||
int pageIndex;
|
int pageIndex;
|
||||||
|
AbstractGui lastGui;
|
||||||
|
|
||||||
|
|
||||||
AbstractGui(UUID uuid) {
|
AbstractGui(UUID uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.currentSlot = 0;
|
this.currentSlot = 0;
|
||||||
|
this.lastGui = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open() {
|
public void open() {
|
||||||
|
|
@ -60,6 +62,11 @@ public abstract class AbstractGui implements InventoryHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean addItem(int slot, ItemStack icon) {
|
||||||
|
currentSlot = slot;
|
||||||
|
return addItem(icon);
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean addItem(ItemStack icon) {
|
protected boolean addItem(ItemStack icon) {
|
||||||
if (currentSlot == inventory.getSize())
|
if (currentSlot == inventory.getSize())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -77,7 +84,8 @@ public abstract class AbstractGui implements InventoryHolder {
|
||||||
|
|
||||||
protected void clearInvBody() {
|
protected void clearInvBody() {
|
||||||
for (int i = 0; i < inventory.getSize() - 9; ++i) {
|
for (int i = 0; i < inventory.getSize() - 9; ++i) {
|
||||||
inventory.setItem(i, null);
|
// inventory.setItem(i, null);
|
||||||
|
inventory.setItem(i, getDivider());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,4 +121,38 @@ public abstract class AbstractGui implements InventoryHolder {
|
||||||
return GuiIcon.DIVIDER.getItemStack();
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,16 @@ public enum GuiIcon {
|
||||||
MANAGE_SHOP_SALES,
|
MANAGE_SHOP_SALES,
|
||||||
MANAGE_SHOP_ITEM,
|
MANAGE_SHOP_ITEM,
|
||||||
MANAGE_SHOP_TYPE,
|
MANAGE_SHOP_TYPE,
|
||||||
|
MANAGE_SHOP_AMOUNT,
|
||||||
|
MANAGE_SHOP_PRICE,
|
||||||
|
|
||||||
HOME_LIST_OWN_SHOPS,
|
HOME_LIST_OWN_SHOPS,
|
||||||
HOME_LIST_PLAYERS,
|
HOME_LIST_PLAYERS,
|
||||||
HOME_SETTINGS,
|
HOME_SETTINGS,
|
||||||
LIST_SHOP,
|
LIST_SHOP,
|
||||||
LIST_PLAYER,
|
LIST_PLAYER,
|
||||||
LIST_PLAYER_ADMIN;
|
LIST_PLAYER_ADMIN,
|
||||||
|
EMPTY_SHOP;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final int slot;
|
private final int slot;
|
||||||
|
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
package com.alttd.playershops.gui;
|
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.shop.PlayerShop;
|
||||||
import com.alttd.playershops.utils.Util;
|
import com.alttd.playershops.utils.Util;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.Bukkit;
|
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;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ShopManagementGui extends AbstractGui {
|
public class ShopManagementGui extends AbstractGui {
|
||||||
|
|
@ -15,30 +24,70 @@ public class ShopManagementGui extends AbstractGui {
|
||||||
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.management-title", null));
|
this.inventory = Bukkit.createInventory(this, INV_SIZE, Util.parseMiniMessage("Config.gui.management-title", null));
|
||||||
this.shop = shop;
|
this.shop = shop;
|
||||||
initInvContents();
|
initInvContents();
|
||||||
|
makeMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void initInvContents() {
|
void initInvContents() {
|
||||||
// super.initInvContents();
|
super.initInvContents();
|
||||||
makeMenuBar();
|
|
||||||
for (int i = 0; i < inventory.getSize() - 9; ++i) {
|
ItemStack shopIcon = GuiIcon.MANAGE_SHOP.getItemStack();
|
||||||
inventory.setItem(i, getDivider());
|
ItemMeta meta = shopIcon.getItemMeta();
|
||||||
}
|
List<Component> lore = new ArrayList<>();
|
||||||
inventory.setItem(GuiIcon.MANAGE_SHOP.getSlot(), GuiIcon.MANAGE_SHOP.getItemStack());
|
lore.add(Util.parseMiniMessage("Balance: " + shop.getBalance(), null));
|
||||||
|
lore.add(Util.parseMiniMessage("item: " + shop.getItemStack(), null));
|
||||||
|
lore.add(Util.parseMiniMessage("amount: " + shop.getAmount(), null));
|
||||||
|
lore.add(Util.parseMiniMessage("Type: " + shop.getType(), null));
|
||||||
|
lore.add(Util.parseMiniMessage("Price: " + shop.getPrice(), null));
|
||||||
|
|
||||||
|
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_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_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_SALES.getSlot(), GuiIcon.MANAGE_SHOP_SALES.getItemStack());
|
||||||
inventory.setItem(GuiIcon.MANAGE_SHOP_ITEM.getSlot(), GuiIcon.MANAGE_SHOP_ITEM.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_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
|
@Override
|
||||||
void makeMenuBar() {
|
void makeMenuBar() {
|
||||||
super.makeMenuBar();
|
super.makeMenuBar();
|
||||||
inventory.setItem(GuiIcon.MENUBAR_BACK.getSlot(), GuiIcon.MENUBAR_BACK.getItemStack());
|
}
|
||||||
inventory.setItem(GuiIcon.MENUBAR_PREV_PAGE.getSlot(), GuiIcon.MENUBAR_PREV_PAGE.getItemStack());
|
|
||||||
// inventory.setItem(49, new ItemStack(Material.NETHER_STAR));
|
@Override
|
||||||
inventory.setItem(GuiIcon.MENUBAR_NEXT_PAGE.getSlot(), GuiIcon.MENUBAR_NEXT_PAGE.getItemStack());
|
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)) {
|
||||||
|
openChangePrompt(ConversationType.ADD_BALANCE);
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ 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.shop.PlayerShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
|
import com.alttd.playershops.storage.database.DatabaseHelper;
|
||||||
|
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;
|
||||||
|
|
@ -12,6 +14,8 @@ import org.bukkit.Tag;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -34,6 +38,25 @@ public class ShopHandler {
|
||||||
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);
|
shopMaterials.add(Material.BARREL);
|
||||||
|
|
||||||
|
loadShops();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
public PlayerShop getShop(Location location) {
|
||||||
|
|
@ -50,6 +73,10 @@ public class ShopHandler {
|
||||||
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,7 +85,11 @@ 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();
|
shopSignLocation.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -93,6 +124,7 @@ public class ShopHandler {
|
||||||
public void removeShop(PlayerShop shop) {
|
public void removeShop(PlayerShop shop) {
|
||||||
shopLocation.remove(shop.getShopLocation());
|
shopLocation.remove(shop.getShopLocation());
|
||||||
shopSignLocation.remove(shop.getSignLocation());
|
shopSignLocation.remove(shop.getSignLocation());
|
||||||
|
plugin.getDatabaseHelper().removeShop(shop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canPlayerBreakShop(Player player, PlayerShop shop) { // TODO move to util?
|
public boolean canPlayerBreakShop(Player player, PlayerShop shop) { // TODO move to util?
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,12 @@ public class BlockListener extends EventListener {
|
||||||
if (shop == null)
|
if (shop == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event.setCancelled(!shopHandler.canPlayerBreakShop(event.getPlayer(), shop));
|
if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shopHandler.removeShop(shop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
|
@ -78,6 +82,11 @@ public class BlockListener extends EventListener {
|
||||||
if (shop == null)
|
if (shop == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event.setCancelled(!shopHandler.canPlayerBreakShop(event.getPlayer(), shop));
|
if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shopHandler.removeShop(shop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ 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.PlayerShop;
|
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;
|
||||||
|
|
@ -132,9 +133,16 @@ public class PlayerListener extends EventListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!EconomyUtils.hasSufficientFunds(player, Config.shopCreationBalance)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PlayerShop playerShop = new PlayerShop(bRelative.getLocation(), signBlock.getLocation(), player);
|
PlayerShop playerShop = new PlayerShop(bRelative.getLocation(), signBlock.getLocation(), player);
|
||||||
// TODO instance shopCreationManagement
|
playerShop.addBalance(Config.shopCreationBalance);
|
||||||
|
EconomyUtils.removeFunds(player, Config.shopCreationBalance);
|
||||||
shopHandler.addShop(playerShop);
|
shopHandler.addShop(playerShop);
|
||||||
|
PlayerShops.getInstance().getDatabaseHelper().createShop(playerShop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,11 @@ import com.alttd.playershops.handler.ShopHandler;
|
||||||
import com.alttd.playershops.hook.WorldGuardHook;
|
import com.alttd.playershops.hook.WorldGuardHook;
|
||||||
import com.alttd.playershops.shop.PlayerShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import com.alttd.playershops.shop.TransactionError;
|
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 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.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.Tag;
|
import org.bukkit.Tag;
|
||||||
|
|
@ -35,20 +39,19 @@ public class TransactionListener extends EventListener {
|
||||||
if(!this.isRegistered)
|
if(!this.isRegistered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
if (event.getHand() == EquipmentSlot.OFF_HAND)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK))
|
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Block block = event.getClickedBlock();
|
Block block = event.getClickedBlock();
|
||||||
if (block == null || Tag.WALL_SIGNS.isTagged(block.getType()))
|
if (block == null || !Tag.WALL_SIGNS.isTagged(block.getType()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlayerShop playerShop = plugin.getShopHandler().getShopBySignLocation(block.getLocation());
|
PlayerShop playerShop = plugin.getShopHandler().getShopBySignLocation(block.getLocation());
|
||||||
if (playerShop == null || !playerShop.isInitialized())
|
if (playerShop == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if we ever need worldguard support add it to the hook
|
// if we ever need worldguard support add it to the hook
|
||||||
|
|
@ -59,23 +62,29 @@ public class TransactionListener extends EventListener {
|
||||||
|
|
||||||
if (!player.hasPermission("playershops.shop.use." + playerShop.getType().toString())) {
|
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
|
player.sendMiniMessage("<red>You do not have permission to use " + playerShop.getType().toString() + " shops.", null); // TODO config
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShopHandler shopHandler = plugin.getShopHandler();
|
ShopHandler shopHandler = plugin.getShopHandler();
|
||||||
|
|
||||||
// Failsafe. If we have a shopsign but no block cancel the event, log error save and unload the shop
|
// 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())) {
|
if (!shopHandler.isShopMaterial(playerShop.getShopLocation().getBlock())) {
|
||||||
|
Logger.error("We have a shop here but no connected container");
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
// TODO LOG THIS ERROR
|
// TODO LOG THIS ERROR
|
||||||
shopHandler.removeShop(playerShop);
|
shopHandler.removeShop(playerShop);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO upgrade this to an util method check if owner/trusted and open management interface
|
if (ShopUtil.canManageShop(player, playerShop)) {
|
||||||
if (playerShop.getOwnerUUID().equals(player.getUniqueId())) {
|
|
||||||
ShopManagementGui gui = new ShopManagementGui(player.getUniqueId(), playerShop);
|
ShopManagementGui gui = new ShopManagementGui(player.getUniqueId(), playerShop);
|
||||||
gui.open();
|
gui.open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!playerShop.isInitialized())
|
||||||
|
return;
|
||||||
|
|
||||||
executeTransaction(player, playerShop);
|
executeTransaction(player, playerShop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +99,11 @@ public class TransactionListener extends EventListener {
|
||||||
TransactionError transactionError = shop.executeTransaction(orders, player);
|
TransactionError transactionError = shop.executeTransaction(orders, player);
|
||||||
|
|
||||||
// TODO minimessage placeholders
|
// TODO minimessage placeholders
|
||||||
|
TagResolver placeholders = TagResolver.resolver(
|
||||||
|
Placeholder.unparsed("ownername", shop.getOwnerName()),
|
||||||
|
Placeholder.unparsed("price", shop.getPrice() + ""),
|
||||||
|
Placeholder.unparsed("amount", shop.getAmount() + "")
|
||||||
|
);
|
||||||
if (transactionError != TransactionError.NONE) {
|
if (transactionError != TransactionError.NONE) {
|
||||||
switch (transactionError) {
|
switch (transactionError) {
|
||||||
case INSUFFICIENT_FUNDS_SHOP -> {
|
case INSUFFICIENT_FUNDS_SHOP -> {
|
||||||
|
|
@ -99,25 +112,25 @@ public class TransactionListener extends EventListener {
|
||||||
// TODO notify shopowner in game if not on cooldown and once per day on discord if linked and enabled
|
// 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().shopSold, null));
|
shopOwner.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().shopSold, null));
|
||||||
}
|
}
|
||||||
player.sendMiniMessage(shop.getType().getShopTypeConfig().shopNoStock, null);
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().shopNoStock, placeholders);
|
||||||
}
|
}
|
||||||
case INSUFFICIENT_FUNDS_PLAYER -> {
|
case INSUFFICIENT_FUNDS_PLAYER -> {
|
||||||
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerNoFunds, null);
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerNoFunds, placeholders);
|
||||||
}
|
}
|
||||||
case INVENTORY_FULL_SHOP -> {
|
case INVENTORY_FULL_SHOP -> {
|
||||||
Player shopOwner = Bukkit.getPlayer(shop.getOwnerUUID());
|
Player shopOwner = Bukkit.getPlayer(shop.getOwnerUUID());
|
||||||
if (shopOwner != null && notifyOwner(shop)) {
|
if (shopOwner != null && notifyOwner(shop)) {
|
||||||
// TODO notify shopowner in game if not on cooldown and once per day on discord if linked and enabled
|
// 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, null);
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().shopInventoryFull, placeholders);
|
||||||
}
|
}
|
||||||
case INVENTORY_FULL_PLAYER -> {
|
case INVENTORY_FULL_PLAYER -> {
|
||||||
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerInventoryFull, null);
|
player.sendMiniMessage(shop.getType().getShopTypeConfig().playerInventoryFull, placeholders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().playerBought, null));
|
player.sendActionBar(Util.parseMiniMessage(shop.getType().getShopTypeConfig().playerBought, placeholders));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean notifyOwner(PlayerShop playerShop) {
|
private boolean notifyOwner(PlayerShop playerShop) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import lombok.Setter;
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
@ -59,11 +60,11 @@ public class PlayerShop {
|
||||||
|
|
||||||
public PlayerShop(Location shopLocation, Location signLocation, UUID uuid, String playerName) {
|
public PlayerShop(Location shopLocation, Location signLocation, UUID uuid, String playerName) {
|
||||||
this.shopID = UUID.randomUUID();
|
this.shopID = UUID.randomUUID();
|
||||||
this.shopLocation = shopLocation;
|
this.shopLocation = new Location(shopLocation.getWorld(), shopLocation.getBlockX(), shopLocation.getBlockY(), shopLocation.getBlockZ());
|
||||||
this.signLocation = signLocation;
|
this.signLocation = new Location(signLocation.getWorld(), signLocation.getBlockX(), signLocation.getBlockY(), signLocation.getBlockZ());
|
||||||
this.ownerUUID = uuid;
|
this.ownerUUID = uuid;
|
||||||
this.ownerName = playerName;
|
this.ownerName = playerName;
|
||||||
updateSign();
|
this.server = Bukkit.getServerName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlayerShop load(UUID shopID, String ownerName, UUID ownerUUID, ShopType shopType, String server,
|
public static PlayerShop load(UUID shopID, String ownerName, UUID ownerUUID, ShopType shopType, String server,
|
||||||
|
|
@ -133,23 +134,29 @@ public class PlayerShop {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSign() {
|
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() {
|
new BukkitRunnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
Sign signBlock = (Sign) signLocation.getBlock().getState();
|
Sign signBlock = (Sign) signLocation.getBlock().getState();
|
||||||
MiniMessage miniMessage = MiniMessage.miniMessage();
|
MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||||
List<String> signLines;
|
|
||||||
TagResolver tagResolver = TagResolver.resolver(
|
TagResolver tagResolver = TagResolver.resolver(
|
||||||
Placeholder.unparsed("ownername", getOwnerName()),
|
Placeholder.unparsed("ownername", getOwnerName()),
|
||||||
Placeholder.unparsed("price", String.valueOf(getPrice())),
|
Placeholder.unparsed("price", String.valueOf(getPrice())),
|
||||||
Placeholder.unparsed("amount", String.valueOf(getAmount()))
|
Placeholder.unparsed("amount", String.valueOf(getAmount())),
|
||||||
|
Placeholder.unparsed("item", ShopUtil.getItemName(getItemStack()))
|
||||||
);
|
);
|
||||||
if (!isInitialized()) {
|
|
||||||
signLines = type.getShopTypeConfig().inActiveSignLines;
|
|
||||||
} else {
|
|
||||||
signLines = type.getShopTypeConfig().activeSignLines;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
signBlock.line(i, miniMessage.deserialize(signLines.get(i), tagResolver));
|
signBlock.line(i, miniMessage.deserialize(signLines.get(i), tagResolver));
|
||||||
}
|
}
|
||||||
|
|
@ -159,18 +166,18 @@ public class PlayerShop {
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getPricePerItem() {
|
public double getPricePerItem() {
|
||||||
double pricePer = this.getPrice() / this.getAmount();
|
|
||||||
return this.getPrice() / this.getAmount();
|
return this.getPrice() / this.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeBalance(double amount) {
|
public boolean removeBalance(double amount) {
|
||||||
ShopBalanceChangeEvent shopBalanceChangeEvent = new ShopBalanceChangeEvent(this, ShopBalanceChangeEvent.ChangeReason.WIDRAW);
|
ShopBalanceChangeEvent shopBalanceChangeEvent = new ShopBalanceChangeEvent(this, ShopBalanceChangeEvent.ChangeReason.WITHDRAW);
|
||||||
if (Util.callCancellableEvent(shopBalanceChangeEvent))
|
if (Util.callCancellableEvent(shopBalanceChangeEvent))
|
||||||
return false; // cancelled by another plugin, does this need logging?
|
return false; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
update();
|
update();
|
||||||
this.balance -= amount;
|
this.balance -= amount;
|
||||||
|
this.setLastTransaction(System.currentTimeMillis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,6 +189,7 @@ public class PlayerShop {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
update();
|
update();
|
||||||
this.balance += amount;
|
this.balance += amount;
|
||||||
|
this.setLastTransaction(System.currentTimeMillis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,13 +288,14 @@ public class PlayerShop {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItemStack(ItemStack itemStack) {
|
public void setItemStack(ItemStack itemStack) {
|
||||||
if (this.itemStack.equals(itemStack))
|
if (this.itemStack != null && this.itemStack.equals(itemStack))
|
||||||
return; // no changes have been made.
|
return; // no changes have been made.
|
||||||
ShopItemChangeEvent shopItemChangeEvent = new ShopItemChangeEvent(this, itemStack);
|
ShopItemChangeEvent shopItemChangeEvent = new ShopItemChangeEvent(this, itemStack);
|
||||||
if (Util.callCancellableEvent(shopItemChangeEvent))
|
if (Util.callCancellableEvent(shopItemChangeEvent))
|
||||||
return; // cancelled by another plugin, does this need logging?
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
this.itemStack = itemStack;
|
this.itemStack = itemStack;
|
||||||
|
this.itemStack.setAmount(this.amount != 0 ? this.amount : 1);
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
@ -311,6 +320,8 @@ public class PlayerShop {
|
||||||
return; // cancelled by another plugin, does this need logging?
|
return; // cancelled by another plugin, does this need logging?
|
||||||
|
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
|
if (this.itemStack != null)
|
||||||
|
this.itemStack.setAmount(this.amount);
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +342,11 @@ public class PlayerShop {
|
||||||
* Updates and saves the PlayerShop in the database
|
* Updates and saves the PlayerShop in the database
|
||||||
*/
|
*/
|
||||||
private void update() {
|
private void update() {
|
||||||
|
PlayerShops.getInstance().getDatabaseHelper().updateShop(this, false);
|
||||||
|
if (!ShopUtil.isLoaded(signLocation))
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateSign();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,18 @@ public enum ShopType {
|
||||||
return shopTypeConfig;
|
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() {
|
||||||
return name().toLowerCase();
|
return name().toLowerCase();
|
||||||
|
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
||||||
package com.alttd.playershops.storage;
|
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
|
||||||
import com.alttd.playershops.config.DatabaseConfig;
|
|
||||||
import com.alttd.playershops.storage.database.DatabaseQuery;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DatabaseConnection getConnection() {
|
|
||||||
for (int i = 0; i < DatabaseConfig.maxDatabaseConnections; i++) {
|
|
||||||
DatabaseConnection connection = CONNECTIONPOOL.get(i);
|
|
||||||
if (connection == null) {
|
|
||||||
return genConnection(i);
|
|
||||||
} else if (!connection.isActive()) {
|
|
||||||
if (connection.isValid()) {
|
|
||||||
return connection;
|
|
||||||
} else {
|
|
||||||
connection.close();
|
|
||||||
return genConnection(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will cause an infinite running loop, throw an exception or wait for a connection to be available?
|
|
||||||
return getConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private DatabaseConnection genConnection(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();
|
|
||||||
}
|
|
||||||
|
|
||||||
class DatabaseConnection implements AutoCloseable {
|
|
||||||
private Connection connection;
|
|
||||||
private volatile boolean isActive;
|
|
||||||
|
|
||||||
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&allowPublicKeyRetrieval=true",
|
|
||||||
DatabaseConfig.USERNAME, DatabaseConfig.PASSWORD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Connection getConnection() {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DatabaseQueue extends BukkitRunnable {
|
|
||||||
|
|
||||||
private final DatabaseManager databaseManager;
|
|
||||||
|
|
||||||
DatabaseQueue(DatabaseManager databaseManager) {
|
|
||||||
this.databaseManager = databaseManager;
|
|
||||||
}
|
|
||||||
@Getter
|
|
||||||
private static final Queue<DatabaseQuery> databaseQueryQueue = new LinkedBlockingQueue<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runTaskQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void runTaskQueue() {
|
|
||||||
if (databaseQueryQueue.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DatabaseConnection databaseConnection = databaseManager.getConnection();
|
|
||||||
Connection connection = databaseConnection.getConnection();
|
|
||||||
|
|
||||||
try {
|
|
||||||
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,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,178 @@
|
||||||
|
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.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ public class DatabaseQuery {
|
||||||
|
|
||||||
public interface DatabaseTask {
|
public interface DatabaseTask {
|
||||||
|
|
||||||
void edit(PreparedStatement preparedStatement);
|
void edit(PreparedStatement preparedStatement) throws SQLException;
|
||||||
|
|
||||||
default void onSuccess() {};
|
default void onSuccess() {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
package com.alttd.playershops.utils;
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import org.bukkit.Material;
|
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||||
import org.bukkit.World;
|
import org.bukkit.*;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ShopUtil {
|
public class ShopUtil {
|
||||||
|
|
||||||
|
|
@ -106,18 +109,89 @@ public class ShopUtil {
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String serialize(ItemStack itemStack) {
|
public static String locationToString(Location location) {
|
||||||
YamlConfiguration cfg = new YamlConfiguration();
|
return location.getWorld().getName() + ":" +
|
||||||
cfg.set("item", itemStack);
|
AMath.round(location.getX(), 1) + ":" +
|
||||||
return cfg.saveToString();
|
AMath.round(location.getY(), 1) + ":" +
|
||||||
|
AMath.round(location.getZ(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack deserialize(String config) throws InvalidConfigurationException {
|
public static Location stringToLocation(String string) {
|
||||||
YamlConfiguration cfg = new YamlConfiguration();
|
String[] split = string.split(":");
|
||||||
cfg.loadFromString(config);
|
if (split.length != 4) {
|
||||||
ItemStack stack = cfg.getItemStack("item");
|
Logger.warn("Unable to load location [" + string + "] due to invalid format");
|
||||||
return stack;
|
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 String getItemName(ItemStack item) {
|
||||||
|
if (item == null || !item.getType().equals(Material.AIR))
|
||||||
|
return "Nothing";
|
||||||
|
|
||||||
|
String NAME = "{item}";
|
||||||
|
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
|
||||||
|
String replacer = ChatColor.translateAlternateColorCodes('&',NAME+"&r");
|
||||||
|
if (dname) {
|
||||||
|
String trp = item.getItemMeta().getDisplayName();
|
||||||
|
replacer = replacer.replace(NAME, trp);
|
||||||
|
} else {
|
||||||
|
replacer = replacer.replace(NAME, materialToName(item.getType()));
|
||||||
|
}
|
||||||
|
return replacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String materialToName(Material m) {
|
||||||
|
if (m.equals(Material.TNT)) {
|
||||||
|
return "TNT";
|
||||||
|
}
|
||||||
|
String orig = m.toString().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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user