mirror of
https://github.com/Flowsqy/ShopChest.git
synced 2024-11-30 01:43:22 +01:00
Load/unload shops on chunk load/unload
This breaks shop limits, only loaded shops are counted at the moment
This commit is contained in:
parent
f15fdc781f
commit
c595b574ec
@ -43,6 +43,8 @@ import me.wiefferink.areashop.AreaShop;
|
|||||||
import net.milkbowl.vault.economy.Economy;
|
import net.milkbowl.vault.economy.Economy;
|
||||||
import org.bstats.bukkit.Metrics;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
@ -65,6 +67,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class ShopChest extends JavaPlugin {
|
public class ShopChest extends JavaPlugin {
|
||||||
|
|
||||||
@ -437,13 +440,26 @@ public class ShopChest extends JavaPlugin {
|
|||||||
* Initializes the shops
|
* Initializes the shops
|
||||||
*/
|
*/
|
||||||
private void initializeShops() {
|
private void initializeShops() {
|
||||||
debug("Initializing Shops...");
|
getShopDatabase().connect(new Callback<Integer>(this) {
|
||||||
shopUtils.reloadShops(false, true, new Callback<Integer>(this) {
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Integer result) {
|
public void onResult(Integer result) {
|
||||||
Bukkit.getServer().getPluginManager().callEvent(new ShopInitializedEvent(result));
|
Chunk[] loadedChunks = getServer().getWorlds().stream().map(World::getLoadedChunks)
|
||||||
getLogger().info("Initialized " + result + " Shops");
|
.flatMap(Stream::of).toArray(Chunk[]::new);
|
||||||
debug("Initialized " + result + " Shops");
|
|
||||||
|
shopUtils.loadShops(loadedChunks, new Callback<Integer>(ShopChest.this) {
|
||||||
|
@Override
|
||||||
|
public void onResult(Integer result) {
|
||||||
|
getServer().getPluginManager().callEvent(new ShopInitializedEvent(result));
|
||||||
|
getLogger().info("Loaded " + result + " shops in already loaded chunks");
|
||||||
|
debug("Loaded " + result + " shops in already loaded chunks");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable throwable) {
|
||||||
|
getLogger().severe("Failed to load shops in already loaded chunks");
|
||||||
|
if (throwable != null) getLogger().severe(throwable.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,8 +26,10 @@ import de.epiceric.shopchest.utils.ClickType.CreateClickType;
|
|||||||
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
|
import de.epiceric.shopchest.utils.ClickType.SelectClickType;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -36,7 +38,9 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
class ShopCommandExecutor implements CommandExecutor {
|
class ShopCommandExecutor implements CommandExecutor {
|
||||||
|
|
||||||
@ -191,12 +195,40 @@ class ShopCommandExecutor implements CommandExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
shopUtils.reloadShops(true, true, new Callback<Integer>(plugin) {
|
// Reload configurations
|
||||||
|
plugin.getShopChestConfig().reload(false, true, true);
|
||||||
|
plugin.getHologramFormat().reload();
|
||||||
|
plugin.getUpdater().restart();
|
||||||
|
|
||||||
|
// Remove all shops
|
||||||
|
Iterator<Shop> iter = shopUtils.getShops().iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
shopUtils.removeShop(iter.next(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk[] loadedChunks = Bukkit.getWorlds().stream().map(World::getLoadedChunks)
|
||||||
|
.flatMap(Stream::of).toArray(Chunk[]::new);
|
||||||
|
|
||||||
|
// Reconnect to the database and re-load shops in loaded chunks
|
||||||
|
plugin.getShopDatabase().connect(new Callback<Integer>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Integer result) {
|
public void onResult(Integer result) {
|
||||||
sender.sendMessage(LanguageUtils.getMessage(Message.RELOADED_SHOPS,
|
shopUtils.loadShops(loadedChunks, new Callback<Integer>(plugin) {
|
||||||
new Replacement(Placeholder.AMOUNT, String.valueOf(result))));
|
@Override
|
||||||
plugin.debug(sender.getName() + " has reloaded " + result + " shops");
|
public void onResult(Integer result) {
|
||||||
|
sender.sendMessage(LanguageUtils.getMessage(Message.RELOADED_SHOPS,
|
||||||
|
new Replacement(Placeholder.AMOUNT, String.valueOf(result))));
|
||||||
|
plugin.debug(sender.getName() + " has reloaded " + result + " shops");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable throwable) {
|
||||||
|
sender.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED,
|
||||||
|
new Replacement(Placeholder.ERROR, "Failed to load shops from database")));
|
||||||
|
plugin.getLogger().severe("Failed to load shops");
|
||||||
|
if (throwable != null) plugin.getLogger().severe(throwable.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,6 +3,11 @@ package de.epiceric.shopchest.event;
|
|||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link ShopsLoadedEvent} instead since shops are loaded
|
||||||
|
* dynamically based on chunk loading
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ShopInitializedEvent extends Event {
|
public class ShopInitializedEvent extends Event {
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.epiceric.shopchest.event;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
import de.epiceric.shopchest.shop.Shop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when shops have been loaded and added to the server
|
||||||
|
*/
|
||||||
|
public class ShopsLoadedEvent extends Event {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private Collection<Shop> shops;
|
||||||
|
|
||||||
|
public ShopsLoadedEvent(Collection<Shop> shops) {
|
||||||
|
this.shops = shops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Shop> getShops() {
|
||||||
|
return shops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package de.epiceric.shopchest.event;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
import de.epiceric.shopchest.shop.Shop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when shops have been unloaded and removed from the server
|
||||||
|
*/
|
||||||
|
public class ShopsUnloadedEvent extends Event {
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private Collection<Shop> shops;
|
||||||
|
|
||||||
|
public ShopsUnloadedEvent(Collection<Shop> shops) {
|
||||||
|
this.shops = shops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Shop> getShops() {
|
||||||
|
return shops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,10 @@ import de.epiceric.shopchest.ShopChest;
|
|||||||
import de.epiceric.shopchest.shop.Shop;
|
import de.epiceric.shopchest.shop.Shop;
|
||||||
import de.epiceric.shopchest.utils.Callback;
|
import de.epiceric.shopchest.utils.Callback;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -12,12 +16,14 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
public class ShopUpdateListener implements Listener {
|
public class ShopUpdateListener implements Listener {
|
||||||
|
|
||||||
private ShopChest plugin;
|
private final ShopChest plugin;
|
||||||
|
private final Set<Chunk> newLoadedChunks = new HashSet<>();
|
||||||
|
|
||||||
public ShopUpdateListener(ShopChest plugin) {
|
public ShopUpdateListener(ShopChest plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -83,23 +89,55 @@ public class ShopUpdateListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldLoad(WorldLoadEvent e) {
|
public void onChunkLoad(ChunkLoadEvent e) {
|
||||||
final String worldName = e.getWorld().getName();
|
if (!plugin.getShopDatabase().isInitialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
plugin.getShopUtils().reloadShops(false, false, new Callback<Integer>(plugin) {
|
// Wait 10 ticks after first event is triggered, so that multiple
|
||||||
@Override
|
// chunk loads can be handled at the same time without having to
|
||||||
public void onResult(Integer result) {
|
// send a database request for each chunk.
|
||||||
plugin.getLogger().info(String.format("Reloaded %d shops because a new world '%s' was loaded", result, worldName));
|
if (newLoadedChunks.isEmpty()) {
|
||||||
plugin.debug(String.format("Reloaded %d shops because a new world '%s' was loaded", result, worldName));
|
new BukkitRunnable(){
|
||||||
}
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int chunkCount = newLoadedChunks.size();
|
||||||
|
plugin.getShopUtils().loadShops(newLoadedChunks.toArray(new Chunk[chunkCount]), new Callback<Integer>(plugin) {
|
||||||
|
@Override
|
||||||
|
public void onResult(Integer result) {
|
||||||
|
if (result == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plugin.debug("Loaded " + result + " shops in " + chunkCount + " chunks");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable throwable) {
|
||||||
|
// Database connection probably failed => disable plugin to prevent more errors
|
||||||
|
plugin.getLogger().severe("Failed to load shops in newly loaded chunks");
|
||||||
|
plugin.debug("Failed to load shops in newly loaded chunks");
|
||||||
|
if (throwable != null) plugin.debug(throwable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newLoadedChunks.clear();
|
||||||
|
}
|
||||||
|
}.runTaskLater(plugin, 10L);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
newLoadedChunks.add(e.getChunk());
|
||||||
public void onError(Throwable throwable) {
|
}
|
||||||
// Database connection probably failed => disable plugin to prevent more errors
|
|
||||||
plugin.getLogger().severe("No database access. Disabling ShopChest");
|
@EventHandler
|
||||||
if (throwable != null) plugin.getLogger().severe(throwable.getMessage());
|
public void onChunkUnload(ChunkUnloadEvent e) {
|
||||||
plugin.getServer().getPluginManager().disablePlugin(plugin);
|
if (!plugin.getShopDatabase().isInitialized()) {
|
||||||
}
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
int num = plugin.getShopUtils().unloadShops(e.getChunk());
|
||||||
|
|
||||||
|
if (num > 0) {
|
||||||
|
String chunkStr = "[" + e.getChunk().getX() + "; " + e.getChunk().getZ() + "]";
|
||||||
|
plugin.debug("Unloaded " + num + " shops in chunk " + chunkStr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import de.epiceric.shopchest.ShopChest;
|
|||||||
import de.epiceric.shopchest.config.Config;
|
import de.epiceric.shopchest.config.Config;
|
||||||
import de.epiceric.shopchest.event.ShopBuySellEvent;
|
import de.epiceric.shopchest.event.ShopBuySellEvent;
|
||||||
import de.epiceric.shopchest.event.ShopBuySellEvent.Type;
|
import de.epiceric.shopchest.event.ShopBuySellEvent.Type;
|
||||||
import de.epiceric.shopchest.exceptions.WorldNotFoundException;
|
|
||||||
import de.epiceric.shopchest.shop.Shop;
|
import de.epiceric.shopchest.shop.Shop;
|
||||||
import de.epiceric.shopchest.shop.ShopProduct;
|
import de.epiceric.shopchest.shop.ShopProduct;
|
||||||
import de.epiceric.shopchest.shop.Shop.ShopType;
|
import de.epiceric.shopchest.shop.Shop.ShopType;
|
||||||
import de.epiceric.shopchest.utils.Callback;
|
import de.epiceric.shopchest.utils.Callback;
|
||||||
import de.epiceric.shopchest.utils.Utils;
|
import de.epiceric.shopchest.utils.Utils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -28,16 +28,20 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
public abstract class Database {
|
public abstract class Database {
|
||||||
private final Set<String> notFoundWorlds = new HashSet<>();
|
|
||||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
String tableShops;
|
String tableShops;
|
||||||
String tableLogs;
|
String tableLogs;
|
||||||
String tableLogouts;
|
String tableLogouts;
|
||||||
@ -305,6 +309,7 @@ public abstract class Database {
|
|||||||
ResultSet rs = s.executeQuery("SELECT COUNT(id) FROM " + tableShops);
|
ResultSet rs = s.executeQuery("SELECT COUNT(id) FROM " + tableShops);
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
int count = rs.getInt(1);
|
int count = rs.getInt(1);
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
plugin.debug("Initialized database with " + count + " entries");
|
plugin.debug("Initialized database with " + count + " entries");
|
||||||
|
|
||||||
@ -362,74 +367,108 @@ public abstract class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all shops from the database
|
* Get all shops from the database that are located in the given chunks
|
||||||
*
|
*
|
||||||
* @param showConsoleMessages Whether console messages (errors or warnings)
|
* @param chunks Shops in these chunks are retrieved
|
||||||
* should be shown
|
* @param callback Callback that returns an immutable collection of shops if succeeded
|
||||||
* @param callback Callback that - if succeeded - returns a read-only
|
|
||||||
* collection of all shops (as
|
|
||||||
* {@code Collection<Shop>})
|
|
||||||
*/
|
*/
|
||||||
public void getShops(final boolean showConsoleMessages, final Callback<Collection<Shop>> callback) {
|
public void getShopsInChunks(final Chunk[] chunks, final Callback<Collection<Shop>> callback) {
|
||||||
new BukkitRunnable() {
|
// Split chunks into packages containing each {splitSize} chunks at max
|
||||||
|
int splitSize = 80;
|
||||||
|
int parts = (int) Math.ceil(chunks.length / (double) splitSize);
|
||||||
|
Chunk[][] splitChunks = new Chunk[parts][];
|
||||||
|
for (int i = 0; i < parts; i++) {
|
||||||
|
int size = i < parts - 1 ? splitSize : chunks.length % splitSize;
|
||||||
|
Chunk[] tmp = new Chunk[size];
|
||||||
|
System.arraycopy(chunks, i * splitSize, tmp, 0, size);
|
||||||
|
splitChunks[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
new BukkitRunnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ArrayList<Shop> shops = new ArrayList<>();
|
List<Shop> shops = new ArrayList<>();
|
||||||
|
|
||||||
try (Connection con = dataSource.getConnection();
|
// Send a request for each chunk package
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableShops + "")) {
|
for (Chunk[] newChunks : splitChunks) {
|
||||||
ResultSet rs = ps.executeQuery();
|
|
||||||
|
|
||||||
while (rs.next()) {
|
// Map chunks by world
|
||||||
int id = rs.getInt("id");
|
Map<String, Set<Chunk>> chunksByWorld = new HashMap<>();
|
||||||
|
for (Chunk chunk : newChunks) {
|
||||||
plugin.debug("Getting Shop... (#" + id + ")");
|
String world = chunk.getWorld().getName();
|
||||||
|
Set<Chunk> chunksForWorld = chunksByWorld.getOrDefault(world, new HashSet<>());
|
||||||
String worldName = rs.getString("world");
|
chunksForWorld.add(chunk);
|
||||||
World world = Bukkit.getWorld(worldName);
|
chunksByWorld.put(world, chunksForWorld);
|
||||||
|
}
|
||||||
if (world == null) {
|
|
||||||
WorldNotFoundException ex = new WorldNotFoundException(worldName);
|
// Create query dynamically
|
||||||
if (showConsoleMessages && !notFoundWorlds.contains(worldName)) {
|
String query = "SELECT * FROM " + tableShops + " WHERE ";
|
||||||
plugin.getLogger().warning(ex.getMessage());
|
for (String world : chunksByWorld.keySet()) {
|
||||||
notFoundWorlds.add(worldName);
|
query += "(world = ? AND (";
|
||||||
}
|
int chunkNum = chunksByWorld.get(world).size();
|
||||||
plugin.debug("Failed to get shop (#" + id + ")");
|
for (int i = 0; i < chunkNum; i++) {
|
||||||
plugin.debug(ex);
|
query += "((x BETWEEN ? AND ?) AND (z BETWEEN ? AND ?)) OR ";
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
query += "1=0)) OR ";
|
||||||
int x = rs.getInt("x");
|
|
||||||
int y = rs.getInt("y");
|
|
||||||
int z = rs.getInt("z");
|
|
||||||
Location location = new Location(world, x, y, z);
|
|
||||||
OfflinePlayer vendor = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor")));
|
|
||||||
ItemStack itemStack = Utils.decode(rs.getString("product"));
|
|
||||||
int amount = rs.getInt("amount");
|
|
||||||
ShopProduct product = new ShopProduct(itemStack, amount);
|
|
||||||
double buyPrice = rs.getDouble("buyprice");
|
|
||||||
double sellPrice = rs.getDouble("sellprice");
|
|
||||||
ShopType shopType = ShopType.valueOf(rs.getString("shoptype"));
|
|
||||||
|
|
||||||
plugin.debug("Initializing new shop... (#" + id + ")");
|
|
||||||
|
|
||||||
shops.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType));
|
|
||||||
}
|
}
|
||||||
|
query += "1=0";
|
||||||
|
|
||||||
|
try (Connection con = dataSource.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement(query)) {
|
||||||
|
int index = 0;
|
||||||
|
for (String world : chunksByWorld.keySet()) {
|
||||||
|
ps.setString(++index, world);
|
||||||
|
for (Chunk chunk : chunksByWorld.get(world)) {
|
||||||
|
int minX = chunk.getX() * 16;
|
||||||
|
int minZ = chunk.getZ() * 16;
|
||||||
|
ps.setInt(++index, minX);
|
||||||
|
ps.setInt(++index, minX + 15);
|
||||||
|
ps.setInt(++index, minZ);
|
||||||
|
ps.setInt(++index, minZ + 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
int id = rs.getInt("id");
|
||||||
|
|
||||||
|
plugin.debug("Getting Shop... (#" + id + ")");
|
||||||
|
|
||||||
|
int x = rs.getInt("x");
|
||||||
|
int y = rs.getInt("y");
|
||||||
|
int z = rs.getInt("z");
|
||||||
|
|
||||||
|
World world = plugin.getServer().getWorld(rs.getString("world"));
|
||||||
|
Location location = new Location(world, x, y, z);
|
||||||
|
OfflinePlayer vendor = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor")));
|
||||||
|
ItemStack itemStack = Utils.decode(rs.getString("product"));
|
||||||
|
int amount = rs.getInt("amount");
|
||||||
|
ShopProduct product = new ShopProduct(itemStack, amount);
|
||||||
|
double buyPrice = rs.getDouble("buyprice");
|
||||||
|
double sellPrice = rs.getDouble("sellprice");
|
||||||
|
ShopType shopType = ShopType.valueOf(rs.getString("shoptype"));
|
||||||
|
|
||||||
|
plugin.debug("Initializing new shop... (#" + id + ")");
|
||||||
|
|
||||||
|
shops.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType));
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.callSyncError(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getLogger().severe("Failed to get shops from database");
|
||||||
|
plugin.debug("Failed to get shops");
|
||||||
|
plugin.debug(ex);
|
||||||
|
|
||||||
if (callback != null) {
|
return;
|
||||||
callback.callSyncResult(Collections.unmodifiableCollection(shops));
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
|
||||||
if (callback != null) {
|
|
||||||
callback.callSyncError(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getLogger().severe("Failed to get shops from database");
|
|
||||||
plugin.debug("Failed to get shops");
|
|
||||||
plugin.debug(ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (callback != null) {
|
||||||
|
callback.callSyncResult(Collections.unmodifiableCollection(shops));
|
||||||
|
}
|
||||||
|
};
|
||||||
}.runTaskAsynchronously(plugin);
|
}.runTaskAsynchronously(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,6 +769,13 @@ public abstract class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a connection to the database has been established
|
||||||
|
*/
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
public enum DatabaseType {
|
public enum DatabaseType {
|
||||||
SQLite, MySQL
|
SQLite, MySQL
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,12 @@ package de.epiceric.shopchest.utils;
|
|||||||
|
|
||||||
import de.epiceric.shopchest.ShopChest;
|
import de.epiceric.shopchest.ShopChest;
|
||||||
import de.epiceric.shopchest.config.Config;
|
import de.epiceric.shopchest.config.Config;
|
||||||
|
import de.epiceric.shopchest.event.ShopsLoadedEvent;
|
||||||
|
import de.epiceric.shopchest.event.ShopsUnloadedEvent;
|
||||||
import de.epiceric.shopchest.shop.Shop;
|
import de.epiceric.shopchest.shop.Shop;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.block.Chest;
|
import org.bukkit.block.Chest;
|
||||||
@ -246,6 +250,7 @@ public class ShopUtils {
|
|||||||
* @return The amount of a shops a player has (if {@link Config#excludeAdminShops} is true, admin shops won't be counted)
|
* @return The amount of a shops a player has (if {@link Config#excludeAdminShops} is true, admin shops won't be counted)
|
||||||
*/
|
*/
|
||||||
public int getShopAmount(OfflinePlayer p) {
|
public int getShopAmount(OfflinePlayer p) {
|
||||||
|
// FIXME: currently only showing loaded shops
|
||||||
float shopCount = 0;
|
float shopCount = 0;
|
||||||
|
|
||||||
for (Shop shop : getShops()) {
|
for (Shop shop : getShops()) {
|
||||||
@ -265,54 +270,65 @@ public class ShopUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the shops
|
* Gets all shops in the given chunk from the database and adds them to the server
|
||||||
* @param reloadConfig Whether the configuration should also be reloaded
|
* @param chunk The chunk to load shops from
|
||||||
* @param showConsoleMessages Whether messages about the language file should be shown in the console
|
* @param callback Callback that returns the amount of shops added if succeeded
|
||||||
* @param callback Callback that - if succeeded - returns the amount of shops that were reloaded (as {@code int})
|
* @see ShopUtils#loadShops(Chunk[], Callback)
|
||||||
*/
|
*/
|
||||||
public void reloadShops(boolean reloadConfig, final boolean showConsoleMessages, final Callback<Integer> callback) {
|
public void loadShops(final Chunk chunk, final Callback<Integer> callback) {
|
||||||
plugin.debug("Reloading shops...");
|
loadShops(new Chunk[] {chunk}, callback);
|
||||||
|
}
|
||||||
|
|
||||||
if (reloadConfig) {
|
/**
|
||||||
plugin.getShopChestConfig().reload(false, true, showConsoleMessages);
|
* Gets all shops in the given chunks from the database and adds them to the server
|
||||||
plugin.getHologramFormat().reload();
|
* @param chunk The chunks to load shops from
|
||||||
plugin.getUpdater().restart();
|
* @param callback Callback that returns the amount of shops added if succeeded
|
||||||
}
|
* @see ShopUtils#loadShops(Chunk Callback)
|
||||||
|
*/
|
||||||
plugin.getShopDatabase().connect(new Callback<Integer>(plugin) {
|
public void loadShops(final Chunk[] chunks, final Callback<Integer> callback) {
|
||||||
|
plugin.getShopDatabase().getShopsInChunks(chunks, new Callback<Collection<Shop>>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Integer result) {
|
public void onResult(Collection<Shop> result) {
|
||||||
for (Shop shop : getShopsCopy()) {
|
for (Shop shop : result) {
|
||||||
removeShop(shop, false);
|
if (shop.create(true)) {
|
||||||
plugin.debug("Removed shop (#" + shop.getID() + ")");
|
addShop(shop, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getShopDatabase().getShops(showConsoleMessages, new Callback<Collection<Shop>>(plugin) {
|
if (callback != null) callback.onResult(result.size());
|
||||||
@Override
|
|
||||||
public void onResult(Collection<Shop> result) {
|
|
||||||
for (Shop shop : result) {
|
|
||||||
if (shop.create(showConsoleMessages)) {
|
|
||||||
addShop(shop, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback != null) callback.callSyncResult(result.size());
|
Bukkit.getPluginManager().callEvent(new ShopsLoadedEvent(result));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable throwable) {
|
|
||||||
if (callback != null) callback.callSyncError(throwable);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable throwable) {
|
public void onError(Throwable throwable) {
|
||||||
if (callback != null) callback.callSyncError(throwable);
|
if (callback != null) callback.onError(throwable);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all shops from the given chunk from the server
|
||||||
|
* @param chunk The chunk containing the shops to unload
|
||||||
|
* @return The amount of shops that were unloaded
|
||||||
|
*/
|
||||||
|
public int unloadShops(final Chunk chunk) {
|
||||||
|
Set<Shop> unloadedShops = new HashSet<>();
|
||||||
|
|
||||||
|
Iterator<Shop> iter = getShops().iterator();
|
||||||
|
while(iter.hasNext()) {
|
||||||
|
Shop shop = iter.next();
|
||||||
|
if (shop.getLocation().getChunk().equals(chunk)) {
|
||||||
|
removeShop(shop, false);
|
||||||
|
unloadedShops.add(shop);
|
||||||
|
plugin.debug("Unloaded shop (#" + shop.getID() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().callEvent(new ShopsUnloadedEvent(Collections.unmodifiableCollection(unloadedShops)));
|
||||||
|
return unloadedShops.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update hologram and item of all shops for a player
|
* Update hologram and item of all shops for a player
|
||||||
* @param player Player to show the updates
|
* @param player Player to show the updates
|
||||||
|
Loading…
Reference in New Issue
Block a user