Skip to content

Commit

Permalink
Merge pull request #10
Browse files Browse the repository at this point in the history
5.0.0_snapshot
  • Loading branch information
HoshiKurama authored Jul 14, 2021
2 parents eecb696 + 6511f7f commit 38a8831
Show file tree
Hide file tree
Showing 47 changed files with 7,402 additions and 3,185 deletions.
22 changes: 12 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
.gradle
.idea
build
gradle
API_KEYS.kt
src/main/Stuff.txt
gradle.properties
gradlew
gradlew.bat
settings.gradle.kts
/Paper/build/
/.gradle/
/.idea/
/build/
/gradle/
/gradlew
/gradlew.bat
/common/build/
/common/src/main/kotlin/com/github/hoshikurama/ticketmanager/common/API_KEYS.kt
/src/
/Spigot/Spigot.iml
/Spigot/build/
44 changes: 44 additions & 0 deletions Paper/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
plugins {
id("com.github.johnrengelman.shadow") version "7.0.0"
kotlin("jvm")
java
application
}

application {
mainClass.set("com.github.hoshikurama.ticketmanager.paper.TicketManagerPlugin")
}

repositories {
mavenCentral()
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
maven { url = uri("https://jitpack.io") }
}

dependencies {
compileOnly("io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT")
implementation(kotlin("stdlib", version = "1.5.21"))
implementation("com.github.HoshiKurama:KyoriComponentDSL:1.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.1")
implementation("net.kyori:adventure-extra-kotlin:4.8.1")
implementation("joda-time:joda-time:2.10.10")
compileOnly("com.github.MilkBowl:VaultAPI:1.7")
implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:1.5.0")
implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:1.5.0")
implementation(project(":common"))
}

