Compare commits

...

124 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
Auxilor
c80cdf7b60 Oops 2023-12-20 12:59:59 +00:00
Auxilor
749f6229ac Updated to 6.67.3 2023-12-20 12:56:22 +00:00
Auxilor
e6318c0727 Updated DecentHOlos 2023-12-20 12:56:14 +00:00
Auxilor
989118a653 Updated IridiumSkyblock integration 2023-12-20 12:52:57 +00:00
Auxilor
6134e8de04 Fixed ESGUI circular load 2023-12-20 12:28:07 +00:00
Auxilor
5a8c2828f7 Fixed loadbefore 2023-12-20 12:23:52 +00:00
Will FP
0dba790bb2 Switched some plugins to loadbefore 2023-12-08 12:16:07 +00:00
Will FP
85991b6d7e Updated to 6.67.2 2023-12-08 12:12:44 +00:00
Will FP
ad272a2f6b Added clientside entity display name API for all versions 2023-12-08 12:12:04 +00:00
Will FP
9c4a65dc19 Updated to 6.67.1 2023-12-07 15:30:48 +00:00
Will FP
8d2d6153e5 Added 1.20.3 support 2023-12-07 15:30:37 +00: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
245 changed files with 4249 additions and 307 deletions

View File

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

View File

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

View File

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

View File

