Merge branch 'master' into folia
# Conflicts: # eco-core/core-plugin/build.gradle
This commit is contained in:
@@ -1,86 +0,0 @@
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":eco-core:core-proxy")
|
||||
compileOnly project(":eco-core:core-backend")
|
||||
compileOnly project(":eco-core:core-folia")
|
||||
|
||||
// Libraries
|
||||
implementation 'com.github.WillFP:Crunch:1.1.3'
|
||||
implementation 'mysql:mysql-connector-java:8.0.28'
|
||||
implementation 'org.jetbrains.exposed:exposed-core:0.37.3'
|
||||
implementation 'org.jetbrains.exposed:exposed-dao:0.37.3'
|
||||
implementation 'org.jetbrains.exposed:exposed-jdbc:0.37.3'
|
||||
implementation 'com.zaxxer:HikariCP:5.0.0'
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
implementation 'org.javassist:javassist:3.28.0-GA'
|
||||
implementation 'org.mongodb:mongodb-driver-sync:4.6.0'
|
||||
implementation 'org.litote.kmongo:kmongo-coroutine:4.6.0'
|
||||
implementation('com.moandjiezana.toml:toml4j:0.7.2') {
|
||||
exclude group: 'com.google.code.gson', module: 'gson'
|
||||
}
|
||||
|
||||
// Included in spigot jar
|
||||
compileOnly 'com.google.code.gson:gson:2.8.8'
|
||||
compileOnly 'io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT'
|
||||
|
||||
// Plugin dependencies
|
||||
compileOnly 'com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT'
|
||||
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.7-SNAPSHOT'
|
||||
compileOnly 'com.github.TechFortress:GriefPrevention:16.17.1'
|
||||
compileOnly('com.github.TownyAdvanced:Towny:0.97.2.6') {
|
||||
exclude group: 'com.zaxxer', module: 'HikariCP'
|
||||
}
|
||||
compileOnly 'com.github.angeschossen:LandsAPI:6.26.18'
|
||||
compileOnly 'com.github.angeschossen:PluginFrameworkAPI:1.0.0'
|
||||
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
|
||||
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
|
||||
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.202'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.10'
|
||||
compileOnly 'com.github.oraxen:oraxen:bea381fb82'
|
||||
compileOnly 'com.github.brcdev-minecraft:shopgui-api:3.0.0'
|
||||
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
|
||||
compileOnly 'com.arcaniax:HeadDatabase-API:1.3.0'
|
||||
compileOnly 'com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.0'
|
||||
compileOnly 'com.github.EssentialsX:Essentials:2.18.2'
|
||||
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:1.8.3'
|
||||
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
|
||||
compileOnly 'com.github.WhipDevelopment:CrashClaim:f9cd7d92eb'
|
||||
compileOnly 'com.wolfyscript.wolfyutilities:wolfyutilities:3.16.0.0'
|
||||
compileOnly 'com.github.decentsoftware-eu:decentholograms:2.1.2'
|
||||
compileOnly 'com.github.Gypopo:EconomyShopGUI-API:1.4.6'
|
||||
compileOnly 'com.github.N0RSKA:ScytherAPI:55a'
|
||||
compileOnly 'com.ticxo.modelengine:api:R3.0.1'
|
||||
compileOnly 'me.TechsCode:UltraEconomyAPI:1.0.0'
|
||||
compileOnly 'com.github.Ssomar-Developement:SCore:3.4.7'
|
||||
|
||||
// MythicMobs
|
||||
compileOnly 'io.lumine:Mythic:5.2.1'
|
||||
compileOnly 'io.lumine:LumineUtils:1.19-SNAPSHOT'
|
||||
|
||||
// CombatLogX V10 + NewbieHelper Expansion
|
||||
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'
|
||||
|
||||
// CombatLogX V11 + NewbieHelper Expansion
|
||||
compileOnly 'com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT'
|
||||
|
||||
// LibsDisguises
|
||||
compileOnly 'LibsDisguises:LibsDisguises:10.0.26'
|
||||
|
||||
// All other libs
|
||||
compileOnly fileTree(dir: '../../lib', include: ['*.jar'])
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
minimize {
|
||||
exclude(dependency('org.litote.kmongo:kmongo-coroutine:.*'))
|
||||
exclude(dependency('org.jetbrains.exposed:.*:.*'))
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) {
|
||||
expand projectVersion: project.version
|
||||
}
|
||||
}
|
||||
84
eco-core/core-plugin/build.gradle.kts
Normal file
84
eco-core/core-plugin/build.gradle.kts
Normal file
@@ -0,0 +1,84 @@
|
||||
group = "com.willfp"
|
||||
version = rootProject.version
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":eco-core:core-proxy"))
|
||||
compileOnly(project(":eco-core:core-backend"))
|
||||
|
||||
// Libraries
|
||||
implementation("com.github.WillFP:Crunch:1.1.3")
|
||||
implementation("mysql:mysql-connector-java:8.0.25")
|
||||
implementation("org.jetbrains.exposed:exposed-core:0.37.3")
|
||||
implementation("org.jetbrains.exposed:exposed-dao:0.37.3")
|
||||
implementation("org.jetbrains.exposed:exposed-jdbc:0.37.3")
|
||||
implementation("com.zaxxer:HikariCP:5.0.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.1.0")
|
||||
implementation("org.javassist:javassist:3.28.0-GA")
|
||||
implementation("org.mongodb:mongodb-driver-sync:4.6.0")
|
||||
implementation("org.litote.kmongo:kmongo-coroutine:4.6.0")
|
||||
implementation("com.moandjiezana.toml:toml4j:0.7.2") {
|
||||
exclude(group = "com.google.code.gson", module = "gson")
|
||||
}
|
||||
|
||||
// Included in spigot jar
|
||||
compileOnly("com.google.code.gson:gson:2.8.8")
|
||||
compileOnly("io.papermc.paper:paper-api:1.19.3-R0.1-SNAPSHOT")
|
||||
|
||||
// Plugin dependencies
|
||||
compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT")
|
||||
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.7-SNAPSHOT")
|
||||
compileOnly("com.github.TechFortress:GriefPrevention:16.17.1")
|
||||
compileOnly("com.github.TownyAdvanced:Towny:0.97.2.6") {
|
||||
exclude(group = "com.zaxxer", module = "HikariCP")
|
||||
}
|
||||
compileOnly("com.github.angeschossen:LandsAPI:6.26.18")
|
||||
compileOnly("com.github.angeschossen:PluginFrameworkAPI:1.0.0")
|
||||
compileOnly("fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT")
|
||||
compileOnly("com.github.jiangdashao:matrix-api-repo:317d4635fd")
|
||||
compileOnly("com.gmail.nossr50.mcMMO:mcMMO:2.1.202")
|
||||
compileOnly("me.clip:placeholderapi:2.10.10")
|
||||
compileOnly("com.github.oraxen:oraxen:1.155.0")
|
||||
compileOnly("com.github.brcdev-minecraft:shopgui-api:3.0.0")
|
||||
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.4.7")
|
||||
compileOnly("com.arcaniax:HeadDatabase-API:1.3.0")
|
||||
compileOnly("com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.0")
|
||||
compileOnly("com.github.EssentialsX:Essentials:2.18.2")
|
||||
compileOnly("com.bgsoftware:SuperiorSkyblockAPI:1.8.3")
|
||||
compileOnly("com.github.MilkBowl:VaultAPI:1.7")
|
||||
compileOnly("com.github.WhipDevelopment:CrashClaim:f9cd7d92eb")
|
||||
compileOnly("com.wolfyscript.wolfyutilities:wolfyutilities:3.16.0.0")
|
||||
compileOnly("com.github.decentsoftware-eu:decentholograms:2.1.2")
|
||||
compileOnly("com.github.Gypopo:EconomyShopGUI-API:1.4.6")
|
||||
compileOnly("com.github.N0RSKA:ScytherAPI:55a")
|
||||
compileOnly("com.ticxo.modelengine:api:R3.0.1")
|
||||
compileOnly("me.TechsCode:UltraEconomyAPI:1.0.0")
|
||||
compileOnly("org.black_ixx:playerpoints:3.2.5")
|
||||
compileOnly("com.github.Ssomar-Developement:SCore:3.4.7")
|
||||
compileOnly("io.lumine:Mythic:5.2.1")
|
||||
compileOnly("io.lumine:LumineUtils:1.19-SNAPSHOT")
|
||||
compileOnly("com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT")
|
||||
compileOnly("com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT")
|
||||
compileOnly("LibsDisguises:LibsDisguises:10.0.26")
|
||||
compileOnly("com.denizenscript:denizen:1.2.7-SNAPSHOT") {
|
||||
exclude(group = "*", module = "*")
|
||||
}
|
||||
|
||||
compileOnly(fileTree("../../lib") {
|
||||
include("*.jar")
|
||||
})
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
minimize {
|
||||
exclude(dependency("org.litote.kmongo:kmongo-coroutine:.*"))
|
||||
exclude(dependency("org.jetbrains.exposed:.*:.*"))
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
filesMatching(listOf("**plugin.yml", "**eco.yml")) {
|
||||
expand("projectVersion" to project.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ enum class ConflictType(
|
||||
}
|
||||
|
||||
private fun Plugin.getConflict(): Conflict? {
|
||||
@Suppress("DEPRECATION")
|
||||
if (this.description.libraries.any { it.contains("kotlin-stdlib") }) {
|
||||
return Conflict(this, ConflictType.LIB_LOADER)
|
||||
}
|
||||
|
||||
@@ -14,12 +14,14 @@ import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.menu.MenuType
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.packet.Packet
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.internal.EcoPropsParser
|
||||
import com.willfp.eco.internal.command.EcoPluginCommand
|
||||
import com.willfp.eco.internal.command.EcoSubcommand
|
||||
import com.willfp.eco.internal.config.*
|
||||
import com.willfp.eco.internal.config.handler.ReflectiveConfigHandler
|
||||
import com.willfp.eco.internal.config.handler.SimpleConfigHandler
|
||||
import com.willfp.eco.internal.drops.EcoDropQueue
|
||||
import com.willfp.eco.internal.drops.EcoFastCollatedDropQueue
|
||||
import com.willfp.eco.internal.events.EcoEventManager
|
||||
@@ -36,6 +38,7 @@ import com.willfp.eco.internal.gui.menu.renderedInventory
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder
|
||||
import com.willfp.eco.internal.integrations.PAPIExpansion
|
||||
import com.willfp.eco.internal.logging.EcoLogger
|
||||
import com.willfp.eco.internal.placeholder.PlaceholderParser
|
||||
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||
import com.willfp.eco.internal.scheduling.EcoSchedulerFolia
|
||||
import com.willfp.eco.internal.scheduling.EcoSchedulerSpigot
|
||||
@@ -44,7 +47,9 @@ import com.willfp.eco.internal.spigot.data.KeyRegistry
|
||||
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
||||
import com.willfp.eco.internal.spigot.math.evaluateExpression
|
||||
import com.willfp.eco.internal.spigot.math.DelegatedExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.math.ImmediatePlaceholderTranslationExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.math.LazyPlaceholderTranslationExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||
@@ -88,6 +93,15 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
||||
SafeInternalNamespacedKeyFactory() else FastInternalNamespacedKeyFactory()
|
||||
|
||||
private val placeholderParser = PlaceholderParser()
|
||||
|
||||
private val crunchHandler = DelegatedExpressionHandler(
|
||||
this,
|
||||
if (this.configYml.getBool("use-immediate-placeholder-translation-for-math"))
|
||||
ImmediatePlaceholderTranslationExpressionHandler(placeholderParser)
|
||||
else LazyPlaceholderTranslationExpressionHandler(placeholderParser),
|
||||
)
|
||||
|
||||
override fun createScheduler(plugin: EcoPlugin) =
|
||||
if (Prerequisite.HAS_FOLIA.isMet) EcoSchedulerFolia(plugin) else EcoSchedulerSpigot(plugin)
|
||||
|
||||
@@ -107,7 +121,8 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
EcoExtensionLoader(plugin)
|
||||
|
||||
override fun createConfigHandler(plugin: EcoPlugin) =
|
||||
EcoConfigHandler(plugin)
|
||||
if (plugin.props.isUsingReflectiveReload) ReflectiveConfigHandler(plugin)
|
||||
else SimpleConfigHandler()
|
||||
|
||||
override fun createLogger(plugin: EcoPlugin) =
|
||||
EcoLogger(plugin)
|
||||
@@ -311,8 +326,8 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
override fun getTPS() =
|
||||
getProxy(TPSProxy::class.java).getTPS()
|
||||
|
||||
override fun evaluate(expression: String, context: MathContext) =
|
||||
evaluateExpression(expression, context)
|
||||
override fun evaluate(expression: String, context: PlaceholderContext) =
|
||||
crunchHandler.evaluate(expression, context)
|
||||
|
||||
override fun getOpenMenu(player: Player) =
|
||||
player.renderedInventory?.menu
|
||||
@@ -325,4 +340,10 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
|
||||
override fun sendPacket(player: Player, packet: Packet) =
|
||||
this.getProxy(PacketHandlerProxy::class.java).sendPacket(player, packet)
|
||||
|
||||
override fun translatePlaceholders(text: String, context: PlaceholderContext) =
|
||||
placeholderParser.translatePlacholders(text, context)
|
||||
|
||||
override fun getPlaceholderValue(plugin: EcoPlugin?, args: String, context: PlaceholderContext) =
|
||||
placeholderParser.getPlaceholderResult(plugin, args, context)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.Prerequisite
|
||||
import com.willfp.eco.core.data.ExternalDataStore
|
||||
import com.willfp.eco.core.entities.Entities
|
||||
import com.willfp.eco.core.integrations.IntegrationLoader
|
||||
import com.willfp.eco.core.integrations.afk.AFKManager
|
||||
@@ -19,6 +20,8 @@ import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.packet.PacketListener
|
||||
import com.willfp.eco.core.particle.Particles
|
||||
import com.willfp.eco.core.price.Prices
|
||||
import com.willfp.eco.internal.data.MavenVersionToStringAdapter
|
||||
import com.willfp.eco.internal.data.VersionToStringAdapter
|
||||
import com.willfp.eco.internal.entities.EntityArgParserAdult
|
||||
import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
|
||||
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
|
||||
@@ -92,6 +95,7 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefWorldGuard
|
||||
import com.willfp.eco.internal.spigot.integrations.customentities.CustomEntitiesMythicMobs
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsCustomCrafting
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsDenizen
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsExecutableItems
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsHeadDatabase
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsItemsAdder
|
||||
@@ -107,6 +111,7 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicD
|
||||
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
|
||||
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
||||
import com.willfp.eco.internal.spigot.integrations.placeholder.PlaceholderIntegrationPAPI
|
||||
import com.willfp.eco.internal.spigot.integrations.price.PriceFactoryPlayerPoints
|
||||
import com.willfp.eco.internal.spigot.integrations.price.PriceFactoryUltraEconomy
|
||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
||||
@@ -120,6 +125,7 @@ import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
|
||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler
|
||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler
|
||||
import com.willfp.eco.util.ClassUtils
|
||||
import me.TechsCode.UltraEconomy.UltraEconomy
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||
import net.milkbowl.vault.economy.Economy
|
||||
@@ -178,6 +184,20 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
SegmentParserUseIfPresent.register()
|
||||
|
||||
CustomItemsManager.registerProviders()
|
||||
|
||||
ExternalDataStore.registerAdapter(VersionToStringAdapter)
|
||||
// Handle with shadow.
|
||||
val className = listOf(
|
||||
"org",
|
||||
"apache",
|
||||
"maven",
|
||||
"artifact",
|
||||
"versioning",
|
||||
"DefaultArtifactVersion"
|
||||
).joinToString(".")
|
||||
if (ClassUtils.exists(className)) {
|
||||
ExternalDataStore.registerAdapter(MavenVersionToStringAdapter(className))
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleEnable() {
|
||||
@@ -270,6 +290,8 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
IntegrationLoader("CombatLogX") {
|
||||
val pluginManager = Bukkit.getPluginManager()
|
||||
val combatLogXPlugin = pluginManager.getPlugin("CombatLogX") ?: return@IntegrationLoader
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val pluginVersion = combatLogXPlugin.description.version
|
||||
if (pluginVersion.startsWith("10")) {
|
||||
AntigriefManager.register(AntigriefCombatLogXV10())
|
||||
@@ -293,7 +315,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) },
|
||||
|
||||
// Custom Items
|
||||
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) },
|
||||
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen(this)) },
|
||||
IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) },
|
||||
IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) },
|
||||
IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) },
|
||||
@@ -303,6 +325,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
},
|
||||
IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) },
|
||||
IntegrationLoader("Scyther") { CustomItemsManager.register(CustomItemsScyther()) },
|
||||
IntegrationLoader("Denizen") { CustomItemsManager.register(CustomItemsDenizen()) },
|
||||
|
||||
// Shop
|
||||
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
|
||||
@@ -335,6 +358,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
Prices.registerPriceFactory(PriceFactoryUltraEconomy(currency))
|
||||
}
|
||||
},
|
||||
IntegrationLoader("PlayerPoints") { Prices.registerPriceFactory(PriceFactoryPlayerPoints()) },
|
||||
|
||||
// Placeholder
|
||||
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
||||
|
||||
@@ -16,9 +16,7 @@ abstract class EcoProfile(
|
||||
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
|
||||
this.data[key] = value
|
||||
|
||||
val changedKeys = CHANGE_MAP[uuid] ?: mutableSetOf()
|
||||
changedKeys.add(key)
|
||||
CHANGE_MAP[uuid] = changedKeys
|
||||
CHANGE_MAP.add(uuid)
|
||||
}
|
||||
|
||||
override fun <T : Any> read(key: PersistentDataKey<T>): T {
|
||||
@@ -44,7 +42,7 @@ abstract class EcoProfile(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CHANGE_MAP: MutableMap<UUID, MutableSet<PersistentDataKey<*>>> = ConcurrentHashMap()
|
||||
val CHANGE_MAP: MutableSet<UUID> = ConcurrentHashMap.newKeySet()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import com.willfp.eco.internal.spigot.ServerLocking
|
||||
import com.willfp.eco.internal.spigot.data.storage.DataHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||
import com.willfp.eco.internal.spigot.data.storage.LegacyMySQLDataHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.MongoDataHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.MySQLDataHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.YamlDataHandler
|
||||
@@ -22,24 +21,16 @@ class ProfileHandler(
|
||||
private val type: HandlerType,
|
||||
private val plugin: EcoSpigotPlugin
|
||||
) {
|
||||
private val loaded = mutableMapOf<UUID, Profile>()
|
||||
private val loaded = mutableMapOf<UUID, EcoProfile>()
|
||||
|
||||
val handler: DataHandler = when (type) {
|
||||
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
||||
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
||||
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
||||
HandlerType.LEGACY_MYSQL -> LegacyMySQLDataHandler(plugin, this)
|
||||
}
|
||||
|
||||
init {
|
||||
if (handler.type == HandlerType.LEGACY_MYSQL) {
|
||||
plugin.logger.warning("You're using the legacy MySQL handler!")
|
||||
plugin.logger.warning("Some features will not work and you may get unfixable errors.")
|
||||
plugin.logger.warning("Support cannot be given to data issues related to legacy MySQL.")
|
||||
plugin.logger.warning("Change your data handler to mysql, mongo, or yaml to fix this!")
|
||||
plugin.logger.warning("This can be done in /plugins/eco/config.yml")
|
||||
}
|
||||
}
|
||||
fun accessLoadedProfile(uuid: UUID): EcoProfile? =
|
||||
loaded[uuid]
|
||||
|
||||
fun loadGenericProfile(uuid: UUID): Profile {
|
||||
val found = loaded[uuid]
|
||||
@@ -87,11 +78,7 @@ class ProfileHandler(
|
||||
}
|
||||
|
||||
|
||||
var previousHandlerType = HandlerType.valueOf(plugin.dataYml.getString("previous-handler"))
|
||||
|
||||
if (previousHandlerType == HandlerType.MYSQL && !plugin.dataYml.has("new-mysql")) {
|
||||
previousHandlerType = HandlerType.LEGACY_MYSQL
|
||||
}
|
||||
val previousHandlerType = HandlerType.valueOf(plugin.dataYml.getString("previous-handler"))
|
||||
|
||||
if (previousHandlerType == type) {
|
||||
return
|
||||
@@ -101,7 +88,6 @@ class ProfileHandler(
|
||||
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
||||
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
||||
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
||||
HandlerType.LEGACY_MYSQL -> LegacyMySQLDataHandler(plugin, this)
|
||||
}
|
||||
|
||||
ServerLocking.lock("Migrating player data! Check console for more information.")
|
||||
|
||||
@@ -3,6 +3,5 @@ package com.willfp.eco.internal.spigot.data.storage
|
||||
enum class HandlerType {
|
||||
YAML,
|
||||
MYSQL,
|
||||
MONGO,
|
||||
LEGACY_MYSQL
|
||||
MONGO
|
||||
}
|
||||
|
||||
@@ -1,315 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import org.jetbrains.exposed.dao.id.UUIDTable
|
||||
import org.jetbrains.exposed.sql.BooleanColumnType
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.DoubleColumnType
|
||||
import org.jetbrains.exposed.sql.IntegerColumnType
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.VarCharColumnType
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/*
|
||||
|
||||
The MySQL data handler is hot garbage for several reasons:
|
||||
- Using MySQL on unstructured data: it's being horrifically misused, but that's just how it has to be.
|
||||
- Can't remove un-needed keys, there's wasted space in the columns everywhere.
|
||||
- No native support for the STRING_LIST type, instead it 'serializes' the lists with semicolons as separators.
|
||||
- General lack of flexibility, it's too rigid.
|
||||
|
||||
That's why I added the MongoDB handler, it's far, far better suited for what eco does - use it over
|
||||
MySQL if you can.
|
||||
|
||||
Oh, also - I don't really know how this class works. I've rewritten it and hacked it together several ways
|
||||
in several sessions, and it's basically complete gibberish to me. Adding the STRING_LIST type is probably
|
||||
the worst bodge I've shipped in production.
|
||||
|
||||
*/
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class LegacyMySQLDataHandler(
|
||||
plugin: EcoSpigotPlugin,
|
||||
handler: ProfileHandler
|
||||
) : DataHandler(HandlerType.LEGACY_MYSQL) {
|
||||
private val database: Database
|
||||
private val playerHandler: ImplementedMySQLHandler
|
||||
private val serverHandler: ImplementedMySQLHandler
|
||||
|
||||
init {
|
||||
val config = HikariConfig()
|
||||
config.driverClassName = "com.mysql.cj.jdbc.Driver"
|
||||
config.username = plugin.configYml.getString("mysql.user")
|
||||
config.password = plugin.configYml.getString("mysql.password")
|
||||
config.jdbcUrl = "jdbc:mysql://" +
|
||||
"${plugin.configYml.getString("mysql.host")}:" +
|
||||
"${plugin.configYml.getString("mysql.port")}/" +
|
||||
plugin.configYml.getString("mysql.database")
|
||||
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
||||
|
||||
database = Database.connect(HikariDataSource(config))
|
||||
|
||||
playerHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_players"),
|
||||
plugin
|
||||
)
|
||||
|
||||
serverHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_server"),
|
||||
plugin
|
||||
)
|
||||
}
|
||||
|
||||
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
||||
return applyFor(uuid) {
|
||||
it.read(uuid, key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: T) {
|
||||
applyFor(uuid) {
|
||||
it.write(uuid, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
applyFor(uuid) {
|
||||
it.saveKeysForRow(uuid, keys)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <R> applyFor(uuid: UUID, function: (ImplementedMySQLHandler) -> R): R {
|
||||
return if (uuid == serverProfileUUID) {
|
||||
function(serverHandler)
|
||||
} else {
|
||||
function(playerHandler)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
playerHandler.initialize()
|
||||
serverHandler.initialize()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private inner class ImplementedMySQLHandler(
|
||||
private val handler: ProfileHandler,
|
||||
private val table: UUIDTable,
|
||||
private val plugin: EcoPlugin
|
||||
) {
|
||||
private val rows = Caffeine.newBuilder()
|
||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
||||
.build<UUID, ResultRow>()
|
||||
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-legacy-mysql-thread-%d").build()
|
||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
||||
val registeredKeys = mutableSetOf<PersistentDataKey<*>>()
|
||||
|
||||
init {
|
||||
transaction(database) {
|
||||
SchemaUtils.create(table)
|
||||
}
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
transaction(database) {
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun ensureKeyRegistration(key: PersistentDataKey<*>) {
|
||||
if (table.columns.any { it.name == key.key.toString() }) {
|
||||
registeredKeys.add(key)
|
||||
return
|
||||
}
|
||||
|
||||
registerColumn(key)
|
||||
registeredKeys.add(key)
|
||||
}
|
||||
|
||||
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
|
||||
getRow(uuid)
|
||||
doWrite(uuid, key, key.type.constrainSQLTypes(value))
|
||||
}
|
||||
|
||||
private fun doWrite(uuid: UUID, key: PersistentDataKey<*>, constrainedValue: Any) {
|
||||
val column: Column<Any> = getColumn(key) as Column<Any>
|
||||
|
||||
executor.submit {
|
||||
transaction(database) {
|
||||
table.update({ table.id eq uuid }) {
|
||||
it[column] = constrainedValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
saveRow(uuid, keys)
|
||||
}
|
||||
|
||||
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = handler.loadGenericProfile(uuid)
|
||||
|
||||
executor.submit {
|
||||
transaction(database) {
|
||||
getRow(uuid)
|
||||
|
||||
for (key in keys) {
|
||||
doWrite(uuid, key, key.type.constrainSQLTypes(profile.read(key)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
||||
val doRead = Callable<T?> {
|
||||
transaction(database) {
|
||||
val row = getRow(uuid)
|
||||
val column = getColumn(key)
|
||||
val raw = row[column]
|
||||
key.type.fromConstrained(raw)
|
||||
}
|
||||
}
|
||||
|
||||
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
|
||||
|
||||
doRead.call()
|
||||
|
||||
return if (Eco.get().ecoPlugin.configYml.getBool("mysql.async-reads")) {
|
||||
executor.submit(doRead).get()
|
||||
} else {
|
||||
doRead.call()
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> registerColumn(key: PersistentDataKey<T>) {
|
||||
try {
|
||||
transaction(database) {
|
||||
try {
|
||||
table.apply {
|
||||
if (table.columns.any { it.name == key.key.toString() }) {
|
||||
return@apply
|
||||
}
|
||||
|
||||
when (key.type) {
|
||||
PersistentDataKeyType.INT -> registerColumn<Int>(key.key.toString(), IntegerColumnType())
|
||||
.default(key.defaultValue as Int)
|
||||
|
||||
PersistentDataKeyType.DOUBLE -> registerColumn<Double>(
|
||||
key.key.toString(),
|
||||
DoubleColumnType()
|
||||
).default(key.defaultValue as Double)
|
||||
|
||||
PersistentDataKeyType.BOOLEAN -> registerColumn<Boolean>(
|
||||
key.key.toString(),
|
||||
BooleanColumnType()
|
||||
).default(key.defaultValue as Boolean)
|
||||
|
||||
PersistentDataKeyType.STRING -> registerColumn<String>(
|
||||
key.key.toString(),
|
||||
VarCharColumnType(512)
|
||||
).default(key.defaultValue as String)
|
||||
|
||||
PersistentDataKeyType.STRING_LIST -> registerColumn<String>(
|
||||
key.key.toString(),
|
||||
VarCharColumnType(8192)
|
||||
).default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List<String>) as String)
|
||||
|
||||
PersistentDataKeyType.CONFIG -> throw IllegalArgumentException(
|
||||
"Config Persistent Data Keys are not supported by the legacy MySQL handler!"
|
||||
)
|
||||
|
||||
else -> throw NullPointerException("Null value found!")
|
||||
}
|
||||
}
|
||||
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
} catch (e: Exception) {
|
||||
plugin.logger.info("MySQL Error 1!")
|
||||
e.printStackTrace()
|
||||
// What's that? Two enormous exception catches? That's right! This code sucks.
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
plugin.logger.info("MySQL Error 2!")
|
||||
e.printStackTrace()
|
||||
// It might fail. Who cares? This is legacy.
|
||||
}
|
||||
}
|
||||
|
||||
private fun getColumn(key: PersistentDataKey<*>): Column<*> {
|
||||
ensureKeyRegistration(key)
|
||||
|
||||
val name = key.key.toString()
|
||||
|
||||
return table.columns.first { it.name == name }
|
||||
}
|
||||
|
||||
private fun getRow(uuid: UUID): ResultRow {
|
||||
fun select(uuid: UUID): ResultRow? {
|
||||
return transaction(database) {
|
||||
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
return rows.get(uuid) {
|
||||
val row = select(uuid)
|
||||
|
||||
return@get if (row != null) {
|
||||
row
|
||||
} else {
|
||||
transaction(database) {
|
||||
table.insert { it[id] = uuid }
|
||||
}
|
||||
select(uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> PersistentDataKeyType<T>.constrainSQLTypes(value: Any): Any {
|
||||
return if (this == PersistentDataKeyType.STRING_LIST) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
value as List<String>
|
||||
value.joinToString(separator = ";")
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> PersistentDataKeyType<T>.fromConstrained(constrained: Any?): T? {
|
||||
if (constrained == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return if (this == PersistentDataKeyType.STRING_LIST) {
|
||||
constrained as String
|
||||
constrained.split(";").toList()
|
||||
} else {
|
||||
constrained
|
||||
} as T
|
||||
}
|
||||
@@ -34,7 +34,7 @@ Whatever. At least it works.
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MySQLDataHandler(
|
||||
private val plugin: EcoSpigotPlugin,
|
||||
plugin: EcoSpigotPlugin,
|
||||
private val handler: ProfileHandler
|
||||
) : DataHandler(HandlerType.MYSQL) {
|
||||
private val database: Database
|
||||
@@ -149,9 +149,4 @@ class MySQLDataHandler(
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
plugin.dataYml.set("new-mysql", true)
|
||||
plugin.dataYml.save()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,16 @@ class ProfileSaver(
|
||||
val interval = plugin.configYml.getInt("save-interval").toLong()
|
||||
|
||||
plugin.scheduler.runTimer(20, interval) {
|
||||
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
||||
handler.saveKeysFor(uuid, set)
|
||||
val iterator = EcoProfile.CHANGE_MAP.iterator()
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
val uuid = iterator.next()
|
||||
iterator.remove()
|
||||
|
||||
val profile = handler.accessLoadedProfile(uuid) ?: continue
|
||||
|
||||
handler.saveKeysFor(uuid, profile.data.keys)
|
||||
}
|
||||
EcoProfile.CHANGE_MAP.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.bukkit.event.entity.EntityDeathEvent
|
||||
class EntityDeathByEntityListeners(
|
||||
private val plugin: EcoPlugin
|
||||
) : Listener {
|
||||
private val events = HashSet<EntityDeathByEntityBuilder>()
|
||||
private val events = mutableSetOf<EntityDeathByEntityBuilder>()
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
fun onEntityDamage(event: EntityDamageByEntityEvent) {
|
||||
@@ -28,8 +28,10 @@ class EntityDeathByEntityListeners(
|
||||
val builtEvent = EntityDeathByEntityBuilder()
|
||||
builtEvent.victim = victim
|
||||
builtEvent.damager = event.damager
|
||||
events.add(builtEvent)
|
||||
this.plugin.scheduler.run {
|
||||
|
||||
events += builtEvent
|
||||
|
||||
this.plugin.scheduler.runLater(5) { // Fixes conflicts with WildStacker
|
||||
events.remove(builtEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ class Metrics(private val plugin: EcoPlugin) {
|
||||
}
|
||||
|
||||
private fun appendServiceData(builder: JsonObjectBuilder) {
|
||||
@Suppress("DEPRECATION")
|
||||
builder.appendField("pluginVersion", plugin.description.version)
|
||||
}
|
||||
|
||||
@@ -238,15 +239,6 @@ class Metrics(private val plugin: EcoPlugin) {
|
||||
// Inform the server owners about bStats
|
||||
config
|
||||
.options()
|
||||
.header(
|
||||
"""
|
||||
bStats (https://bStats.org) collects some basic information for plugin authors, like how
|
||||
many people use their plugin and their total player count. It's recommended to keep bStats
|
||||
enabled, but if you're not comfortable with this, you can turn this setting off. There is no
|
||||
performance penalty associated with having metrics enabled, and data sent to bStats is fully
|
||||
anonymous.
|
||||
""".trimIndent()
|
||||
)
|
||||
.copyDefaults(true)
|
||||
config.save(configFile)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.denizenscript.denizen.objects.ItemTag
|
||||
import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper
|
||||
import com.willfp.eco.core.items.Items
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
class CustomItemsDenizen : CustomItemsIntegration, Listener {
|
||||
|
||||
override fun registerProvider() {
|
||||
Items.registerItemProvider(DenizenProvider())
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "Denizen"
|
||||
}
|
||||
|
||||
private class DenizenProvider : ItemProvider("denizen") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = ItemTag.valueOf(key, false) ?: return null
|
||||
val id = item.scriptName
|
||||
val namespacedKey = NamespacedKeyUtils.create("denizen", id)
|
||||
val stack = item.itemStack
|
||||
return CustomItem(
|
||||
namespacedKey,
|
||||
{ id.equals(ItemScriptHelper.getItemScriptNameText(it), ignoreCase = true) },
|
||||
stack
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.Items
|
||||
@@ -7,16 +8,27 @@ import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import io.th0rgal.oraxen.api.OraxenItems
|
||||
import io.th0rgal.oraxen.api.events.OraxenItemsLoadedEvent
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
class CustomItemsOraxen : CustomItemsIntegration {
|
||||
class CustomItemsOraxen(
|
||||
private val plugin: EcoPlugin
|
||||
) : CustomItemsIntegration, Listener {
|
||||
override fun registerProvider() {
|
||||
Items.registerItemProvider(OraxenProvider())
|
||||
plugin.eventManager.registerListener(this)
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "Oraxen"
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun onItemRegister(event: OraxenItemsLoadedEvent) {
|
||||
Items.registerItemProvider(OraxenProvider())
|
||||
}
|
||||
|
||||
private class OraxenProvider : ItemProvider("oraxen") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = OraxenItems.getItemById(key) ?: return null
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.price
|
||||
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import org.black_ixx.playerpoints.PlayerPoints
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class PriceFactoryPlayerPoints : PriceFactory {
|
||||
override fun getNames() = listOf(
|
||||
"player_points",
|
||||
"p_points"
|
||||
)
|
||||
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PricePlayerPoints(baseContext) { function.get(it).roundToInt() }
|
||||
}
|
||||
|
||||
private class PricePlayerPoints(
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val function: (PlaceholderContext) -> Int
|
||||
) : Price {
|
||||
private val api = PlayerPoints.getInstance().api
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
|
||||
override fun canAfford(player: Player, multiplier: Double): Boolean {
|
||||
return api.look(player.uniqueId) >= getValue(player, multiplier)
|
||||
}
|
||||
|
||||
override fun pay(player: Player, multiplier: Double) {
|
||||
api.take(player.uniqueId, getValue(player, multiplier).roundToInt())
|
||||
}
|
||||
|
||||
override fun giveTo(player: Player, multiplier: Double) {
|
||||
api.give(player.uniqueId, getValue(player, multiplier).roundToInt())
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return function(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
return multipliers[player.uniqueId] ?: 1.0
|
||||
}
|
||||
|
||||
override fun setMultiplier(player: Player, multiplier: Double) {
|
||||
multipliers[player.uniqueId] = multiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.price
|
||||
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import com.willfp.eco.util.toSingletonList
|
||||
@@ -9,21 +10,20 @@ import me.TechsCode.UltraEconomy.objects.Account
|
||||
import me.TechsCode.UltraEconomy.objects.Currency
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import java.util.function.Function
|
||||
|
||||
class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||
override fun getNames(): List<String> {
|
||||
return currency.name.lowercase().toSingletonList()
|
||||
}
|
||||
|
||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||
return PriceUltraEconomy(currency, baseContext) { function.apply(it) }
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PriceUltraEconomy(currency, baseContext) { function.get(it) }
|
||||
}
|
||||
|
||||
private class PriceUltraEconomy(
|
||||
private val currency: Currency,
|
||||
private val baseContext: MathContext,
|
||||
private val function: (MathContext) -> Double
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val function: (PlaceholderContext) -> Double
|
||||
) : Price {
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
private val api = UltraEconomy.getAPI()
|
||||
@@ -44,7 +44,7 @@ class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return function(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier
|
||||
return function(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.math
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
||||
import org.bukkit.entity.Player
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.data.FastNumberParsing
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
import redempt.crunch.functional.Function
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder().build()
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
private val min = Function("min", 2) {
|
||||
min(it[0], it[1])
|
||||
}
|
||||
|
||||
private val max = Function("max", 2) {
|
||||
max(it[0], it[1])
|
||||
}
|
||||
|
||||
fun evaluateExpression(expression: String, context: MathContext) =
|
||||
evaluateExpression(expression, context.player, context.injectableContext, context.additionalPlayers)
|
||||
.let { if (!it.isFinite()) 0.0 else it } // Fixes NaN bug.
|
||||
|
||||
private fun evaluateExpression(
|
||||
expression: String,
|
||||
player: Player?,
|
||||
context: PlaceholderInjectable,
|
||||
additional: Collection<AdditionalPlayer>
|
||||
): Double {
|
||||
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
.map { PlaceholderManager.translatePlaceholders(it, player, context, additional) }
|
||||
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = cache.get(expression) {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(it)
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
env.addFunctions(min, max)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.willfp.eco.internal.spigot.math
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class DelegatedExpressionHandler(
|
||||
plugin: EcoPlugin,
|
||||
private val handler: ExpressionHandler
|
||||
) : ExpressionHandler {
|
||||
private val evaluationCache: Cache<Int, Double> = Caffeine.newBuilder()
|
||||
.expireAfterWrite(plugin.configYml.getInt("math-cache-ttl").toLong(), TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
// Peak performance (totally not having fun with bitwise operators)
|
||||
val hash = (((expression.hashCode() shl 5) - expression.hashCode()) xor
|
||||
(context.player?.uniqueId?.hashCode() ?: 0)
|
||||
) xor context.injectableContext.hashCode()
|
||||
|
||||
return evaluationCache.get(hash) {
|
||||
handler.evaluate(expression, context)
|
||||
.let { if (!it.isFinite()) 0.0 else it } // Fixes NaN bug.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.willfp.eco.internal.spigot.math
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.internal.placeholder.PlaceholderParser
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
import redempt.crunch.functional.Function
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
private val min = Function("min", 2) {
|
||||
min(it[0], it[1])
|
||||
}
|
||||
|
||||
private val max = Function("max", 2) {
|
||||
max(it[0], it[1])
|
||||
}
|
||||
|
||||
interface ExpressionHandler {
|
||||
fun evaluate(expression: String, context: PlaceholderContext): Double
|
||||
}
|
||||
private fun String.fastToDoubleOrNull(): Double? {
|
||||
if (isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
var idx = 0
|
||||
val isNegative = this[0] == '-'
|
||||
if (isNegative) idx++
|
||||
|
||||
var integerPart = 0.0
|
||||
var decimalPart = 0.0
|
||||
var decimalIdx = -1
|
||||
|
||||
while (idx < length) {
|
||||
|
||||
when (val char = this[idx]) {
|
||||
'.' -> {
|
||||
if (decimalIdx != -1) return null
|
||||
decimalIdx = idx
|
||||
}
|
||||
in '0'..'9' -> {
|
||||
val number = (char.code - '0'.code).toDouble()
|
||||
if (decimalIdx != -1) {
|
||||
decimalPart = decimalPart * 10 + number
|
||||
} else {
|
||||
integerPart = integerPart * 10 + number
|
||||
}
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
idx++
|
||||
}
|
||||
|
||||
decimalPart /= 10.0.pow((length - decimalIdx - 1).toDouble())
|
||||
|
||||
return if (isNegative) -(integerPart + decimalPart) else integerPart + decimalPart
|
||||
}
|
||||
|
||||
|
||||
class ImmediatePlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
.expireAfterAccess(500, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
private val env = EvaluationEnvironment().apply {
|
||||
addFunctions(min, max)
|
||||
}
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
val translatedExpression = placeholderParser.translatePlacholders(expression, context)
|
||||
|
||||
val compiled = cache.get(translatedExpression) {
|
||||
runCatching { Crunch.compileExpression(translatedExpression, env) }
|
||||
.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate() }.getOrDefault(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
class LazyPlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
|
||||
val placeholderValues = placeholderParser.parseIndividualPlaceholders(placeholders, context)
|
||||
.map { it.fastToDoubleOrNull() ?: 0.0 }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = cache.get(expression) {
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
env.addFunctions(min, max)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class StackedRecipeListener(
|
||||
// Just to be safe, modify the instance (safe check) Using ?. causes a warning.
|
||||
@Suppress("SENSELESS_COMPARISON") // I hate compiler warnings
|
||||
if (inventory.matrix[i] != null) {
|
||||
inventory.matrix[i].amount = amount
|
||||
inventory.matrix[i]?.amount = amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,6 @@ conflicts:
|
||||
# Disable it if it changes drop mechanics too much for you.
|
||||
use-fast-collated-drops: true
|
||||
|
||||
# Some plugins use their own item display systems (eg Triton)
|
||||
# And must be run after eco. Don't enable this unless you run a conflicting plugin
|
||||
# and have been told to enable it.
|
||||
use-lower-protocollib-priority: false
|
||||
|
||||
# Display frames massively optimize PacketWindowItems, however some users have
|
||||
# reported display bugs by using it. If you have any problems with it, then you
|
||||
# should disable this option.
|
||||
@@ -82,4 +77,17 @@ displayed-recipes: true
|
||||
# If eco plugins should not check for updates; only enable this if you know what you're doing
|
||||
# as there can be urgent hotfixes that you are then not notified about. If you're confident
|
||||
# that you can manage updates on your own, turn this on.
|
||||
no-update-checker: false
|
||||
no-update-checker: false
|
||||
|
||||
# Math expressions are parsed using Crunch, which allows for variables to be used in expressions.
|
||||
# If this is false, variables will be used to represent placeholders, which leads to fewer
|
||||
# expression compilations at the expense of slower evaluation times. If this is true, variables
|
||||
# will instead be translated before compilation to reduce evaluation times at the expense of
|
||||
# longer compilation times. If your expressions usually contain many variables, then you
|
||||
# should enable this option as it may improve performance. If you're unsure, leave it disabled.
|
||||
use-immediate-placeholder-translation-for-math: false
|
||||
|
||||
# The time (in milliseconds) for math expressions to be cached for. Higher values will lead to
|
||||
# faster evaluation times (less CPU usage) at the expense of slightly more memory usage and
|
||||
# less reactive values.
|
||||
math-cache-ttl: 200
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
resource-id: 773
|
||||
bstats-id: 10043
|
||||
proxy-package: com.willfp.eco.internal.spigot.proxy
|
||||
color: '&a'
|
||||
supports-extensions: false
|
||||
options:
|
||||
resource-id: 773
|
||||
bstats-id: 10043
|
||||
proxy-package: com.willfp.eco.internal.spigot.proxy
|
||||
color: '&a'
|
||||
supports-extensions: false
|
||||
uses-reflective-reload: false
|
||||
|
||||
198
eco-core/core-plugin/src/main/resources/paper-plugin.yml
Normal file
198
eco-core/core-plugin/src/main/resources/paper-plugin.yml
Normal file
@@ -0,0 +1,198 @@
|
||||
name: eco
|
||||
version: ${projectVersion}
|
||||
main: com.willfp.eco.internal.spigot.EcoImpl
|
||||
api-version: 1.19
|
||||
load: STARTUP
|
||||
|
||||
dependencies:
|
||||
- name: ProtocolLib
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: WorldGuard
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: GriefPrevention
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Towny
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: FactionsUUID
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Lands
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Kingdoms
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: NoCheatPlus
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: AAC
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Matrix
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Spartan
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Vulcan
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: PlaceholderAPI
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: mcMMO
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: CombatLogX
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: ShopGUIPlus
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: ItemsAdder
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Oraxen
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: HeadDatabase
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Multiverse-Inventories
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Alice
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: HolographicDisplays
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: GHolo
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: CMI
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Essentials
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Vault
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: BentoBox
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: DeluxeCombat
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: IridiumSkyblock
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: SuperiorSkyblock2
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: FabledSkyBlock
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: CrashClaim
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: DecentHolograms
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: MythicMobs
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: CustomCrafting
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: ExecutableItems
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: RPGHorses
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: EconomyShopGUI
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: EconomyShopGUI-Premium
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: zShop
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: DeluxeSellwands
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Scyther
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: ModelEngine
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: PvPManager
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: DeluxeMenus
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: UltraEconomy
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: PlayerPoints
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Denizen
|
||||
required: false
|
||||
bootstrap: false
|
||||
@@ -51,3 +51,6 @@ softdepend:
|
||||
- ModelEngine
|
||||
- PvPManager
|
||||
- DeluxeMenus
|
||||
- UltraEconomy
|
||||
- PlayerPoints
|
||||
- Denizen
|
||||
|
||||
Reference in New Issue
Block a user