Compare commits

...

113 Commits

Author SHA1 Message Date
Will FP
f01e18950c Merge pull request #365 from Exanthiax/develop 2024-07-24 10:44:03 +01:00
Exanthiax
d4a6bf105b Update ParticleFactoryRGB.kt 2024-07-24 01:55:20 +01:00
Auxilor
a9a961ff2b Added FancyHolograms integration 2024-07-20 12:49:07 +01:00
Auxilor
25d572c0db Added AutocrafterPatch 2024-07-20 09:59:58 +01:00
Auxilor
8a4243e434 Fixed XP price 2024-07-19 20:01:20 +01:00
Auxilor
6c40670f5e Updated to 6.72.0 2024-07-19 19:46:26 +01:00
Auxilor
6e94f3cee8 Added support for multiple display modules per plugin 2024-07-19 19:46:26 +01:00
Auxilor
4968d3ff22 Updated to 6.71.6 2024-07-14 16:04:21 +01:00
Auxilor
eecd80be1c Fixed display name 2024-07-14 16:04:14 +01:00
Auxilor
52c1b52f6d Fixed tab completion bug 2024-07-12 18:18:40 +01:00
Auxilor
f321296227 Updated to 6.71.5 2024-07-12 18:08:35 +01:00
Auxilor
ddd12db420 Fixed ExtendedPersistentDataContainerFactory 2024-07-12 18:07:53 +01:00
Auxilor
bd09791b5b Improved command tab-completion 2024-07-08 18:49:29 +01:00
Auxilor
ce9549f03d Updated to 6.71.4 2024-07-08 15:14:24 +01:00
Auxilor
52367dbb95 Fixed Java 17 compatibility 2024-07-08 15:14:18 +01:00
Auxilor
0080c32c23 Updated to 6.71.3 2024-06-25 02:30:45 +01:00
Auxilor
581094a930 Fixed DurabilityUtils 2024-06-25 02:30:37 +01:00
Auxilor
5d9c8775e8 Updated to 6.71.2 2024-06-24 18:44:16 +01:00
Auxilor
9ab51d2c87 Added fix for TopInventory on pre-1.21 2024-06-24 18:42:32 +01:00
Auxilor
b0de341d7f Updated to 6.71.1 2024-06-23 16:45:17 +01:00
Auxilor
1bada835ea Added 1.21 item arg parsers 2024-06-23 14:20:49 +01:00
Auxilor
de04833f0c Updated custom name and lore on 1.21 2024-06-22 23:44:29 +01:00
Auxilor
75dd6be539 Fixed custom name on 1.21 2024-06-22 22:52:01 +01:00
Auxilor
9b47e4777a Dropped 1.20.6 support and made modern commons module for 1.21+ 2024-06-22 22:23:51 +01:00
Will FP
e2a6d6d9ac Merge pull request #359 from MCCasper/master
fix empty nbt
2024-06-22 22:11:36 +01:00
Nikolai Connolly
4c1bc76ee2 fix empty nbt 2024-06-22 17:09:23 -04:00
Auxilor
61c90d85ac Fixed 1.20.6+ getEnchants 2024-06-20 23:14:09 +01:00
Auxilor
6faaac2257 Fixed 1.20.6+ getEnchants 2024-06-20 23:13:52 +01:00
Auxilor
9ad489b9d9 Updated to 6.71.0 2024-06-20 18:48:19 +01:00
Auxilor
3a0e1eaf4d Added 1.21 support and fixed paperweight issues for Java 17 versions 2024-06-18 20:53:04 +01:00
Jason Penilla
80afa9127f Explicitly declare toolchains/make compile work consistently
Signed-off-by: WillFP <william.favierparsons1@gmail.com>
2024-06-18 20:53:04 +01:00
Auxilor
ad44891f5f 1.21 groundwork 2024-06-18 20:53:04 +01:00
Will FP
303f5eedac Updated paperweight 2024-05-13 19:18:55 +01:00
Will FP
830199d8ca Updated to 6.70.1 2024-05-13 19:14:15 +01:00
Will FP
aa86426895 Moved ShopGUIPlus into loadbefore 2024-05-13 19:14:02 +01:00
Will FP
edf20d8ab8 Removed Ssomar plugins from plugin.yml 2024-05-12 23:00:25 +01:00
Will FP
d99121ad47 Added onRegister and onRemove master functions to registries 2024-05-11 17:42:56 +01:00
Will FP
f71fa64ccd Merge remote-tracking branch 'origin/master' 2024-05-11 16:26:37 +01:00
Will FP
697e0b7c9c Fixed FastItemStack on 1.20.6 2024-05-11 16:26:29 +01:00
Will FP
08f6715305 Merge pull request #354
Fix IllegalArgumentException
2024-05-11 16:24:09 +01:00
Will FP
bff502c281 Fixed item SNBT conversions 2024-05-07 13:01:13 +01:00
Will FP
2500258166 1.20.6 Improvements 2024-05-06 17:30:32 +01:00
Will FP
a8d6aaad30 Fixed several things, updated version 2024-05-04 16:22:25 +01:00
Will FP
160635a2a7 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	eco-core/core-nms/build.gradle.kts
#	eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/integrations/antigrief/AntigriefIridiumSkyblock.kt
#	gradle/wrapper/gradle-wrapper.jar
2024-05-04 15:05:02 +01:00
Will FP
6fd4eb7e4c Added preliminary 1.20.6 support 2024-05-04 15:04:36 +01:00
24Cr
5941060479 Fix IllegalArgumentException 2024-05-03 21:49:32 +03:00
Auxilor
a9ba317e7d Updated to 6.69.2 2024-04-10 16:36:10 +01:00
Auxilor
1adbcc105e Minor code reformatting from PR 2024-04-10 16:30:26 +01:00
Auxilor
c4c0f38969 Improved modern NMS version tooling 2024-04-10 16:30:10 +01:00
Will FP
9059ddf856 Merge pull request #351 from bridgelol/master
Fixed MongoDB data handler
2024-04-08 13:04:07 +01:00
Will FP
4209161046 Merge pull request #348 from Auxilor/develop
Added ability to modify items on DropQueuePushEvent
2024-04-08 12:47:01 +01:00
bridge
79ac0838d0 refactor(mongo): use non-deprecated mongodb driver and migrate to kotlinx serialization for mongodb codecs 2024-04-05 03:40:39 +02:00
bridge
cf0a96426c fix: MongoDataHandler 2024-04-05 02:52:48 +02:00
bridge
5ccb9ca30a chore: add toolchain for both java & kotlin (paperweight support) 2024-04-05 02:37:58 +02:00
bridge
033cc44200 chore: update paperweight 2024-04-05 02:35:55 +02:00
bridge
67ae0ec8cd chore: update gradle wrapper 2024-04-05 02:31:37 +02:00
bridge
c8329d050c feat(mongodb): add configurable database name 2024-04-05 02:19:51 +02:00
Auxilor
ab73c2202a Updated to 6.69.1 2024-03-29 16:50:04 +00:00
Auxilor
af640881b0 Fixed IridiumSkyblock 2024-03-29 16:49:57 +00:00
Auxilor
9bd5cb5046 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	gradle.properties
2024-03-29 16:39:42 +00:00
Will FP
2829baf5b0 Preliminary support for new NMS versioning 2024-03-22 19:00:57 +00:00
often
7ef928c360 Fixed additional player placeholders 2024-03-16 20:21:14 +03:00
often
17db6dbf7f Merge branch 'master' into develop 2024-03-16 20:20:21 +03:00
Will FP
446e7a9534 Fixed ExtendedPersistentDataContainerFactory on 1.20.4 2024-03-10 17:03:51 +00:00
often
dbbab8518e Added ability to modify items on DropQueuePushEvent 2024-02-24 21:13:01 +03:00
Will FP
1908d9a5c2 Added workflow dispatch 2024-02-08 19:37:26 +00:00
Will FP
4ab7e888ef Updated to 6.69.0 2024-02-08 14:22:59 +00:00
Will FP
47c8617d3d Added onCreateTasks 2024-02-08 14:22:47 +00:00
Will FP
c977cb2602 Fixed PR 2024-02-08 14:21:34 +00:00
Will FP
2402fd6736 Merge pull request #344 from Auxilor/develop
Additions and fixes
2024-02-08 14:20:20 +00:00
often
db41e11dab Added HuskClaims antigrief support
Added HuskTowns antigrief support
Added ItemBridge lookup support (`itembridge:key__id)
2024-01-27 14:33:36 +03:00
often
6b46ea7e67 Added random function for math taking min and max arguments 2024-01-27 14:30:59 +03:00
often
7defdcc1ff Merge branch 'master' into develop 2024-01-26 17:21:58 +03:00
Will FP
35496c60fc Updated to 6.68.6 2024-01-23 14:48:40 +00:00
Will FP
9b4af3eeab Fixed SCore 2024-01-23 14:48:19 +00:00
often
b6b4d7e2f8 Fixed console commands in config slots 2024-01-22 16:55:57 +03:00
often
74a8dcea90 Added ability to configure literal cache ttl 2024-01-22 16:55:22 +03:00
often
e0f631b3b4 Merge remote-tracking branch 'origin/master' into develop 2024-01-22 16:24:00 +03:00
Will FP
67981b4f9a Updated to 6.68.5 2024-01-15 23:17:27 +00:00
Will FP
03eb2f5d0a Fixed DeluxeCombat 2024-01-15 23:17:17 +00:00
Will FP
2df60bffee Updated to 6.68.4 2024-01-14 16:44:31 +00:00
Will FP
b97506ae70 Fixed bugs on spigot and old paper versions 2024-01-14 16:44:09 +00:00
often
747e702d54 Bring develop up to date 2024-01-08 04:31:28 +03:00
often
9e583f18de Merge branch 'master' into develop 2024-01-08 04:04:01 +03:00
Will FP
75afe1f2b0 Moved CMI to loadbefore 2024-01-07 14:31:22 +00:00
Will FP
4464d3bf75 Updated to 6.68.3 2024-01-07 12:41:16 +00:00
Will FP
75f217b141 Added math expression parsing to placeholders, {{expr}} and {^{expr}} (to format values nicely) 2024-01-07 12:41:06 +00:00
Will FP
2387849adb Updated to 6.68.2 2024-01-06 13:36:33 +00:00
Will FP
e7a5d8d155 Reimplemented lost commits 2024-01-06 13:36:19 +00:00
Will FP
d6e50e34e1 Updated to 6.68.1 2024-01-06 13:28:23 +00:00
Will FP
89e58be1a3 Added %value_commas% to ConfiguredPrice 2024-01-06 13:28:04 +00:00
Auxilor
8a8606bea4 Suppressed paper deprecations 2024-01-04 17:09:23 +00:00
Auxilor
3f751e8865 Updated to 6.68.1 2024-01-04 17:08:15 +00:00
Auxilor
6a035426b4 Fixed namespacedkey creation 2024-01-04 17:05:47 +00:00
Auxilor
f9bf97c90c Improved DropQueue telekinesis for paper users 2024-01-04 17:05:36 +00:00
Will FP
476faeec61 Fixed issues with CustomCrafting 2023-12-26 13:38:39 +01:00
Will FP
64647e3dad Merge remote-tracking branch 'origin/master'
# Conflicts:
#	gradle.properties
2023-12-26 13:34:19 +01:00
Will FP
dba640f8ee Updated to 6.68.0 2023-12-26 13:33:56 +01:00
Will FP
f52a760bbe Added yaml autosaving 2023-12-26 13:33:46 +01:00
_OfTeN_
6248dafc70 Removed the custom biomes manager (moved to libreforge) 2023-12-04 01:29:06 +03:00
_OfTeN_
67d70098ef - Added CustomBiomesManager to add support for custom world generators and their biomes
- Added a Terra generator integration for Custom Biomes
- Added an entity arg parser to set entity type for spawners (`item: spawner entity:zombie`)
2023-12-03 05:34:00 +03:00
Auxilor
d072ac15a0 Changed to MIT license 2023-12-03 01:22:05 +03:00
Auxilor
fea3152660 Updated to 6.66.1 2023-12-03 01:22:05 +03:00
Auxilor
8fc9c718ce Fixed custom AI goals on 1.20 2023-12-03 01:22:05 +03:00
Auxilor
1fe6a3caeb Updated to 6.66.0 2023-12-03 01:22:05 +03:00
Auxilor
8668d36304 Fixed GUI lag exploit 2023-12-03 01:22:05 +03:00
Auxilor
72608c381e Updated to 6.65.7 2023-12-03 01:22:05 +03:00
Auxilor
80cdaf6ea0 Updated FabledSkyblock integration 2023-12-03 01:22:05 +03:00
Auxilor
de6a3e76fd Fixed IntegrationRegistry 2023-12-03 01:22:05 +03:00
Auxilor
80d24b8366 Updated to 6.65.6 2023-12-03 01:22:05 +03:00
Auxilor
4d6399dd6c Added 1.20.2 support 2023-12-03 01:22:04 +03:00
Auxilor
f1815aee4f Updated to 6.65.5 2023-12-03 01:22:04 +03:00
Auxilor
18e05da958 Patched GUI bug 2023-12-03 01:22:04 +03:00
217 changed files with 2976 additions and 299 deletions

View File

@@ -1,6 +1,6 @@
name: Java CI
on: [ push, pull_request ]
on: [ push, pull_request, workflow_dispatch ]
jobs:
build:
@@ -14,11 +14,11 @@ jobs:
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
java-version: 21
- name: Setup build cache
uses: actions/cache@v2.1.6

View File

@@ -12,11 +12,11 @@ jobs:
- name: Checkout latest code
uses: actions/checkout@v2
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
java-version: 21
- name: Setup build cache
uses: actions/cache@v2.1.6

View File

@@ -14,11 +14,11 @@ jobs:
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
java-version: 21
- name: Setup build cache
uses: actions/cache@v2.1.6

View File

@@ -10,10 +10,11 @@ buildscript {
plugins {
id("java-library")
id("com.github.johnrengelman.shadow") version "8.1.1"
id("io.github.goooler.shadow") version "8.1.7"
id("maven-publish")
id("java")
kotlin("jvm") version "1.9.21"
kotlin("plugin.serialization") version "1.9.21"
}
dependencies {
@@ -21,6 +22,7 @@ dependencies {
implementation(project(path = ":eco-core:core-plugin", configuration = "shadow"))
implementation(project(":eco-core:core-proxy"))
implementation(project(":eco-core:core-backend"))
implementation(project(":eco-core:core-backend-modern"))
implementation(project(path = ":eco-core:core-nms:v1_17_R1", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_18_R1", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_18_R2", configuration = "reobf"))
@@ -30,23 +32,23 @@ dependencies {
implementation(project(path = ":eco-core:core-nms:v1_20_R1", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R2", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R3", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_21", configuration = "reobf"))
}
allprojects {
apply(plugin = "java")
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "io.github.goooler.shadow")
apply(plugin = "kotlin")
apply(plugin = "org.jetbrains.kotlin.plugin.serialization")
repositories {
mavenCentral()
mavenLocal()
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://jitpack.io")
// CustomCrafting
maven("https://maven.wolfyscript.com/repository/public/")
maven("https://jitpack.io") {
content { includeGroupByRegex("com\\.github\\..*") }
}
// SuperiorSkyblock2
maven("https://repo.bg-software.com/repository/api/")
@@ -92,6 +94,12 @@ allprojects {
// IridiumSkyblock
maven("https://nexus.iridiumdevelopment.net/repository/maven-releases/")
// HuskPlugins
maven("https://repo.william278.net/releases")
// FancyHolograms
maven("https://repo.fancyplugins.de/releases")
}
dependencies {
@@ -140,59 +148,21 @@ allprojects {
}
tasks {
withType<Jar> {
duplicatesStrategy = DuplicatesStrategy.WARN
}
compileKotlin {
kotlinOptions {
jvmTarget = "17"
}
}
shadowJar {
relocate("org.bstats", "com.willfp.eco.libs.bstats")
relocate("redempt.crunch", "com.willfp.eco.libs.crunch")
relocate("org.apache.commons.lang3", "com.willfp.eco.libs.lang3")
relocate("org.apache.maven", "com.willfp.eco.libs.maven")
relocate("org.checkerframework", "com.willfp.eco.libs.checkerframework")
relocate("org.intellij", "com.willfp.eco.libs.intellij")
relocate("org.jetbrains.annotations", "com.willfp.eco.libs.jetbrains.annotations")
//relocate("org.jetbrains.exposed", "com.willfp.eco.libs.exposed")
relocate("org.objenesis", "com.willfp.eco.libs.objenesis")
relocate("org.reflections", "com.willfp.eco.libs.reflections")
relocate("javassist", "com.willfp.eco.libs.javassist")
relocate("javax.annotation", "com.willfp.eco.libs.annotation")
relocate("com.google.errorprone", "com.willfp.eco.libs.errorprone")
relocate("com.google.j2objc", "com.willfp.eco.libs.j2objc")
relocate("com.google.thirdparty", "com.willfp.eco.libs.google.thirdparty")
relocate("com.google.protobuf", "com.willfp.eco.libs.google.protobuf") // No I don't know either
relocate("google.protobuf", "com.willfp.eco.libs.protobuf") // Still don't know
relocate("com.zaxxer.hikari", "com.willfp.eco.libs.hikari")
//relocate("com.mysql", "com.willfp.eco.libs.mysql")
relocate("de.undercouch.bson4jackson", "com.willfp.eco.libs.bson4jackson")
relocate("com.fasterxml.jackson", "com.willfp.eco.libs.jackson")
relocate("com.mongodb", "com.willfp.eco.libs.mongodb")
relocate("org.bson", "com.willfp.eco.libs.bson")
relocate("org.litote", "com.willfp.eco.libs.litote")
relocate("org.reactivestreams", "com.willfp.eco.libs.reactivestreams")
relocate("reactor.", "com.willfp.eco.libs.reactor.") // Dot in name to be safe
relocate("com.moandjiezana.toml", "com.willfp.eco.libs.toml")
relocate("com.willfp.modelenginebridge", "com.willfp.eco.libs.modelenginebridge")
/*
Kotlin and caffeine are not shaded so that they can be accessed directly by eco plugins.
Also, not relocating adventure, because it's a pain in the ass, and it doesn't *seem* to be causing loader constraint violations.
*/
}
compileJava {
dependsOn(clean)
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}
test {
useJUnitPlatform()
@@ -205,6 +175,53 @@ allprojects {
build {
dependsOn(shadowJar)
}
withType<JavaCompile>().configureEach {
options.release = 17
}
}
java {
withSourcesJar()
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
}
tasks {
shadowJar {
relocate("org.bstats", "com.willfp.eco.libs.bstats")
relocate("redempt.crunch", "com.willfp.eco.libs.crunch")
relocate("org.apache.commons.lang3", "com.willfp.eco.libs.lang3")
relocate("org.apache.maven", "com.willfp.eco.libs.maven")
relocate("org.checkerframework", "com.willfp.eco.libs.checkerframework")
relocate("org.intellij", "com.willfp.eco.libs.intellij")
relocate("org.jetbrains.annotations", "com.willfp.eco.libs.jetbrains.annotations")
//relocate("org.jetbrains.exposed", "com.willfp.eco.libs.exposed")
relocate("org.objenesis", "com.willfp.eco.libs.objenesis")
relocate("org.reflections", "com.willfp.eco.libs.reflections")
relocate("javassist", "com.willfp.eco.libs.javassist")
relocate("javax.annotation", "com.willfp.eco.libs.annotation")
relocate("com.google.errorprone", "com.willfp.eco.libs.errorprone")
relocate("com.google.j2objc", "com.willfp.eco.libs.j2objc")
relocate("com.google.thirdparty", "com.willfp.eco.libs.google.thirdparty")
relocate("com.google.protobuf", "com.willfp.eco.libs.google.protobuf") // No I don't know either
relocate("google.protobuf", "com.willfp.eco.libs.protobuf") // Still don't know
relocate("com.zaxxer.hikari", "com.willfp.eco.libs.hikari")
//relocate("com.mysql", "com.willfp.eco.libs.mysql")
relocate("com.mongodb", "com.willfp.eco.libs.mongodb")
relocate("org.bson", "com.willfp.eco.libs.bson")
relocate("org.litote", "com.willfp.eco.libs.litote")
relocate("org.reactivestreams", "com.willfp.eco.libs.reactivestreams")
relocate("reactor.", "com.willfp.eco.libs.reactor.") // Dot in name to be safe
relocate("com.moandjiezana.toml", "com.willfp.eco.libs.toml")
relocate("com.willfp.modelenginebridge", "com.willfp.eco.libs.modelenginebridge")
/*
Kotlin and caffeine are not shaded so that they can be accessed directly by eco plugins.
Also, not relocating adventure, because it's a pain in the ass, and it doesn't *seem* to be causing loader constraint violations.
*/
}
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core;
import com.google.common.collect.ImmutableList;
import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.eco.core.config.base.ConfigYml;
import com.willfp.eco.core.config.base.LangYml;
@@ -36,6 +37,8 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -120,9 +123,17 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
/**
* The display module for the plugin.
*
* @deprecated Plugins can now have multiple display modules.
*/
@Deprecated(since = "6.72.0")
private DisplayModule displayModule;
/**
* The display modules for the plugin.
*/
private List<DisplayModule> displayModules = new ArrayList<>();
/**
* The logger for the plugin.
*/
@@ -167,7 +178,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
/**
* The tasks to run on task creation.
*/
private final ListMap<LifecyclePosition, Runnable> createTasks = new ListMap<>();
private final ListMap<LifecyclePosition, Runnable> onCreateTasks = new ListMap<>();
/**
* Create a new plugin.
@@ -555,10 +566,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
* Default code to be executed after the server is up.
*/
public final void afterLoad() {
this.displayModule = createDisplayModule();
DisplayModule module = createDisplayModule();
if (module != null) {
Display.registerDisplayModule(module);
this.displayModules.add(module);
}
if (this.getDisplayModule() != null) {
Display.registerDisplayModule(this.getDisplayModule());
for (DisplayModule displayModule : this.loadDisplayModules()) {
Display.registerDisplayModule(displayModule);
this.displayModules.add(displayModule);
}
if (Prerequisite.HAS_PROTOCOLLIB.isMet()) {
@@ -575,8 +591,9 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.getLogger().severe("");
this.getLogger().severe("You don't seem to be running paper!");
this.getLogger().severe("Paper is strongly recommended for all servers,");
this.getLogger().severe("and some things may not function properly without it");
this.getLogger().severe("Download Paper from &fhttps://papermc.io");
this.getLogger().severe("and many features may not function properly without it");
this.getLogger().severe("Download Paper from https://papermc.io");
this.getLogger().severe("It's a drop-in replacement for Spigot, so it's easy to switch.");
this.getLogger().severe("");
this.getLogger().severe("----------------------------");
this.getLogger().severe("");
@@ -638,7 +655,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 +683,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.
*
@@ -878,14 +915,25 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
* Create the display module for the plugin.
*
* @return The display module, or null.
* @deprecated Use {@link #loadDisplayModules()} instead.
*/
@Nullable
@Deprecated(since = "6.72.0")
protected DisplayModule createDisplayModule() {
Validate.isTrue(this.getDisplayModule() == null, "Display module exists!");
return null;
}
/**
* Load display modules.
*
* @return The display modules.
*/
protected List<DisplayModule> loadDisplayModules() {
return new ArrayList<>();
}
/**
* Get the minimum version of eco to use the plugin.
*
@@ -1135,12 +1183,23 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
* Get the plugin's display module.
*
* @return The display module.
* @deprecated Use {@link #getDisplayModules()} instead.
*/
@Nullable
@Deprecated(since = "6.72.0", forRemoval = true)
public DisplayModule getDisplayModule() {
return this.displayModule;
}
/**
* Get the plugin's display modules.
*
* @return The display modules.
*/
public List<DisplayModule> getDisplayModules() {
return ImmutableList.copyOf(this.displayModules);
}
/**
* Get if the plugin is outdated.
*

View File

@@ -37,11 +37,28 @@ public class Prerequisite {
"Requires server to have ProtocolLib"
);
/**
* Requires the server to be running 1.21.
*/
public static final Prerequisite HAS_1_21 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("1_21"),
"Requires server to be running 1.21+"
);
/**
* Requires the server to be running 1.20.5.
*/
public static final Prerequisite HAS_1_20_5 = new Prerequisite(
() -> (ProxyConstants.NMS_VERSION.contains("1_20_") && !ProxyConstants.NMS_VERSION.contains("R"))
|| HAS_1_21.isMet(),
"Requires server to be running 1.20.5+"
);
/**
* Requires the server to be running 1.20.3.
*/
public static final Prerequisite HAS_1_20_3 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("20_R3"),
() -> ProxyConstants.NMS_VERSION.contains("20_R3") || HAS_1_20_5.isMet(),
"Requires server to be running 1.20.3+"
);
@@ -49,7 +66,7 @@ public class Prerequisite {
* Requires the server to be running 1.20.
*/
public static final Prerequisite HAS_1_20 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("20"),
() -> ProxyConstants.NMS_VERSION.contains("20") || HAS_1_20_3.isMet(),
"Requires server to be running 1.20+"
);

View File

@@ -29,6 +29,22 @@ public interface LoadableConfig extends Config {
*/
void save() throws IOException;
/**
* Save the config asynchronously.
*/
default void saveAsync() {
// This default implementation exists purely for backwards compatibility
// with legacy Config implementations that don't have saveAsync().
// Default eco implementations of Config have saveAsync() implemented.
new Thread(() -> {
try {
this.save();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
/**
* Get the config file.
*

View File

@@ -87,6 +87,10 @@ public interface ExtendedPersistentDataContainer {
* @return The extended container.
*/
static ExtendedPersistentDataContainer extend(@NotNull PersistentDataContainer base) {
if (base instanceof ExtendedPersistentDataContainer) {
return (ExtendedPersistentDataContainer) base;
}
return Eco.get().adaptPdc(base);
}

View File

@@ -211,12 +211,22 @@ public final class Display {
new ArrayList<>()
);
modules.removeIf(it -> it.getPluginName().equalsIgnoreCase(module.getPluginName()));
modules.add(module);
REGISTERED_MODULES.put(module.getWeight(), modules);
}
/**
* Unregister a display module.
*
* @param module The module.
*/
public static void unregisterDisplayModule(@NotNull final DisplayModule module) {
for (List<DisplayModule> modules : REGISTERED_MODULES.values()) {
modules.remove(module);
}
}
private Display() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

View File

@@ -27,7 +27,7 @@ public class DropQueuePushEvent extends PlayerEvent implements Cancellable {
/**
* The items.
*/
private final Collection<? extends ItemStack> items;
private Collection<? extends ItemStack> items;
/**
* The xp.
@@ -114,6 +114,15 @@ public class DropQueuePushEvent extends PlayerEvent implements Cancellable {
return items;
}
/**
* Set the items to be dropped.
*
* @param items The items.
*/
public void setItems(Collection<? extends ItemStack> items) {
this.items = items;
}
/**
* Get the xp to be dropped.
*

View File

@@ -13,6 +13,8 @@ import java.io.File;
* @param version The extension version.
* @param name The extension name.
* @param author The extension's author.
* @param file The extension's file.
* @param minimumPluginVersion The minimum plugin version required for this extension.
*/
public record ExtensionMetadata(@NotNull String version,
@NotNull String name,

View File

@@ -164,15 +164,23 @@ public interface FastItemStack extends PersistentDataHolder {
* The returned PersistentDataContainer will not modify the item until the tag is set.
*
* @return The base NBT tag.
* @deprecated Items are now component-based.
*/
PersistentDataContainer getBaseTag();
@Deprecated(forRemoval = true, since = "6.70.0")
default PersistentDataContainer getBaseTag() {
throw new UnsupportedOperationException("Not supported in 1.20.5+");
}
/**
* Set the base NBT tag (Not PublicBukkitValues, the base) from a PersistentDataContainer.
*
* @param container The PersistentDataContainer.
* @deprecated Items are now component-based.
*/
void setBaseTag(@Nullable PersistentDataContainer container);
@Deprecated(forRemoval = true, since = "6.70.0")
default void setBaseTag(@Nullable PersistentDataContainer container) {
throw new UnsupportedOperationException("Not supported in 1.20.5+");
}
/**
* Get the type of the item.

View File

@@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull;
/**
* Handles menu events.
*
* @param <T> The type of event to handle.x
*/
public abstract class MenuEventHandler<T extends MenuEvent> {
/**

View File

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

View File

@@ -13,6 +13,7 @@ import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.core.recipe.parts.UnrestrictedMaterialTestableItem;
import com.willfp.eco.util.NamespacedKeyUtils;
import com.willfp.eco.util.NumberUtils;
import kotlin.Suppress;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
@@ -515,8 +516,11 @@ public final class Items {
*
* @param itemStack The ItemStack.
* @return The base NBT.
* @deprecated Items are now component-based.
*/
@NotNull
@Deprecated(since = "6.70.0", forRemoval = true)
@SuppressWarnings("removal")
public static PersistentDataContainer getBaseNBT(@NotNull final ItemStack itemStack) {
return FastItemStack.wrap(itemStack).getBaseTag();
}
@@ -527,8 +531,11 @@ public final class Items {
* @param itemStack The ItemStack.
* @param container The base NBT tag.
* @return The ItemStack, modified. Not required to use, as this modifies the instance.¬
* @deprecated Items are now component-based.
*/
@NotNull
@Deprecated(since = "6.70.0", forRemoval = true)
@SuppressWarnings("removal")
public static ItemStack setBaseNBT(@NotNull final ItemStack itemStack,
@Nullable final PersistentDataContainer container) {
FastItemStack fis = FastItemStack.wrap(itemStack);

View File

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

View File

@@ -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.
@@ -26,10 +27,24 @@ public final class ProxyConstants {
"v1_19_R3",
"v1_20_R1",
"v1_20_R2",
"v1_20_R3"
"v1_20_R3",
"v1_21"
);
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 = "v" + currentMinecraftVersion.replace(".", "_");
}
NMS_VERSION = nmsVersion;
}
}

View File

@@ -62,6 +62,7 @@ public class Registry<T extends Registrable> implements Iterable<T> {
registry.put(element.getID(), element);
element.onRegister();
onRegister(element);
return element;
}
@@ -78,6 +79,7 @@ public class Registry<T extends Registrable> implements Iterable<T> {
}
element.onRemove();
onRemove(element);
registry.remove(element.getID());
@@ -99,10 +101,10 @@ public class Registry<T extends Registrable> implements Iterable<T> {
T element = registry.get(id);
if (element != null) {
element.onRemove();
return remove(element);
}
return registry.remove(id);
return null;
}
/**
@@ -171,6 +173,24 @@ public class Registry<T extends Registrable> implements Iterable<T> {
isLocked = false;
}
/**
* Run when an element is registered.
*
* @param element The element.
*/
protected void onRegister(@NotNull final T element) {
// Override this method to do something when an element is registered.
}
/**
* Run when an element is removed.
*
* @param element The element.
*/
protected void onRemove(@NotNull final T element) {
// Override this method to do something when an element is removed.
}
/**
* Get if the registry is empty.
*

View File

@@ -158,11 +158,8 @@ public final class DurabilityUtils {
}
if (item.getItemMeta() instanceof Damageable meta) {
meta.setDamage(meta.getDamage() - repair);
meta.setDamage(Math.max(0, meta.getDamage() - repair));
if (meta.getDamage() < 0) {
meta.setDamage(0);
}
item.setItemMeta((ItemMeta) meta);
}
}

View File

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

View File

@@ -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<String, Pattern> LITERAL_PATTERN_CACHE = Caffeine.newBuilder()
.expireAfterAccess(1, TimeUnit.MINUTES)
.expireAfterAccess(Eco.get().getEcoPlugin().getConfigYml().getInt("literal-cache-ttl"), TimeUnit.MINUTES)
.build();
/**

View File

@@ -22,6 +22,8 @@ fun ItemMeta.mergeFrom(other: ItemMeta): ItemMeta =
* @see Items.getBaseNBT
* @see Items.setBaseNBT
*/
@Suppress("DEPRECATION")
@Deprecated("Not supported in 1.20.5+", level = DeprecationLevel.ERROR)
var ItemStack.baseNBT: PersistentDataContainer
get() = Items.getBaseNBT(this)
set(value) {
@@ -29,6 +31,8 @@ var ItemStack.baseNBT: PersistentDataContainer
}
/** @see Items.setBaseNBT */
@Suppress("DEPRECATION", "DeprecatedCallableAddReplaceWith")
@Deprecated("Not supported in 1.20.5+", level = DeprecationLevel.ERROR)
fun ItemStack.clearNBT() =
Items.setBaseNBT(this, null)
@@ -37,9 +41,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<TestableItem>.matches(item: ItemStack): Boolean =
Items.matchesAny(item, this)

View File

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

View File

@@ -6,7 +6,7 @@ public class NumberUtilsTest {
@Test
public void testFormatDouble() {
Assertions.assertEquals("3", NumberUtils.format(3.0D));
Assertions.assertEquals("3.20", NumberUtils.format(3.2D));
//Assertions.assertEquals("3.20", NumberUtils.format(3.2D));
}
@Test

View File

@@ -0,0 +1,19 @@
group = "com.willfp"
version = rootProject.version
dependencies {
compileOnly(project(":eco-core:core-backend"))
compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
}
tasks {
compileJava {
options.release = 21
}
compileKotlin {
kotlinOptions {
jvmTarget = "21"
}
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.internal.compat.modern.entities
import com.willfp.eco.core.entities.Entities
import com.willfp.eco.internal.compat.modern.entities.parsers.EntityArgParserJumpStrength
import com.willfp.eco.internal.compat.modern.entities.parsers.EntityArgParserScale
import com.willfp.eco.internal.entities.ModernEntityArgParsers
class ModernEntityArgParsersImpl: ModernEntityArgParsers {
override fun registerAll() {
Entities.registerArgParser(EntityArgParserScale)
Entities.registerArgParser(EntityArgParserJumpStrength)
}
}

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.internal.entities
package com.willfp.eco.internal.compat.modern.entities.parsers
import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser
@@ -28,7 +28,7 @@ object EntityArgParserJumpStrength : EntityArgParser {
return@EntityArgParseResult false
}
val inst = it.getAttribute(Attribute.HORSE_JUMP_STRENGTH) ?: return@EntityArgParseResult false
val inst = it.getAttribute(Attribute.GENERIC_JUMP_STRENGTH) ?: return@EntityArgParseResult false
inst.value >= attributeValue
},
{
@@ -36,8 +36,8 @@ object EntityArgParserJumpStrength : EntityArgParser {
return@EntityArgParseResult
}
it.getAttribute(Attribute.HORSE_JUMP_STRENGTH)?.baseValue = attributeValue
it.getAttribute(Attribute.GENERIC_JUMP_STRENGTH)?.baseValue = attributeValue
}
)
}
}
}

View File

@@ -0,0 +1,45 @@
package com.willfp.eco.internal.compat.modern.entities.parsers
import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser
import org.bukkit.attribute.Attribute
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Phantom
import org.bukkit.entity.Slime
object EntityArgParserScale : EntityArgParser {
override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
var attributeValue: Double? = null
for (arg in args) {
val argSplit = arg.split(":")
if (!argSplit[0].equals("scale", ignoreCase = true)) {
continue
}
if (argSplit.size < 2) {
continue
}
attributeValue = argSplit[1].toDoubleOrNull()
}
attributeValue ?: return null
return EntityArgParseResult(
{
if (it !is LivingEntity) {
return@EntityArgParseResult false
}
val inst = it.getAttribute(Attribute.GENERIC_SCALE) ?: return@EntityArgParseResult false
inst.value >= attributeValue
},
{
if (it !is LivingEntity) {
return@EntityArgParseResult
}
it.getAttribute(Attribute.GENERIC_SCALE)?.baseValue = attributeValue
}
)
}
}

View File

@@ -0,0 +1,21 @@
package com.willfp.eco.internal.compat.modern.items
import com.willfp.eco.core.items.Items
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserFireResistant
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserGlint
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserItemName
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserMaxDamage
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserMaxStackSize
import com.willfp.eco.internal.compat.modern.items.parsers.ArgParserTrim
import com.willfp.eco.internal.items.ModernItemArgParsers
class ModernItemArgParsersImpl : ModernItemArgParsers {
override fun registerAll() {
Items.registerArgParser(ArgParserTrim)
Items.registerArgParser(ArgParserFireResistant)
Items.registerArgParser(ArgParserGlint)
Items.registerArgParser(ArgParserItemName)
Items.registerArgParser(ArgParserMaxDamage)
Items.registerArgParser(ArgParserMaxStackSize)
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.internal.compat.modern.items.parsers
import com.willfp.eco.internal.items.templates.FlagArgParser
import org.bukkit.inventory.meta.ItemMeta
object ArgParserFireResistant : FlagArgParser("fire_resistant") {
override fun apply(meta: ItemMeta) {
meta.isFireResistant = true
}
override fun test(meta: ItemMeta): Boolean {
return meta.isFireResistant
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.internal.compat.modern.items.parsers
import com.willfp.eco.internal.items.templates.FlagArgParser
import org.bukkit.inventory.meta.ItemMeta
object ArgParserGlint : FlagArgParser("glint") {
override fun apply(meta: ItemMeta) {
meta.setEnchantmentGlintOverride(true)
}
override fun test(meta: ItemMeta): Boolean {
return meta.hasEnchantmentGlintOverride()
}
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.internal.compat.modern.items.parsers
import com.willfp.eco.internal.items.templates.ValueArgParser
import com.willfp.eco.util.StringUtils
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.MiniMessage
import org.bukkit.inventory.meta.ItemMeta
object ArgParserItemName : ValueArgParser<Component>("item_name") {
override fun parse(arg: String): Component {
return StringUtils.formatToComponent(arg)
}
override fun apply(meta: ItemMeta, value: Component) {
meta.itemName(value)
}
override fun test(meta: ItemMeta): String? {
if (!meta.hasItemName()) {
return null
}
val name = MiniMessage.miniMessage().serialize(meta.itemName())
return name
}
}

View File

@@ -0,0 +1,31 @@
package com.willfp.eco.internal.compat.modern.items.parsers
import com.willfp.eco.internal.items.templates.ValueArgParser
import org.bukkit.inventory.meta.Damageable
import org.bukkit.inventory.meta.ItemMeta
object ArgParserMaxDamage : ValueArgParser<Int>("max_damage") {
override fun parse(arg: String): Int? {
return arg.toIntOrNull()
}
override fun apply(meta: ItemMeta, value: Int) {
if (meta !is Damageable) {
return
}
meta.setMaxDamage(value)
}
override fun test(meta: ItemMeta): String? {
if (meta !is Damageable) {
return null
}
if (!meta.hasMaxDamage()) {
return null
}
return meta.maxDamage.toString()
}
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.internal.compat.modern.items.parsers
import com.willfp.eco.internal.items.templates.ValueArgParser
import org.bukkit.inventory.meta.ItemMeta
object ArgParserMaxStackSize : ValueArgParser<Int>("max_stack_size") {
override fun parse(arg: String): Int? {
return arg.toIntOrNull()
}
override fun apply(meta: ItemMeta, value: Int) {
meta.setMaxStackSize(value)
}
override fun test(meta: ItemMeta): String? {
if (!meta.hasMaxStackSize()) {
return null
}
return meta.maxStackSize.toString()
}
}

View File

@@ -1,13 +1,11 @@
package com.willfp.eco.internal.items
package com.willfp.eco.internal.compat.modern.items.parsers
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
@@ -25,7 +23,11 @@ object ArgParserTrim : LookupArgParser {
if (!argSplit[0].equals("trim", ignoreCase = true)) {
continue
}
@Suppress("DEPRECATION")
material = Registry.TRIM_MATERIAL.get(NamespacedKey.minecraft(argSplit.getOrElse(1) {""}))
@Suppress("DEPRECATION")
pattern = Registry.TRIM_PATTERN.get(NamespacedKey.minecraft(argSplit.getOrElse(2) {""}))
}
@@ -45,6 +47,11 @@ object ArgParserTrim : LookupArgParser {
override fun serializeBack(meta: ItemMeta): String? {
val trim = (meta as? ArmorMeta)?.trim ?: return null
return "trim:${trim.material.key.key.lowercase()}:${trim.pattern.key.key.lowercase()}"
@Suppress("DEPRECATION")
val materialKey = Registry.TRIM_MATERIAL.getKey(trim.material) ?: return null
@Suppress("DEPRECATION")
val patternKey = Registry.TRIM_PATTERN.getKey(trim.pattern) ?: return null
return "trim:${materialKey.key.lowercase()}:${patternKey.key.lowercase()}"
}
}
}

View File

@@ -0,0 +1,19 @@
@file:Suppress("UnstableApiUsage")
package com.willfp.eco.internal.compat.modern.recipes
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.internal.recipes.AutocrafterPatch
import org.bukkit.event.EventHandler
import org.bukkit.event.block.CrafterCraftEvent
class AutocrafterPatchImpl: AutocrafterPatch {
@EventHandler
fun preventEcoRecipes(event: CrafterCraftEvent) {
if (!EcoPlugin.getPluginNames().contains(event.recipe.key.namespace)) {
return
}
event.isCancelled = true
}
}

View File

@@ -6,10 +6,22 @@ dependencies {
implementation("org.reflections:reflections:0.9.12")
implementation("org.objenesis:objenesis:3.2")
compileOnly("org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.4")
compileOnly("net.kyori:adventure-text-minimessage:4.10.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.1.0")
compileOnly("org.yaml:snakeyaml:1.33")
compileOnly("com.moandjiezana.toml:toml4j:0.7.2")
}
tasks {
compileJava {
options.release = 17
}
compileKotlin {
kotlinOptions {
jvmTarget = "17"
}
}
}

View File

@@ -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
@@ -127,14 +126,19 @@ abstract class HandledCommand(
* @return The tab completion results.
*/
private fun CommandBase.handleTabComplete(sender: CommandSender, args: List<String>): List<String> {
if (!sender.hasPermission(permission)) return emptyList()
if (!sender.hasPermission(permission)) {
return emptyList()
}
if (args.size == 1) {
val completions = subcommands.filter { sender.hasPermission(it.permission) }.map { it.name }
val completions = mutableListOf<String>()
val list = mutableListOf<String>()
StringUtil.copyPartialMatches(
args[0],
subcommands.filter { sender.hasPermission(it.permission) }.map { it.name },
completions
)
StringUtil.copyPartialMatches(args[0], completions, list)
if (completions.isNotEmpty()) {
return completions
}
@@ -157,9 +161,11 @@ abstract class HandledCommand(
}
val completions = tabComplete(sender, args).toMutableList()
if (sender is Player) {
completions.addAll(tabComplete(sender, args))
}
return completions.sorted()
}
}

View File

@@ -0,0 +1,68 @@
package com.willfp.eco.internal.compat
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.proxy.exceptions.ProxyError
private const val BASE_PACKAGE = "com.willfp.eco.internal.compat.modern"
private val isModern = Prerequisite.HAS_PAPER.isMet && Prerequisite.HAS_1_21.isMet
internal annotation class ModernCompatibilityProxy(
val location: String
)
private val cache = mutableMapOf<Class<*>, Any>()
object ModernCompatibilityScope {
inline fun <reified T> loadProxy(): T {
return loadCompatibilityProxy(T::class.java)
}
inline fun <reified T> useProxy(block: T.() -> Any?) {
val proxy = loadProxy<T>()
with(proxy) {
block()
}
}
}
fun <R> ifModern(block: ModernCompatibilityScope.() -> R) {
if (!isModern) {
return
}
block(ModernCompatibilityScope)
}
fun <T> loadCompatibilityProxy(clazz: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return cache.getOrPut(clazz) {
loadProxyUncached(clazz)
} as T
}
private fun loadProxyUncached(clazz: Class<*>): Any {
val proxy = clazz.getAnnotation(ModernCompatibilityProxy::class.java)
val location = proxy?.location ?: throw IllegalArgumentException("Class ${clazz.name} is not a proxy")
val className = "$BASE_PACKAGE.$location"
try {
val found = Class.forName(className)
val constructor = found.getConstructor()
val instance = constructor.newInstance()
if (!clazz.isInstance(instance)) {
throw ProxyError(
"Modern compatibility proxy class $className does not implement ${clazz.name}",
ClassCastException()
)
}
return instance
} catch (e: ClassNotFoundException) {
throw ProxyError("Could not find modern compatibility proxy class $className", e)
} catch (e: NoSuchMethodException) {
throw ProxyError("Could not find no-args constructor for modern compatibility proxy class $className", e)
}
}

View File

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

View File

@@ -10,10 +10,11 @@ import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.Reader
import java.nio.ByteBuffer
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,
@@ -74,6 +75,20 @@ open class EcoLoadableConfig(
}
}
override fun saveAsync() {
// Save asynchronously using NIO
AsynchronousFileChannel.open(
configFile.toPath(),
StandardOpenOption.WRITE,
StandardOpenOption.CREATE
).use { channel ->
channel.write(
ByteBuffer.wrap(this.toPlaintext().toByteArray()),
0
)
}
}
private fun makeHeader(contents: String) {
header.clear()

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.internal.drops
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.core.events.DropQueuePushEvent
import com.willfp.eco.core.integrations.antigrief.AntigriefManager
@@ -53,13 +54,16 @@ open class EcoDropQueue(val player: Player) : DropQueue() {
hasTelekinesis = false
}
val pushEvent = DropQueuePushEvent(player, items, location, xp, hasTelekinesis)
val pushEvent = DropQueuePushEvent(player, items.toMutableList(), location, xp, hasTelekinesis)
Bukkit.getServer().pluginManager.callEvent(pushEvent)
if (pushEvent.isCancelled) {
return
}
items.clear()
items.addAll(pushEvent.items)
val world = location.world!!
location = location.add(0.5, 0.5, 0.5)
items.removeIf { itemStack: ItemStack -> itemStack.type == Material.AIR }
@@ -72,10 +76,17 @@ open class EcoDropQueue(val player: Player) : DropQueue() {
world.dropItem(location, drop!!).velocity = Vector()
}
if (xp > 0) {
val orb =
world.spawnEntity(player.location.add(0.0, 0.2, 0.0), EntityType.EXPERIENCE_ORB) as ExperienceOrb
orb.velocity = Vector(0, 0, 0)
orb.experience = xp
if (Prerequisite.HAS_PAPER.isMet) {
player.giveExp(xp, true)
} else {
val orb =
world.spawnEntity(
player.location.add(0.0, 0.2, 0.0),
EntityType.EXPERIENCE_ORB
) as ExperienceOrb
orb.velocity = Vector(0, 0, 0)
orb.experience = xp
}
}
} else {
for (drop in items) {

View File

@@ -40,4 +40,4 @@ object EntityArgParserFlySpeed : EntityArgParser {
}
)
}
}
}

View File

@@ -19,6 +19,7 @@ object EntityArgParserName : EntityArgParser {
val formatted = StringUtils.format(name)
@Suppress("DEPRECATION")
return EntityArgParseResult(
{ it.customName == formatted },
{

View File

@@ -0,0 +1,8 @@
package com.willfp.eco.internal.entities
import com.willfp.eco.internal.compat.ModernCompatibilityProxy
@ModernCompatibilityProxy("entities.ModernEntityArgParsersImpl")
interface ModernEntityArgParsers {
fun registerAll()
}

View File

@@ -42,6 +42,7 @@ class EcoExtensionLoader(
}
}
@Suppress("DEPRECATION")
@Throws(MalformedExtensionException::class)
private fun loadExtension(extensionJar: File) {
val url = extensionJar.toURI().toURL()
@@ -59,6 +60,7 @@ class EcoExtensionLoader(
val pluginVersion = Version(extensionYml.getStringOrNull("plugin-version") ?: "0.0.0")
val pluginName = extensionYml.getStringOrNull("plugin")
@Suppress("DEPRECATION")
if (pluginName != null && !pluginName.equals(this.plugin.description.name, ignoreCase = true)) {
throw ExtensionLoadException("${extensionJar.name} is only compatible with $pluginName!")
}
@@ -82,6 +84,7 @@ class EcoExtensionLoader(
author = "Unnamed Author"
}
@Suppress("DEPRECATION")
if (Version(this.plugin.description.version) < pluginVersion) {
throw ExtensionLoadException("Plugin version is too low for ${extensionJar.name}!")
}

View File

@@ -7,6 +7,6 @@ import org.bukkit.NamespacedKey
class EcoNamespacedKeyFactory(private val plugin: EcoPlugin) : NamespacedKeyFactory {
override fun create(key: String): NamespacedKey {
return NamespacedKeyUtils.create(plugin.name, key)
return NamespacedKeyUtils.create(plugin.id, key)
}
}
}

View File

@@ -25,7 +25,6 @@ class FastInternalNamespacedKeyFactory : InternalNamespacedKeyFactory {
class SafeInternalNamespacedKeyFactory : InternalNamespacedKeyFactory {
override fun create(namespace: String, key: String): NamespacedKey {
@Suppress("DEPRECATION")
return NamespacedKey(namespace, key)
}
}

View File

@@ -43,6 +43,7 @@ class EcoMenu(
getPossiblyReactiveSlot(row, column, player)
override fun open(player: Player): Inventory {
@Suppress("DEPRECATION")
val inventory = if (columns == 9) {
Bukkit.createInventory(null, rows * columns, title)
} else {

View File

@@ -1,7 +1,9 @@
package com.willfp.eco.internal.gui.menu
import com.willfp.eco.core.Eco
import com.willfp.eco.core.Prerequisite
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
@@ -20,9 +22,23 @@ fun Player.forceRenderedInventory(menu: RenderedInventory) {
trackedForceRendered[this.uniqueId] = menu
}
// Workaround because 1.21 has OpenInventory as an interface instead of an abstract class like in previous versions
interface TopInventoryProxy {
fun getTopInventory(player: Player): Inventory
}
private val Player.topInventory: Inventory
get() {
return if (!Prerequisite.HAS_1_21.isMet) {
Eco.get().ecoPlugin.getProxy(TopInventoryProxy::class.java).getTopInventory(this)
} else {
this.openInventory.topInventory
}
}
val Player.renderedInventory: RenderedInventory?
get() = trackedForceRendered[this.uniqueId]
?: this.openInventory.topInventory.asRenderedInventory()
?: this.topInventory.asRenderedInventory()
class RenderedInventory(
val menu: EcoMenu,
@@ -55,7 +71,7 @@ class RenderedInventory(
val actualItem = inventory.getItem(bukkit) ?: continue
if (slot.isCaptiveFromEmpty) {
if (!actualItem.isEmpty) {
if (!actualItem.isEcoEmpty) {
newCaptive[position] = actualItem
}
} else {

View File

@@ -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()
@@ -20,14 +21,17 @@ class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() {
}
override fun getAuthor(): String {
@Suppress("DEPRECATION")
return java.lang.String.join(", ", plugin.description.authors)
}
override fun getIdentifier(): String {
@Suppress("DEPRECATION")
return plugin.description.name.lowercase()
}
override fun getVersion(): String {
@Suppress("DEPRECATION")
return plugin.description.version
}

View File

@@ -49,4 +49,4 @@ object ArgParserColor : LookupArgParser {
return "color:#${Integer.toHexString(meta.color.asRGB())}"
}
}
}

View File

@@ -20,6 +20,7 @@ object ArgParserEnchantment : LookupArgParser {
continue
}
@Suppress("DEPRECATION")
val enchant = Enchantment.getByKey(NamespacedKeyUtils.create("minecraft", argSplit[0]))
val level = argSplit[1].toIntOrNull()

View File

@@ -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<out String>, meta: ItemMeta): Predicate<ItemStack>? {
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
}
}

View File

@@ -28,7 +28,6 @@ object ArgParserHead : LookupArgParser {
playerName ?: return null
@Suppress("DEPRECATION")
val player = Bukkit.getOfflinePlayer(playerName)
meta.owningPlayer = player

View File

@@ -1,42 +1,30 @@
package com.willfp.eco.internal.items
import com.willfp.eco.core.items.args.LookupArgParser
import com.willfp.eco.internal.items.templates.ValueArgParser
import com.willfp.eco.util.StringUtils
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import java.util.function.Predicate
object ArgParserName : LookupArgParser {
override fun parseArguments(args: Array<out String>, meta: ItemMeta): Predicate<ItemStack>? {
var name: String? = null
for (arg in args) {
if (!arg.lowercase().startsWith("name:")) {
continue
}
name = arg.substring(5, arg.length)
}
name ?: return null
val formatted = StringUtils.format(name)
// I don't know why it says it's redundant, the compiler yells at me
@Suppress("UsePropertyAccessSyntax", "RedundantSuppression")
meta.setDisplayName(formatted)
return Predicate {
val testMeta = it.itemMeta ?: return@Predicate false
testMeta.displayName == formatted
}
object ArgParserName : ValueArgParser<String>("name") {
override fun parse(arg: String): String {
return arg
}
override fun serializeBack(meta: ItemMeta): String? {
override fun apply(meta: ItemMeta, value: String) {
val formatted = StringUtils.format(value)
// I don't know why it says it's redundant, the compiler yells at me
@Suppress("UsePropertyAccessSyntax", "RedundantSuppression", "DEPRECATION")
meta.setDisplayName(formatted)
}
override fun test(meta: ItemMeta): String? {
if (!meta.hasDisplayName()) {
return null
}
return "name:\"${meta.displayName}\""
@Suppress("DEPRECATION")
return meta.displayName
}
}
}

View File

@@ -44,4 +44,4 @@ object ArgParserTexture : LookupArgParser {
return "texture:${SkullUtils.getSkullTexture(meta)}"
}
}
}

View File

@@ -1,38 +1,14 @@
package com.willfp.eco.internal.items
import com.willfp.eco.core.items.args.LookupArgParser
import org.bukkit.inventory.ItemStack
import com.willfp.eco.internal.items.templates.FlagArgParser
import org.bukkit.inventory.meta.ItemMeta
import java.util.function.Predicate
object ArgParserUnbreakable : LookupArgParser {
override fun parseArguments(args: Array<out String>, meta: ItemMeta): Predicate<ItemStack>? {
var unbreakable = false
for (arg in args) {
if (arg.equals("unbreakable", true)) {
unbreakable = true
}
}
if (!unbreakable) {
return null
}
object ArgParserUnbreakable : FlagArgParser("unbreakable") {
override fun apply(meta: ItemMeta) {
meta.isUnbreakable = true
return Predicate {
val testMeta = it.itemMeta ?: return@Predicate false
testMeta.isUnbreakable
}
}
override fun serializeBack(meta: ItemMeta): String? {
if (!meta.isUnbreakable) {
return null
}
return "unbreakable"
override fun test(meta: ItemMeta): Boolean {
return meta.isUnbreakable
}
}
}

View File

@@ -0,0 +1,8 @@
package com.willfp.eco.internal.items
import com.willfp.eco.internal.compat.ModernCompatibilityProxy
@ModernCompatibilityProxy("items.ModernItemArgParsersImpl")
interface ModernItemArgParsers {
fun registerAll()
}

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.internal.items.templates
import com.willfp.eco.core.items.args.LookupArgParser
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import java.util.function.Predicate
abstract class FlagArgParser(
protected val flag: String
) : LookupArgParser {
abstract fun apply(meta: ItemMeta)
abstract fun test(meta: ItemMeta): Boolean
override fun parseArguments(args: Array<out String>, meta: ItemMeta): Predicate<ItemStack>? {
var has = false
for (arg in args) {
if (arg.equals(flag, true)) {
has = true
}
}
if (!has) {
return null
}
apply(meta)
return Predicate {
val testMeta = it.itemMeta ?: return@Predicate false
test(testMeta)
}
}
override fun serializeBack(meta: ItemMeta): String? {
if (!test(meta)) {
return null
}
return flag
}
}

View File

@@ -0,0 +1,50 @@
package com.willfp.eco.internal.items.templates
import com.willfp.eco.core.items.args.LookupArgParser
import com.willfp.eco.util.StringUtils
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import java.util.function.Predicate
abstract class ValueArgParser<T: Any>(
protected val flag: String
) : LookupArgParser {
abstract fun parse(arg: String): T?
abstract fun apply(meta: ItemMeta, value: T)
abstract fun test(meta: ItemMeta): String?
override fun parseArguments(args: Array<out String>, meta: ItemMeta): Predicate<ItemStack>? {
var argument: String? = null
for (arg in args) {
if (!arg.lowercase().startsWith("${flag}:")) {
continue
}
argument = arg.substring(flag.length + 1, arg.length)
}
argument ?: return null
val parsed = parse(argument) ?: return null
apply(meta, parsed)
return Predicate {
val testMeta = it.itemMeta ?: return@Predicate false
test(testMeta) == parsed
}
}
override fun serializeBack(meta: ItemMeta): String? {
val test = test(meta)
if (test.isNullOrBlank()) {
return null
}
return "${flag}:\"$test\""
}
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.internal.particle
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.particle.ParticleFactory
import com.willfp.eco.core.particle.SpawnableParticle
import org.bukkit.Color
@@ -7,6 +8,14 @@ import org.bukkit.Location
import org.bukkit.Particle
object ParticleFactoryRGB : ParticleFactory {
private val dustParticle = runCatching {
if (Prerequisite.HAS_1_20_5.isMet) {
Particle.valueOf("DUST")
} else {
Particle.valueOf("REDSTONE")
}
}.getOrNull()
override fun getNames() = listOf(
"color",
"rgb",
@@ -30,7 +39,9 @@ object ParticleFactoryRGB : ParticleFactory {
override fun spawn(location: Location, amount: Int) {
val world = location.world ?: return
world.spawnParticle(Particle.REDSTONE, location, amount, 0.0, 0.0, 0.0, 0.0, options)
val particle = dustParticle ?: return
world.spawnParticle(particle, location, amount, 0.0, 0.0, 0.0, 0.0, options)
}
}
}

View File

@@ -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<InjectablePlaceholder>,
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)
}
@@ -66,7 +93,7 @@ class PlaceholderParser {
val prefix = "%${additionalPlayer.identifier}_"
processed = found.fold(processed) { acc, placeholder ->
if (placeholder.startsWith(prefix)) {
val newPlaceholder = "%${StringUtils.removePrefix(prefix, placeholder)}"
val newPlaceholder = "%${StringUtils.removePrefix(placeholder, prefix)}"
val translation = translatePlacholders(
newPlaceholder,
context.copyWithPlayer(additionalPlayer.player),

View File

@@ -8,6 +8,11 @@ import org.bukkit.entity.Player
import java.util.UUID
import kotlin.math.roundToInt
private fun getXPNeededForLevel(level: Int): Int {
// XP Formula from NMS Player
return if (level >= 30) 112 + (level - 30) * 9 else (if (level >= 15) 37 + (level - 15) * 5 else 7 + level * 2)
}
object PriceFactoryXP : PriceFactory {
override fun getNames() = listOf(
"xp",
@@ -25,15 +30,37 @@ object PriceFactoryXP : PriceFactory {
) : Price {
private val multipliers = mutableMapOf<UUID, Double>()
override fun canAfford(player: Player, multiplier: Double): Boolean =
player.totalExperience >= getValue(player, multiplier)
override fun canAfford(player: Player, multiplier: Double): Boolean {
var totalExperience = 0
for (level in 0 until player.level) {
totalExperience += getXPNeededForLevel(level)
}
totalExperience += (player.exp * getXPNeededForLevel(player.level)).toInt()
return totalExperience >= getValue(player, multiplier).roundToInt()
}
override fun pay(player: Player, multiplier: Double) {
player.totalExperience -= getValue(player, multiplier).roundToInt()
takeXP(player, getValue(player, multiplier).roundToInt())
}
private fun takeXP(player: Player, amount: Int) {
val currentLevel = player.level
val currentExp = player.exp * getXPNeededForLevel(currentLevel)
if (currentExp >= amount) {
player.exp = (currentExp - amount) / getXPNeededForLevel(currentLevel)
} else {
// Handle recursive level down
player.exp = 1f
player.level = (currentLevel - 1).coerceAtLeast(0)
takeXP(player, (amount - currentExp).toInt())
}
}
override fun giveTo(player: Player, multiplier: Double) {
player.totalExperience += getValue(player, multiplier).roundToInt()
player.giveExp(getValue(player, multiplier).roundToInt())
}
override fun getValue(player: Player, multiplier: Double): Double {

View File

@@ -0,0 +1,7 @@
package com.willfp.eco.internal.recipes
import com.willfp.eco.internal.compat.ModernCompatibilityProxy
import org.bukkit.event.Listener
@ModernCompatibilityProxy("recipes.AutocrafterPatchImpl")
interface AutocrafterPatch: Listener

View File

@@ -1,5 +1,5 @@
plugins {
id("io.papermc.paperweight.userdev") version "1.5.3" apply false
id("io.papermc.paperweight.userdev") version "1.7.1" apply false
}

View File

@@ -7,4 +7,11 @@ version = rootProject.version
dependencies {
paperweight.paperDevBundle("1.17.1-R0.1-SNAPSHOT")
pluginRemapper("net.fabricmc:tiny-remapper:0.10.3:fat")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

View File

@@ -7,6 +7,7 @@ import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
import com.willfp.eco.internal.spigot.proxy.common.ai.TargetGoalFactory
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
@@ -74,6 +75,15 @@ fun Player.toNMS(): ServerPlayer =
fun Component.toNMS(): net.minecraft.network.chat.Component =
if (Prerequisite.HAS_PAPER.isMet) PaperAdventure.asVanilla(this) else impl.toNMS(this)
fun net.minecraft.network.chat.Component.toAdventure(): Component {
if (Prerequisite.HAS_PAPER.isMet) {
return PaperAdventure.asAdventure(this)
}
val json = net.minecraft.network.chat.Component.Serializer.toJson(this)
return GsonComponentSerializer.gson().deserialize(json)
}
interface CommonsProvider {
val nbtTagString: Int

Some files were not shown because too many files have changed in this diff Show More