Skip to content

Commit e9be1ce

Browse files
committed
add database
1 parent 9bf3b0b commit e9be1ce

10 files changed

Lines changed: 258 additions & 4 deletions

File tree

build.gradle.kts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ repositories {
2020
dependencies {
2121
compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT")
2222
implementation(project(":core"))
23+
24+
implementation("org.jetbrains.exposed:exposed-core:1.0.0-beta-5")
25+
implementation("org.jetbrains.exposed:exposed-jdbc:1.0.0-beta-5")
26+
implementation("org.jetbrains.exposed:exposed-dao:1.0.0-beta-5") // Optional
2327
}
2428

2529
kotlin {
@@ -37,9 +41,19 @@ tasks.register<ShadowJar>("shadowJarPlugin") {
3741
from(sourceSets.main.get().output)
3842
configurations = listOf(project.configurations.runtimeClasspath.get())
3943

44+
exclude("com/zaxxer/**")
4045
exclude("kotlin/**", "kotlinx/**")
4146
exclude("org/intellij/**")
4247
exclude("org/jetbrains/**")
48+
exclude("org/slf4j/**")
49+
50+
relocate("org.bstats", "io.github.grassproject.framework.shadow.bstats")
51+
52+
exclude(
53+
"META-INF/*.SF",
54+
"META-INF/*.DSA",
55+
"META-INF/*.RSA",
56+
)
4357
}
4458

4559
tasks {

core/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ dependencies {
2626
compileOnly(fileTree("lib") {
2727
include("*.jar")
2828
})
29+
30+
implementation("org.bstats:bstats-bukkit:3.1.0")
31+
32+
implementation("com.zaxxer:HikariCP:7.0.2")
33+
implementation("org.jetbrains.exposed:exposed-core:1.0.0-beta-5")
34+
implementation("org.jetbrains.exposed:exposed-jdbc:1.0.0-beta-5")
35+
implementation("org.jetbrains.exposed:exposed-dao:1.0.0-beta-5") // Optional
2936
}
3037

3138
kotlin {
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package io.github.grassproject.framework.config
2+
3+
import io.github.grassproject.framework.core.GPPlugin
4+
import org.bukkit.configuration.file.FileConfiguration
5+
import org.bukkit.configuration.file.YamlConfiguration
6+
import java.io.File
7+
8+
fun GPPlugin.saveResource(resource: String, file: File) {
9+
if (file.exists()) return
10+
file.parentFile.mkdirs()
11+
12+
val inputStream = getResource(resource)
13+
// ?: throw IllegalArgumentException("Resource '$resource' not found in plugin JAR!")
14+
15+
if (inputStream != null) {
16+
file.outputStream().use { output ->
17+
inputStream.use { input ->
18+
input.copyTo(output)
19+
}
20+
}
21+
} else {
22+
file.createNewFile()
23+
}
24+
}
25+
26+
fun GPPlugin.init(vararg configs: GPFile) {
27+
configs.forEach { yaml ->
28+
val file = File(dataFolder, yaml.name)
29+
if (!file.exists()) saveResource(yaml.name, file)
30+
31+
yaml.reload(file)
32+
}
33+
}
34+
35+
abstract class Config {
36+
37+
abstract var config: FileConfiguration
38+
open var autoSave: Boolean = true
39+
40+
open operator fun contains(key: String) = config.contains(key)
41+
open operator fun get(key: String) = config[key]
42+
open operator fun set(key: String, value: Any?) {
43+
config.set(key, value)
44+
if (autoSave) save()
45+
}
46+
47+
open val sections: Set<String> get() = config.getKeys(false)
48+
open fun section(path: String) = config.getConfigurationSection(path)
49+
open fun keys(path: String, deep: Boolean = false) = section(path)?.getKeys(deep) ?: emptySet()
50+
51+
open fun list(path: String) = config.getList(path).orEmpty()
52+
open fun string(path: String, def: String = "") = config.getString(path, def)!!
53+
open fun stringList(path: String) = config.getStringList(path)
54+
open fun boolean(path: String, def: Boolean = false) = config.getBoolean(path, def)
55+
open fun booleanList(path: String) = config.getBooleanList(path)
56+
open fun int(path: String, def: Int = 0) = config.getInt(path, def)
57+
open fun intList(path: String) = config.getIntegerList(path)
58+
open fun long(path: String, def: Long = 0L) = config.getLong(path, def)
59+
open fun longList(path: String) = config.getLongList(path)
60+
open fun double(path: String, def: Double = 0.0) = config.getDouble(path, def)
61+
open fun doubleList(path: String) = config.getDoubleList(path)
62+
63+
inline fun <reified T : Enum<T>> enum(path: String, def: T): T {
64+
val str = string(path, def.name)
65+
return runCatching { enumValueOf<T>(str.uppercase()) }.getOrDefault(def)
66+
}
67+
68+
fun <T : Enum<T>> setEnum(path: String, value: T) = set(path, value.name)
69+
70+
open fun save() {}
71+
}
72+
73+
open class ConfigFile(open val file: File) : Config() {
74+
override var config: FileConfiguration = YamlConfiguration.loadConfiguration(file)
75+
set(value) {
76+
field = value
77+
save()
78+
}
79+
80+
override fun save() {
81+
config.save(file)
82+
}
83+
84+
fun reload(file: File? = null) {
85+
config = if (file != null) YamlConfiguration.loadConfiguration(file)
86+
else YamlConfiguration.loadConfiguration(this.file)
87+
}
88+
}
89+
90+
open class GPFile(pluginFolder: File, open var name: String) :
91+
ConfigFile(File(pluginFolder, name)) {
92+
93+
constructor(pluginFolder: File, name: String, autoCreate: Boolean = true) : this(pluginFolder, name) {
94+
if (autoCreate && !file.exists()) {
95+
file.parentFile.mkdirs()
96+
file.createNewFile()
97+
}
98+
}
99+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.github.grassproject.framework.database
2+
3+
import com.zaxxer.hikari.HikariConfig
4+
import com.zaxxer.hikari.HikariDataSource
5+
import io.github.grassproject.framework.config.GPFile
6+
import io.github.grassproject.framework.core.GPPlugin
7+
import org.jetbrains.exposed.v1.core.Table
8+
import org.jetbrains.exposed.v1.jdbc.Database
9+
import org.jetbrains.exposed.v1.jdbc.SchemaUtils
10+
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
11+
import java.io.File
12+
import java.io.IOException
13+
14+
object DatabaseManager {
15+
16+
private var driver: DataDriver? = null
17+
18+
fun init(driver: DataDriver) {
19+
this.driver = driver
20+
}
21+
22+
fun initConfig(config: GPFile) {
23+
val type = config.enum("database.type", DataType.SQLITE)
24+
25+
val host = config.string("database.credentials.host", "localhost")
26+
val port = config.int("database.credentials.port", 3306)
27+
val database = config.string("database.credentials.database", "database")
28+
val username = config.string("database.credentials.username", "root")
29+
val password = config.string("database.credentials.password", "password")
30+
val maxPoolSize = config.int("database.pool_options.size", 10)
31+
32+
driver = when (type) {
33+
DataType.MYSQL -> MySQLDriver(host, port, database, username, password, maxPoolSize)
34+
DataType.SQLITE -> buildSQLiteDriver(database, maxPoolSize)
35+
}
36+
}
37+
38+
fun connect() = driver?.connect()
39+
?: throw IllegalStateException("Database driver not initialized")
40+
41+
fun close() {
42+
driver?.close()
43+
driver = null
44+
}
45+
46+
fun createTables(vararg tables: Table) {
47+
transaction(connect()) {
48+
SchemaUtils.create(*tables)
49+
}
50+
}
51+
52+
// private fun buildSQLiteDriver(pluginFolder: File, databaseName: String, maxPoolSize: Int): DataDriver {
53+
// // val dbFile = GPFile(pluginFolder, "${databaseName}.db")
54+
// val dbFile = File("gpframework-database", "${databaseName}.db")
55+
// val databasePath = dbFile.absolutePath
56+
// return SQLiteDriver(databasePath, maxPoolSize)
57+
// }
58+
59+
private fun buildSQLiteDriver(databaseName: String, maxPoolSize: Int): DataDriver {
60+
val folder = File("gpframework-database").also { it.mkdirs() }
61+
val databaseFile = File(folder, "$databaseName.db").apply { createNewFile() }
62+
return SQLiteDriver(databaseFile.absolutePath, maxPoolSize)
63+
}
64+
65+
abstract class DataDriver(protected val config: HikariConfig) {
66+
private val dataSource: HikariDataSource by lazy { HikariDataSource(config) }
67+
68+
fun connect(): Database = Database.connect(dataSource)
69+
70+
fun close() {
71+
if (!dataSource.isClosed) dataSource.close()
72+
}
73+
}
74+
75+
enum class DataType {
76+
MYSQL, SQLITE
77+
}
78+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.github.grassproject.framework.database
2+
3+
import com.zaxxer.hikari.HikariConfig
4+
5+
class MySQLDriver(
6+
host: String,
7+
port: Int,
8+
database: String,
9+
username: String,
10+
password: String,
11+
maxPoolSize: Int = 10
12+
) : DatabaseManager.DataDriver(HikariConfig().apply {
13+
this.driverClassName = "com.mysql.cj.jdbc.Driver"
14+
this.jdbcUrl = "jdbc:mysql://$host:$port/$database?useSSL=false&serverTimezone=Asia/Seoul&characterEncoding=UTF-8"
15+
this.username = username
16+
this.password = password
17+
this.maximumPoolSize = maxPoolSize
18+
this.poolName = "gpframework"
19+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.github.grassproject.framework.database
2+
3+
import com.zaxxer.hikari.HikariConfig
4+
5+
class SQLiteDriver(
6+
databasePath: String,
7+
maxPoolSize: Int = 1
8+
) : DatabaseManager.DataDriver(HikariConfig().apply {
9+
this.driverClassName = "org.sqlite.JDBC"
10+
this.jdbcUrl = "jdbc:sqlite:$databasePath"
11+
this.maximumPoolSize = maxPoolSize
12+
this.poolName = "gpframework"
13+
})

src/main/java/io/github/grassproject/framework/GPFrameworkLoader.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ public void classloader(PluginClasspathBuilder classpathBuilder) {
1515
resolver.addDependency(new Dependency(new DefaultArtifact("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.0"), null));
1616
resolver.addDependency(new Dependency(new DefaultArtifact("org.jetbrains.kotlin:kotlin-reflect:2.2.0"), null));
1717

18+
resolver.addDependency(new Dependency(new DefaultArtifact("com.zaxxer:HikariCP:7.0.2"), null));
19+
20+
resolver.addDependency(new Dependency(new DefaultArtifact("org.jetbrains.exposed:exposed-core:1.0.0-beta-5"), null));
21+
resolver.addDependency(new Dependency(new DefaultArtifact("org.jetbrains.exposed:exposed-jdbc:1.0.0-beta-5"), null));
22+
resolver.addDependency(new Dependency(new DefaultArtifact("org.jetbrains.exposed:exposed-dao:1.0.0-beta-5"), null));
23+
1824
resolver.addRepository(new RemoteRepository.Builder("paper", "default", "https://repo.papermc.io/repository/maven-public/").build());
1925

2026
classpathBuilder.addLibrary(resolver);

src/main/kotlin/io/github/grassproject/framework/GPFrameworkPlugin.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package io.github.grassproject.framework
22

3+
import io.github.grassproject.framework.config.GPFile
4+
import io.github.grassproject.framework.config.init
35
import io.github.grassproject.framework.core.GPPlugin
6+
import io.github.grassproject.framework.database.DatabaseManager
47

58
class GPFrameworkPlugin : GPPlugin() {
69

@@ -13,7 +16,12 @@ class GPFrameworkPlugin : GPPlugin() {
1316
instance = this
1417
}
1518

16-
override fun enable() {}
19+
override fun enable() {
20+
val config = GPFile(dataFolder, "config.yml")
21+
init(config)
22+
DatabaseManager.initConfig(config)
23+
DatabaseManager.connect()
24+
}
1725

1826
override fun disable() {}
1927
}

src/main/resources/config.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
database:
2+
type: SQLITE
3+
credentials:
4+
host: localhost
5+
port: 3306
6+
database: database
7+
username: root
8+
password: password
9+
pool_options:
10+
size: 10

src/main/resources/paper-plugin.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ dependencies:
2222
required: false
2323
join-classpath: true
2424
CraftEngine:
25-
required: true
25+
required: false
2626
join-classpath: true
2727
ItemsAdder:
28-
required: true
28+
required: false
2929
join-classpath: true
3030
Nexo:
31-
required: true
31+
required: false
3232
join-classpath: true

0 commit comments

Comments
 (0)