Untitled

 avatar
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