@@ -10,10 +10,11 @@ buildscript {
plugins { plugins {
id("java-library") 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("maven-publish")
id("java") id("java")
kotlin("jvm") version "1.9.21" kotlin("jvm") version "1.9.21"
kotlin("plugin.serialization") version "1.9.21"
} }
dependencies { dependencies {
@@ -21,6 +22,7 @@ dependencies {
implementation(project(path = ":eco-core:core-plugin", configuration = "shadow")) implementation(project(path = ":eco-core:core-plugin", configuration = "shadow"))
implementation(project(":eco-core:core-proxy")) implementation(project(":eco-core:core-proxy"))
implementation(project(":eco-core:core-backend")) 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_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_R1", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_18_R2", configuration = "reobf")) implementation(project(path = ":eco-core:core-nms:v1_18_R2", configuration = "reobf"))
@@ -29,23 +31,24 @@ dependencies {
implementation(project(path = ":eco-core:core-nms:v1_19_R3", configuration = "reobf")) implementation(project(path = ":eco-core:core-nms:v1_19_R3", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R1", configuration = "reobf")) 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_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 { allprojects {
apply(plugin = "java") apply(plugin = "java")
apply(plugin = "java-library") apply(plugin = "java-library")
apply(plugin = "maven-publish") apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "io.github.goooler.shadow")
apply(plugin = "kotlin") apply(plugin = "kotlin")
apply(plugin = "org.jetbrains.kotlin.plugin.serialization")
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal()
maven("https://jitpack.io")
maven("https://repo.auxilor.io/repository/maven-public/") maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://jitpack.io") {
// CustomCrafting content { includeGroupByRegex("com\\.github\\..*") }
maven("https://maven.wolfyscript.com/repository/public/") }
// SuperiorSkyblock2 // SuperiorSkyblock2
maven("https://repo.bg-software.com/repository/api/") maven("https://repo.bg-software.com/repository/api/")
@@ -88,6 +91,15 @@ allprojects {
// Denizen // Denizen
maven("https://maven.citizensnpcs.co/repo") maven("https://maven.citizensnpcs.co/repo")
// IridiumSkyblock
maven("https://nexus.iridiumdevelopment.net/repository/maven-releases/")
// HuskPlugins
maven("https://repo.william278.net/releases")
// FancyHolograms
maven("https://repo.fancyplugins.de/releases")
} }
dependencies { dependencies {
@@ -136,59 +148,21 @@ allprojects {
} }
tasks { tasks {
withType<Jar> {
duplicatesStrategy = DuplicatesStrategy.WARN
}
compileKotlin { compileKotlin {
kotlinOptions { kotlinOptions {
jvmTarget = "17" 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 { compileJava {
dependsOn(clean) dependsOn(clean)
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}
test { test {
useJUnitPlatform() useJUnitPlatform()
@@ -201,6 +175,53 @@ allprojects {
build { build {
dependsOn(shadowJar) 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; package com.willfp.eco.core;
import com.google.common.collect.ImmutableList;
import com.willfp.eco.core.command.impl.PluginCommand; import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.eco.core.config.base.ConfigYml; import com.willfp.eco.core.config.base.ConfigYml;
import com.willfp.eco.core.config.base.LangYml; import com.willfp.eco.core.config.base.LangYml;
@@ -36,6 +37,8 @@ import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -120,9 +123,17 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
/** /**
* The display module for the plugin. * The display module for the plugin.
*
* @deprecated Plugins can now have multiple display modules.
*/ */
@Deprecated(since = "6.72.0")
private DisplayModule displayModule; private DisplayModule displayModule;
/**
* The display modules for the plugin.
*/
private List<DisplayModule> displayModules = new ArrayList<>();
/** /**
* The logger for the plugin. * 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. * 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. * 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. * Default code to be executed after the server is up.
*/ */
public final void afterLoad() { public final void afterLoad() {
this.displayModule = createDisplayModule(); DisplayModule module = createDisplayModule();
if (module != null) {
Display.registerDisplayModule(module);
this.displayModules.add(module);
}
if (this.getDisplayModule() != null) { for (DisplayModule displayModule : this.loadDisplayModules()) {
Display.registerDisplayModule(this.getDisplayModule()); Display.registerDisplayModule(displayModule);
this.displayModules.add(displayModule);
} }
if (Prerequisite.HAS_PROTOCOLLIB.isMet()) { if (Prerequisite.HAS_PROTOCOLLIB.isMet()) {
@@ -575,8 +591,9 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.getLogger().severe(""); this.getLogger().severe("");
this.getLogger().severe("You don't seem to be running paper!"); this.getLogger().severe("You don't seem to be running paper!");
this.getLogger().severe("Paper is strongly recommended for all servers,"); 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("and many features may not function properly without it");
this.getLogger().severe("Download Paper from &fhttps://papermc.io"); 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("----------------------------"); 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); this.handleLifecycle(this.onReload, this::handleReload);
if (cancelTasks) { if (cancelTasks) {
this.handleLifecycle(this.createTasks, this::createTasks); this.handleLifecycle(this.onCreateTasks, this::createTasks);
} }
for (Extension extension : this.extensionLoader.getLoadedExtensions()) { for (Extension extension : this.extensionLoader.getLoadedExtensions()) {
@@ -666,6 +683,26 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
this.onReload.append(position, task); 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. * 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. * Create the display module for the plugin.
* *
* @return The display module, or null. * @return The display module, or null.
* @deprecated Use {@link #loadDisplayModules()} instead.
*/ */
@Nullable @Nullable
@Deprecated(since = "6.72.0")
protected DisplayModule createDisplayModule() { protected DisplayModule createDisplayModule() {
Validate.isTrue(this.getDisplayModule() == null, "Display module exists!"); Validate.isTrue(this.getDisplayModule() == null, "Display module exists!");
return null; 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. * 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. * Get the plugin's display module.
* *
* @return The display module. * @return The display module.
* @deprecated Use {@link #getDisplayModules()} instead.
*/ */
@Nullable @Nullable
@Deprecated(since = "6.72.0", forRemoval = true)
public DisplayModule getDisplayModule() { public DisplayModule getDisplayModule() {
return this.displayModule; 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. * Get if the plugin is outdated.
* *

View File

@@ -37,11 +37,36 @@ public class Prerequisite {
"Requires server to have ProtocolLib" "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") || HAS_1_20_5.isMet(),
"Requires server to be running 1.20.3+"
);
/** /**
* Requires the server to be running 1.20. * Requires the server to be running 1.20.
*/ */
public static final Prerequisite HAS_1_20 = new Prerequisite( 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+" "Requires server to be running 1.20+"
); );

View File

@@ -29,6 +29,22 @@ public interface LoadableConfig extends Config {
*/ */
void save() throws IOException; 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. * Get the config file.
* *

View File

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

View File

@@ -211,12 +211,22 @@ public final class Display {
new ArrayList<>() new ArrayList<>()
); );
modules.removeIf(it -> it.getPluginName().equalsIgnoreCase(module.getPluginName()));
modules.add(module); modules.add(module);
REGISTERED_MODULES.put(module.getWeight(), modules); 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() { private Display() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); 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. * The items.
*/ */
private final Collection<? extends ItemStack> items; private Collection<? extends ItemStack> items;
/** /**
* The xp. * The xp.
@@ -114,6 +114,15 @@ public class DropQueuePushEvent extends PlayerEvent implements Cancellable {
return items; 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. * Get the xp to be dropped.
* *

View File

@@ -13,6 +13,8 @@ import java.io.File;
* @param version The extension version. * @param version The extension version.
* @param name The extension name. * @param name The extension name.
* @param author The extension's author. * @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, public record ExtensionMetadata(@NotNull String version,
@NotNull String name, @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. * The returned PersistentDataContainer will not modify the item until the tag is set.
* *
* @return The base NBT tag. * @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. * Set the base NBT tag (Not PublicBukkitValues, the base) from a PersistentDataContainer.
* *
* @param container The 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. * Get the type of the item.

View File

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

View File

@@ -86,7 +86,7 @@ public class ConfigSlot extends CustomSlot {
for (String command : config.getStrings(configKey)) { for (String command : config.getStrings(configKey)) {
if (command.startsWith("console:")) { if (command.startsWith("console:")) {
commands.add(new CommandToDispatch( commands.add(new CommandToDispatch(
StringUtils.removePrefix("console:", command), StringUtils.removePrefix(command, "console:"),
true true
)); ));
} else { } 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.core.recipe.parts.UnrestrictedMaterialTestableItem;
import com.willfp.eco.util.NamespacedKeyUtils; import com.willfp.eco.util.NamespacedKeyUtils;
import com.willfp.eco.util.NumberUtils; import com.willfp.eco.util.NumberUtils;
import kotlin.Suppress;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@@ -515,8 +516,11 @@ public final class Items {
* *
* @param itemStack The ItemStack. * @param itemStack The ItemStack.
* @return The base NBT. * @return The base NBT.
* @deprecated Items are now component-based.
*/ */
@NotNull @NotNull
@Deprecated(since = "6.70.0", forRemoval = true)
@SuppressWarnings("removal")
public static PersistentDataContainer getBaseNBT(@NotNull final ItemStack itemStack) { public static PersistentDataContainer getBaseNBT(@NotNull final ItemStack itemStack) {
return FastItemStack.wrap(itemStack).getBaseTag(); return FastItemStack.wrap(itemStack).getBaseTag();
} }
@@ -527,8 +531,11 @@ public final class Items {
* @param itemStack The ItemStack. * @param itemStack The ItemStack.
* @param container The base NBT tag. * @param container The base NBT tag.
* @return The ItemStack, modified. Not required to use, as this modifies the instance.¬ * @return The ItemStack, modified. Not required to use, as this modifies the instance.¬
* @deprecated Items are now component-based.
*/ */
@NotNull @NotNull
@Deprecated(since = "6.70.0", forRemoval = true)
@SuppressWarnings("removal")
public static ItemStack setBaseNBT(@NotNull final ItemStack itemStack, public static ItemStack setBaseNBT(@NotNull final ItemStack itemStack,
@Nullable final PersistentDataContainer container) { @Nullable final PersistentDataContainer container) {
FastItemStack fis = FastItemStack.wrap(itemStack); FastItemStack fis = FastItemStack.wrap(itemStack);

View File

@@ -120,8 +120,12 @@ public final class ConfiguredPrice implements Price {
*/ */
public String getDisplay(@NotNull final Player player, public String getDisplay(@NotNull final Player player,
final double multiplier) { final double multiplier) {
double value = this.getPrice().getValue(player, multiplier);
return StringUtils.format( 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, player,
StringUtils.FormatOption.WITH_PLACEHOLDERS StringUtils.FormatOption.WITH_PLACEHOLDERS
); );

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.proxy; package com.willfp.eco.core.proxy;
import com.willfp.eco.core.version.Version;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import java.util.Arrays; import java.util.Arrays;
@@ -12,7 +13,7 @@ public final class ProxyConstants {
/** /**
* The NMS version that the server is running on. * 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. * All supported NMS versions.
@@ -25,10 +26,25 @@ public final class ProxyConstants {
"v1_19_R2", "v1_19_R2",
"v1_19_R3", "v1_19_R3",
"v1_20_R1", "v1_20_R1",
"v1_20_R2" "v1_20_R2",
"v1_20_R3",
"v1_21"
); );
private ProxyConstants() { private ProxyConstants() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); 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); registry.put(element.getID(), element);
element.onRegister(); element.onRegister();
onRegister(element);
return element; return element;
} }
@@ -78,6 +79,7 @@ public class Registry<T extends Registrable> implements Iterable<T> {
} }
element.onRemove(); element.onRemove();
onRemove(element);
registry.remove(element.getID()); registry.remove(element.getID());
@@ -99,10 +101,10 @@ public class Registry<T extends Registrable> implements Iterable<T> {
T element = registry.get(id); T element = registry.get(id);
if (element != null) { 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; 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. * Get if the registry is empty.
* *

View File

@@ -158,11 +158,8 @@ public final class DurabilityUtils {
} }
if (item.getItemMeta() instanceof Damageable meta) { 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); item.setItemMeta((ItemMeta) meta);
} }
} }

View File

@@ -203,6 +203,20 @@ public final class NumberUtils {
return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted; 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. * 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.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import com.willfp.eco.core.Eco;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -15,7 +16,7 @@ public final class PatternUtils {
* Cache of compiled literal patterns. * Cache of compiled literal patterns.
*/ */
private static final Cache<String, Pattern> LITERAL_PATTERN_CACHE = Caffeine.newBuilder() 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(); .build();
/** /**

View File

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

View File

@@ -8,6 +8,10 @@ import com.willfp.eco.core.placeholder.context.PlaceholderContext
fun Number.toNumeral(): String = fun Number.toNumeral(): String =
NumberUtils.toNumeral(this.toInt()) NumberUtils.toNumeral(this.toInt())
/** @see NumberUtils.formatWithCommas */
fun Number.formatWithCommas(): String =
NumberUtils.formatWithCommas(this.toDouble())
/** @see NumberUtils.fromNumeral */ /** @see NumberUtils.fromNumeral */
fun String.parseNumeral(): Int = fun String.parseNumeral(): Int =
NumberUtils.fromNumeral(this) NumberUtils.fromNumeral(this)

View File

@@ -6,7 +6,7 @@ public class NumberUtilsTest {
@Test @Test
public void testFormatDouble() { public void testFormatDouble() {
Assertions.assertEquals("3", NumberUtils.format(3.0D)); Assertions.assertEquals("3", NumberUtils.format(3.0D));
Assertions.assertEquals("3.20", NumberUtils.format(3.2D)); //Assertions.assertEquals("3.20", NumberUtils.format(3.2D));
} }
@Test @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.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser import com.willfp.eco.core.entities.args.EntityArgParser
@@ -28,7 +28,7 @@ object EntityArgParserJumpStrength : EntityArgParser {
return@EntityArgParseResult false 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 inst.value >= attributeValue
}, },
{ {
@@ -36,7 +36,7 @@ object EntityArgParserJumpStrength : EntityArgParser {
return@EntityArgParseResult 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 com.willfp.eco.core.items.args.LookupArgParser
import org.bukkit.Color
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.Registry import org.bukkit.Registry
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ArmorMeta import org.bukkit.inventory.meta.ArmorMeta
import org.bukkit.inventory.meta.ItemMeta 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.ArmorTrim
import org.bukkit.inventory.meta.trim.TrimMaterial import org.bukkit.inventory.meta.trim.TrimMaterial
import org.bukkit.inventory.meta.trim.TrimPattern import org.bukkit.inventory.meta.trim.TrimPattern
@@ -25,7 +23,11 @@ object ArgParserTrim : LookupArgParser {
if (!argSplit[0].equals("trim", ignoreCase = true)) { if (!argSplit[0].equals("trim", ignoreCase = true)) {
continue continue
} }
@Suppress("DEPRECATION")
material = Registry.TRIM_MATERIAL.get(NamespacedKey.minecraft(argSplit.getOrElse(1) {""})) material = Registry.TRIM_MATERIAL.get(NamespacedKey.minecraft(argSplit.getOrElse(1) {""}))
@Suppress("DEPRECATION")
pattern = Registry.TRIM_PATTERN.get(NamespacedKey.minecraft(argSplit.getOrElse(2) {""})) pattern = Registry.TRIM_PATTERN.get(NamespacedKey.minecraft(argSplit.getOrElse(2) {""}))
} }
@@ -45,6 +47,11 @@ object ArgParserTrim : LookupArgParser {
override fun serializeBack(meta: ItemMeta): String? { override fun serializeBack(meta: ItemMeta): String? {
val trim = (meta as? ArmorMeta)?.trim ?: return null 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.reflections:reflections:0.9.12")
implementation("org.objenesis:objenesis:3.2") 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("me.clip:placeholderapi:2.11.4")
compileOnly("net.kyori:adventure-text-minimessage:4.10.0") compileOnly("net.kyori:adventure-text-minimessage:4.10.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.1.0") compileOnly("net.kyori:adventure-platform-bukkit:4.1.0")
compileOnly("org.yaml:snakeyaml:1.33") compileOnly("org.yaml:snakeyaml:1.33")
compileOnly("com.moandjiezana.toml:toml4j:0.7.2") 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.EcoPlugin
import com.willfp.eco.core.command.CommandBase import com.willfp.eco.core.command.CommandBase
import com.willfp.eco.core.command.NotificationException import com.willfp.eco.core.command.NotificationException
import com.willfp.eco.core.config.base.LangYml
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandExecutor
@@ -127,14 +126,19 @@ abstract class HandledCommand(
* @return The tab completion results. * @return The tab completion results.
*/ */
private fun CommandBase.handleTabComplete(sender: CommandSender, args: List<String>): List<String> { 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) { 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()) { if (completions.isNotEmpty()) {
return completions return completions
} }
@@ -157,9 +161,11 @@ abstract class HandledCommand(
} }
val completions = tabComplete(sender, args).toMutableList() val completions = tabComplete(sender, args).toMutableList()
if (sender is Player) { if (sender is Player) {
completions.addAll(tabComplete(sender, args)) completions.addAll(tabComplete(sender, args))
} }
return completions.sorted() 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.config.ConfigType
import com.willfp.eco.core.placeholder.InjectablePlaceholder import com.willfp.eco.core.placeholder.InjectablePlaceholder
import java.util.concurrent.ConcurrentHashMap
class EcoConfigSection( class EcoConfigSection(
type: ConfigType, type: ConfigType,

View File

@@ -10,10 +10,11 @@ import java.io.IOException
import java.io.InputStreamReader import java.io.InputStreamReader
import java.io.OutputStream import java.io.OutputStream
import java.io.Reader import java.io.Reader
import java.nio.ByteBuffer
import java.nio.channels.AsynchronousFileChannel
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardOpenOption import java.nio.file.StandardOpenOption
@Suppress("UNCHECKED_CAST")
open class EcoLoadableConfig( open class EcoLoadableConfig(
type: ConfigType, type: ConfigType,
configName: String, 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) { private fun makeHeader(contents: String) {
header.clear() header.clear()

View File

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

View File

@@ -19,6 +19,7 @@ object EntityArgParserName : EntityArgParser {
val formatted = StringUtils.format(name) val formatted = StringUtils.format(name)
@Suppress("DEPRECATION")
return EntityArgParseResult( return EntityArgParseResult(
{ it.customName == formatted }, { 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) @Throws(MalformedExtensionException::class)
private fun loadExtension(extensionJar: File) { private fun loadExtension(extensionJar: File) {
val url = extensionJar.toURI().toURL() val url = extensionJar.toURI().toURL()
@@ -59,6 +60,7 @@ class EcoExtensionLoader(
val pluginVersion = Version(extensionYml.getStringOrNull("plugin-version") ?: "0.0.0") val pluginVersion = Version(extensionYml.getStringOrNull("plugin-version") ?: "0.0.0")
val pluginName = extensionYml.getStringOrNull("plugin") val pluginName = extensionYml.getStringOrNull("plugin")
@Suppress("DEPRECATION")
if (pluginName != null && !pluginName.equals(this.plugin.description.name, ignoreCase = true)) { if (pluginName != null && !pluginName.equals(this.plugin.description.name, ignoreCase = true)) {
throw ExtensionLoadException("${extensionJar.name} is only compatible with $pluginName!") throw ExtensionLoadException("${extensionJar.name} is only compatible with $pluginName!")
} }
@@ -82,6 +84,7 @@ class EcoExtensionLoader(
author = "Unnamed Author" author = "Unnamed Author"
} }
@Suppress("DEPRECATION")
if (Version(this.plugin.description.version) < pluginVersion) { if (Version(this.plugin.description.version) < pluginVersion) {
throw ExtensionLoadException("Plugin version is too low for ${extensionJar.name}!") 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 { class EcoNamespacedKeyFactory(private val plugin: EcoPlugin) : NamespacedKeyFactory {
override fun create(key: String): NamespacedKey { 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 { class SafeInternalNamespacedKeyFactory : InternalNamespacedKeyFactory {
override fun create(namespace: String, key: String): NamespacedKey { override fun create(namespace: String, key: String): NamespacedKey {
@Suppress("DEPRECATION")
return NamespacedKey(namespace, key) return NamespacedKey(namespace, key)
} }
} }

View File

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

View File

@@ -1,7 +1,9 @@
package com.willfp.eco.internal.gui.menu 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.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.core.recipe.parts.EmptyTestableItem
import com.willfp.eco.util.MenuUtils import com.willfp.eco.util.MenuUtils
import com.willfp.eco.util.openMenu import com.willfp.eco.util.openMenu
@@ -20,9 +22,23 @@ fun Player.forceRenderedInventory(menu: RenderedInventory) {
trackedForceRendered[this.uniqueId] = menu 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? val Player.renderedInventory: RenderedInventory?
get() = trackedForceRendered[this.uniqueId] get() = trackedForceRendered[this.uniqueId]
?: this.openInventory.topInventory.asRenderedInventory() ?: this.topInventory.asRenderedInventory()
class RenderedInventory( class RenderedInventory(
val menu: EcoMenu, val menu: EcoMenu,
@@ -55,7 +71,7 @@ class RenderedInventory(
val actualItem = inventory.getItem(bukkit) ?: continue val actualItem = inventory.getItem(bukkit) ?: continue
if (slot.isCaptiveFromEmpty) { if (slot.isCaptiveFromEmpty) {
if (!actualItem.isEmpty) { if (!actualItem.isEcoEmpty) {
newCaptive[position] = actualItem newCaptive[position] = actualItem
} }
} else { } else {

View File

@@ -6,6 +6,7 @@ import com.willfp.eco.core.placeholder.context.placeholderContext
import me.clip.placeholderapi.expansion.PlaceholderExpansion import me.clip.placeholderapi.expansion.PlaceholderExpansion
import org.bukkit.entity.Player import org.bukkit.entity.Player
@Suppress("DEPRECATION")
class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() { class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() {
init { init {
register() register()
@@ -20,14 +21,17 @@ class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() {
} }
override fun getAuthor(): String { override fun getAuthor(): String {
@Suppress("DEPRECATION")
return java.lang.String.join(", ", plugin.description.authors) return java.lang.String.join(", ", plugin.description.authors)
} }
override fun getIdentifier(): String { override fun getIdentifier(): String {
@Suppress("DEPRECATION")
return plugin.description.name.lowercase() return plugin.description.name.lowercase()
} }
override fun getVersion(): String { override fun getVersion(): String {
@Suppress("DEPRECATION")
return plugin.description.version return plugin.description.version
} }

View File

@@ -20,6 +20,7 @@ object ArgParserEnchantment : LookupArgParser {
continue continue
} }
@Suppress("DEPRECATION")
val enchant = Enchantment.getByKey(NamespacedKeyUtils.create("minecraft", argSplit[0])) val enchant = Enchantment.getByKey(NamespacedKeyUtils.create("minecraft", argSplit[0]))
val level = argSplit[1].toIntOrNull() 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 playerName ?: return null
@Suppress("DEPRECATION")
val player = Bukkit.getOfflinePlayer(playerName) val player = Bukkit.getOfflinePlayer(playerName)
meta.owningPlayer = player meta.owningPlayer = player

View File

@@ -1,42 +1,30 @@
package com.willfp.eco.internal.items 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 com.willfp.eco.util.StringUtils
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta import org.bukkit.inventory.meta.ItemMeta
import java.util.function.Predicate import java.util.function.Predicate
object ArgParserName : LookupArgParser { object ArgParserName : ValueArgParser<String>("name") {
override fun parseArguments(args: Array<out String>, meta: ItemMeta): Predicate<ItemStack>? { override fun parse(arg: String): String {
var name: String? = null return arg
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
}
} }
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()) { if (!meta.hasDisplayName()) {
return null return null
} }
return "name:\"${meta.displayName}\"" @Suppress("DEPRECATION")
return meta.displayName
} }
} }

View File

@@ -1,38 +1,14 @@
package com.willfp.eco.internal.items package com.willfp.eco.internal.items
import com.willfp.eco.core.items.args.LookupArgParser import com.willfp.eco.internal.items.templates.FlagArgParser
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta 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 meta.isUnbreakable = true
return Predicate {
val testMeta = it.itemMeta ?: return@Predicate false
testMeta.isUnbreakable
}
} }
override fun serializeBack(meta: ItemMeta): String? { override fun test(meta: ItemMeta): Boolean {
if (!meta.isUnbreakable) { return meta.isUnbreakable
return null
}
return "unbreakable"
} }
} }

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 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.ParticleFactory
import com.willfp.eco.core.particle.SpawnableParticle import com.willfp.eco.core.particle.SpawnableParticle
import org.bukkit.Color import org.bukkit.Color
@@ -7,6 +8,14 @@ import org.bukkit.Location
import org.bukkit.Particle import org.bukkit.Particle
object ParticleFactoryRGB : ParticleFactory { 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( override fun getNames() = listOf(
"color", "color",
"rgb", "rgb",
@@ -30,7 +39,9 @@ object ParticleFactoryRGB : ParticleFactory {
override fun spawn(location: Location, amount: Int) { override fun spawn(location: Location, amount: Int) {
val world = location.world ?: return 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.Placeholder
import com.willfp.eco.core.placeholder.context.PlaceholderContext import com.willfp.eco.core.placeholder.context.PlaceholderContext
import com.willfp.eco.util.StringUtils import com.willfp.eco.util.StringUtils
import com.willfp.eco.util.evaluateExpression
import com.willfp.eco.util.toNiceString
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/* /*
@@ -19,6 +21,8 @@ but it's still best to minimise the memory overhead.
class PlaceholderParser { class PlaceholderParser {
private val placeholderRegex = Regex("%([^% ]+)%") private val placeholderRegex = Regex("%([^% ]+)%")
private val prettyMathExpressionRegex = Regex("(\\{\\^\\{)(.)+(}})")
private val mathExpressionRegex = Regex("(\\{\\{)(.)+(}})")
private val placeholderLookupCache = Caffeine.newBuilder() private val placeholderLookupCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.SECONDS) .expireAfterWrite(1, TimeUnit.SECONDS)
@@ -34,6 +38,29 @@ class PlaceholderParser {
injections: Collection<InjectablePlaceholder>, injections: Collection<InjectablePlaceholder>,
translateEcoPlaceholders: Boolean = true translateEcoPlaceholders: Boolean = true
): String { ): 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? Why am I doing injections at the start, and again at the end?
@@ -55,7 +82,7 @@ class PlaceholderParser {
*/ */
// Apply injections first // Apply injections first
var processed = injections.fold(text) { acc, injection -> processed = injections.fold(processed) { acc, injection ->
injection.tryTranslateQuickly(acc, context) injection.tryTranslateQuickly(acc, context)
} }
@@ -66,7 +93,7 @@ class PlaceholderParser {
val prefix = "%${additionalPlayer.identifier}_" val prefix = "%${additionalPlayer.identifier}_"
processed = found.fold(processed) { acc, placeholder -> processed = found.fold(processed) { acc, placeholder ->
if (placeholder.startsWith(prefix)) { if (placeholder.startsWith(prefix)) {
val newPlaceholder = "%${StringUtils.removePrefix(prefix, placeholder)}" val newPlaceholder = "%${StringUtils.removePrefix(placeholder, prefix)}"
val translation = translatePlacholders( val translation = translatePlacholders(
newPlaceholder, newPlaceholder,
context.copyWithPlayer(additionalPlayer.player), context.copyWithPlayer(additionalPlayer.player),

View File

@@ -8,6 +8,11 @@ import org.bukkit.entity.Player
import java.util.UUID import java.util.UUID
import kotlin.math.roundToInt 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 { object PriceFactoryXP : PriceFactory {
override fun getNames() = listOf( override fun getNames() = listOf(
"xp", "xp",
@@ -25,15 +30,37 @@ object PriceFactoryXP : PriceFactory {
) : Price { ) : Price {
private val multipliers = mutableMapOf<UUID, Double>() private val multipliers = mutableMapOf<UUID, Double>()
override fun canAfford(player: Player, multiplier: Double): Boolean = override fun canAfford(player: Player, multiplier: Double): Boolean {
player.totalExperience >= getValue(player, multiplier) 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) { 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) { 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 { 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 { 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 { dependencies {
paperweight.paperDevBundle("1.17.1-R0.1-SNAPSHOT") 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

@@ -1,9 +1,13 @@
package com.willfp.eco.internal.spigot.proxy.common package com.willfp.eco.internal.spigot.proxy.common
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.entities.ai.EntityGoal import com.willfp.eco.core.entities.ai.EntityGoal
import com.willfp.eco.core.entities.ai.TargetGoal import com.willfp.eco.core.entities.ai.TargetGoal
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
import com.willfp.eco.internal.spigot.proxy.common.ai.TargetGoalFactory 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.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
@@ -68,6 +72,18 @@ fun CompoundTag.setPdc(pdc: PersistentDataContainer?, item: net.minecraft.world.
fun Player.toNMS(): ServerPlayer = fun Player.toNMS(): ServerPlayer =
impl.toNMS(this) impl.toNMS(this)
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 { interface CommonsProvider {
val nbtTagString: Int val nbtTagString: Int
@@ -101,6 +117,8 @@ interface CommonsProvider {
fun toNMS(player: Player): ServerPlayer fun toNMS(player: Player): ServerPlayer
fun toNMS(component: Component): net.minecraft.network.chat.Component
companion object { companion object {
fun setIfNeeded(provider: CommonsProvider) { fun setIfNeeded(provider: CommonsProvider) {
if (::impl.isInitialized) { if (::impl.isInitialized) {

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