tasks {
named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
archiveBaseName.set("TicketManager-Paper")

dependencies {
include(dependency("com.github.HoshiKurama:KyoriComponentDSL:1.1.0"))
include(dependency("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.2.2"))
include(project(":common"))

relocate("com.github.hoshikurama.componentDSL", "com.github.hoshikurama.ticketmanager.componentDSL")
relocate("kotlinx.serialization.json", "com.github.hoshikurama.ticketmanager.shaded.kotlinx.serialization.json")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package com.github.hoshikurama.ticketmanager.paperimport com.github.hoshikurama.componentDSL.buildComponentimport com.github.hoshikurama.componentDSL.formattedContentimport com.github.hoshikurama.ticketmanager.common.ConfigStateimport com.github.hoshikurama.ticketmanager.common.TMLocaleimport com.github.shynixn.mccoroutine.asyncDispatcherimport net.kyori.adventure.audience.Audienceimport net.kyori.adventure.text.Componentimport org.bukkit.Bukkitimport org.bukkit.ChatColorimport org.bukkit.command.CommandSenderimport org.bukkit.entity.Playerimport java.util.*import java.util.logging.Levelimport kotlin.coroutines.CoroutineContextfun consoleLog(level: Level, message: String) = Bukkit.getLogger().log(level, ChatColor.stripColor(message))internal val mainPlugin: TicketManagerPlugin get() = TicketManagerPlugin.plugininternal val configState: ConfigState get() = mainPlugin.configStateIinternal val asyncContext: CoroutineContext get() = mainPlugin.asyncDispatcherinternal fun pushMassNotify(permission: String, localeMsg: (TMLocale) -> Component) { Bukkit.getConsoleSender().sendMessage(localeMsg(mainPlugin.configStateI.localeHandler.consoleLocale)) Bukkit.getOnlinePlayers().asSequence() .filter { it.has(permission) } .forEach { localeMsg(it.toTMLocale()).run(it::sendMessage) }}internal fun Player.has(permission: String) = mainPlugin.perms.has(this, permission)internal fun CommandSender.has(permission: String): Boolean = if (this is Player) has(permission) else trueinternal fun Player.toTMLocale() = configState.localeHandler.getOrDefault(locale().toString())internal fun CommandSender.toTMLocale() = if (this is Player) toTMLocale() else configState.localeHandler.consoleLocaleinternal fun CommandSender.toUUIDOrNull() = if (this is Player) this.uniqueId else nullfun UUID?.toName(locale: TMLocale): String { if (this == null) return locale.consoleName return this.run(Bukkit::getOfflinePlayer).name ?: "UUID"}fun postModifiedStacktrace(e: Exception) { val onlinePlayers = Bukkit.getOnlinePlayers() .asSequence() .filter { it.has("ticketmanager.notify.warning") } .map { it as Audience to it.toTMLocale() } val console = Bukkit.getConsoleSender() as Audience to configState.localeHandler.consoleLocale val playersAndConsole = onlinePlayers + sequenceOf(console) playersAndConsole.forEach { pair -> val audience = pair.first val locale = pair.second audience.sendMessage( buildComponent { // Builds header listOf( locale.stacktraceLine1, locale.stacktraceLine2.replace("%exception%", e.javaClass.simpleName), locale.stacktraceLine3.replace("%message%", e.message ?: "?"), locale.stacktraceLine4, ) .forEach { text { formattedContent(it) } } // Adds stacktrace entries e.stackTrace .filter { it.className.startsWith("com.github.hoshikurama.ticketmanager") } .map { locale.stacktraceEntry .replace("%method%", it.methodName) .replace("%file%", it.fileName ?: "?") .replace("%line%", "${it.lineNumber}") } .forEach { text { formattedContent(it) } } } ) }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.hoshikurama.github.ticketmanager
package com.github.hoshikurama.ticketmanager.paper

import org.bukkit.Bukkit
import org.bukkit.configuration.file.YamlConfiguration
Expand Down Expand Up @@ -809,20 +809,3 @@ class Metrics(plugin: JavaPlugin, serviceId: Int) {
}
}

internal class UpdateChecker(private val resourceID: Int) {
internal fun getLatestVersion(): String? {
var inputStream: InputStream? = null
var scanner: Scanner? = null

return try {
inputStream = URL("https://api.spigotmc.org/legacy/update.php?resource=$resourceID").openStream()
scanner = Scanner(inputStream!!)
if (scanner.hasNext()) scanner.next() else null
}
catch (ignored: Exception) { null }
finally {
inputStream?.close()
scanner?.close()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
package com.github.hoshikurama.ticketmanager.paper

import com.github.hoshikurama.componentDSL.formattedContent
import com.github.hoshikurama.ticketmanager.common.*
import com.github.hoshikurama.ticketmanager.common.databases.Database
import com.github.hoshikurama.ticketmanager.common.databases.Memory
import com.github.hoshikurama.ticketmanager.common.databases.MySQL
import com.github.hoshikurama.ticketmanager.common.databases.SQLite
import com.github.hoshikurama.ticketmanager.paper.events.Commands
import com.github.hoshikurama.ticketmanager.paper.events.PlayerJoin
import com.github.hoshikurama.ticketmanager.paper.events.TabComplete
import com.github.shynixn.mccoroutine.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import net.kyori.adventure.extra.kotlin.text
import net.milkbowl.vault.permission.Permission
import org.bukkit.Bukkit
import java.io.File

class TicketManagerPlugin : SuspendingJavaPlugin() {
internal val pluginState = PluginState()
internal lateinit var perms: Permission private set
internal lateinit var configStateI: ConfigState

private lateinit var metrics: Metrics


companion object { lateinit var plugin: TicketManagerPlugin }
init { plugin = this }

override suspend fun onDisableAsync() {
pluginState.pluginLocked.set(true)
configStateI.database.closeDatabase()
}

override fun onEnable() {

// Find Vault plugin
server.servicesManager.getRegistration(Permission::class.java)?.provider
?.let { perms = it }
?: this.pluginLoader.disablePlugin(this)

// Launch Metrics
launch {
metrics = Metrics(plugin, metricsKey)
metrics.addCustomChart(
Metrics.SingleLineChart("tickets_made") {
runBlocking {
val ticketCount = pluginState.ticketCountMetrics.get()
pluginState.ticketCountMetrics.set(0)
ticketCount
}
}
)
metrics.addCustomChart(
Metrics.SimplePie("database_type") {
configStateI.database.type.name
}
)
} //todo add pie chart for database type being used

// Launches ConfigState initialisation
launchAsync { loadPlugin() }

// Register Event
server.pluginManager.registerSuspendingEvents(PlayerJoin(), plugin)

// Creates task timers
Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, Runnable {
launchAsync { configStateI.cooldowns.filterMapAsync() }

launchAsync {
if (pluginState.pluginLocked.get()) return@launchAsync

try {
// Mass Unread Notify
if (configStateI.allowUnreadTicketUpdates) {
Bukkit.getOnlinePlayers().asFlow()
.filter { it.has("ticketmanager.notify.unreadUpdates.scheduled") }
.onEach {
launch {
val ticketIDs = configStateI.database.getIDsWithUpdatesFor(it.uniqueId).toList()
val tickets = ticketIDs.joinToString(", ")

if (ticketIDs.isEmpty()) return@launch

val template = if (ticketIDs.size > 1) it.toTMLocale().notifyUnreadUpdateMulti
else it.toTMLocale().notifyUnreadUpdateSingle

val sentMessage = template.replace("%num%", tickets)
it.sendMessage(text { formattedContent(sentMessage) })
}
}
}

val openPriority = configStateI.database.getOpenIDPriorityPairs().map { it.first }.toList()
val openCount = openPriority.count()
val assignments = configStateI.database.getBasicTickets(openPriority).mapNotNull { it.assignedTo }.toList()

// Open and Assigned Notify
Bukkit.getOnlinePlayers().asFlow()
.filter { it.has("ticketmanager.notify.openTickets.scheduled") }
.onEach { p ->
launch {
val groups = perms.getPlayerGroups(p).map { "::$it" }
val assignedCount = assignments
.filter { it == p.name || it in groups }
.count()

val sentMessage = p.toTMLocale().notifyOpenAssigned
.replace("%open%", "$openCount")
.replace("%assigned%", "$assignedCount")
p.sendMessage(text { formattedContent(sentMessage) })
}
}
} catch (e: Exception) {
e.printStackTrace()
postModifiedStacktrace(e)
}
}
}, 100, 12000)
}

internal suspend fun loadPlugin() = withContext(plugin.asyncDispatcher) {
pluginState.pluginLocked.set(true)

configStateI = run {
// Creates config file if not found
if (!File(plugin.dataFolder, "config.yml").exists()) {
plugin.saveDefaultConfig()

// Notifies users config was generated after plugin state init
launch {
while (!(::configStateI.isInitialized))
delay(100L)
pushMassNotify("ticketmanager.notify.warning") { text { formattedContent(it.warningsNoConfig) } }
}
}

plugin.reloadConfig()
plugin.config.run {
val path = plugin.dataFolder.absolutePath
val database: () -> Database? = {
val type = getString("Database_Mode", "SQLite")!!
.let { tryOrNull { Database.Type.valueOf(it) } ?: Database.Type.SQLite }

when (type) {
Database.Type.MySQL -> MySQL(
getString("MySQL_Host")!!,
getString("MySQL_Port")!!,
getString("MySQL_DBName")!!,
getString("MySQL_Username")!!,
getString("MySQL_Password")!!,
asyncDispatcher = (plugin.asyncDispatcher as CoroutineDispatcher),
)
Database.Type.SQLite -> SQLite(path)
Database.Type.Memory -> Memory(
filePath = path,
backupFrequency = getLong("Memory_Backup_Frequency", 600)
)
}
}

val cooldown: () -> ConfigState.Cooldown? = {
ConfigState.Cooldown(
getBoolean("Use_Cooldowns", false),
getLong("Cooldown_Time", 0L)
)
}

val localeHandler: suspend () -> LocaleHandler? = {
LocaleHandler.buildLocalesAsync(
getString("Colour_Code", "&3")!!,
getString("Preferred_Locale", "en_ca")!!,
getString("Console_Locale", "en_ca")!!,
getBoolean("Force_Locale", false),
asyncContext
)
}

val allowUnreadTicketUpdates: () -> Boolean? = {
getBoolean("Allow_Unread_Ticket_Updates", true)
}

val checkForPluginUpdate: () -> Boolean? = {
getBoolean("Allow_UpdateChecking", false)
}

val pluginVersion: () -> String = {
mainPlugin.description.version
}

ConfigState.createPluginState(
database,
cooldown,
localeHandler,
allowUnreadTicketUpdates,
checkForPluginUpdate,
pluginVersion,
path,
asyncContext
)
}
}

launch {
val updateNeeded = configStateI.database.updateNeeded()

if (updateNeeded) {
configStateI.database.updateDatabase(
onBegin = {
pushMassNotify("ticketmanager.notify.info") {
text { formattedContent(it.informationDBUpdate) }
}
},
onComplete = {
pushMassNotify("ticketmanager.notify.info") {
text { formattedContent(it.informationDBUpdateComplete) }
}
pluginState.pluginLocked.set(true)
},
offlinePlayerNameToUuidOrNull = {
Bukkit.getOfflinePlayers()
.filter { it.name == name }
.map { it.uniqueId }
.firstOrNull()
},
context = asyncContext
)
} else pluginState.pluginLocked.set(false)
}


withContext(minecraftDispatcher) {
// Register events and commands
configStateI.localeHandler.getCommandBases().forEach {
getCommand(it)!!.setSuspendingExecutor(Commands())
server.pluginManager.registerEvents(TabComplete(), this@TicketManagerPlugin)
// Remember to register any keyword in plugin.yml
}
}
}
}
Loading

0 comments on commit 38a8831

Please sign in to comment.