diff --git a/.github/workflows/java-ci.yml b/.github/workflows/java-ci.yml index 96b17625..011c7417 100644 --- a/.github/workflows/java-ci.yml +++ b/.github/workflows/java-ci.yml @@ -1,6 +1,6 @@ name: Java CI -on: [ push, pull_request ] +on: [ push, pull_request, workflow_dispatch ] jobs: build: diff --git a/build.gradle.kts b/build.gradle.kts index 2bd6aca2..83717d59 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -89,6 +89,9 @@ allprojects { // IridiumSkyblock maven("https://nexus.iridiumdevelopment.net/repository/maven-releases/") + + // HuskPlugins + maven("https://repo.william278.net/releases") } dependencies { diff --git a/eco-api/src/main/java/com/willfp/eco/core/EcoPlugin.java b/eco-api/src/main/java/com/willfp/eco/core/EcoPlugin.java index 88b18f2a..faa85cbf 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/EcoPlugin.java +++ b/eco-api/src/main/java/com/willfp/eco/core/EcoPlugin.java @@ -167,7 +167,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist /** * The tasks to run on task creation. */ - private final ListMap createTasks = new ListMap<>(); + private final ListMap onCreateTasks = new ListMap<>(); /** * Create a new plugin. @@ -638,7 +638,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist this.handleLifecycle(this.onReload, this::handleReload); if (cancelTasks) { - this.handleLifecycle(this.createTasks, this::createTasks); + this.handleLifecycle(this.onCreateTasks, this::createTasks); } for (Extension extension : this.extensionLoader.getLoadedExtensions()) { @@ -666,6 +666,26 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist this.onReload.append(position, task); } + /** + * Add new task to run on createTasks. + * + * @param task The task. + */ + public final void onCreateTasks(@NotNull final Runnable task) { + this.onCreateTasks(LifecyclePosition.END, task); + } + + /** + * Add new task to run on createTasks. + * + * @param position The position to run the task. + * @param task The task. + */ + public final void onCreateTasks(@NotNull final LifecyclePosition position, + @NotNull final Runnable task) { + this.onCreateTasks.append(position, task); + } + /** * Reload the plugin and return the time taken to reload. * diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ConfigSlot.java b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ConfigSlot.java index f73734d6..68ef65c9 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ConfigSlot.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ConfigSlot.java @@ -86,7 +86,7 @@ public class ConfigSlot extends CustomSlot { for (String command : config.getStrings(configKey)) { if (command.startsWith("console:")) { commands.add(new CommandToDispatch( - StringUtils.removePrefix("console:", command), + StringUtils.removePrefix(command, "console:"), true )); } else { diff --git a/eco-api/src/main/java/com/willfp/eco/core/price/ConfiguredPrice.java b/eco-api/src/main/java/com/willfp/eco/core/price/ConfiguredPrice.java index d2a2f563..d6f97d60 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/price/ConfiguredPrice.java +++ b/eco-api/src/main/java/com/willfp/eco/core/price/ConfiguredPrice.java @@ -120,8 +120,12 @@ public final class ConfiguredPrice implements Price { */ public String getDisplay(@NotNull final Player player, final double multiplier) { + double value = this.getPrice().getValue(player, multiplier); + return StringUtils.format( - formatString.replace("%value%", NumberUtils.format(this.getPrice().getValue(player, multiplier))), + formatString + .replace("%value%", NumberUtils.format(value)) + .replace("%value_commas%", NumberUtils.formatWithCommas(value)), player, StringUtils.FormatOption.WITH_PLACEHOLDERS ); diff --git a/eco-api/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java b/eco-api/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java index 05079b89..a2f17cc1 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java +++ b/eco-api/src/main/java/com/willfp/eco/core/proxy/ProxyConstants.java @@ -1,5 +1,6 @@ package com.willfp.eco.core.proxy; +import com.willfp.eco.core.version.Version; import org.bukkit.Bukkit; import java.util.Arrays; @@ -12,7 +13,7 @@ public final class ProxyConstants { /** * The NMS version that the server is running on. */ - public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + public static final String NMS_VERSION; /** * All supported NMS versions. @@ -32,4 +33,17 @@ public final class ProxyConstants { private ProxyConstants() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } + + static { + String currentMinecraftVersion = Bukkit.getServer().getBukkitVersion().split("-")[0]; + String nmsVersion; + + if (new Version(currentMinecraftVersion).compareTo(new Version("1.20.5")) < 0) { + nmsVersion = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + } else { + nmsVersion = currentMinecraftVersion.replace(".", "_"); + } + + NMS_VERSION = nmsVersion; + } } diff --git a/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java b/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java index 61192def..05cc91a9 100644 --- a/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java +++ b/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java @@ -203,6 +203,20 @@ public final class NumberUtils { return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted; } + /** + * Format double to string with commas. + * + * @param toFormat The number to format. + * @return Formatted. + */ + @NotNull + public static String formatWithCommas(final double toFormat) { + DecimalFormat df = new DecimalFormat("#,##0.00"); + String formatted = df.format(toFormat); + + return formatted.endsWith(".00") ? formatted.substring(0, formatted.length() - 3) : formatted; + } + /** * Evaluate an expression. * diff --git a/eco-api/src/main/java/com/willfp/eco/util/PatternUtils.java b/eco-api/src/main/java/com/willfp/eco/util/PatternUtils.java index 1eccedba..fab42407 100644 --- a/eco-api/src/main/java/com/willfp/eco/util/PatternUtils.java +++ b/eco-api/src/main/java/com/willfp/eco/util/PatternUtils.java @@ -2,6 +2,7 @@ package com.willfp.eco.util; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import com.willfp.eco.core.Eco; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; @@ -15,7 +16,7 @@ public final class PatternUtils { * Cache of compiled literal patterns. */ private static final Cache LITERAL_PATTERN_CACHE = Caffeine.newBuilder() - .expireAfterAccess(1, TimeUnit.MINUTES) + .expireAfterAccess(Eco.get().getEcoPlugin().getConfigYml().getInt("literal-cache-ttl"), TimeUnit.MINUTES) .build(); /** diff --git a/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt b/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt index 7cf81af1..5d56d779 100644 --- a/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt +++ b/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt @@ -37,9 +37,14 @@ fun ItemStack.toSNBT() = Items.toSNBT(this) /** @see Items.isEmpty */ +@Deprecated("Use ItemStack.isEcoEmpty", ReplaceWith("Items.isEmpty(this)")) val ItemStack?.isEmpty: Boolean get() = Items.isEmpty(this) +/** @see Items.isEmpty */ +val ItemStack?.isEcoEmpty: Boolean + get() = Items.isEmpty(this) + /** @see Items.matchesAny */ fun Collection.matches(item: ItemStack): Boolean = Items.matchesAny(item, this) diff --git a/eco-api/src/main/kotlin/com/willfp/eco/util/NumberUtils.kt b/eco-api/src/main/kotlin/com/willfp/eco/util/NumberUtils.kt index 281b80a5..29c3a3ec 100644 --- a/eco-api/src/main/kotlin/com/willfp/eco/util/NumberUtils.kt +++ b/eco-api/src/main/kotlin/com/willfp/eco/util/NumberUtils.kt @@ -8,6 +8,10 @@ import com.willfp.eco.core.placeholder.context.PlaceholderContext fun Number.toNumeral(): String = NumberUtils.toNumeral(this.toInt()) +/** @see NumberUtils.formatWithCommas */ +fun Number.formatWithCommas(): String = + NumberUtils.formatWithCommas(this.toDouble()) + /** @see NumberUtils.fromNumeral */ fun String.parseNumeral(): Int = NumberUtils.fromNumeral(this) diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/HandledCommand.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/HandledCommand.kt index c4dd15e3..0318d946 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/HandledCommand.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/command/HandledCommand.kt @@ -3,7 +3,6 @@ package com.willfp.eco.internal.command import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.command.CommandBase import com.willfp.eco.core.command.NotificationException -import com.willfp.eco.core.config.base.LangYml import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt index f6c24e19..65dbc5ac 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt @@ -2,7 +2,6 @@ package com.willfp.eco.internal.config import com.willfp.eco.core.config.ConfigType import com.willfp.eco.core.placeholder.InjectablePlaceholder -import java.util.concurrent.ConcurrentHashMap class EcoConfigSection( type: ConfigType, diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoLoadableConfig.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoLoadableConfig.kt index d8920fe3..2faab918 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoLoadableConfig.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoLoadableConfig.kt @@ -15,7 +15,6 @@ import java.nio.channels.AsynchronousFileChannel import java.nio.file.Files import java.nio.file.StandardOpenOption -@Suppress("UNCHECKED_CAST") open class EcoLoadableConfig( type: ConfigType, configName: String, diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/extensions/EcoExtensionLoader.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/extensions/EcoExtensionLoader.kt index d7cc2e43..e265d40e 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/extensions/EcoExtensionLoader.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/extensions/EcoExtensionLoader.kt @@ -42,6 +42,7 @@ class EcoExtensionLoader( } } + @Suppress("DEPRECATION") @Throws(MalformedExtensionException::class) private fun loadExtension(extensionJar: File) { val url = extensionJar.toURI().toURL() diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/fast/InternalNamespacedKeyFactory.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/fast/InternalNamespacedKeyFactory.kt index a86cb0fb..5459e280 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/fast/InternalNamespacedKeyFactory.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/fast/InternalNamespacedKeyFactory.kt @@ -25,7 +25,6 @@ class FastInternalNamespacedKeyFactory : InternalNamespacedKeyFactory { class SafeInternalNamespacedKeyFactory : InternalNamespacedKeyFactory { override fun create(namespace: String, key: String): NamespacedKey { - @Suppress("DEPRECATION") return NamespacedKey(namespace, key) } } diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/RenderedInventory.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/RenderedInventory.kt index 609f4c1c..718645ad 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/RenderedInventory.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/RenderedInventory.kt @@ -1,7 +1,7 @@ package com.willfp.eco.internal.gui.menu import com.willfp.eco.core.gui.menu.events.CaptiveItemChangeEvent -import com.willfp.eco.core.items.isEmpty +import com.willfp.eco.core.items.isEcoEmpty import com.willfp.eco.core.recipe.parts.EmptyTestableItem import com.willfp.eco.util.MenuUtils import com.willfp.eco.util.openMenu @@ -55,7 +55,7 @@ class RenderedInventory( val actualItem = inventory.getItem(bukkit) ?: continue if (slot.isCaptiveFromEmpty) { - if (!actualItem.isEmpty) { + if (!actualItem.isEcoEmpty) { newCaptive[position] = actualItem } } else { diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/integrations/PAPIExpansion.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/integrations/PAPIExpansion.kt index 8858efff..a488ccf8 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/integrations/PAPIExpansion.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/integrations/PAPIExpansion.kt @@ -6,6 +6,7 @@ import com.willfp.eco.core.placeholder.context.placeholderContext import me.clip.placeholderapi.expansion.PlaceholderExpansion import org.bukkit.entity.Player +@Suppress("DEPRECATION") class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() { init { register() diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEntity.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEntity.kt new file mode 100644 index 00000000..05387c11 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEntity.kt @@ -0,0 +1,64 @@ +package com.willfp.eco.internal.items + +import com.willfp.eco.core.items.args.LookupArgParser +import org.bukkit.block.CreatureSpawner +import org.bukkit.entity.EntityType +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.BlockStateMeta +import org.bukkit.inventory.meta.ItemMeta +import java.util.function.Predicate + +object ArgParserEntity : LookupArgParser { + override fun parseArguments(args: Array, meta: ItemMeta): Predicate? { + if (meta !is BlockStateMeta) { + return null + } + + if (meta.hasBlockState() || meta.blockState !is CreatureSpawner) { + return null + } + + val state = meta.blockState as CreatureSpawner + + var type: String? = null + + for (arg in args) { + val argSplit = arg.split(":") + if (!argSplit[0].equals("entity", ignoreCase = true)) { + continue + } + if (argSplit.size < 2) { + continue + } + type = argSplit[1] + } + + type ?: return null + + val entityType = runCatching { EntityType.valueOf(type.uppercase()) }.getOrNull() ?: return null + + state.spawnedType = entityType + + meta.blockState = state + + return Predicate { + val testMeta = ((it.itemMeta as? BlockStateMeta) as? CreatureSpawner) ?: return@Predicate false + + testMeta.spawnedType?.name?.equals(type, true) == true + } + } + + override fun serializeBack(meta: ItemMeta): String? { + if (meta !is BlockStateMeta) { + return null + } + + if (meta.hasBlockState() || meta.blockState !is CreatureSpawner) { + return null + } + + val state = meta.blockState as CreatureSpawner + + return state.spawnedType?.let { "entity:${state.spawnedType!!.name}" } ?: return null + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserHead.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserHead.kt index 1d73f594..fe96be30 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserHead.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserHead.kt @@ -28,7 +28,6 @@ object ArgParserHead : LookupArgParser { playerName ?: return null - @Suppress("DEPRECATION") val player = Bukkit.getOfflinePlayer(playerName) meta.owningPlayer = player diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTrim.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTrim.kt index 3de5e82b..80d7f40b 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTrim.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTrim.kt @@ -1,13 +1,11 @@ package com.willfp.eco.internal.items import com.willfp.eco.core.items.args.LookupArgParser -import org.bukkit.Color import org.bukkit.NamespacedKey import org.bukkit.Registry import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.ArmorMeta import org.bukkit.inventory.meta.ItemMeta -import org.bukkit.inventory.meta.LeatherArmorMeta import org.bukkit.inventory.meta.trim.ArmorTrim import org.bukkit.inventory.meta.trim.TrimMaterial import org.bukkit.inventory.meta.trim.TrimPattern diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/placeholder/PlaceholderParser.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/placeholder/PlaceholderParser.kt index e0774ff5..72b17368 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/placeholder/PlaceholderParser.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/placeholder/PlaceholderParser.kt @@ -7,6 +7,8 @@ import com.willfp.eco.core.placeholder.InjectablePlaceholder import com.willfp.eco.core.placeholder.Placeholder import com.willfp.eco.core.placeholder.context.PlaceholderContext import com.willfp.eco.util.StringUtils +import com.willfp.eco.util.evaluateExpression +import com.willfp.eco.util.toNiceString import java.util.concurrent.TimeUnit /* @@ -19,6 +21,8 @@ but it's still best to minimise the memory overhead. class PlaceholderParser { private val placeholderRegex = Regex("%([^% ]+)%") + private val prettyMathExpressionRegex = Regex("(\\{\\^\\{)(.)+(}})") + private val mathExpressionRegex = Regex("(\\{\\{)(.)+(}})") private val placeholderLookupCache = Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.SECONDS) @@ -34,6 +38,29 @@ class PlaceholderParser { injections: Collection, translateEcoPlaceholders: Boolean = true ): String { + var processed = text + + // Only evaluate math expressions if there might be any + // Checking { as a char is faster than checking a string sequence, + // even if it might lead to false positives. + if ('{' in processed) { + if ('^' in processed) { + // Evaluate pretty math expressions + processed = prettyMathExpressionRegex.findAll(processed).fold(processed) { acc, matchResult -> + val expression = matchResult.value.substring(3, matchResult.value.length - 2) + val result = evaluateExpression(expression, context) + acc.replace(matchResult.value, result.toNiceString()) + } + } + + // Evaluate math expressions + processed = mathExpressionRegex.findAll(processed).fold(processed) { acc, matchResult -> + val expression = matchResult.value.substring(2, matchResult.value.length - 2) + val result = evaluateExpression(expression, context) + acc.replace(matchResult.value, result.toString()) + } + } + /* Why am I doing injections at the start, and again at the end? @@ -55,7 +82,7 @@ class PlaceholderParser { */ // Apply injections first - var processed = injections.fold(text) { acc, injection -> + processed = injections.fold(processed) { acc, injection -> injection.tryTranslateQuickly(acc, context) } diff --git a/eco-core/core-nms/v1_20_R3/build.gradle.kts b/eco-core/core-nms/v1_20_R3/build.gradle.kts index fbc42137..d10e0a8e 100644 --- a/eco-core/core-nms/v1_20_R3/build.gradle.kts +++ b/eco-core/core-nms/v1_20_R3/build.gradle.kts @@ -7,7 +7,7 @@ version = rootProject.version dependencies { implementation(project(":eco-core:core-nms:nms-common")) - paperweight.paperDevBundle("1.20.3-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.20.4-R0.1-SNAPSHOT") implementation("net.kyori:adventure-text-minimessage:4.11.0") { version { diff --git a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_20_R3/ExtendedPersistentDataContainerFactory.kt b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_20_R3/ExtendedPersistentDataContainerFactory.kt index fe688996..a3bea877 100644 --- a/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_20_R3/ExtendedPersistentDataContainerFactory.kt +++ b/eco-core/core-nms/v1_20_R3/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_20_R3/ExtendedPersistentDataContainerFactory.kt @@ -46,17 +46,17 @@ class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFa override fun set(key: String, dataType: PersistentDataType, value: Z) { customDataTags[key] = - registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext)) + registry.wrap(dataType, dataType.toPrimitive(value, handle.adapterContext)) } override fun has(key: String, dataType: PersistentDataType): Boolean { val value = customDataTags[key] ?: return false - return registry.isInstanceOf(dataType.primitiveType, value) + return registry.isInstanceOf(dataType, value) } override fun get(key: String, dataType: PersistentDataType): Z? { val value = customDataTags[key] ?: return null - return dataType.fromPrimitive(registry.extract(dataType.primitiveType, value), handle.adapterContext) + return dataType.fromPrimitive(registry.extract(dataType, value), handle.adapterContext) } override fun getOrDefault( diff --git a/eco-core/core-plugin/build.gradle.kts b/eco-core/core-plugin/build.gradle.kts index 85bee0c6..66e7bc1b 100644 --- a/eco-core/core-plugin/build.gradle.kts +++ b/eco-core/core-plugin/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { // 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") + compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") // Plugin dependencies compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT") @@ -62,6 +62,9 @@ dependencies { exclude(group = "*", module = "*") } compileOnly("com.iridium:IridiumSkyblock:4.0.8") + compileOnly("net.william278.huskclaims:huskclaims-bukkit:1.0.1") + compileOnly("net.william278:husktowns:2.6.1") + compileOnly("com.github.jojodmo:ItemBridge:b0054538c1") compileOnly(fileTree("../../lib") { include("*.jar") diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index 9b5c1753..fc215bf3 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -22,34 +22,8 @@ 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 -import com.willfp.eco.internal.entities.EntityArgParserBaby -import com.willfp.eco.internal.entities.EntityArgParserCharged -import com.willfp.eco.internal.entities.EntityArgParserEquipment -import com.willfp.eco.internal.entities.EntityArgParserExplosionRadius -import com.willfp.eco.internal.entities.EntityArgParserFlySpeed -import com.willfp.eco.internal.entities.EntityArgParserFollowRange -import com.willfp.eco.internal.entities.EntityArgParserHealth -import com.willfp.eco.internal.entities.EntityArgParserJumpStrength -import com.willfp.eco.internal.entities.EntityArgParserKnockback -import com.willfp.eco.internal.entities.EntityArgParserKnockbackResistance -import com.willfp.eco.internal.entities.EntityArgParserName -import com.willfp.eco.internal.entities.EntityArgParserNoAI -import com.willfp.eco.internal.entities.EntityArgParserSilent -import com.willfp.eco.internal.entities.EntityArgParserSize -import com.willfp.eco.internal.entities.EntityArgParserSpawnReinforcements -import com.willfp.eco.internal.entities.EntityArgParserSpeed -import com.willfp.eco.internal.items.ArgParserColor -import com.willfp.eco.internal.items.ArgParserCustomModelData -import com.willfp.eco.internal.items.ArgParserEnchantment -import com.willfp.eco.internal.items.ArgParserFlag -import com.willfp.eco.internal.items.ArgParserHead -import com.willfp.eco.internal.items.ArgParserName -import com.willfp.eco.internal.items.ArgParserTexture -import com.willfp.eco.internal.items.ArgParserTrim -import com.willfp.eco.internal.items.ArgParserUnbreakable +import com.willfp.eco.internal.entities.* +import com.willfp.eco.internal.items.* import com.willfp.eco.internal.lookup.SegmentParserGroup import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent import com.willfp.eco.internal.particle.ParticleFactoryRGB @@ -69,37 +43,10 @@ import com.willfp.eco.internal.spigot.eventlisteners.armor.ArmorListener import com.willfp.eco.internal.spigot.gui.GUIListener import com.willfp.eco.internal.spigot.integrations.afk.AFKIntegrationCMI import com.willfp.eco.internal.spigot.integrations.afk.AFKIntegrationEssentials -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatAAC -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatAlice -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatMatrix -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatNCP -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatSpartan -import com.willfp.eco.internal.spigot.integrations.anticheat.AnticheatVulcan -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefBentoBox -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogXV10 -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogXV11 -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCrashClaim -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefDeluxeCombat -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFabledSkyBlock -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFactionsUUID -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPrevention -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefIridiumSkyblock -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefKingdoms -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefLands -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefPvPManager -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefRPGHorses -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2 -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.anticheat.* +import com.willfp.eco.internal.spigot.integrations.antigrief.* 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 -import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsMythicMobs -import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsOraxen -import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsScyther +import com.willfp.eco.internal.spigot.integrations.customitems.* import com.willfp.eco.internal.spigot.integrations.customrecipes.CustomRecipeCustomCrafting import com.willfp.eco.internal.spigot.integrations.economy.EconomyVault import com.willfp.eco.internal.spigot.integrations.entitylookup.EntityLookupModelEngine @@ -149,6 +96,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { Items.registerArgParser(ArgParserUnbreakable) Items.registerArgParser(ArgParserName) Items.registerArgParser(ArgParserHead) + Items.registerArgParser(ArgParserEntity) if (Prerequisite.HAS_1_20.isMet) { Items.registerArgParser(ArgParserTrim) } @@ -296,6 +244,8 @@ abstract class EcoSpigotPlugin : EcoPlugin() { IntegrationLoader("Kingdoms") { AntigriefManager.register(AntigriefKingdoms()) }, IntegrationLoader("RPGHorses") { AntigriefManager.register(AntigriefRPGHorses()) }, IntegrationLoader("CrashClaim") { AntigriefManager.register(AntigriefCrashClaim()) }, + IntegrationLoader("HuskTowns") { AntigriefManager.register(AntigriefHuskTowns()) }, + IntegrationLoader("HuskClaims") { AntigriefManager.register(AntigriefHuskClaims()) }, IntegrationLoader("CombatLogX") { val pluginManager = Bukkit.getPluginManager() val combatLogXPlugin = pluginManager.getPlugin("CombatLogX") ?: return@IntegrationLoader @@ -335,6 +285,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) }, IntegrationLoader("Scyther") { CustomItemsManager.register(CustomItemsScyther()) }, IntegrationLoader("Denizen") { CustomItemsManager.register(CustomItemsDenizen()) }, + IntegrationLoader("ItemBridge") { CustomItemsManager.register(CustomItemsItemBridge()) }, // Shop IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) }, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/arrows/ArrowDataListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/arrows/ArrowDataListener.kt index 385d8dad..6e0efe7b 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/arrows/ArrowDataListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/arrows/ArrowDataListener.kt @@ -1,7 +1,7 @@ package com.willfp.eco.internal.spigot.arrows import com.willfp.eco.core.EcoPlugin -import com.willfp.eco.core.items.isEmpty +import com.willfp.eco.core.items.isEcoEmpty import org.bukkit.entity.Arrow import org.bukkit.entity.LivingEntity import org.bukkit.event.EventHandler @@ -29,7 +29,7 @@ class ArrowDataListener( val item = entity.equipment?.itemInMainHand - if (item.isEmpty || item == null) { + if (item.isEcoEmpty || item == null) { return } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskClaims.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskClaims.kt new file mode 100644 index 00000000..91ff9211 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskClaims.kt @@ -0,0 +1,135 @@ +package com.willfp.eco.internal.spigot.integrations.antigrief + +import com.willfp.eco.core.integrations.antigrief.AntigriefIntegration +import net.crashcraft.crashclaim.CrashClaim +import net.crashcraft.crashclaim.permissions.PermissionRoute +import net.william278.huskclaims.api.HuskClaimsAPI +import net.william278.huskclaims.libraries.cloplib.operation.Operation +import net.william278.huskclaims.libraries.cloplib.operation.OperationPosition +import net.william278.huskclaims.libraries.cloplib.operation.OperationType +import net.william278.huskclaims.position.Position +import net.william278.huskclaims.position.World +import org.bukkit.Location +import org.bukkit.block.Block +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Monster +import org.bukkit.entity.Player +import kotlin.jvm.optionals.getOrElse + +class AntigriefHuskClaims : AntigriefIntegration { + override fun canBreakBlock( + player: Player, + block: Block + ): Boolean { + val api = HuskClaimsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player.uniqueId) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + OperationType.BLOCK_BREAK, + Position.at( + block.x.toDouble(), + block.y.toDouble(), + block.z.toDouble(), + api.getWorld(block.location.world.name) + ), + true + ) + ) + } + + override fun canCreateExplosion( + player: Player, + location: Location + ): Boolean { + val api = HuskClaimsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player.uniqueId) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + OperationType.EXPLOSION_DAMAGE_ENTITY, + Position.at( + location.x, + location.y, + location.z, + api.getWorld(location.world.name) + ), + true + ) + ) + } + + override fun canPlaceBlock( + player: Player, + block: Block + ): Boolean { + val api = HuskClaimsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player.uniqueId) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + OperationType.BLOCK_PLACE, + Position.at( + block.x.toDouble(), + block.y.toDouble(), + block.z.toDouble(), + api.getWorld(block.location.world.name) + ), + true + ) + ) + } + + override fun canInjure( + player: Player, + victim: LivingEntity + ): Boolean { + val api = HuskClaimsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player.uniqueId) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + when (victim) { + is Monster -> OperationType.PLAYER_DAMAGE_MONSTER + is Player -> OperationType.PLAYER_DAMAGE_PLAYER + else -> OperationType.PLAYER_DAMAGE_ENTITY + }, + Position.at( + victim.x, + victim.y, + victim.z, + api.getWorld(victim.location.world.name) + ), + true + ) + ) + } + + override fun canPickupItem(player: Player, location: Location): Boolean { + return true + } + + override fun getPluginName(): String { + return "HuskClaims" + } + + override fun equals(other: Any?): Boolean { + if (other !is AntigriefIntegration) { + return false + } + + return other.pluginName == this.pluginName + } + + override fun hashCode(): Int { + return this.pluginName.hashCode() + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskTowns.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskTowns.kt new file mode 100644 index 00000000..d94456fd --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefHuskTowns.kt @@ -0,0 +1,129 @@ +package com.willfp.eco.internal.spigot.integrations.antigrief + +import com.willfp.eco.core.integrations.antigrief.AntigriefIntegration +import net.william278.husktowns.api.HuskTownsAPI +import net.william278.husktowns.claim.Position +import net.william278.husktowns.listener.Operation +import org.bukkit.Location +import org.bukkit.block.Block +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Monster +import org.bukkit.entity.Player + +class AntigriefHuskTowns : AntigriefIntegration { + override fun canBreakBlock( + player: Player, + block: Block + ): Boolean { + val api = HuskTownsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + Operation.Type.BLOCK_BREAK, + Position.at( + block.location.x, + block.location.y, + block.location.z, + api.getWorld(block.world) + ), + true + ) + ) + } + + override fun canCreateExplosion( + player: Player, + location: Location + ): Boolean { + val api = HuskTownsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + Operation.Type.EXPLOSION_DAMAGE_ENTITY, + Position.at( + location.x, + location.y, + location.z, + api.getWorld(location.world) + ), + true + ) + ) + } + + override fun canPlaceBlock( + player: Player, + block: Block + ): Boolean { + val api = HuskTownsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + Operation.Type.BLOCK_PLACE, + Position.at( + block.location.x, + block.location.y, + block.location.z, + api.getWorld(block.world) + ), + true + ) + ) + } + + override fun canInjure( + player: Player, + victim: LivingEntity + ): Boolean { + val api = HuskTownsAPI.getInstance() ?: return true + + val user = api.getOnlineUser(player) ?: return true + + return api.isOperationAllowed( + Operation.of( + user, + when(victim) { + is Monster -> Operation.Type.PLAYER_DAMAGE_MONSTER + is Player -> Operation.Type.PLAYER_DAMAGE_PLAYER + else -> Operation.Type.PLACE_HANGING_ENTITY + }, + Position.at( + player.location.x, + player.location.y, + player.location.z, + api.getWorld(player.world) + ), + true + ) + ) + } + + override fun canPickupItem(player: Player, location: Location): Boolean { + return true + } + + override fun getPluginName(): String { + return "HuskTowns" + } + + override fun equals(other: Any?): Boolean { + if (other !is AntigriefIntegration) { + return false + } + + return other.pluginName == this.pluginName + } + + override fun hashCode(): Int { + return this.pluginName.hashCode() + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemBridge.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemBridge.kt new file mode 100644 index 00000000..f34d4207 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/customitems/CustomItemsItemBridge.kt @@ -0,0 +1,47 @@ +package com.willfp.eco.internal.spigot.integrations.customitems + +import com.jojodmo.itembridge.ItemBridge +import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration +import com.willfp.eco.core.items.CustomItem +import com.willfp.eco.core.items.Items +import com.willfp.eco.core.items.TestableItem +import com.willfp.eco.core.items.provider.ItemProvider +import com.willfp.eco.util.namespacedKeyOf +import org.bukkit.inventory.ItemStack + +class CustomItemsItemBridge : CustomItemsIntegration { + override fun registerProvider() { + Items.registerItemProvider(ItemBridgeProvider()) + } + + override fun getPluginName(): String { + return "ItemBridge" + } + + private class ItemBridgeProvider : ItemProvider("itembridge") { + override fun provideForKey(key: String): TestableItem? { + + val split = key.split(":").toMutableList() + + if (split.size < 2) { + return null + } + + val itemKey = split[0] + + val item = split[1] + + val stack = ItemBridge.getItemStack(itemKey, item) ?: kotlin.run { + return null + } + + return CustomItem( + namespacedKeyOf("eco:${key.lowercase().replace(":", "__")}"), + { test: ItemStack -> + ItemBridge.isItemStack(test, itemKey, item) + }, + stack + ) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/ExpressionHandlers.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/ExpressionHandlers.kt index 6021f0e0..9c8dc549 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/ExpressionHandlers.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/ExpressionHandlers.kt @@ -5,6 +5,7 @@ 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 com.willfp.eco.util.randDouble import redempt.crunch.CompiledExpression import redempt.crunch.Crunch import redempt.crunch.functional.EvaluationEnvironment @@ -22,6 +23,10 @@ private val max = Function("max", 2) { max(it[0], it[1]) } +private val rand = Function("random", 2) { + randDouble(it[0], it[1]) +} + interface ExpressionHandler { fun evaluate(expression: String, context: PlaceholderContext): Double? } @@ -77,7 +82,7 @@ class ImmediatePlaceholderTranslationExpressionHandler( .build() private val env = EvaluationEnvironment().apply { - addFunctions(min, max) + addFunctions(min, max, rand) } override fun evaluate(expression: String, context: PlaceholderContext): Double? { @@ -106,7 +111,7 @@ class LazyPlaceholderTranslationExpressionHandler( val compiled = cache.getOrPut(expression) { val env = EvaluationEnvironment() env.setVariableNames(*placeholders.toTypedArray()) - env.addFunctions(min, max) + env.addFunctions(rand, min, max) runCatching { Crunch.compileExpression(expression, env) }.getOrNull() } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt index bfd6560b..36fcd28c 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt @@ -2,7 +2,7 @@ package com.willfp.eco.internal.spigot.recipes import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.items.TestableItem -import com.willfp.eco.core.items.isEmpty +import com.willfp.eco.core.items.isEcoEmpty import com.willfp.eco.core.recipe.Recipes import com.willfp.eco.core.recipe.parts.GroupedTestableItems import com.willfp.eco.core.recipe.parts.TestableStack @@ -33,7 +33,7 @@ class StackedRecipeListener( } // Just in case - if (inventory.getItem(event.slot).isEmpty) { + if (inventory.getItem(event.slot).isEcoEmpty) { return } diff --git a/eco-core/core-plugin/src/main/resources/config.yml b/eco-core/core-plugin/src/main/resources/config.yml index dc1f4ecb..43ac9693 100644 --- a/eco-core/core-plugin/src/main/resources/config.yml +++ b/eco-core/core-plugin/src/main/resources/config.yml @@ -96,6 +96,11 @@ use-immediate-placeholder-translation-for-math: false # less reactive values. math-cache-ttl: 200 +# The time (in minutes) for literal patterns 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. (Do not change unless you are told to). +literal-cache-ttl: 1 + # If anonymous usage statistics should be tracked. This is very valuable information as it # helps understand how eco and other plugins are being used by logging player and server # counts. This is completely anonymous and no personal information is logged. This data diff --git a/eco-core/core-plugin/src/main/resources/lang.yml b/eco-core/core-plugin/src/main/resources/lang.yml index 54bd9317..393e0681 100644 --- a/eco-core/core-plugin/src/main/resources/lang.yml +++ b/eco-core/core-plugin/src/main/resources/lang.yml @@ -2,6 +2,7 @@ multiple-in-craft: '&l&c! &fThis recipe requires &a%amount%&f of this item.' # Specify default display names for prices made through ConfiguredPrice#create # These will override any custom configured price display names. +# You can use %value% and %value_commas% as placeholders. price-display: - type: example_type display: "&e%value% Price" diff --git a/eco-core/core-plugin/src/main/resources/plugin.yml b/eco-core/core-plugin/src/main/resources/plugin.yml index 350858e4..9791b46a 100644 --- a/eco-core/core-plugin/src/main/resources/plugin.yml +++ b/eco-core/core-plugin/src/main/resources/plugin.yml @@ -13,7 +13,15 @@ loadbefore: - Lands - EconomyShopGUI - EconomyShopGUI-Premium + - CMI + - DeluxeCombat + - SCore + - ExecutableItems softdepend: + - ItemBridge + - HuskClaims + - HuskTowns + - Terra - ProtocolLib - WorldGuard - GriefPrevention @@ -35,18 +43,15 @@ softdepend: - Alice - HolographicDisplays - GHolo - - CMI - Essentials - Vault - BentoBox - - DeluxeCombat - IridiumSkyblock - SuperiorSkyblock2 - FabledSkyBlock - CrashClaim - DecentHolograms - MythicMobs - - ExecutableItems - RPGHorses - zShop - DeluxeSellwands diff --git a/gradle.properties b/gradle.properties index d6a16f98..f06a7116 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version = 6.68.1 +version = 6.69.0 kotlin.incremental.useClasspathSnapshot=false \ No newline at end of file diff --git a/lib/fabledskyblock3.jar b/lib/fabledskyblock3.jar new file mode 100644 index 00000000..211c555f Binary files /dev/null and b/lib/fabledskyblock3.jar differ