Merge branch 'master' into folia

# Conflicts:
#	eco-core/core-plugin/build.gradle
This commit is contained in:
Auxilor
2023-05-09 13:00:09 +01:00
195 changed files with 4709 additions and 2469 deletions

View File

@@ -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
}
}

View 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)
}
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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()) },

View File

@@ -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()
}
}

View File

@@ -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.")

View File

@@ -3,6 +3,5 @@ package com.willfp.eco.internal.spigot.data.storage
enum class HandlerType {
YAML,
MYSQL,
MONGO,
LEGACY_MYSQL
MONGO
}

View File

@@ -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
}

View File

@@ -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()
}
}

View File

@@ -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()
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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
)
}
}
}

View File

@@ -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

View File

@@ -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
}
}
}

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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.
}
}
}

View File

@@ -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)
}
}

View File

@@ -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
}
}
}

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -51,3 +51,6 @@ softdepend:
- ModelEngine
- PvPManager
- DeluxeMenus
- UltraEconomy
- PlayerPoints
- Denizen