Skip to content

Commit

Permalink
Base UX (#13)
Browse files Browse the repository at this point in the history
* feat: afk and onlinetime

* feat: custom chat

* feat: remove useless perms
  • Loading branch information
InvalidJoker authored Apr 23, 2024
1 parent 04722ff commit 8c12653
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 8 deletions.
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ val deps = listOf(

dependencies {
compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")

// External dependencies
compileOnly("com.mojang:authlib:1.6.25")
compileOnly("me.clip:placeholderapi:2.11.5")

deps.forEach {
implementation(it)
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/net/blockventuremc/Plugin.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.blockventuremc

import io.github.cdimascio.dotenv.dotenv
import net.blockventuremc.cache.PlayerCache
import net.blockventuremc.database.DatabaseManager
import net.blockventuremc.modules.i18n.TranslationCache
import net.blockventuremc.utils.RegisterManager.registerAll
Expand All @@ -21,12 +22,16 @@ class Plugin: JavaPlugin() {
logger.info("Loading database...")
DatabaseManager.database

DatabaseManager.register()

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

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

PlayerCache.runOnlineTimeScheduler()

logger.info("Hello, Minecraft!")
}
}
29 changes: 29 additions & 0 deletions src/main/kotlin/net/blockventuremc/cache/PlayerCache.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package net.blockventuremc.cache

import net.blockventuremc.Plugin
import net.blockventuremc.database.model.DatabaseUser
import net.blockventuremc.extensions.toDatabaseUserDB
import org.bukkit.Bukkit
import org.bukkit.scheduler.BukkitTask
import java.util.UUID
import kotlin.time.Duration.Companion.seconds

object PlayerCache {
private var _cache = mapOf<UUID, DatabaseUser>()
Expand All @@ -13,4 +17,29 @@ object PlayerCache {
_cache += Pair(user.uuid, user)
return user
}


private fun updateCached(user: DatabaseUser): DatabaseUser {
_cache -= user.uuid
_cache += Pair(user.uuid, user)
return user
}


private var task: BukkitTask? = null
fun runOnlineTimeScheduler() {
task = Bukkit.getScheduler().runTaskTimerAsynchronously(Plugin.instance, Runnable {
Bukkit.getOnlinePlayers().forEach { player ->
val dbUser = get(player.uniqueId)
dbUser.testForActivity()
if (dbUser.afk) return@forEach

updateCached(dbUser.copy(onlineTime = dbUser.onlineTime + 1.seconds))
}
}, 20L, 20L)
}

fun cleanup() {
task?.cancel()
}
}
5 changes: 5 additions & 0 deletions src/main/kotlin/net/blockventuremc/consts/General.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.blockventuremc.consts

import kotlin.time.Duration.Companion.seconds

val AFK_DURATION = 15.seconds
5 changes: 0 additions & 5 deletions src/main/kotlin/net/blockventuremc/consts/Permissions.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import dev.fruxz.ascend.tool.time.calendar.Calendar
import net.blockventuremc.Plugin
import net.blockventuremc.database.functions.TableUsers
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.Instant
Expand All @@ -22,6 +24,12 @@ internal object DatabaseManager {
maximumPoolSize = 100
}
val database = Database.connect(HikariDataSource(dbConfig))

fun register() = smartTransaction {
SchemaUtils.createMissingTablesAndColumns(
TableUsers
)
}
}

internal fun Instant.toCalendar() =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package net.blockventuremc.database.model

import dev.fruxz.ascend.extension.logging.getItsLogger
import dev.fruxz.ascend.tool.time.calendar.Calendar
import net.blockventuremc.consts.AFK_DURATION
import net.blockventuremc.modules.general.events.custom.AFKChangeEvent
import net.blockventuremc.modules.general.model.Languages
import net.blockventuremc.modules.general.model.Ranks
import java.util.*
Expand All @@ -16,4 +19,32 @@ data class DatabaseUser(
val firstJoined: Calendar = Calendar.now(),
val lastTimeJoined: Calendar = Calendar.now(),
val onlineTime: Duration = Duration.ZERO,
)

var afk: Boolean = false,
var lastActivity: Calendar = Calendar.now()
) {

fun testForActivity() {
if (afk) return
val lastActivityDuration = lastActivity.durationToNow()
if (lastActivityDuration >= AFK_DURATION) {
val afkStatusChangedEvent = AFKChangeEvent(true, AFKChangeEvent.Cause.NO_ACTIVITY)
if (afkStatusChangedEvent.isCancelled) return
afk = true
getItsLogger().info("Player $username ($uuid) is now AFK")
}
}

fun addActivity(cause: AFKChangeEvent.Cause) {
if (afk) {
val afkStatusChangedEvent = AFKChangeEvent(false, cause)
if (afkStatusChangedEvent.isCancelled) return
afk = false
val afkDuration = lastActivity.durationToNow()
getItsLogger().info("Player $username ($uuid) is no longer AFK (${cause.name}) after $afkDuration")
}
lastActivity = Calendar.now()
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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.general.model.Ranks
import net.blockventuremc.modules.i18n.TranslationCache
import net.blockventuremc.modules.i18n.model.Translation
import org.bukkit.Bukkit
Expand Down Expand Up @@ -55,7 +56,7 @@ fun String.toOfflinePlayerIfCached(): OfflinePlayer? {


val Player.canBuild: Boolean
get() = gameMode == GameMode.SPECTATOR || (this.hasPermission(BUILD_PERMISSIONS) && hasBuildTag)
get() = gameMode == GameMode.SPECTATOR || (this.toDatabaseUser().rank.isHigherOrEqual(Ranks.Staff) && hasBuildTag)

var Player.hasBuildTag: Boolean
get() = this.scoreboardTags.contains("builder")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.bukkit.entity.Player
@BlockCommand(
name = "build",
description = "Change your build mode",
permission = BUILD_PERMISSIONS,
permission = "blockventure.build",
permissionDefault = PermissionDefault.OP,
usage = "/build",
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package net.blockventuremc.modules.general.events

import org.bukkit.Location
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerCommandPreprocessEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerTeleportEvent
import io.papermc.paper.event.player.AsyncChatEvent
import net.blockventuremc.extensions.toDatabaseUser
import net.blockventuremc.modules.general.events.custom.AFKChangeEvent

class ActivityEvents: Listener {

private fun handleMovement(from: Location, to: Location, player: Player) {
if (from.blockX != to.blockX || from.blockZ != to.blockZ) {
player.toDatabaseUser().addActivity(AFKChangeEvent.Cause.MOVE)
}
}

@EventHandler
fun onMove(event: PlayerMoveEvent) {
val player = event.player
val from = event.from
val to = event.to
handleMovement(from, to, player)
}


@EventHandler
fun onTeleportIntoArea(event: PlayerTeleportEvent) {
val player = event.player
val from = event.from
val to = event.to
handleMovement(from, to, player)
}

@EventHandler
fun onChat(event: AsyncChatEvent) {
val player = event.player
player.toDatabaseUser().addActivity(AFKChangeEvent.Cause.CHAT)
}

@EventHandler
fun onCommand(event: PlayerCommandPreprocessEvent) {
val player = event.player
player.toDatabaseUser().addActivity(AFKChangeEvent.Cause.CHAT)
}

@EventHandler
fun onInteract(event: PlayerInteractEvent) {
val player = event.player
player.toDatabaseUser().addActivity(AFKChangeEvent.Cause.INTERACT)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package net.blockventuremc.modules.general.events

import dev.fruxz.stacked.extension.asPlainString
import dev.fruxz.stacked.text
import io.papermc.paper.event.player.AsyncChatEvent
import me.clip.placeholderapi.PlaceholderAPI
import net.blockventuremc.extensions.toDatabaseUser
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener

class ChatEvent: Listener {

private val chatFormat = "<color:%color%>%rank% <color:#3d3d3d>»</color> <color:#c8d6e5>%playername%</color> <color:#f6e58d>"

private val urlRegex =
Regex("http[s]?:\\/\\/(?:[a-zA-Z]|[0-9]|[\$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")

@EventHandler
fun onChat(event: AsyncChatEvent): Unit = with(event) {
val player = player

val placeHolderText = chatFormat
val messagePlain = message().asPlainString

val format =
text(parsePlaceholders(placeHolderText, player)).append(text(parsePlaceholders(messagePlain, player)))

event.renderer { _, _, _, _ ->
return@renderer format
}
}

private fun parsePlaceholders(text: String, player: Player): String {
var parsed = text
parsed = parsed.replace("%playername%", player.name)
parsed = parsed.replace("%displayname%", player.displayName().asPlainString)
parsed = parsed.replace("%color%", player.toDatabaseUser().rank.color)
parsed = parsed.replace("%rank%", player.toDatabaseUser().rank.name)

if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
parsed = PlaceholderAPI.setPlaceholders(player, parsed)
}

val plainText = text(parsed).asPlainString

// Test for link and replace it with a clickable link
for (match in urlRegex.findAll(plainText)) {
val url = match.value
val urlText = "<color:#7593ff><click:open_url:'$url'>$url</click></color>"
parsed = parsed.replace(url, urlText)
}
return parsed
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.blockventuremc.modules.general.events.custom

import org.bukkit.event.HandlerList

class AFKChangeEvent(var afk: Boolean, val cause: Cause) : BooleanStatusChangedEvent(afk) {

companion object {
private val handlerList = HandlerList()

fun getHandlerList(): HandlerList {
return handlerList
}
}

override fun getHandlers(): HandlerList {
return handlerList
}


enum class Cause {
NO_ACTIVITY,
MOVE,
CHAT,
INTERACT,
UNKNOWN
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.blockventuremc.modules.general.events.custom

import org.bukkit.event.Cancellable
import org.bukkit.event.Event

abstract class BooleanStatusChangedEvent(var newValue: Boolean) : Event(), Cancellable {
private var cancelled = false

override fun isCancelled(): Boolean {
return cancelled
}

override fun setCancelled(cancel: Boolean) {
cancelled = cancel
}
}

0 comments on commit 8c12653

Please sign in to comment.