Untitled
unknown
plain_text
a year ago
8.4 kB
15
Indexable
package dev.smartshub.chestShop.managers
import dev.smartshub.chestShop.ChestShop
import dev.smartshub.chestShop.Util.Companion.fromBase64ItemStack
import dev.smartshub.chestShop.Util.Companion.toBase64
import dev.smartshub.chestShop.objects.DeleteData
import dev.smartshub.chestShop.objects.Shop
import dev.smartshub.chestShop.objects.ShopType
import org.bukkit.Bukkit
import org.bukkit.Chunk
import org.bukkit.block.Chest
import org.bukkit.block.Sign
import org.bukkit.block.data.Directional
import java.io.File
import java.sql.Connection
import java.sql.DriverManager
import java.sql.SQLException
import java.util.*
import java.util.concurrent.CompletableFuture
class StorageManager(private val plugin: ChestShop) {
private var connection: Connection? = null
private val deleteQueue: Queue<DeleteData> = LinkedList()
init {
connect()
}
private val STORAGE_TABLE_NAME = "shops"
private val CREATE_TABLE_QUERY = """
CREATE TABLE IF NOT EXISTS $STORAGE_TABLE_NAME (
id INT AUTO_INCREMENT PRIMARY KEY,
owner_uuid VARCHAR(36) NOT NULL,
sign_x INT NOT NULL,
sign_y INT NOT NULL,
sign_z INT NOT NULL,
world VARCHAR(50) NOT NULL,
item TEXT NOT NULL,
type ENUM('SELL', 'BUY') NOT NULL,
price DOUBLE NOT NULL,
amount INT NOT NULL
);
"""
private val INSERT_SHOP_QUERY = """
INSERT INTO $STORAGE_TABLE_NAME (owner_uuid, sign_x, sign_y, sign_z, world, item, type, price, amount)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
"""
private val DELETE_SHOP_QUERY = """
DELETE FROM $STORAGE_TABLE_NAME WHERE sign_x = ? AND sign_y = ? AND sign_z = ? AND world = ?;
"""
private val SELECT_SHOP_BY_SIGN_QUERY = """
SELECT * FROM $STORAGE_TABLE_NAME WHERE sign_x = ? AND sign_y = ? AND sign_z = ? AND world = ?;
"""
private val SELECT_SHOPS_IN_CHUNK_QUERY = """
SELECT * FROM $STORAGE_TABLE_NAME WHERE
sign_x >= ? AND sign_x < ? AND
sign_z >= ? AND sign_z < ? AND
world = ?;
"""
fun connect() {
val file = File(plugin.dataFolder, "database.db")
try {
Class.forName("org.sqlite.JDBC")
connection = DriverManager.getConnection("jdbc:sqlite:$file")
createTable()
delete()
} catch (e: ClassNotFoundException) {
throw RuntimeException(e)
} catch (e: SQLException) {
throw RuntimeException(e)
}
}
fun createTable() {
println(isConnected())
try {
connection!!.prepareStatement(CREATE_TABLE_QUERY).executeUpdate()
} catch (e: SQLException) {
throw RuntimeException(e)
}
}
fun isConnected(): Boolean {
return this.connection != null
}
private fun save(shop: Shop){
try {
val statement = connection!!.prepareStatement(INSERT_SHOP_QUERY)
statement.setString(1, shop.owner().toString())
statement.setInt(2, shop.sign().location.blockX)
statement.setInt(3, shop.sign().location.blockY)
statement.setInt(4, shop.sign().location.blockZ)
statement.setString(5, shop.sign().world.name)
statement.setString(6, toBase64(shop.item()))
statement.setString(7, shop.type().name)
statement.setDouble(8, shop.price())
statement.setInt(9, shop.amount())
statement.executeUpdate()
} catch (e: SQLException) {
throw RuntimeException(e)
}
}
private fun load(chunk: Chunk): List<Shop>{
val shops = mutableListOf<Shop>()
try {
val statement = connection!!.prepareStatement(SELECT_SHOPS_IN_CHUNK_QUERY)
statement.setInt(1, chunk.x * 16)
statement.setInt(2, chunk.x * 16 + 16)
statement.setInt(3, chunk.z * 16)
statement.setInt(4, chunk.z * 16 + 16)
statement.setString(5, chunk.world.name)
val result = statement.executeQuery()
while (result.next()) {
val x = result.getInt("sign_x")
val y = result.getInt("sign_y")
val z = result.getInt("sign_z")
val world = result.getString("world")
val item = result.getString("item")
val type = ShopType.valueOf(result.getString("type"))
val price = result.getDouble("price")
val amount = result.getInt("amount")
val owner = UUID.fromString(result.getString("owner_uuid"))
val block = chunk.world.getBlockAt(x, y, z)
if (!(block.type.name.contains("SIGN") && block.type.name.contains("WALL"))){
deleteQueue.add(DeleteData(x, y, z, world))
continue
}
if(block.state !is Sign) {
deleteQueue.add(DeleteData(x, y, z, world))
continue
}
val chest = block.getRelative((block.blockData as Directional).facing.oppositeFace).state
if(chest !is Chest) {
deleteQueue.add(DeleteData(x, y, z, world))
continue
}
val shop = fromBase64ItemStack(item)?.let { Shop(chest, sign = block.state as Sign, it, owner) } ?: continue
shop.type(type)
shop.price(price)
shop.amount(amount)
shop.spawnHologram()
shops.add(shop)
}
} catch (e: SQLException) {
throw RuntimeException(e)
}
plugin.logger.info("Loaded ${shops.size} shops in chunk ${chunk.x}, ${chunk.z}")
return shops
}
private fun unload(shop: Shop){
try {
val statement = connection!!.prepareStatement(INSERT_SHOP_QUERY)
statement.setString(1, shop.owner().toString())
statement.setInt(2, shop.sign().location.blockX)
statement.setInt(3, shop.sign().location.blockY)
statement.setInt(4, shop.sign().location.blockZ)
statement.setString(5, shop.sign().world.name)
statement.setString(6, toBase64(shop.item()))
statement.setString(7, shop.type().name)
statement.setDouble(8, shop.price())
statement.setInt(9, shop.amount())
statement.executeUpdate()
} catch (e: SQLException) {
throw RuntimeException(e)
}
}
fun delete(){
Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, Runnable {
if(deleteQueue.isEmpty()) return@Runnable
try {
val statement = connection!!.prepareStatement(DELETE_SHOP_QUERY)
for (deleteData in deleteQueue) {
statement.setInt(1, deleteData.getX())
statement.setInt(2, deleteData.getY())
statement.setInt(3, deleteData.getZ())
statement.setString(4, deleteData.getWorld())
statement.executeUpdate()
}
} catch (e: SQLException) {
throw RuntimeException(e)
}
}, 20L, (20L*60)*10)
}
fun save(){
for (shop in plugin.shopManager().shops()) {
unload(shop)
}
}
fun disconnect() {
if (!isConnected()) return
try {
connection!!.close()
} catch (e: SQLException) {
throw java.lang.RuntimeException(e)
}
}
fun loadToCache(chunk: Chunk) {
CompletableFuture.runAsync {
load(chunk).forEach {
if(plugin.shopManager().shop(it.sign()) == null) plugin.shopManager().addShop(it)
}
}
}
fun loadToCache(shop: Shop){
CompletableFuture.runAsync {
plugin.shopManager().addShop(shop)
}
}
fun unloadFromCache(chunk: Chunk) {
CompletableFuture.runAsync {
plugin.shopManager().getShopsInChunk(chunk).forEach { unload(it) }
}
}
}
Editor is loading...
Leave a Comment