Skip to content

Commit

Permalink
Plugin basics (#5)
Browse files Browse the repository at this point in the history
* feat: user tables

* feat: base translations

* feat: build system events

* chore: simplify permission system

* chore: add more utility extensions

* feat: coroutine utils

* chore: add example-env

---------

Signed-off-by: Liam Sage <[email protected]>
Co-authored-by: Liam Sage <[email protected]>
  • Loading branch information
InvalidJoker and CoasterFreakDE authored Apr 23, 2024
1 parent fbf70f2 commit 04722ff
Show file tree
Hide file tree
Showing 18 changed files with 692 additions and 7 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DATABASE_URL=jdbc:mysql://localhost:3306/your_database
DATABASE_DRIVER=com.mysql.cj.jdbc.Driver
DATABASE_USER=your_user
DATABASE_PASSWORD=your_password
5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.net.URL
plugins {
kotlin("jvm") version "2.0.0-RC1"
id("com.github.johnrengelman.shadow") version "8.1.1"
kotlin("plugin.serialization") version "1.9.22"
id("org.jetbrains.dokka") version "1.9.20"
id("org.sonarqube") version "5.0.0.4638"
id("io.sentry.jvm.gradle") version "3.12.0"
Expand Down Expand Up @@ -48,6 +49,10 @@ val deps = listOf(
"org.jetbrains.exposed:exposed-dao:$exposedVersion",
"org.jetbrains.exposed:exposed-jdbc:$exposedVersion",
"org.jetbrains.exposed:exposed-java-time:$exposedVersion",
"com.google.code.gson:gson:2.10.1",
"org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2",


"com.zaxxer:HikariCP:5.1.0",
"org.mariadb.jdbc:mariadb-java-client:3.3.3",
)
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/net/blockventuremc/Plugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package net.blockventuremc

import io.github.cdimascio.dotenv.dotenv
import net.blockventuremc.database.DatabaseManager
import net.blockventuremc.modules.i18n.TranslationCache
import net.blockventuremc.utils.RegisterManager.registerAll
import org.bukkit.plugin.java.JavaPlugin

Expand All @@ -20,6 +21,9 @@ class Plugin: JavaPlugin() {
logger.info("Loading database...")
DatabaseManager.database

logger.info("Loading translations...")
TranslationCache.loadAll()

logger.info("Registering modules...")
registerAll()

Expand Down
16 changes: 16 additions & 0 deletions src/main/kotlin/net/blockventuremc/cache/PlayerCache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.blockventuremc.cache

import net.blockventuremc.database.model.DatabaseUser
import net.blockventuremc.extensions.toDatabaseUserDB
import java.util.UUID

object PlayerCache {
private var _cache = mapOf<UUID, DatabaseUser>()

fun get(uuid: UUID): DatabaseUser = _cache[uuid] ?: register(uuid.toDatabaseUserDB())

private fun register(user: DatabaseUser): DatabaseUser {
_cache += Pair(user.uuid, user)
return user
}
}
5 changes: 2 additions & 3 deletions src/main/kotlin/net/blockventuremc/consts/Permissions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.blockventuremc.consts

import org.bukkit.permissions.Permission
import org.bukkit.permissions.PermissionDefault
const val BUILD_PERMISSIONS ="blockventure.build"

val BUILD_PERMISSIONS = Permission("blockventure.build", PermissionDefault.OP)
const val ADMIN_PERMISSIONS = "blockventure.admin"
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.zaxxer.hikari.HikariDataSource
import dev.fruxz.ascend.tool.time.calendar.Calendar
import net.blockventuremc.Plugin
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
Expand All @@ -24,3 +26,9 @@ internal object DatabaseManager {

internal fun Instant.toCalendar() =
Calendar(GregorianCalendar.from(ZonedDateTime.from(this.atZone(ZoneId.systemDefault()))))

internal fun <T> smartTransaction(block: Transaction.() -> T): T {
return transaction {
return@transaction block()
}
}
62 changes: 62 additions & 0 deletions src/main/kotlin/net/blockventuremc/database/functions/Users.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package net.blockventuremc.database.functions

import net.blockventuremc.database.functions.TableUsers.userUUID
import net.blockventuremc.database.model.DatabaseUser
import net.blockventuremc.database.smartTransaction
import net.blockventuremc.database.toCalendar
import net.blockventuremc.modules.general.model.Languages
import net.blockventuremc.modules.general.model.Ranks
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.javatime.timestamp
import java.util.*
import kotlin.time.Duration.Companion.seconds

object TableUsers : Table("users") {
val userUUID = varchar("uuid", 45)
val userName = varchar("username", 24)
val userRank = enumerationByName("rank", 24, Ranks::class).default(Ranks.Default)
val userLanguage = enumerationByName("language", 2, Languages::class).default(Languages.EN)

val userFirstJoined = timestamp("firstJoined")
val userLastJoined = timestamp("lastTimeOnline")
val onlineTime = long("onlineTime").default(0)

override val primaryKey = PrimaryKey(userUUID)
}


fun getDatabaseUserOrNull(uuid: UUID): DatabaseUser? = smartTransaction {
return@smartTransaction TableUsers.selectAll().where { userUUID eq uuid.toString() }.firstOrNull()?.let(::mapToDatabaseUser)
}

private fun mapToDatabaseUser(row: ResultRow): DatabaseUser = with(row) {
return DatabaseUser(
uuid = UUID.fromString(this[userUUID]),
username = this[TableUsers.userName],
rank = this[TableUsers.userRank],
language = this[TableUsers.userLanguage],
firstJoined = this[TableUsers.userFirstJoined].toCalendar(),
lastTimeJoined = this[TableUsers.userLastJoined].toCalendar(),
onlineTime = this[TableUsers.onlineTime].seconds,
)
}


fun createDatabaseUser(user: DatabaseUser): DatabaseUser = smartTransaction {
TableUsers.insert {
it[userUUID] = user.uuid.toString()
it[userName] = user.username
}
return@smartTransaction user
}

fun updateDatabaseUser(user: DatabaseUser) = smartTransaction {
TableUsers.update({ userUUID eq user.uuid.toString() }) {
it[userName] = user.username
it[userRank] = user.rank
it[userLanguage] = user.language
it[userFirstJoined] = user.firstJoined.javaInstant
it[userLastJoined] = user.lastTimeJoined.javaInstant
it[onlineTime] = user.onlineTime.inWholeSeconds
}
}
19 changes: 19 additions & 0 deletions src/main/kotlin/net/blockventuremc/database/model/DatabaseUser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.blockventuremc.database.model

import dev.fruxz.ascend.tool.time.calendar.Calendar
import net.blockventuremc.modules.general.model.Languages
import net.blockventuremc.modules.general.model.Ranks
import java.util.*
import kotlin.time.Duration

data class DatabaseUser(
val uuid: UUID,
val username: String,
val rank: Ranks = Ranks.Default,
val language: Languages = Languages.EN,

// Other
val firstJoined: Calendar = Calendar.now(),
val lastTimeJoined: Calendar = Calendar.now(),
val onlineTime: Duration = Duration.ZERO,
)
36 changes: 35 additions & 1 deletion src/main/kotlin/net/blockventuremc/extensions/PlayerExtension.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package net.blockventuremc.extensions

import dev.fruxz.stacked.text
import net.blockventuremc.cache.PlayerCache
import net.blockventuremc.consts.*
import net.blockventuremc.database.functions.createDatabaseUser
import net.blockventuremc.database.functions.getDatabaseUserOrNull
import net.blockventuremc.database.model.DatabaseUser
import net.blockventuremc.modules.i18n.TranslationCache
import net.blockventuremc.modules.i18n.model.Translation
import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.OfflinePlayer
Expand All @@ -26,6 +32,14 @@ fun CommandSender.sendText(message: String) = sendMessage(text(TEXT_GRAY + messa
fun CommandSender.sendTextPrefixedIf(message: String, condition: Boolean) = if(condition) sendMessage(text(PREFIX + message)) else Unit
fun CommandSender.sendTextPrefixed(message: String) = sendMessage(text(PREFIX + message))

fun Player.sendDeniedSound() = playSound(location, "minecraft:block.note_block.bass", 1f, 1f)

fun Player.sendSuccessSound() = playSound(location, "minecraft:block.note_block.pling", 1f, 1f)

fun Player.sendTeleportSound() = playSound(location, "minecraft:block.note_block.harp", 1f, 1f)

fun Player.sendOpenSound() = playSound(location, "minecraft:block.note_block.chime", 1f, 1f)


fun UUID.toOfflinePlayer(): OfflinePlayer {
return Bukkit.getOfflinePlayer(this)
Expand All @@ -47,4 +61,24 @@ var Player.hasBuildTag: Boolean
get() = this.scoreboardTags.contains("builder")
set(value) {
if (value) this.addScoreboardTag("builder") else this.removeScoreboardTag("builder")
}
}

fun DatabaseUser.translate(message: String, placeholders: Map<String, Any?> = emptyMap()): Translation? {
return TranslationCache.get(language.getLanguageCode(), message, placeholders)
}

fun Player.translate(message: String, placeholders: Map<String, Any?> = emptyMap()): Translation? {
return toDatabaseUser().translate(message, placeholders)
}

fun Player.toDatabaseUser(): DatabaseUser {
return PlayerCache.get(uniqueId)
}

fun UUID.toDatabaseUser(): DatabaseUser {
return PlayerCache.get(this)
}

fun UUID.toDatabaseUserDB(): DatabaseUser {
return getDatabaseUserOrNull(this) ?: createDatabaseUser(DatabaseUser(this, Bukkit.getPlayer(this)?.name ?: Bukkit.getOfflinePlayer(this).name ?: "Unknown"))
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package net.blockventuremc.modules.general.commands

import net.blockventuremc.annotations.BlockCommand
import net.blockventuremc.extensions.hasBuildTag
import net.blockventuremc.extensions.sendMessagePrefixed
import net.blockventuremc.consts.*
import net.blockventuremc.extensions.*
import org.bukkit.command.CommandExecutor
import org.bukkit.permissions.PermissionDefault
import org.bukkit.command.Command
Expand All @@ -13,7 +13,7 @@ import org.bukkit.entity.Player
@BlockCommand(
name = "build",
description = "Change your build mode",
permission = "pixel.build",
permission = BUILD_PERMISSIONS,
permissionDefault = PermissionDefault.OP,
usage = "/build",
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.blockventuremc.modules.general.commands

import net.blockventuremc.annotations.BlockCommand
import net.blockventuremc.database.model.DatabaseUser
import net.blockventuremc.modules.general.model.Ranks
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.permissions.PermissionDefault

@BlockCommand(
name = "test",
description = "Test command",
permissionDefault = PermissionDefault.FALSE,
)
class TestCommand: CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
if (sender !is Player) return false

val u = DatabaseUser(sender.uniqueId, sender.name)

if (!u.rank.isHigherOrEqual(Ranks.Staff)) {
sender.sendMessage("You do not have permission to use this command.")
return true
}
sender.sendMessage("Test command")
return true
}
}
Loading

0 comments on commit 04722ff

Please sign in to comment.