Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
969329486d | ||
|
|
aab2e8237c | ||
|
|
30457c29a1 | ||
|
|
9ad480ecf0 | ||
|
|
b0d3256d1b | ||
|
|
4ff9d82cc1 | ||
|
|
f9178e248b | ||
|
|
cc8a799438 | ||
|
|
90b81f56df | ||
|
|
1240c14c14 | ||
|
|
ed46900f2f | ||
|
|
dade3d7fbb | ||
|
|
df141875d3 | ||
|
|
50b07de5d1 | ||
|
|
e2a033c24f | ||
|
|
3fa574105f | ||
|
|
a64386f980 | ||
|
|
4c5a0f9887 | ||
|
|
cbd43f5757 | ||
|
|
01f1425557 | ||
|
|
25e8cc0837 | ||
|
|
7ff3eeef06 | ||
|
|
58faf6de23 | ||
|
|
7f42cbe32e | ||
|
|
ae12ab17fe | ||
|
|
9949ed4f5f | ||
|
|
e3f81a51e8 | ||
|
|
a06d782dea | ||
|
|
7e60ee63ea | ||
|
|
e349f47e66 | ||
|
|
f710a69455 | ||
|
|
20b06be1f2 | ||
|
|
9992820580 | ||
|
|
feebbd8ec7 | ||
|
|
5302aa07a5 | ||
|
|
d124c5b274 | ||
|
|
f188919197 | ||
|
|
388268e906 | ||
|
|
6367867d2b | ||
|
|
291357e235 | ||
|
|
07178b0645 | ||
|
|
70ef99e875 | ||
|
|
885a7835ea | ||
|
|
94e9b47f02 | ||
|
|
e8f4bdd4aa | ||
|
|
c01e409904 | ||
|
|
f1cf82160e | ||
|
|
d1c15f8699 | ||
|
|
be6e7b1f46 | ||
|
|
b78fc2fb66 | ||
|
|
23a297b8e3 | ||
|
|
4e99ca51f0 | ||
|
|
47c93a6dbe | ||
|
|
da7f47d1ba | ||
|
|
144ea0dd10 | ||
|
|
732aaa3bf1 | ||
|
|
a38387be33 | ||
|
|
582f9b08f3 | ||
|
|
638367cbb2 | ||
|
|
ec35e7d779 | ||
|
|
1cc2a585d6 | ||
|
|
aa553b96d6 | ||
|
|
feb7ecee48 | ||
|
|
c0be6a12ff | ||
|
|
1dc6b651a0 | ||
|
|
3c26c02642 | ||
|
|
343508f099 | ||
|
|
76dc4948bc | ||
|
|
8fa209a981 | ||
|
|
b3a0634ad0 | ||
|
|
97d7acc0a9 | ||
|
|
ebac75b0ee | ||
|
|
02d0fa85b5 | ||
|
|
168915868c | ||
|
|
d62d598fd6 | ||
|
|
06561c5387 | ||
|
|
c9805e91b4 | ||
|
|
e3be95ca4d | ||
|
|
2e6463aed9 | ||
|
|
2501574eeb | ||
|
|
3c237fd856 | ||
|
|
7b3fd1d0c2 | ||
|
|
e599add6de | ||
|
|
1bda970f6b | ||
|
|
eb1f694905 | ||
|
|
efd3403eda | ||
|
|
08b563d528 | ||
|
|
c3f88bf7b0 | ||
|
|
eb6d76e0c6 | ||
|
|
f2d0e8c368 | ||
|
|
5e7b9573a1 | ||
|
|
7d457ea496 | ||
|
|
806bf9a43f | ||
|
|
316f134b71 | ||
|
|
0d363b9fb6 | ||
|
|
2890083eaa | ||
|
|
694646431b | ||
|
|
86d5e9d09e | ||
|
|
8635e5f7a5 | ||
|
|
aa718649eb | ||
|
|
1dc0fa449b | ||
|
|
19e3061a13 | ||
|
|
ecafbd76de | ||
|
|
3728f2fc7a | ||
|
|
56c124dbd2 | ||
|
|
6730697fc5 | ||
|
|
c8e1c83061 | ||
|
|
a9fd5a9418 | ||
|
|
7b1179f402 | ||
|
|
b4f3988fc7 | ||
|
|
e7e1751acc | ||
|
|
e68d482aa5 | ||
|
|
c0547a7c34 |
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Auxilor Community Discord
|
||||
url: https://discord.gg/ZcwpSsE/
|
||||
about: Join the Auxilor discord to get help from support staff and the general community!
|
||||
- name: The most common issues people have
|
||||
url: https://github.com/Auxilor/eco/issues/78
|
||||
about: Check the list of known common issues to see if your issue has already been solved
|
||||
31
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Report a Bug
|
||||
about: Report an issue with the plugin
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Server Information (please complete the following information):**
|
||||
- Version: (output of `/ver` command)
|
||||
- Version of plugin and eco (`/ver eco`, `/ver <plugin>`)
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/request-a-feature.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/request-a-feature.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Request a Feature
|
||||
about: Suggest an idea for this plugin
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
42
.github/workflows/test-publish.yml
vendored
Normal file
42
.github/workflows/test-publish.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Publish API (Dev)
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
publish-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout latest code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
- name: Setup build cache
|
||||
uses: actions/cache@v2.1.6
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
|
||||
- name: Publish artifact
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# The GITHUB_REF tag comes in the format 'refs/tags/xxx'.
|
||||
# So if we split on '/' and take the 3rd value, we can get the release name.
|
||||
run: |
|
||||
NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3)
|
||||
echo "New version: ${{ steps.vars.outputs.sha_short }}"
|
||||
echo "Github username: ${GITHUB_ACTOR}"
|
||||
./gradlew -Pversion=${{ steps.vars.outputs.sha_short }} publish
|
||||
@@ -64,6 +64,12 @@ allprojects {
|
||||
|
||||
// MythicMobs
|
||||
maven("https://mvn.lumine.io/repository/maven-public/")
|
||||
|
||||
// Crunch
|
||||
maven("https://redempt.dev")
|
||||
|
||||
// LibsDisguises
|
||||
maven("https://repo.md-5.net/content/groups/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -77,6 +83,10 @@ allprojects {
|
||||
compileOnly("net.kyori:adventure-api:4.9.3")
|
||||
compileOnly("net.kyori:adventure-text-serializer-gson:4.9.3")
|
||||
compileOnly("net.kyori:adventure-text-serializer-legacy:4.9.3")
|
||||
|
||||
// Other
|
||||
compileOnly("com.google.guava:guava:31.0.1-jre")
|
||||
compileOnly("com.github.ben-manes.caffeine:caffeine:3.0.5")
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
dependencies {
|
||||
// Kotlin
|
||||
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0'
|
||||
|
||||
// Adventure
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
|
||||
@@ -17,10 +25,20 @@ dependencies {
|
||||
compileOnly 'com.google.code.gson:gson:2.8.8'
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
build.dependsOn publishToMavenLocal
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@ import org.apache.commons.lang.Validate;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Holds the instance of the eco handler for bridging between the frontend
|
||||
* and backend.
|
||||
@@ -52,6 +58,24 @@ public final class Eco {
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eco Handler components are internals, so if a class is marked as a handler component,
|
||||
* then it should be treated the same as if it was marked with {@link ApiStatus.Internal}.
|
||||
* <p>
|
||||
* If a class is marked with {@link HandlerComponent}, <strong>Do not reference it in
|
||||
* your code!</strong> It can and will contain breaking changes between minor versions and
|
||||
* even patches, and you will create compatibility issues by using them.
|
||||
* <p>
|
||||
* Handler components should also be marked with {@link ApiStatus.Internal} in order to
|
||||
* cause compiler / IDE warnings.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface HandlerComponent {
|
||||
|
||||
}
|
||||
|
||||
private Eco() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
||||
DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version);
|
||||
if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
|
||||
this.outdated = true;
|
||||
this.getLogger().warning("&c " + this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
|
||||
this.getLogger().warning("&c" + this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
|
||||
this.getLogger().warning("&cThe newest version is &f" + version);
|
||||
this.getLogger().warning("&cDownload the new version!");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.willfp.eco.core;
|
||||
|
||||
import com.willfp.eco.core.config.updating.ConfigHandler;
|
||||
import com.willfp.eco.core.config.wrapper.ConfigFactory;
|
||||
import com.willfp.eco.core.data.PlayerProfileHandler;
|
||||
import com.willfp.eco.core.data.ProfileHandler;
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry;
|
||||
import com.willfp.eco.core.drops.DropQueueFactory;
|
||||
import com.willfp.eco.core.events.EventManager;
|
||||
@@ -19,6 +19,7 @@ import com.willfp.eco.core.requirement.RequirementFactory;
|
||||
import com.willfp.eco.core.scheduling.Scheduler;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -233,7 +234,7 @@ public interface Handler {
|
||||
* @return The handler.
|
||||
*/
|
||||
@NotNull
|
||||
PlayerProfileHandler getPlayerProfileHandler();
|
||||
ProfileHandler getProfileHandler();
|
||||
|
||||
/**
|
||||
* Create dummy entity - never spawned, exists purely in code.
|
||||
@@ -243,4 +244,19 @@ public interface Handler {
|
||||
*/
|
||||
@NotNull
|
||||
Entity createDummyEntity(@NotNull Location location);
|
||||
|
||||
/**
|
||||
* Create a {@link NamespacedKey} quickly
|
||||
* <p>
|
||||
* Bypasses the constructor, allowing for the creation of invalid keys,
|
||||
* therefore this is considered unsafe and should only be called after
|
||||
* the key has been confirmed to be valid.
|
||||
*
|
||||
* @param namespace The namespace.
|
||||
* @param key The key.
|
||||
* @return The key.
|
||||
*/
|
||||
@NotNull
|
||||
NamespacedKey createNamespacedKey(@NotNull String namespace,
|
||||
@NotNull String key);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.TransientConfig;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -108,6 +110,29 @@ public interface Config extends Cloneable {
|
||||
return Objects.requireNonNullElse(getIntOrNull(path), def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default int getIntFromExpression(@NotNull String path) {
|
||||
return getIntFromExpression(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param player The player to evaluate placeholders with respect to.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default int getIntFromExpression(@NotNull String path,
|
||||
@Nullable Player player) {
|
||||
return Double.valueOf(getDoubleFromExpression(path, player)).intValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an integer from config.
|
||||
*
|
||||
@@ -519,6 +544,28 @@ public interface Config extends Cloneable {
|
||||
return Objects.requireNonNullElse(getDoubleOrNull(path), 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path) {
|
||||
return getDoubleFromExpression(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param player The player to evaluate placeholders with respect to.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@Nullable Player player) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal from config.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.config.wrapper;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
@@ -14,6 +15,7 @@ import java.util.Map;
|
||||
* Internal component to create backend config implementations.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface ConfigFactory {
|
||||
/**
|
||||
* Updatable config.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.willfp.eco.core.data;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -12,26 +11,7 @@ import java.util.UUID;
|
||||
* <p>
|
||||
* Profiles save automatically, so there is no need to save after changes.
|
||||
*/
|
||||
public interface PlayerProfile {
|
||||
/**
|
||||
* Write a key to a player's persistent data.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param value The value.
|
||||
* @param <T> The type of the key.
|
||||
*/
|
||||
<T> void write(@NotNull PersistentDataKey<T> key,
|
||||
@NotNull T value);
|
||||
|
||||
/**
|
||||
* Read a key from a player's persistent data.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param <T> The type of the key.
|
||||
* @return The value, or the default value if not found.
|
||||
*/
|
||||
<T> @NotNull T read(@NotNull PersistentDataKey<T> key);
|
||||
|
||||
public interface PlayerProfile extends Profile {
|
||||
/**
|
||||
* Load a player profile.
|
||||
*
|
||||
@@ -51,6 +31,6 @@ public interface PlayerProfile {
|
||||
*/
|
||||
@NotNull
|
||||
static PlayerProfile load(@NotNull final UUID uuid) {
|
||||
return Eco.getHandler().getPlayerProfileHandler().load(uuid);
|
||||
return Eco.getHandler().getProfileHandler().load(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
30
eco-api/src/main/java/com/willfp/eco/core/data/Profile.java
Normal file
30
eco-api/src/main/java/com/willfp/eco/core/data/Profile.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.willfp.eco.core.data;
|
||||
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Persistent data storage interface.
|
||||
* <p>
|
||||
* Profiles save automatically, so there is no need to save after changes.
|
||||
*/
|
||||
public interface Profile {
|
||||
/**
|
||||
* Write a key to persistent data.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param value The value.
|
||||
* @param <T> The type of the key.
|
||||
*/
|
||||
<T> void write(@NotNull PersistentDataKey<T> key,
|
||||
@NotNull T value);
|
||||
|
||||
/**
|
||||
* Read a key from persistent data.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param <T> The type of the key.
|
||||
* @return The value, or the default value if not found.
|
||||
*/
|
||||
<T> @NotNull T read(@NotNull PersistentDataKey<T> key);
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
package com.willfp.eco.core.data;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* API to handle player profiles.
|
||||
* API to handle profiles.
|
||||
*/
|
||||
public interface PlayerProfileHandler {
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface ProfileHandler {
|
||||
/**
|
||||
* Load a player profile.
|
||||
*
|
||||
@@ -18,6 +22,13 @@ public interface PlayerProfileHandler {
|
||||
*/
|
||||
PlayerProfile load(@NotNull UUID uuid);
|
||||
|
||||
/**
|
||||
* Load the server profile.
|
||||
*
|
||||
* @return The profile.
|
||||
*/
|
||||
ServerProfile loadServerProfile();
|
||||
|
||||
/**
|
||||
* Unload a player profile from memory.
|
||||
* <p>
|
||||
@@ -37,7 +48,7 @@ public interface PlayerProfileHandler {
|
||||
*/
|
||||
@Deprecated
|
||||
default void savePlayer(@NotNull UUID uuid) {
|
||||
this.saveKeysForPlayer(uuid, PersistentDataKey.values());
|
||||
this.saveKeysFor(uuid, PersistentDataKey.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,8 +59,8 @@ public interface PlayerProfileHandler {
|
||||
* @param uuid The uuid.
|
||||
* @param keys The keys.
|
||||
*/
|
||||
void saveKeysForPlayer(@NotNull UUID uuid,
|
||||
@NotNull Set<PersistentDataKey<?>> keys);
|
||||
void saveKeysFor(@NotNull UUID uuid,
|
||||
@NotNull Set<PersistentDataKey<?>> keys);
|
||||
|
||||
/**
|
||||
* Save all player data.
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.eco.core.data;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Persistent data storage interface for servers.
|
||||
* <p>
|
||||
* Profiles save automatically, so there is no need to save after changes.
|
||||
*/
|
||||
public interface ServerProfile extends Profile {
|
||||
/**
|
||||
* Load the server profile.
|
||||
*
|
||||
* @return The profile.
|
||||
*/
|
||||
@NotNull
|
||||
static ServerProfile load() {
|
||||
return Eco.getHandler().getProfileHandler().loadServerProfile();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class PersistentDataKey<T> {
|
||||
/**
|
||||
* The persistent data key type.
|
||||
*/
|
||||
private final PersistentDataKeyType type;
|
||||
private final PersistentDataKeyType<T> type;
|
||||
|
||||
/**
|
||||
* Create a new Persistent Data Key.
|
||||
@@ -35,7 +35,7 @@ public class PersistentDataKey<T> {
|
||||
* @param defaultValue The default value.
|
||||
*/
|
||||
public PersistentDataKey(@NotNull final NamespacedKey key,
|
||||
@NotNull final PersistentDataKeyType type,
|
||||
@NotNull final PersistentDataKeyType<T> type,
|
||||
@NotNull final T defaultValue) {
|
||||
this.key = key;
|
||||
this.defaultValue = defaultValue;
|
||||
@@ -53,15 +53,6 @@ public class PersistentDataKey<T> {
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all persistent data keys.
|
||||
*
|
||||
* @return The keys.
|
||||
*/
|
||||
public static Set<PersistentDataKey<?>> values() {
|
||||
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key.
|
||||
*
|
||||
@@ -85,7 +76,16 @@ public class PersistentDataKey<T> {
|
||||
*
|
||||
* @return The key type.
|
||||
*/
|
||||
public PersistentDataKeyType getType() {
|
||||
public PersistentDataKeyType<T> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all persistent data keys.
|
||||
*
|
||||
* @return The keys.
|
||||
*/
|
||||
public static Set<PersistentDataKey<?>> values() {
|
||||
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,108 @@
|
||||
package com.willfp.eco.core.data.keys;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* All storable data key types.
|
||||
*
|
||||
* @param <T> The type.
|
||||
*/
|
||||
public enum PersistentDataKeyType {
|
||||
public final class PersistentDataKeyType<T> {
|
||||
/**
|
||||
* The registered key types.
|
||||
*/
|
||||
private static final List<PersistentDataKeyType<?>> VALUES = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* String.
|
||||
*/
|
||||
STRING,
|
||||
public static final PersistentDataKeyType<String> STRING = new PersistentDataKeyType<>(String.class, "STRING");
|
||||
|
||||
/**
|
||||
* Boolean.
|
||||
*/
|
||||
BOOLEAN,
|
||||
public static final PersistentDataKeyType<Boolean> BOOLEAN = new PersistentDataKeyType<>(Boolean.class, "BOOLEAN");
|
||||
|
||||
/**
|
||||
* Integer.
|
||||
* Int.
|
||||
*/
|
||||
INT,
|
||||
public static final PersistentDataKeyType<Integer> INT = new PersistentDataKeyType<>(Integer.class, "INT");
|
||||
|
||||
/**
|
||||
* Double.
|
||||
*/
|
||||
DOUBLE
|
||||
public static final PersistentDataKeyType<Double> DOUBLE = new PersistentDataKeyType<>(Double.class, "DOUBLE");
|
||||
|
||||
/**
|
||||
* The class of the type.
|
||||
*/
|
||||
private final Class<T> typeClass;
|
||||
|
||||
/**
|
||||
* The name of the key type.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Get the class of the type.
|
||||
*
|
||||
* @return The class.
|
||||
*/
|
||||
public Class<T> getTypeClass() {
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the key type.
|
||||
*
|
||||
* @return The name.
|
||||
*/
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new PersistentDataKeyType.
|
||||
*
|
||||
* @param typeClass The type class.
|
||||
* @param name The name.
|
||||
*/
|
||||
private PersistentDataKeyType(@NotNull final Class<T> typeClass,
|
||||
@NotNull final String name) {
|
||||
VALUES.add(this);
|
||||
|
||||
this.typeClass = typeClass;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered {@link PersistentDataKeyType}s.
|
||||
*
|
||||
* @return The registered types.
|
||||
*/
|
||||
@NotNull
|
||||
public static PersistentDataKeyType<?>[] values() {
|
||||
return VALUES.toArray(new PersistentDataKeyType[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a key type from a name.
|
||||
*
|
||||
* @param name The name.
|
||||
* @return The type, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
public static PersistentDataKeyType<?> valueOf(@NotNull final String name) {
|
||||
for (PersistentDataKeyType<?> type : VALUES) {
|
||||
if (type.name.equalsIgnoreCase(name)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package com.willfp.eco.core.display;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for display implementations.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface DisplayHandler {
|
||||
/**
|
||||
* Register display module.
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package com.willfp.eco.core.drops;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Internal component to create backend DropQueue implementations.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface DropQueueFactory {
|
||||
/**
|
||||
* Create a DropQueue.
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.willfp.eco.core.drops;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -9,6 +11,8 @@ import java.util.Collection;
|
||||
/**
|
||||
* Internal interface for backend DropQueue implementations.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface InternalDropQueue {
|
||||
/**
|
||||
* Add item to queue.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.willfp.eco.core.entities;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.willfp.eco.core.entities.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.entities.TestableEntity;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.entities.impl;
|
||||
|
||||
import com.willfp.eco.core.entities.TestableEntity;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.entities.impl;
|
||||
|
||||
import com.willfp.eco.core.entities.TestableEntity;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package com.willfp.eco.core.gui;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder;
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Internal component used by {@link com.willfp.eco.core.gui.menu.Menu#builder(int)}
|
||||
* and {@link com.willfp.eco.core.gui.slot.Slot#builder(ItemStack)}.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface GUIFactory {
|
||||
/**
|
||||
* Create slot builder.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.willfp.eco.core.integrations.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -28,12 +30,20 @@ public class PlaceholderEntry {
|
||||
*/
|
||||
private final boolean requiresPlayer;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
*/
|
||||
@Nullable
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a placeholder entry that doesn't require a player.
|
||||
*
|
||||
* @param identifier The identifier of the placeholder.
|
||||
* @param function A lambda to get the result of the placeholder given a player.
|
||||
* @deprecated Specify a plugin.
|
||||
*/
|
||||
@Deprecated
|
||||
public PlaceholderEntry(@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
this(identifier, function, false);
|
||||
@@ -45,10 +55,41 @@ public class PlaceholderEntry {
|
||||
* @param identifier The identifier of the placeholder.
|
||||
* @param function A lambda to get the result of the placeholder.
|
||||
* @param requiresPlayer If the placeholder requires a player.
|
||||
* @deprecated Specify a plugin.
|
||||
*/
|
||||
@Deprecated
|
||||
public PlaceholderEntry(@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function,
|
||||
final boolean requiresPlayer) {
|
||||
this(null, identifier, function, requiresPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a placeholder entry that doesn't require a player.
|
||||
*
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @param identifier The identifier of the placeholder.
|
||||
* @param function A lambda to get the result of the placeholder given a player.
|
||||
*/
|
||||
public PlaceholderEntry(@Nullable final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
this(plugin, identifier, function, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a placeholder entry that may require a player.
|
||||
*
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @param identifier The identifier of the placeholder.
|
||||
* @param function A lambda to get the result of the placeholder.
|
||||
* @param requiresPlayer If the placeholder requires a player.
|
||||
*/
|
||||
public PlaceholderEntry(@Nullable final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function,
|
||||
final boolean requiresPlayer) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
this.requiresPlayer = requiresPlayer;
|
||||
@@ -85,10 +126,37 @@ public class PlaceholderEntry {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
@Nullable
|
||||
public EcoPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*/
|
||||
public void register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof PlaceholderEntry entry)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), entry.getIdentifier())
|
||||
&& Objects.equals(this.getPlugin(), entry.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper class for placeholder integrations.
|
||||
*/
|
||||
@@ -24,4 +27,14 @@ public interface PlaceholderIntegration extends Integration {
|
||||
*/
|
||||
String translate(@NotNull String text,
|
||||
@Nullable Player player);
|
||||
|
||||
/**
|
||||
* Find all placeholders in a given text.
|
||||
*
|
||||
* @param text The text.
|
||||
* @return The placeholders.
|
||||
*/
|
||||
default List<String> findPlaceholdersIn(@NotNull String text) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package com.willfp.eco.core.integrations.placeholder;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Class to handle placeholder integrations.
|
||||
@@ -16,17 +23,24 @@ public final class PlaceholderManager {
|
||||
/**
|
||||
* All registered placeholders.
|
||||
*/
|
||||
private static final Map<String, PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
private static final Map<EcoPlugin, Map<String, PlaceholderEntry>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* All registered placeholder integrations.
|
||||
*/
|
||||
private static final Set<PlaceholderIntegration> REGISTERED_INTEGRATIONS = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Placeholder Cache.
|
||||
*/
|
||||
private static final LoadingCache<EntryWithPlayer, String> PLACEHOLDER_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(key -> key.entry.getResult(key.player));
|
||||
|
||||
/**
|
||||
* Register a new placeholder integration.
|
||||
*
|
||||
* @param integration The {@link PlaceholderIntegration} to register.
|
||||
* @param integration The {@link com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration} to register.
|
||||
*/
|
||||
public static void addIntegration(@NotNull final PlaceholderIntegration integration) {
|
||||
integration.registerIntegration();
|
||||
@@ -36,11 +50,14 @@ public final class PlaceholderManager {
|
||||
/**
|
||||
* Register a placeholder.
|
||||
*
|
||||
* @param expansion The {@link PlaceholderEntry} to register.
|
||||
* @param expansion The {@link com.willfp.eco.core.integrations.placeholder.PlaceholderEntry} to register.
|
||||
*/
|
||||
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
|
||||
REGISTERED_PLACEHOLDERS.remove(expansion.getIdentifier());
|
||||
REGISTERED_PLACEHOLDERS.put(expansion.getIdentifier(), expansion);
|
||||
EcoPlugin plugin = expansion.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : expansion.getPlugin();
|
||||
Map<String, PlaceholderEntry> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
.getOrDefault(plugin, new HashMap<>());
|
||||
pluginPlaceholders.put(expansion.getIdentifier(), expansion);
|
||||
REGISTERED_PLACEHOLDERS.put(plugin, pluginPlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,10 +66,36 @@ public final class PlaceholderManager {
|
||||
* @param player The player to get the result from.
|
||||
* @param identifier The placeholder identifier.
|
||||
* @return The value of the placeholder.
|
||||
* @deprecated Specify a plugin to get the result from.
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier) {
|
||||
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.get(identifier.toLowerCase());
|
||||
return getResult(player, identifier, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of a placeholder with respect to a player.
|
||||
*
|
||||
* @param player The player to get the result from.
|
||||
* @param identifier The placeholder identifier.
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @return The value of the placeholder.
|
||||
*/
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier,
|
||||
@Nullable final EcoPlugin plugin) {
|
||||
EcoPlugin owner = plugin == null ? Eco.getHandler().getEcoPlugin() : plugin;
|
||||
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
|
||||
|
||||
if (entry == null && plugin != null) {
|
||||
PlaceholderEntry alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
|
||||
.get(identifier.toLowerCase());
|
||||
if (alternate != null) {
|
||||
entry = alternate;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
return "";
|
||||
}
|
||||
@@ -61,7 +104,7 @@ public final class PlaceholderManager {
|
||||
return "";
|
||||
}
|
||||
|
||||
return entry.getResult(player);
|
||||
return PLACEHOLDER_CACHE.get(new EntryWithPlayer(entry, player));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +123,26 @@ public final class PlaceholderManager {
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all placeholders in a given text.
|
||||
*
|
||||
* @param text The text.
|
||||
* @return The placeholders.
|
||||
*/
|
||||
public static List<String> findPlaceholdersIn(@NotNull final String text) {
|
||||
List<String> found = new ArrayList<>();
|
||||
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
|
||||
found.addAll(integration.findPlaceholdersIn(text));
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private static record EntryWithPlayer(@NotNull PlaceholderEntry entry,
|
||||
@Nullable Player player) {
|
||||
|
||||
}
|
||||
|
||||
private PlaceholderManager() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
103
eco-api/src/main/java/com/willfp/eco/core/items/HashedItem.java
Normal file
103
eco-api/src/main/java/com/willfp/eco/core/items/HashedItem.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package com.willfp.eco.core.items;
|
||||
|
||||
import com.willfp.eco.core.fast.FastItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An item and its {@link com.willfp.eco.core.fast.FastItemStack} hash.
|
||||
*/
|
||||
public final class HashedItem {
|
||||
/**
|
||||
* The item.
|
||||
*/
|
||||
private final ItemStack item;
|
||||
|
||||
/**
|
||||
* The hash.
|
||||
*/
|
||||
private final int hash;
|
||||
|
||||
/**
|
||||
* Create new hashed item.
|
||||
*
|
||||
* @param item The item.
|
||||
* @param hash The hash.
|
||||
*/
|
||||
private HashedItem(@NotNull final ItemStack item,
|
||||
final int hash) {
|
||||
this.item = item;
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item.
|
||||
*
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash.
|
||||
*
|
||||
* @return The hash.
|
||||
*/
|
||||
public int getHash() {
|
||||
return this.hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin destructuring support.
|
||||
*
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack component1() {
|
||||
return this.getItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin destructuring support.
|
||||
*
|
||||
* @return The hash.
|
||||
*/
|
||||
public int component2() {
|
||||
return this.getHash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object other) {
|
||||
if (!(other instanceof HashedItem o)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return o.hash == this.hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashed item from an item.
|
||||
*
|
||||
* @param item The item.
|
||||
* @return The hashed item.
|
||||
*/
|
||||
public static HashedItem of(@NotNull final ItemStack item) {
|
||||
return new HashedItem(item, FastItemStack.wrap(item).hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashed item from a fast item stack.
|
||||
*
|
||||
* @param item The item.
|
||||
* @return The hashed item.
|
||||
*/
|
||||
public static HashedItem of(@NotNull final FastItemStack item) {
|
||||
return new HashedItem(item.unwrap(), item.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.core.items;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.willfp.eco.core.items.args.LookupArgParser;
|
||||
import com.willfp.eco.core.items.provider.ItemProvider;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
@@ -20,8 +22,10 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -34,6 +38,25 @@ public final class Items {
|
||||
*/
|
||||
private static final Map<NamespacedKey, TestableItem> REGISTRY = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cached custom item lookups, using {@link HashedItem}.
|
||||
*/
|
||||
private static final LoadingCache<HashedItem, Optional<TestableItem>> CACHE = Caffeine.newBuilder()
|
||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||
.build(
|
||||
key -> {
|
||||
TestableItem match = null;
|
||||
for (TestableItem item : REGISTRY.values()) {
|
||||
if (item.matches(key.getItem())) {
|
||||
match = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.ofNullable(match);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* All item providers.
|
||||
*/
|
||||
@@ -194,7 +217,7 @@ public final class Items {
|
||||
}
|
||||
}
|
||||
|
||||
// Marked as redundant but i am covering all bases here
|
||||
// Marked as redundant but I am covering all bases here
|
||||
if (item == null || item instanceof EmptyTestableItem) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
@@ -276,12 +299,7 @@ public final class Items {
|
||||
* @return If is recipe.
|
||||
*/
|
||||
public static boolean isCustomItem(@NotNull final ItemStack itemStack) {
|
||||
for (TestableItem item : REGISTRY.values()) {
|
||||
if (item.matches(itemStack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return getCustomItem(itemStack) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,12 +310,7 @@ public final class Items {
|
||||
*/
|
||||
@Nullable
|
||||
public static CustomItem getCustomItem(@NotNull final ItemStack itemStack) {
|
||||
for (TestableItem item : REGISTRY.values()) {
|
||||
if (item.matches(itemStack)) {
|
||||
return getOrWrap(item);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return CACHE.get(HashedItem.of(itemStack)).map(Items::getOrWrap).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Parse leather armor colors.
|
||||
*
|
||||
* @deprecated Moved to internals.
|
||||
*/
|
||||
@Deprecated(since = "6.16.0", forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
|
||||
public class ColorArgParser implements LookupArgParser {
|
||||
/**
|
||||
* Instantiate arg parser.
|
||||
*/
|
||||
public ColorArgParser() {
|
||||
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static {
|
||||
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + ColorArgParser.class.getName() + "), this will throw an error in the next release!");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Parse custom model data.
|
||||
*
|
||||
* @deprecated Moved to internals.
|
||||
*/
|
||||
@Deprecated(since = "6.16.0", forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
|
||||
public class CustomModelDataArgParser implements LookupArgParser {
|
||||
/**
|
||||
* Instantiate arg parser.
|
||||
*/
|
||||
public CustomModelDataArgParser() {
|
||||
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static {
|
||||
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + CustomModelDataArgParser.class.getName() + "), this will throw an error in the next release!");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Parses enchantment arguments.
|
||||
*
|
||||
* @deprecated Moved to internals.
|
||||
*/
|
||||
@Deprecated(since = "6.16.0", forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
|
||||
public class EnchantmentArgParser implements LookupArgParser {
|
||||
/**
|
||||
* Instantiate arg parser.
|
||||
*/
|
||||
public EnchantmentArgParser() {
|
||||
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static {
|
||||
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + EnchantmentArgParser.class.getName() + "), this will throw an error in the next release!");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Parse skull textures.
|
||||
*
|
||||
* @deprecated Moved to internals.
|
||||
*/
|
||||
@Deprecated(since = "6.16.0", forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
|
||||
public class TextureArgParser implements LookupArgParser {
|
||||
/**
|
||||
* Instantiate arg parser.
|
||||
*/
|
||||
public TextureArgParser() {
|
||||
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static {
|
||||
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + TextureArgParser.class.getName() + "), this will throw an error in the next release!");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.items.Items;
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
|
||||
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
|
||||
import com.willfp.eco.util.NamespacedKeyUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -58,7 +60,10 @@ public final class Recipes {
|
||||
}
|
||||
|
||||
if (key.getKey().contains("_displayed")) {
|
||||
NamespacedKey otherKey = new NamespacedKey(key.getNamespace(), key.getKey().replace("_displayed", ""));
|
||||
NamespacedKey otherKey = NamespacedKeyUtils.create(
|
||||
key.getNamespace(),
|
||||
key.getKey().replace("_displayed", "")
|
||||
);
|
||||
|
||||
return RECIPES.get(otherKey);
|
||||
}
|
||||
@@ -92,6 +97,7 @@ public final class Recipes {
|
||||
* @param permission The permission.
|
||||
* @return The recipe.
|
||||
*/
|
||||
@Nullable
|
||||
public static CraftingRecipe createAndRegisterRecipe(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String key,
|
||||
@NotNull final ItemStack output,
|
||||
@@ -105,6 +111,12 @@ public final class Recipes {
|
||||
builder.setRecipePart(i, Items.lookup(recipeStrings.get(i)));
|
||||
}
|
||||
|
||||
if (builder.isAir()) {
|
||||
Bukkit.getLogger().warning("RECIPE ERROR! " + plugin.getName() + ":" + key + " consists only");
|
||||
Bukkit.getLogger().warning("of air or invalid items! Please change that or disable this recipe.");
|
||||
return null;
|
||||
}
|
||||
|
||||
ShapedCraftingRecipe recipe = builder.build();
|
||||
recipe.register();
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
|
||||
assert lore != null;
|
||||
lore.add("");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getString("multiple-in-craft");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getFormattedString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(item.getAmount()));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
@@ -287,6 +287,20 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if recipe parts are all air.
|
||||
*
|
||||
* @return If recipe parts are all air.
|
||||
*/
|
||||
public boolean isAir() {
|
||||
for (TestableItem recipePart : this.recipeParts) {
|
||||
if (recipePart!= null && !(recipePart instanceof EmptyTestableItem)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the recipe.
|
||||
*
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface for internal requirement factory implementations.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface RequirementFactory {
|
||||
/**
|
||||
* Create a requirement.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for {@link NamespacedKey}s.
|
||||
*/
|
||||
@@ -17,7 +16,7 @@ public final class NamespacedKeyUtils {
|
||||
*/
|
||||
@NotNull
|
||||
public static NamespacedKey createEcoKey(@NotNull final String string) {
|
||||
return Objects.requireNonNull(NamespacedKey.fromString("eco:" + string));
|
||||
return NamespacedKeyUtils.create("eco", string);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,7 +29,28 @@ public final class NamespacedKeyUtils {
|
||||
@NotNull
|
||||
public static NamespacedKey create(@NotNull final String namespace,
|
||||
@NotNull final String key) {
|
||||
return Objects.requireNonNull(NamespacedKey.fromString(namespace + ":" + key));
|
||||
return Eco.getHandler().createNamespacedKey(
|
||||
namespace,
|
||||
key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a NamespacedKey from a string.
|
||||
* <p>
|
||||
* Preferred over {@link NamespacedKey#fromString(String)} for performance reasons.
|
||||
*
|
||||
* @param string The string.
|
||||
* @return The key.
|
||||
*/
|
||||
@NotNull
|
||||
public static NamespacedKey fromString(@NotNull final String string) {
|
||||
int index = string.indexOf(":");
|
||||
|
||||
return NamespacedKeyUtils.create(
|
||||
string.substring(0, index),
|
||||
string.substring(index + 1)
|
||||
);
|
||||
}
|
||||
|
||||
private NamespacedKeyUtils() {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for numbers.
|
||||
@@ -16,6 +21,11 @@ public final class NumberUtils {
|
||||
*/
|
||||
private static final double[] SIN_LOOKUP = new double[65536];
|
||||
|
||||
/**
|
||||
* Crunch handler.
|
||||
*/
|
||||
private static BiFunction<String, Player, Double> crunch = null;
|
||||
|
||||
/**
|
||||
* Set of roman numerals to look up.
|
||||
*/
|
||||
@@ -83,7 +93,9 @@ public final class NumberUtils {
|
||||
* @param toChange The value to test.
|
||||
* @param limit The maximum.
|
||||
* @return The new value.
|
||||
* @deprecated Pointless method.
|
||||
*/
|
||||
@Deprecated(since = "6.19.0")
|
||||
public static int equalIfOver(final int toChange,
|
||||
final int limit) {
|
||||
return Math.min(toChange, limit);
|
||||
@@ -95,7 +107,9 @@ public final class NumberUtils {
|
||||
* @param toChange The value to test.
|
||||
* @param limit The maximum.
|
||||
* @return The new value.
|
||||
* @deprecated Pointless method.
|
||||
*/
|
||||
@Deprecated(since = "6.19.0")
|
||||
public static double equalIfOver(final double toChange,
|
||||
final double limit) {
|
||||
return Math.min(toChange, limit);
|
||||
@@ -218,6 +232,39 @@ public final class NumberUtils {
|
||||
return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression) {
|
||||
return evaluateExpression(expression, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression with respect to a player (for placeholders).
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@Nullable final Player player) {
|
||||
return crunch.apply(expression, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init crunch handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void initCrunch(@NotNull final BiFunction<String, Player, Double> handler) {
|
||||
Validate.isTrue(crunch == null, "Already initialized!");
|
||||
crunch = handler;
|
||||
}
|
||||
|
||||
private NumberUtils() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
@@ -20,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -66,6 +69,42 @@ public final class StringUtils {
|
||||
.emitLegacyHoverEvent()
|
||||
.build();
|
||||
|
||||
/**
|
||||
* String format cache.
|
||||
*/
|
||||
private static final LoadingCache<String, String> STRING_FORMAT_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||
.build(StringUtils::processFormatting);
|
||||
|
||||
/**
|
||||
* Json -> Legacy Cache.
|
||||
*/
|
||||
private static final LoadingCache<String, String> JSON_TO_LEGACY = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||
.build(
|
||||
json -> {
|
||||
try {
|
||||
Component component = GSON_COMPONENT_SERIALIZER.deserialize(json);
|
||||
return LEGACY_COMPONENT_SERIALIZER.serialize(component);
|
||||
} catch (JsonSyntaxException e) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Legacy -> Json Cache.
|
||||
*/
|
||||
private static final LoadingCache<String, String> LEGACY_TO_JSON = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.SECONDS)
|
||||
.build(
|
||||
legacy -> GSON_COMPONENT_SERIALIZER.serialize(
|
||||
Component.empty().decoration(TextDecoration.ITALIC, false).append(
|
||||
LEGACY_COMPONENT_SERIALIZER.deserialize(legacy)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Color map.
|
||||
*/
|
||||
@@ -272,6 +311,11 @@ public final class StringUtils {
|
||||
if (option == FormatOption.WITH_PLACEHOLDERS) {
|
||||
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
|
||||
}
|
||||
return STRING_FORMAT_CACHE.get(processedMessage);
|
||||
}
|
||||
|
||||
private static String processFormatting(@NotNull final String message) {
|
||||
String processedMessage = message;
|
||||
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
|
||||
processedMessage = translateGradients(processedMessage);
|
||||
processedMessage = translateHexColorCodes(processedMessage);
|
||||
@@ -423,11 +467,8 @@ public final class StringUtils {
|
||||
if (legacy == null) {
|
||||
processed = "";
|
||||
}
|
||||
return GSON_COMPONENT_SERIALIZER.serialize(
|
||||
Component.empty().decoration(TextDecoration.ITALIC, false).append(
|
||||
LEGACY_COMPONENT_SERIALIZER.deserialize(processed)
|
||||
)
|
||||
);
|
||||
|
||||
return LEGACY_TO_JSON.get(processed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,12 +483,7 @@ public final class StringUtils {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
Component component = GSON_COMPONENT_SERIALIZER.deserialize(json);
|
||||
return LEGACY_COMPONENT_SERIALIZER.serialize(component);
|
||||
} catch (JsonSyntaxException e) {
|
||||
return json;
|
||||
}
|
||||
return JSON_TO_LEGACY.get(json);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
18
eco-api/src/main/kotlin/com/willfp/eco/core/data/Profiles.kt
Normal file
18
eco-api/src/main/kotlin/com/willfp/eco/core/data/Profiles.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
@file:JvmName("ProfileExtensions")
|
||||
|
||||
package com.willfp.eco.core.data
|
||||
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.Server
|
||||
|
||||
/**
|
||||
* @see PlayerProfile.load
|
||||
*/
|
||||
val OfflinePlayer.profile: PlayerProfile
|
||||
get() = PlayerProfile.load(this)
|
||||
|
||||
/**
|
||||
* @see ServerProfile.load
|
||||
*/
|
||||
val Server.profile: ServerProfile
|
||||
get() = ServerProfile.load()
|
||||
@@ -0,0 +1,11 @@
|
||||
@file:JvmName("FastItemStackExtensions")
|
||||
|
||||
package com.willfp.eco.core.fast
|
||||
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
/**
|
||||
* @see FastItemStack.wrap
|
||||
*/
|
||||
fun ItemStack.fast(): FastItemStack =
|
||||
FastItemStack.wrap(this)
|
||||
@@ -0,0 +1,96 @@
|
||||
@file:JvmName("GUIHelperExtensions")
|
||||
|
||||
package com.willfp.eco.core.gui
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder
|
||||
import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.onLeftClick
|
||||
*/
|
||||
fun SlotBuilder.onLeftClick(action: (InventoryClickEvent, Slot, Menu) -> Unit): SlotBuilder =
|
||||
this.onLeftClick { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.onRightClick
|
||||
*/
|
||||
fun SlotBuilder.onRightClick(action: (InventoryClickEvent, Slot, Menu) -> Unit): SlotBuilder =
|
||||
this.onRightClick { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.onShiftLeftClick
|
||||
*/
|
||||
fun SlotBuilder.onShiftLeftClick(action: (InventoryClickEvent, Slot, Menu) -> Unit): SlotBuilder =
|
||||
this.onShiftLeftClick { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.onShiftRightClick
|
||||
*/
|
||||
fun SlotBuilder.onShiftRightClick(action: (InventoryClickEvent, Slot, Menu) -> Unit): SlotBuilder =
|
||||
this.onShiftRightClick { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.onShiftRightClick
|
||||
*/
|
||||
fun SlotBuilder.onMiddleClick(action: (InventoryClickEvent, Slot, Menu) -> Unit): SlotBuilder =
|
||||
this.onMiddleClick { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* @see SlotBuilder.setModifier
|
||||
*/
|
||||
fun SlotBuilder.setModifier(action: (Player, Menu, ItemStack) -> Unit): SlotBuilder =
|
||||
this.setModifier { a, b, c -> action(a, b, c) }
|
||||
|
||||
/**
|
||||
* Kotlin builder for slots.
|
||||
*/
|
||||
fun slot(
|
||||
item: ItemStack,
|
||||
init: SlotBuilder.() -> Unit
|
||||
): Slot {
|
||||
val builder = Slot.builder(item)
|
||||
init(builder)
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin builder for slots.
|
||||
*/
|
||||
fun slot(
|
||||
provider: (Player, Menu) -> ItemStack,
|
||||
init: SlotBuilder.() -> Unit
|
||||
): Slot {
|
||||
val builder = Slot.builder { a, b -> provider(a, b) }
|
||||
init(builder)
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MenuBuilder.onClose
|
||||
*/
|
||||
fun MenuBuilder.onClose(action: (InventoryCloseEvent, Menu) -> Unit): MenuBuilder =
|
||||
this.onClose { a, b -> action(a, b) }
|
||||
|
||||
/**
|
||||
* @see MenuBuilder.modify
|
||||
*/
|
||||
fun MenuBuilder.modify(modifier: (MenuBuilder) -> Unit): MenuBuilder =
|
||||
this.modfiy { modifier(it) }
|
||||
|
||||
/**
|
||||
* Kotlin builder for menus.
|
||||
*/
|
||||
fun menu(
|
||||
rows: Int,
|
||||
init: MenuBuilder.() -> Unit
|
||||
): Menu {
|
||||
val builder = Menu.builder(rows)
|
||||
init(builder)
|
||||
return builder.build()
|
||||
}
|
||||
12
eco-api/src/main/kotlin/com/willfp/eco/util/ArrowUtils.kt
Normal file
12
eco-api/src/main/kotlin/com/willfp/eco/util/ArrowUtils.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
@file:JvmName("ArrowUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.entity.Arrow
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
/**
|
||||
* @see ArrowUtils.getBow
|
||||
*/
|
||||
val Arrow.bow: ItemStack?
|
||||
get() = ArrowUtils.getBow(this)
|
||||
11
eco-api/src/main/kotlin/com/willfp/eco/util/BlockUtils.kt
Normal file
11
eco-api/src/main/kotlin/com/willfp/eco/util/BlockUtils.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@file:JvmName("BlockUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.block.Block
|
||||
|
||||
/**
|
||||
* @see ArrowUtils.getBow
|
||||
*/
|
||||
val Block.isPlayerPlaced: Boolean
|
||||
get() = BlockUtils.isPlayerPlaced(this)
|
||||
15
eco-api/src/main/kotlin/com/willfp/eco/util/ListUtils.kt
Normal file
15
eco-api/src/main/kotlin/com/willfp/eco/util/ListUtils.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
@file:JvmName("ListUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
/**
|
||||
* @see ListUtils.listToFrequencyMap
|
||||
*/
|
||||
fun <T> List<T>.toFrequencyMap(): Map<T, Int> =
|
||||
ListUtils.listToFrequencyMap(this)
|
||||
|
||||
/**
|
||||
* @see ListUtils.containsIgnoreCase
|
||||
*/
|
||||
fun Iterable<String>.containsIgnoreCase(element: String): Boolean =
|
||||
ListUtils.containsIgnoreCase(this, element)
|
||||
26
eco-api/src/main/kotlin/com/willfp/eco/util/PlayerUtils.kt
Normal file
26
eco-api/src/main/kotlin/com/willfp/eco/util/PlayerUtils.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
@file:JvmName("PlayerUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import net.kyori.adventure.audience.Audience
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
/**
|
||||
* @see PlayerUtils.getSavedDisplayName
|
||||
*/
|
||||
val OfflinePlayer.savedDisplayName: String
|
||||
get() = PlayerUtils.getSavedDisplayName(this)
|
||||
|
||||
/**
|
||||
* @see PlayerUtils.getAudience
|
||||
*/
|
||||
fun Player.asAudience(): Audience =
|
||||
PlayerUtils.getAudience(this)
|
||||
|
||||
/**
|
||||
* @see PlayerUtils.getAudience
|
||||
*/
|
||||
fun CommandSender.asAudience(): Audience =
|
||||
PlayerUtils.getAudience(this)
|
||||
11
eco-api/src/main/kotlin/com/willfp/eco/util/PotionUtils.kt
Normal file
11
eco-api/src/main/kotlin/com/willfp/eco/util/PotionUtils.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@file:JvmName("PotionUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.potion.PotionData
|
||||
|
||||
/**
|
||||
* @see PotionData.duration
|
||||
*/
|
||||
val PotionData.duration: Int
|
||||
get() = PotionUtils.getDuration(this)
|
||||
11
eco-api/src/main/kotlin/com/willfp/eco/util/ServerUtils.kt
Normal file
11
eco-api/src/main/kotlin/com/willfp/eco/util/ServerUtils.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@file:JvmName("ServerUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.Server
|
||||
|
||||
/**
|
||||
* @see ServerUtils.getTps
|
||||
*/
|
||||
val Server.tps: Double
|
||||
get() = ServerUtils.getTps()
|
||||
17
eco-api/src/main/kotlin/com/willfp/eco/util/SkullUtils.kt
Normal file
17
eco-api/src/main/kotlin/com/willfp/eco/util/SkullUtils.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
@file:JvmName("SkullUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
|
||||
/**
|
||||
* @see SkullUtils.getSkullTexture
|
||||
* @see SkullUtils.setSkullTexture
|
||||
*/
|
||||
var SkullMeta.texture: String?
|
||||
get() = SkullUtils.getSkullTexture(this)
|
||||
set(value) {
|
||||
if (value != null) {
|
||||
SkullUtils.setSkullTexture(this, value)
|
||||
}
|
||||
}
|
||||
42
eco-api/src/main/kotlin/com/willfp/eco/util/StringUtils.kt
Normal file
42
eco-api/src/main/kotlin/com/willfp/eco/util/StringUtils.kt
Normal file
@@ -0,0 +1,42 @@
|
||||
@file:JvmName("StringUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
/**
|
||||
* @see StringUtils.toComponent
|
||||
*/
|
||||
fun String.toComponent(): Component =
|
||||
StringUtils.toComponent(this)
|
||||
|
||||
/**
|
||||
* @see StringUtils.toLegacy
|
||||
*/
|
||||
fun Component.toLegacy(): String =
|
||||
StringUtils.toLegacy(this)
|
||||
|
||||
/**
|
||||
* @see StringUtils.format
|
||||
*/
|
||||
fun String.formatEco(
|
||||
player: Player? = null,
|
||||
formatPlaceholders: Boolean = false
|
||||
) = StringUtils.format(
|
||||
this,
|
||||
player,
|
||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
||||
)
|
||||
|
||||
/**
|
||||
* @see StringUtils.formatList
|
||||
*/
|
||||
fun List<String>.formatEco(
|
||||
player: Player? = null,
|
||||
formatPlaceholders: Boolean = false
|
||||
) = StringUtils.formatList(
|
||||
this,
|
||||
player,
|
||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
||||
)
|
||||
17
eco-api/src/main/kotlin/com/willfp/eco/util/VectorUtils.kt
Normal file
17
eco-api/src/main/kotlin/com/willfp/eco/util/VectorUtils.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
@file:JvmName("VectorUtilsExtensions")
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import org.bukkit.util.Vector
|
||||
|
||||
/**
|
||||
* @see VectorUtils.isFinite
|
||||
*/
|
||||
val Vector.isFinite: Boolean
|
||||
get() = VectorUtils.isFinite(this)
|
||||
|
||||
/**
|
||||
* @see VectorUtils.simplifyVector
|
||||
*/
|
||||
fun Vector.simplify(): Vector =
|
||||
VectorUtils.simplifyVector(this)
|
||||
@@ -7,5 +7,5 @@ dependencies {
|
||||
compileOnly 'org.reflections:reflections:0.9.12'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'com.google.guava:guava:31.0.1-jre'
|
||||
compileOnly 'org.objenesis:objenesis:3.2'
|
||||
}
|
||||
@@ -24,11 +24,7 @@ open class EcoLoadableJSONConfig(
|
||||
private val name: String = "$configName.json"
|
||||
|
||||
fun reloadFromFile() {
|
||||
try {
|
||||
init(configFile)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
runCatching { init(configFile) }.onFailure { it.printStackTrace() }
|
||||
}
|
||||
|
||||
final override fun createFile() {
|
||||
@@ -94,11 +90,7 @@ open class EcoLoadableJSONConfig(
|
||||
createFile()
|
||||
}
|
||||
configFile = File(directory, name)
|
||||
try {
|
||||
init(configFile)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
init(configFile)
|
||||
plugin.configHandler.addConfig(this)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
@@ -21,48 +19,36 @@ open class EcoUpdatableJSONConfig(
|
||||
|
||||
fun update() {
|
||||
super.clearCache()
|
||||
try {
|
||||
this.init(configFile)
|
||||
val newConfig = configInJar
|
||||
if (newConfig.getKeys(true) == this.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key: String ->
|
||||
if (!this.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) {
|
||||
this.set(key, newConfig[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeUnused) {
|
||||
this.getKeys(true).forEach { s ->
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.set(s, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.save()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
this.init(configFile)
|
||||
val newConfig = configInJar ?: return
|
||||
if (newConfig.getKeys(true) == this.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key: String ->
|
||||
if (!this.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) {
|
||||
this.set(key, newConfig[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeUnused) {
|
||||
this.getKeys(true).forEach { s ->
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.set(s, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.save()
|
||||
}
|
||||
|
||||
private val configInJar: YamlConfiguration
|
||||
private val configInJar: YamlConfiguration?
|
||||
get() {
|
||||
val newIn = this.source.getResourceAsStream(resourcePath) ?: throw NullPointerException("$name is null?")
|
||||
val newIn = this.source.getResourceAsStream(resourcePath) ?: return null
|
||||
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
|
||||
val newConfig = YamlConfiguration()
|
||||
try {
|
||||
newConfig.load(reader)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
newConfig.load(reader)
|
||||
return newConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -24,15 +24,15 @@ class EcoConfigHandler(
|
||||
|
||||
override fun callUpdate() {
|
||||
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
|
||||
try {
|
||||
kotlin.runCatching {
|
||||
when (method.parameterCount) {
|
||||
0 -> method.invoke(null)
|
||||
1 -> method.invoke(null, this.plugin)
|
||||
else -> throw InvalidUpdateMethodException("Update method must have 0 parameters or a plugin parameter.")
|
||||
}
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
e.printStackTrace()
|
||||
throw InvalidUpdateMethodException("Update method generated an exception")
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
plugin.logger.severe("Update method ${method.toGenericString()} generated an exception")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package com.willfp.eco.internal.config.yaml
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@@ -23,13 +22,7 @@ open class EcoLoadableYamlConfig(
|
||||
private val name: String = "$configName.yml"
|
||||
|
||||
fun reloadFromFile() {
|
||||
try {
|
||||
handle.load(getConfigFile())
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
handle.load(getConfigFile())
|
||||
}
|
||||
|
||||
final override fun createFile() {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
@@ -21,48 +19,36 @@ class EcoUpdatableYamlConfig(
|
||||
|
||||
fun update() {
|
||||
super.clearCache()
|
||||
try {
|
||||
this.handle.load(configFile)
|
||||
val newConfig = configInJar
|
||||
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key ->
|
||||
if (!this.handle.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
|
||||
this.handle.set(key, newConfig[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeUnused) {
|
||||
this.handle.getKeys(true).forEach { s ->
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.handle.set(s, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.handle.save(configFile)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
this.handle.load(configFile)
|
||||
val newConfig = configInJar ?: return
|
||||
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key ->
|
||||
if (!this.handle.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
|
||||
this.handle.set(key, newConfig[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeUnused) {
|
||||
this.handle.getKeys(true).forEach { s ->
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.handle.set(s, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.handle.save(configFile)
|
||||
}
|
||||
|
||||
private val configInJar: YamlConfiguration
|
||||
private val configInJar: YamlConfiguration?
|
||||
get() {
|
||||
val newIn = source.getResourceAsStream(resourcePath) ?: throw NullPointerException("$name is null?")
|
||||
val newIn = source.getResourceAsStream(resourcePath) ?: return null
|
||||
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
|
||||
val newConfig = YamlConfiguration()
|
||||
try {
|
||||
newConfig.load(reader)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
newConfig.load(reader)
|
||||
return newConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -73,12 +73,10 @@ open class EcoDropQueue(val player: Player) : InternalDropQueue {
|
||||
world.dropItem(location, drop!!).velocity = Vector()
|
||||
}
|
||||
if (xp > 0) {
|
||||
val event = PlayerExpChangeEvent(player, xp)
|
||||
Bukkit.getPluginManager().callEvent(event)
|
||||
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 = event.amount
|
||||
orb.experience = xp
|
||||
}
|
||||
} else {
|
||||
for (drop in items) {
|
||||
@@ -94,4 +92,4 @@ open class EcoDropQueue(val player: Player) : InternalDropQueue {
|
||||
init {
|
||||
location = player.location
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.willfp.eco.internal.entities
|
||||
|
||||
import com.willfp.eco.core.entities.args.EntityArgParseResult
|
||||
import com.willfp.eco.core.entities.args.EntityArgParser
|
||||
import org.bukkit.entity.Animals
|
||||
|
||||
class EntityArgParserSilent : EntityArgParser {
|
||||
override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
|
||||
var silent = false
|
||||
|
||||
for (arg in args) {
|
||||
if (arg.equals("silent", true)) {
|
||||
silent = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return EntityArgParseResult(
|
||||
{
|
||||
it.isSilent
|
||||
},
|
||||
{
|
||||
it.isSilent = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.extensions
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.TransientConfig
|
||||
import com.willfp.eco.core.extensions.Extension
|
||||
@@ -10,8 +11,6 @@ import com.willfp.eco.core.extensions.MalformedExtensionException
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
|
||||
class EcoExtensionLoader(
|
||||
@@ -32,23 +31,18 @@ class EcoExtensionLoader(
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
loadExtension(extensionJar)
|
||||
} catch (e: MalformedExtensionException) {
|
||||
runCatching { loadExtension(extensionJar) }.onFailure {
|
||||
this.plugin.logger.warning(extensionJar.name + " caused an error!")
|
||||
if (Eco.getHandler().ecoPlugin.configYml.getBool("log-full-extension-errors")) {
|
||||
it.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(MalformedExtensionException::class)
|
||||
private fun loadExtension(extensionJar: File) {
|
||||
lateinit var url: URL
|
||||
|
||||
try {
|
||||
url = extensionJar.toURI().toURL()
|
||||
} catch (e: MalformedURLException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
val url = extensionJar.toURI().toURL()
|
||||
|
||||
val classLoader = URLClassLoader(arrayOf(url), this.plugin::class.java.classLoader)
|
||||
val ymlIn = classLoader.getResourceAsStream("extension.yml")
|
||||
|
||||
@@ -2,10 +2,11 @@ package com.willfp.eco.internal.factory
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.factory.NamespacedKeyFactory
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
class EcoNamespacedKeyFactory(private val plugin: EcoPlugin) : NamespacedKeyFactory {
|
||||
override fun create(key: String): NamespacedKey {
|
||||
return NamespacedKey(plugin, key)
|
||||
return NamespacedKeyUtils.create(plugin.name, key)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.willfp.eco.internal.fast
|
||||
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.objenesis.ObjenesisStd
|
||||
|
||||
interface InternalNamespacedKeyFactory {
|
||||
fun create(namespace: String, key: String): NamespacedKey
|
||||
}
|
||||
|
||||
class FastInternalNamespacedKeyFactory : InternalNamespacedKeyFactory {
|
||||
private val creator = ObjenesisStd().getInstantiatorOf(NamespacedKey::class.java)
|
||||
private val namespaceField = NamespacedKey::class.java.getDeclaredField("namespace")
|
||||
.apply { isAccessible = true }
|
||||
private val keyField = NamespacedKey::class.java.getDeclaredField("key")
|
||||
.apply { isAccessible = true }
|
||||
|
||||
|
||||
override fun create(namespace: String, key: String): NamespacedKey {
|
||||
val namespacedKey = creator.newInstance()
|
||||
keyField.set(namespacedKey, key.lowercase())
|
||||
namespaceField.set(namespacedKey, namespace.lowercase())
|
||||
return namespacedKey
|
||||
}
|
||||
}
|
||||
|
||||
class SafeInternalNamespacedKeyFactory : InternalNamespacedKeyFactory {
|
||||
override fun create(namespace: String, key: String): NamespacedKey {
|
||||
@Suppress("DEPRECATION")
|
||||
return NamespacedKey(namespace, key)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
|
||||
class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
||||
private var captive = false
|
||||
private var modifier: SlotModifier = SlotModifier{ player, menu, _ -> provider.provide(player, menu)}
|
||||
private var modifier: SlotModifier = SlotModifier { player, menu, _ -> provider.provide(player, menu) }
|
||||
|
||||
private var onLeftClick =
|
||||
SlotHandler { _, _, _ -> run { } }
|
||||
|
||||
@@ -32,7 +32,7 @@ class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExp
|
||||
player: Player?,
|
||||
identifier: String
|
||||
): String {
|
||||
return PlaceholderManager.getResult(player, identifier)
|
||||
return PlaceholderManager.getResult(player, identifier, plugin)
|
||||
}
|
||||
|
||||
override fun registerIntegration() {
|
||||
@@ -49,4 +49,14 @@ class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExp
|
||||
): String {
|
||||
return PlaceholderAPI.setPlaceholders(player, text)
|
||||
}
|
||||
|
||||
override fun findPlaceholdersIn(text: String): MutableList<String> {
|
||||
val placeholders = mutableListOf<String>()
|
||||
val matcher = PlaceholderAPI.getPlaceholderPattern().matcher(text)
|
||||
while (matcher.find()) {
|
||||
placeholders.add(matcher.group())
|
||||
}
|
||||
|
||||
return placeholders
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package com.willfp.eco.internal.items
|
||||
|
||||
import com.willfp.eco.core.fast.FastItemStack
|
||||
import com.willfp.eco.core.items.args.LookupArgParser
|
||||
import org.bukkit.NamespacedKey
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta
|
||||
@@ -20,7 +20,7 @@ class ArgParserEnchantment : LookupArgParser {
|
||||
continue
|
||||
}
|
||||
|
||||
val enchant = Enchantment.getByKey(NamespacedKey.minecraft(argSplit[0].lowercase()))
|
||||
val enchant = Enchantment.getByKey(NamespacedKeyUtils.create("minecraft", argSplit[0]))
|
||||
val level = argSplit[1].toIntOrNull()
|
||||
|
||||
if (enchant != null && level != null) {
|
||||
|
||||
@@ -11,12 +11,7 @@ class ArgParserFlag : LookupArgParser {
|
||||
val flags = mutableSetOf<ItemFlag>()
|
||||
|
||||
for (arg in args) {
|
||||
val flag = try {
|
||||
ItemFlag.valueOf(arg.uppercase())
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
} ?: continue
|
||||
|
||||
val flag = kotlin.runCatching { ItemFlag.valueOf(arg.uppercase()) }.getOrNull() ?: continue
|
||||
flags.add(flag)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.core.display.Display
|
||||
import com.willfp.eco.internal.spigot.proxy.VillagerTradeProxy
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe
|
||||
@@ -30,21 +31,11 @@ class VillagerTrade : VillagerTradeProxy {
|
||||
}
|
||||
|
||||
private fun getHandle(recipe: CraftMerchantRecipe): net.minecraft.server.v1_16_R3.MerchantRecipe {
|
||||
try {
|
||||
return handle[recipe] as net.minecraft.server.v1_16_R3.MerchantRecipe
|
||||
} catch (e: IllegalAccessException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
throw IllegalArgumentException("Not CMR")
|
||||
return handle[recipe] as net.minecraft.server.v1_16_R3.MerchantRecipe
|
||||
}
|
||||
|
||||
init {
|
||||
try {
|
||||
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
|
||||
handle.isAccessible = true
|
||||
} catch (e: NoSuchFieldException) {
|
||||
e.printStackTrace()
|
||||
throw RuntimeException("Error!")
|
||||
}
|
||||
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
|
||||
handle.isAccessible = true
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3.fast
|
||||
|
||||
import com.willfp.eco.internal.fast.EcoFastItemStack
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import net.minecraft.server.v1_16_R3.Item
|
||||
import net.minecraft.server.v1_16_R3.ItemEnchantedBook
|
||||
@@ -11,7 +12,6 @@ import net.minecraft.server.v1_16_R3.NBTTagList
|
||||
import net.minecraft.server.v1_16_R3.NBTTagString
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
|
||||
import org.bukkit.craftbukkit.v1_16_R3.util.CraftMagicNumbers
|
||||
import org.bukkit.craftbukkit.v1_16_R3.util.CraftNamespacedKey
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.inventory.ItemFlag
|
||||
import kotlin.experimental.and
|
||||
@@ -29,7 +29,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
val compound = base as NBTTagCompound
|
||||
val key = compound.getString("id")
|
||||
val level: Int = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
|
||||
val found = Enchantment.getByKey(CraftNamespacedKey.fromStringOrNull(key))
|
||||
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key))
|
||||
if (found != null) {
|
||||
foundEnchantments[found] = level
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "1.3.3"
|
||||
id("io.papermc.paperweight.userdev") version "1.3.4"
|
||||
}
|
||||
|
||||
group = "com.willfp"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_17_R1.fast
|
||||
|
||||
import com.willfp.eco.internal.fast.EcoFastItemStack
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
@@ -11,7 +12,6 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
|
||||
import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers
|
||||
import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.inventory.ItemFlag
|
||||
import kotlin.experimental.and
|
||||
@@ -31,7 +31,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
val compound = base as CompoundTag
|
||||
val key = compound.getString("id")
|
||||
val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
|
||||
val found = Enchantment.getByKey(CraftNamespacedKey.fromStringOrNull(key))
|
||||
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key))
|
||||
if (found != null) {
|
||||
foundEnchantments[found] = level
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "1.3.3"
|
||||
id("io.papermc.paperweight.userdev") version "1.3.4"
|
||||
}
|
||||
|
||||
group = "com.willfp"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_18_R1.fast
|
||||
|
||||
import com.willfp.eco.internal.fast.EcoFastItemStack
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
@@ -11,7 +12,6 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
|
||||
import org.bukkit.craftbukkit.v1_18_R1.util.CraftMagicNumbers
|
||||
import org.bukkit.craftbukkit.v1_18_R1.util.CraftNamespacedKey
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.inventory.ItemFlag
|
||||
import kotlin.experimental.and
|
||||
@@ -24,15 +24,15 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
|
||||
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> {
|
||||
val enchantmentNBT =
|
||||
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
|
||||
if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
|
||||
handle
|
||||
) else handle.enchantmentTags
|
||||
) else handle.getEnchantmentTags()
|
||||
val foundEnchantments: MutableMap<Enchantment, Int> = HashMap()
|
||||
for (base in enchantmentNBT) {
|
||||
val compound = base as CompoundTag
|
||||
val key = compound.getString("id")
|
||||
val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
|
||||
val found = Enchantment.getByKey(CraftNamespacedKey.fromStringOrNull(key))
|
||||
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key))
|
||||
if (found != null) {
|
||||
foundEnchantments[found] = level
|
||||
}
|
||||
@@ -45,9 +45,9 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
checkStored: Boolean
|
||||
): Int {
|
||||
val enchantmentNBT =
|
||||
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
|
||||
if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
|
||||
handle
|
||||
) else handle.enchantmentTags
|
||||
) else handle.getEnchantmentTags()
|
||||
for (base in enchantmentNBT) {
|
||||
val compound = base as CompoundTag
|
||||
val key = compound.getString("id")
|
||||
@@ -152,16 +152,16 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
|
||||
private var flagBits: Int
|
||||
get() =
|
||||
if (handle.hasTag() && handle.tag!!.contains(
|
||||
if (handle.hasTag() && handle.getTag()!!.contains(
|
||||
"HideFlags",
|
||||
99
|
||||
)
|
||||
) handle.tag!!.getInt("HideFlags") else 0
|
||||
) handle.getTag()!!.getInt("HideFlags") else 0
|
||||
set(value) =
|
||||
handle.orCreateTag.putInt("HideFlags", value)
|
||||
handle.getOrCreateTag().putInt("HideFlags", value)
|
||||
|
||||
override fun getRepairCost(): Int {
|
||||
return handle.baseRepairCost
|
||||
return handle.getBaseRepairCost()
|
||||
}
|
||||
|
||||
override fun setRepairCost(cost: Int) {
|
||||
@@ -177,7 +177,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.getItem()))
|
||||
return handle.getTag()?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.getItem()))
|
||||
}
|
||||
|
||||
private fun apply() {
|
||||
|
||||
@@ -5,6 +5,7 @@ dependencies {
|
||||
implementation('net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT') {
|
||||
exclude group: 'net.kyori', module: 'adventure-api'
|
||||
}
|
||||
implementation 'com.github.Redempt:Crunch:1.0'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
|
||||
compileOnly 'com.google.code.gson:gson:2.8.8'
|
||||
@@ -25,6 +26,7 @@ dependencies {
|
||||
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.202'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.10'
|
||||
compileOnly 'com.github.oraxen:oraxen:bd81ace154'
|
||||
compileOnly 'com.github.Ssomar-Developement:ExecutableItems:master-SNAPSHOT'
|
||||
compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0'
|
||||
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
|
||||
compileOnly 'com.arcaniax:HeadDatabase-API:1.3.0'
|
||||
@@ -38,10 +40,9 @@ dependencies {
|
||||
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:1.8.3'
|
||||
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
|
||||
compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT'
|
||||
compileOnly 'com.google.guava:guava:31.0.1-jre'
|
||||
compileOnly 'com.iridium:IridiumSkyblock:3.1.2'
|
||||
compileOnly 'com.github.WhipDevelopment:CrashClaim:f9cd7d92eb'
|
||||
compileOnly 'com.wolfyscript.wolfyutilities:wolfyutilities:1.7.8.1'
|
||||
compileOnly 'com.wolfyscript.wolfyutilities:wolfyutilities:3.16.0.0'
|
||||
compileOnly 'com.github.decentsoftware-eu:decentholograms:2.1.2'
|
||||
compileOnly 'io.lumine.xikage:MythicMobs:4.9.1'
|
||||
|
||||
@@ -53,6 +54,9 @@ dependencies {
|
||||
compileOnly 'com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT'
|
||||
compileOnly 'com.github.sirblobman.combatlogx.expansion:newbie-helper:11.0.0.0-SNAPSHOT'
|
||||
|
||||
// LibsDisguises
|
||||
compileOnly 'LibsDisguises:LibsDisguises:10.0.26'
|
||||
|
||||
compileOnly fileTree(dir: '../../lib', include: ['*.jar'])
|
||||
}
|
||||
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.recipes;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.items.Items;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.Recipes;
|
||||
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
|
||||
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.CraftItemEvent;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.event.player.PlayerRecipeDiscoverEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements Listener {
|
||||
public ShapedRecipeListener(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
private void allow(@NotNull final Event event,
|
||||
@NotNull final CraftingRecipe recipe) {
|
||||
if (event instanceof PrepareItemCraftEvent) {
|
||||
((PrepareItemCraftEvent) event).getInventory().setResult(recipe.getOutput());
|
||||
}
|
||||
|
||||
if (event instanceof CraftItemEvent) {
|
||||
((CraftItemEvent) event).getInventory().setResult(recipe.getOutput());
|
||||
}
|
||||
}
|
||||
|
||||
private void deny(@NotNull final Event event) {
|
||||
if (event instanceof PrepareItemCraftEvent) {
|
||||
((PrepareItemCraftEvent) event).getInventory().setResult(new ItemStack(Material.AIR));
|
||||
}
|
||||
|
||||
if (event instanceof CraftItemEvent) {
|
||||
((CraftItemEvent) event).getInventory().setResult(new ItemStack(Material.AIR));
|
||||
((CraftItemEvent) event).setResult(Event.Result.DENY);
|
||||
((CraftItemEvent) event).setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void complexRecipeListener(@NotNull final PrepareItemCraftEvent event) {
|
||||
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EcoPlugin.getPluginNames().contains(recipe.getKey().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(event.getInventory().getViewers().get(0) instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack[] matrix = event.getInventory().getMatrix();
|
||||
CraftingRecipe matched = Recipes.getMatch(matrix);
|
||||
|
||||
if (matched == null) {
|
||||
deny(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (matched.test(matrix)) {
|
||||
if (matched.getPermission() != null) {
|
||||
if (player.hasPermission(matched.getPermission())) {
|
||||
allow(event, matched);
|
||||
} else {
|
||||
deny(event);
|
||||
}
|
||||
} else {
|
||||
allow(event, matched);
|
||||
}
|
||||
} else {
|
||||
deny(event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void complexRecipeListener(@NotNull final CraftItemEvent event) {
|
||||
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EcoPlugin.getPluginNames().contains(recipe.getKey().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(event.getInventory().getViewers().get(0) instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack[] matrix = event.getInventory().getMatrix();
|
||||
CraftingRecipe matched = Recipes.getMatch(matrix);
|
||||
|
||||
if (matched == null) {
|
||||
deny(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (matched.test(matrix)) {
|
||||
if (matched.getPermission() != null) {
|
||||
if (player.hasPermission(matched.getPermission())) {
|
||||
allow(event, matched);
|
||||
} else {
|
||||
deny(event);
|
||||
}
|
||||
} else {
|
||||
allow(event, matched);
|
||||
}
|
||||
} else {
|
||||
deny(event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void stackedRecipeListener(@NotNull final CraftItemEvent event) {
|
||||
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EcoPlugin.getPluginNames().contains(recipe.getKey().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack[] matrix = event.getInventory().getMatrix();
|
||||
CraftingRecipe matched = Recipes.getMatch(matrix);
|
||||
|
||||
if (matched == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isStackedRecipe = false;
|
||||
|
||||
int upperBound = 64;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack inMatrix = event.getInventory().getMatrix()[i];
|
||||
TestableItem inRecipe = matched.getParts().get(i);
|
||||
|
||||
if (inRecipe instanceof TestableStack testableStack) {
|
||||
int max = Math.floorDiv(inMatrix.getAmount(), testableStack.getAmount());
|
||||
if (max < upperBound) {
|
||||
upperBound = max;
|
||||
}
|
||||
isStackedRecipe = true;
|
||||
} else if (inMatrix != null) {
|
||||
int max = inMatrix.getAmount();
|
||||
if (max < upperBound) {
|
||||
upperBound = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStackedRecipe) {
|
||||
return;
|
||||
}
|
||||
|
||||
int toGivePerRecipe = event.getRecipe().getResult().getAmount();
|
||||
int maxStackSize = event.getRecipe().getResult().getMaxStackSize();
|
||||
while (toGivePerRecipe * upperBound > maxStackSize) {
|
||||
upperBound--;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack inMatrix = event.getInventory().getMatrix()[i];
|
||||
TestableItem inRecipe = matched.getParts().get(i);
|
||||
|
||||
if (inRecipe instanceof TestableStack testableStack) {
|
||||
if (event.isShiftClick()) {
|
||||
int amount = inMatrix.getAmount() + 1;
|
||||
for (int j = 0; j < upperBound; j++) {
|
||||
amount -= testableStack.getAmount();
|
||||
}
|
||||
inMatrix.setAmount(amount);
|
||||
} else {
|
||||
inMatrix.setAmount(inMatrix.getAmount() - (testableStack.getAmount() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int finalUpperBound = upperBound;
|
||||
|
||||
if (event.isShiftClick()) {
|
||||
ItemStack result = event.getInventory().getResult();
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.setAmount(result.getAmount() * finalUpperBound);
|
||||
event.getInventory().setResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventUsingComplexPartInEcoRecipe(@NotNull final PrepareItemCraftEvent event) {
|
||||
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CraftingRecipe craftingRecipe = Recipes.getRecipe(recipe.getKey());
|
||||
|
||||
if (!(craftingRecipe instanceof ShapedCraftingRecipe shapedCraftingRecipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack itemStack = event.getInventory().getMatrix()[i];
|
||||
TestableItem part = shapedCraftingRecipe.getParts().get(i);
|
||||
if (part instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (part instanceof ModifiedTestableItem modified) {
|
||||
if (modified.getHandle() instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (part instanceof TestableStack modified) {
|
||||
if (modified.getHandle() instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventUsingComplexPartInEcoRecipe(@NotNull final CraftItemEvent event) {
|
||||
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CraftingRecipe craftingRecipe = Recipes.getRecipe(recipe.getKey());
|
||||
|
||||
if (!(craftingRecipe instanceof ShapedCraftingRecipe shapedCraftingRecipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack itemStack = event.getInventory().getMatrix()[i];
|
||||
TestableItem part = shapedCraftingRecipe.getParts().get(i);
|
||||
if (part instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
event.setResult(Event.Result.DENY);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (part instanceof ModifiedTestableItem modified) {
|
||||
if (modified.getHandle() instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
event.setResult(Event.Result.DENY);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (part instanceof TestableStack modified) {
|
||||
if (modified.getHandle() instanceof MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventUsingComplexPartInVanillaRecipe(@NotNull final PrepareItemCraftEvent event) {
|
||||
if (!(event.getRecipe() instanceof Keyed recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (EcoPlugin.getPluginNames().contains(recipe.getKey().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ItemStack itemStack : event.getInventory().getMatrix()) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventUsingComplexPartInVanillaRecipe(@NotNull final CraftItemEvent event) {
|
||||
if (!(event.getRecipe() instanceof Keyed recipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (EcoPlugin.getPluginNames().contains(recipe.getKey().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ItemStack itemStack : event.getInventory().getMatrix()) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.getInventory().setResult(new ItemStack(Material.AIR));
|
||||
event.setResult(Event.Result.DENY);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventLearningDisplayedRecipes(@NotNull final PlayerRecipeDiscoverEvent event) {
|
||||
if (!EcoPlugin.getPluginNames().contains(event.getRecipe().getNamespace())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getRecipe().getKey().contains("_displayed")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ import com.willfp.eco.internal.extensions.EcoExtensionLoader
|
||||
import com.willfp.eco.internal.factory.EcoMetadataValueFactory
|
||||
import com.willfp.eco.internal.factory.EcoNamespacedKeyFactory
|
||||
import com.willfp.eco.internal.factory.EcoRunnableFactory
|
||||
import com.willfp.eco.internal.fast.FastInternalNamespacedKeyFactory
|
||||
import com.willfp.eco.internal.fast.InternalNamespacedKeyFactory
|
||||
import com.willfp.eco.internal.fast.SafeInternalNamespacedKeyFactory
|
||||
import com.willfp.eco.internal.gui.EcoGUIFactory
|
||||
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
|
||||
import com.willfp.eco.internal.logging.EcoLogger
|
||||
@@ -21,7 +24,7 @@ import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||
import com.willfp.eco.internal.requirement.EcoRequirementFactory
|
||||
import com.willfp.eco.internal.scheduling.EcoScheduler
|
||||
import com.willfp.eco.internal.spigot.data.EcoKeyRegistry
|
||||
import com.willfp.eco.internal.spigot.data.EcoPlayerProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.MySQLDataHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.YamlDataHandler
|
||||
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
||||
@@ -29,6 +32,7 @@ import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.logging.Logger
|
||||
@@ -39,11 +43,16 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
private val requirementFactory = EcoRequirementFactory()
|
||||
private var adventure: BukkitAudiences? = null
|
||||
private val keyRegistry = EcoKeyRegistry(this)
|
||||
private val playerProfileHandler = EcoPlayerProfileHandler(
|
||||
private val playerProfileHandler = EcoProfileHandler(
|
||||
if (this.configYml.getBool("mysql.enabled"))
|
||||
MySQLDataHandler(this) else YamlDataHandler(this)
|
||||
)
|
||||
|
||||
@Suppress("RedundantNullableReturnType")
|
||||
private val keyFactory: InternalNamespacedKeyFactory? =
|
||||
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
||||
SafeInternalNamespacedKeyFactory() else FastInternalNamespacedKeyFactory()
|
||||
|
||||
override fun createScheduler(plugin: EcoPlugin): EcoScheduler {
|
||||
return EcoScheduler(plugin)
|
||||
}
|
||||
@@ -136,7 +145,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
return keyRegistry
|
||||
}
|
||||
|
||||
override fun getPlayerProfileHandler(): EcoPlayerProfileHandler {
|
||||
override fun getProfileHandler(): EcoProfileHandler {
|
||||
return playerProfileHandler
|
||||
}
|
||||
|
||||
@@ -147,4 +156,9 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
override fun createDummyEntity(location: Location): Entity {
|
||||
return getProxy(DummyEntityProxy::class.java).createDummyEntity(location)
|
||||
}
|
||||
|
||||
override fun createNamespacedKey(namespace: String, key: String): NamespacedKey {
|
||||
@Suppress("DEPRECATION")
|
||||
return keyFactory?.create(namespace, key) ?: NamespacedKey(namespace, key)
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import com.willfp.eco.internal.entities.EntityArgParserKnockback
|
||||
import com.willfp.eco.internal.entities.EntityArgParserKnockbackResistance
|
||||
import com.willfp.eco.internal.entities.EntityArgParserName
|
||||
import com.willfp.eco.internal.entities.EntityArgParserNoAI
|
||||
import com.willfp.eco.internal.entities.EntityArgParserSilent
|
||||
import com.willfp.eco.internal.entities.EntityArgParserSize
|
||||
import com.willfp.eco.internal.entities.EntityArgParserSpawnReinforcements
|
||||
import com.willfp.eco.internal.entities.EntityArgParserSpeed
|
||||
@@ -81,13 +82,17 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPreve
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefIridiumSkyblock
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefKingdoms
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefLands
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefRPGHorses
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefWorldGuard
|
||||
import com.willfp.eco.internal.spigot.integrations.customentities.CustomEntitiesMythicMobs
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsCustomCrafting
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsExecutableItems
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsHeadDatabase
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsItemsAdder
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsOraxen
|
||||
import com.willfp.eco.internal.spigot.integrations.customrecipes.CustomRecipeCustomCrafting
|
||||
import com.willfp.eco.internal.spigot.integrations.economy.EconomyVault
|
||||
import com.willfp.eco.internal.spigot.integrations.hologram.HologramCMI
|
||||
import com.willfp.eco.internal.spigot.integrations.hologram.HologramDecentHolograms
|
||||
@@ -95,12 +100,17 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicD
|
||||
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
|
||||
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopShopGuiPlus
|
||||
import com.willfp.eco.internal.spigot.math.evaluateExpression
|
||||
import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInEco
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
|
||||
import com.willfp.eco.util.BlockUtils
|
||||
import com.willfp.eco.util.NumberUtils
|
||||
import com.willfp.eco.util.ServerUtils
|
||||
import com.willfp.eco.util.SkullUtils
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||
@@ -142,6 +152,11 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
Entities.registerArgParser(EntityArgParserAdult())
|
||||
Entities.registerArgParser(EntityArgParserCharged())
|
||||
Entities.registerArgParser(EntityArgParserExplosionRadius())
|
||||
Entities.registerArgParser(EntityArgParserSilent())
|
||||
|
||||
ShapedRecipeListener.registerListener(ComplexInComplex())
|
||||
ShapedRecipeListener.registerListener(ComplexInEco())
|
||||
ShapedRecipeListener.registerListener(ComplexInVanilla())
|
||||
|
||||
val skullProxy = getProxy(SkullProxy::class.java)
|
||||
SkullUtils.initialize(
|
||||
@@ -155,6 +170,8 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
val tpsProxy = getProxy(TPSProxy::class.java)
|
||||
ServerUtils.initialize { tpsProxy.getTPS() }
|
||||
|
||||
NumberUtils.initCrunch { exp, player -> evaluateExpression(exp, player) }
|
||||
|
||||
postInit()
|
||||
}
|
||||
|
||||
@@ -178,7 +195,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
override fun handleDisable() {
|
||||
this.logger.info("Saving player data...")
|
||||
val start = System.currentTimeMillis()
|
||||
Eco.getHandler().playerProfileHandler.save()
|
||||
Eco.getHandler().profileHandler.save()
|
||||
this.logger.info("Saved player data! Took ${System.currentTimeMillis() - start}ms")
|
||||
Eco.getHandler().adventure?.close()
|
||||
}
|
||||
@@ -213,6 +230,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
IntegrationLoader("Towny") { AntigriefManager.register(AntigriefTowny()) },
|
||||
IntegrationLoader("Lands") { AntigriefManager.register(AntigriefLands(this)) },
|
||||
IntegrationLoader("Kingdoms") { AntigriefManager.register(AntigriefKingdoms()) },
|
||||
IntegrationLoader("RPGHorses") { AntigriefManager.register(AntigriefRPGHorses()) },
|
||||
IntegrationLoader("CrashClaim") { AntigriefManager.register(AntigriefCrashClaim()) },
|
||||
IntegrationLoader("CombatLogX") {
|
||||
val pluginManager = Bukkit.getPluginManager()
|
||||
@@ -235,12 +253,18 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
IntegrationLoader("Alice") { AnticheatManager.register(this, AnticheatAlice()) },
|
||||
|
||||
// Custom Entities
|
||||
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs())},
|
||||
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) },
|
||||
|
||||
// Custom Items
|
||||
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) },
|
||||
IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder()) },
|
||||
IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) },
|
||||
IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) },
|
||||
IntegrationLoader("CustomCrafting") {
|
||||
CustomItemsManager.register(CustomItemsCustomCrafting()); ShapedRecipeListener.registerValidator(
|
||||
CustomRecipeCustomCrafting()
|
||||
)
|
||||
},
|
||||
|
||||
// Shop
|
||||
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
|
||||
@@ -290,7 +314,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
NaturalExpGainListeners(),
|
||||
ArmorListener(),
|
||||
EntityDeathByEntityListeners(this),
|
||||
ShapedRecipeListener(this),
|
||||
ShapedRecipeListener(),
|
||||
GUIListener(this),
|
||||
ArrowDataListener(this),
|
||||
ArmorChangeEventListeners(this),
|
||||
|
||||
@@ -15,7 +15,7 @@ class DataListener(
|
||||
) : Listener {
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
fun onLeave(event: PlayerQuitEvent) {
|
||||
Eco.getHandler().playerProfileHandler.unloadPlayer(event.player.uniqueId)
|
||||
Eco.getHandler().profileHandler.unloadPlayer(event.player.uniqueId)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -27,6 +27,6 @@ class DataListener(
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
fun onLogin(event: PlayerLoginEvent) {
|
||||
Eco.getHandler().playerProfileHandler.unloadPlayer(event.player.uniqueId)
|
||||
Eco.getHandler().profileHandler.unloadPlayer(event.player.uniqueId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class EcoKeyRegistry(
|
||||
|
||||
this.registry[key.key] = key
|
||||
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).updateKeys()
|
||||
(Eco.getHandler().profileHandler as EcoProfileHandler).updateKeys()
|
||||
}
|
||||
|
||||
override fun getRegisteredKeys(): MutableSet<PersistentDataKey<*>> {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package com.willfp.eco.internal.spigot.data
|
||||
|
||||
import com.willfp.eco.core.data.PlayerProfile
|
||||
import com.willfp.eco.core.data.Profile
|
||||
import com.willfp.eco.core.data.ServerProfile
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.internal.spigot.data.storage.DataHandler
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class EcoPlayerProfile(
|
||||
abstract class EcoProfile(
|
||||
val data: MutableMap<PersistentDataKey<*>, Any>,
|
||||
val uuid: UUID,
|
||||
private val handler: DataHandler
|
||||
) : PlayerProfile {
|
||||
) : Profile {
|
||||
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
|
||||
this.data[key] = value
|
||||
|
||||
@@ -30,22 +32,37 @@ class EcoPlayerProfile(
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is EcoPlayerProfile) {
|
||||
if (other !is EcoProfile) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.data == other.data
|
||||
return this.data == other.data && this.uuid == other.uuid
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return data.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "EcoPlayerProfile{$data}"
|
||||
return this.data.hashCode()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CHANGE_MAP: MutableMap<UUID, MutableSet<PersistentDataKey<*>>> = ConcurrentHashMap()
|
||||
}
|
||||
}
|
||||
|
||||
class EcoPlayerProfile(
|
||||
data: MutableMap<PersistentDataKey<*>, Any>,
|
||||
uuid: UUID,
|
||||
handler: DataHandler
|
||||
) : EcoProfile(data, uuid, handler), PlayerProfile {
|
||||
override fun toString(): String {
|
||||
return "EcoPlayerProfile{uuid=$uuid}"
|
||||
}
|
||||
}
|
||||
|
||||
class EcoServerProfile(
|
||||
data: MutableMap<PersistentDataKey<*>, Any>,
|
||||
handler: DataHandler
|
||||
) : EcoProfile(data, serverProfileUUID, handler), ServerProfile {
|
||||
override fun toString(): String {
|
||||
return "EcoServerProfile"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
package com.willfp.eco.internal.spigot.data
|
||||
|
||||
import com.willfp.eco.core.data.PlayerProfile
|
||||
import com.willfp.eco.core.data.PlayerProfileHandler
|
||||
import com.willfp.eco.core.data.Profile
|
||||
import com.willfp.eco.core.data.ProfileHandler
|
||||
import com.willfp.eco.core.data.ServerProfile
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.internal.spigot.data.storage.DataHandler
|
||||
import java.util.UUID
|
||||
|
||||
class EcoPlayerProfileHandler(
|
||||
private val handler: DataHandler
|
||||
) : PlayerProfileHandler {
|
||||
private val loaded = mutableMapOf<UUID, PlayerProfile>()
|
||||
val serverProfileUUID = UUID(0, 0)
|
||||
|
||||
override fun load(uuid: UUID): PlayerProfile {
|
||||
class EcoProfileHandler(
|
||||
private val handler: DataHandler
|
||||
) : ProfileHandler {
|
||||
private val loaded = mutableMapOf<UUID, Profile>()
|
||||
|
||||
private fun loadGenericProfile(uuid: UUID): Profile {
|
||||
val found = loaded[uuid]
|
||||
if (found != null) {
|
||||
return found
|
||||
@@ -19,13 +23,23 @@ class EcoPlayerProfileHandler(
|
||||
|
||||
val data = mutableMapOf<PersistentDataKey<*>, Any>()
|
||||
|
||||
val profile = EcoPlayerProfile(data, uuid, handler)
|
||||
val profile = if (uuid == serverProfileUUID)
|
||||
EcoServerProfile(data, handler) else EcoPlayerProfile(data, uuid, handler)
|
||||
|
||||
loaded[uuid] = profile
|
||||
return profile
|
||||
}
|
||||
|
||||
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = PlayerProfile.load(uuid)
|
||||
override fun load(uuid: UUID): PlayerProfile {
|
||||
return loadGenericProfile(uuid) as PlayerProfile
|
||||
}
|
||||
|
||||
override fun loadServerProfile(): ServerProfile {
|
||||
return loadGenericProfile(serverProfileUUID) as ServerProfile
|
||||
}
|
||||
|
||||
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = loadGenericProfile(uuid)
|
||||
|
||||
for (key in keys) {
|
||||
handler.write(uuid, key.key, profile.read(key))
|
||||
@@ -55,7 +55,7 @@ class MySQLDataHandler(
|
||||
}
|
||||
|
||||
// Get Exposed to shut the hell up
|
||||
try {
|
||||
runCatching {
|
||||
exposedLogger::class.java.getDeclaredField("logger").apply { isAccessible = true }
|
||||
.apply {
|
||||
get(exposedLogger).apply {
|
||||
@@ -63,8 +63,6 @@ class MySQLDataHandler(
|
||||
.invoke(this, Level.OFF)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Eco.getHandler().ecoPlugin.logger.warning("Failed to silence Exposed logger! You might get some console spam")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@ package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.internal.spigot.data.EcoPlayerProfile
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfile
|
||||
|
||||
class ProfileSaver(plugin: EcoPlugin) {
|
||||
init {
|
||||
plugin.scheduler.runTimer({
|
||||
for ((uuid, set) in EcoPlayerProfile.CHANGE_MAP) {
|
||||
Eco.getHandler().playerProfileHandler.saveKeysForPlayer(uuid, set)
|
||||
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
||||
Eco.getHandler().profileHandler.saveKeysFor(uuid, set)
|
||||
}
|
||||
EcoPlayerProfile.CHANGE_MAP.clear()
|
||||
EcoProfile.CHANGE_MAP.clear()
|
||||
}, 1, 1)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import com.willfp.eco.core.AbstractPacketAdapter
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.internal.spigot.proxy.AutoCraftProxy
|
||||
import org.bukkit.entity.Player
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
class PacketAutoRecipe(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.AUTO_RECIPE, false) {
|
||||
override fun onSend(
|
||||
@@ -27,10 +26,6 @@ class PacketAutoRecipe(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packet
|
||||
getPlugin().getProxy(AutoCraftProxy::class.java).modifyPacket(packet.handle)
|
||||
val newAutoRecipe = PacketContainer(PacketType.Play.Server.AUTO_RECIPE)
|
||||
newAutoRecipe.minecraftKeys.write(0, packet.minecraftKeys.read(0))
|
||||
try {
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newAutoRecipe)
|
||||
} catch (e: InvocationTargetException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newAutoRecipe)
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import com.comphenix.protocol.events.PacketContainer
|
||||
import com.comphenix.protocol.events.PacketEvent
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.AbstractPacketAdapter
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.display.Display
|
||||
import com.willfp.eco.core.fast.FastItemStack
|
||||
import com.willfp.eco.core.items.HashedItem
|
||||
import com.willfp.eco.internal.spigot.display.frame.DisplayFrame
|
||||
import com.willfp.eco.internal.spigot.display.frame.HashedItem
|
||||
import com.willfp.eco.internal.spigot.display.frame.lastDisplayFrame
|
||||
import com.willfp.eco.util.ServerUtils
|
||||
import org.bukkit.entity.Player
|
||||
@@ -47,34 +47,35 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
|
||||
handleRateLimit(player)
|
||||
|
||||
if (usingAsync(player)) {
|
||||
val newPacket = packet.shallowClone()
|
||||
|
||||
fun modifyAndSend(itemStacks: MutableList<ItemStack>, windowId: Int, player: Player) {
|
||||
modifyWindowItems(itemStacks, windowId, player)
|
||||
|
||||
newPacket.itemListModifier.write(0, itemStacks)
|
||||
|
||||
ignorePacketList.add(player.name)
|
||||
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket)
|
||||
}
|
||||
val newPacket = packet.deepClone()
|
||||
|
||||
executor.execute {
|
||||
try {
|
||||
modifyAndSend(itemStacks, windowId, player)
|
||||
} catch (e: Exception) {
|
||||
if (this.getPlugin().configYml.getBool("async-display.log-errors")) {
|
||||
this.getPlugin().logger.warning("Error happened in async processing! Disable async display (/plugins/eco/config.yml)" +
|
||||
"if this is a frequent issue. (Remember to disable ratelimit and emergency too)")
|
||||
}
|
||||
|
||||
this.getPlugin().scheduler.run {
|
||||
modifyAndSend(itemStacks, windowId, player)
|
||||
}
|
||||
}
|
||||
runCatchingWithLogs { modifyAndSend(newPacket, itemStacks, windowId, player) }
|
||||
}
|
||||
} else {
|
||||
packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player))
|
||||
modifyPacket(packet, itemStacks, windowId, player)
|
||||
}
|
||||
}
|
||||
|
||||
private fun modifyPacket(
|
||||
packet: PacketContainer,
|
||||
itemStacks: MutableList<ItemStack>,
|
||||
windowId: Int,
|
||||
player: Player
|
||||
) {
|
||||
packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player))
|
||||
}
|
||||
|
||||
private fun modifyAndSend(
|
||||
packet: PacketContainer,
|
||||
itemStacks: MutableList<ItemStack>,
|
||||
windowId: Int,
|
||||
player: Player
|
||||
) {
|
||||
modifyPacket(packet, itemStacks, windowId, player)
|
||||
ignorePacketList.add(player.name)
|
||||
this.getPlugin().scheduler.run {
|
||||
runCatchingWithLogs { ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +137,7 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
|
||||
val frameMap = mutableMapOf<Byte, HashedItem>()
|
||||
|
||||
for (index in itemStacks.indices) {
|
||||
frameMap[index.toByte()] =
|
||||
HashedItem(FastItemStack.wrap(itemStacks[index]).hashCode(), itemStacks[index])
|
||||
frameMap[index.toByte()] = HashedItem.of(itemStacks[index])
|
||||
}
|
||||
|
||||
val newFrame = DisplayFrame(frameMap)
|
||||
@@ -161,4 +161,15 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
|
||||
|
||||
return itemStacks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> runCatchingWithLogs(toRun: () -> T): Result<T> {
|
||||
return runCatching { toRun() }.onFailure {
|
||||
if (Eco.getHandler().ecoPlugin.configYml.getBool("async-display.log-errors")) {
|
||||
Eco.getHandler().ecoPlugin.logger.warning(
|
||||
"Error happened in async processing! Disable async display (/plugins/eco/config.yml)" +
|
||||
"if this is a frequent issue. (Remember to disable ratelimit and emergency too)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.willfp.eco.internal.spigot.display.frame
|
||||
|
||||
import com.willfp.eco.core.items.HashedItem
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
data class HashedItem(val hash: Int, val item: ItemStack)
|
||||
|
||||
data class DisplayFrame(val items: Map<Byte, HashedItem>) {
|
||||
fun getChangedSlots(newFrame: DisplayFrame): List<Byte> {
|
||||
val changes = mutableListOf<Byte>()
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.antigrief
|
||||
|
||||
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.LivingEntity
|
||||
import org.bukkit.entity.Player
|
||||
import org.plugins.rpghorses.RPGHorsesMain
|
||||
|
||||
class AntigriefRPGHorses : AntigriefWrapper {
|
||||
override fun canBreakBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun canCreateExplosion(
|
||||
player: Player,
|
||||
location: Location
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun canPlaceBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun canInjure(
|
||||
player: Player,
|
||||
victim: LivingEntity
|
||||
): Boolean {
|
||||
val horse = RPGHorsesMain.getInstance().rpgHorseManager.getRPGHorse(victim)?: return true
|
||||
return horse.horseOwner.uuid.equals(player.uniqueId)
|
||||
}
|
||||
|
||||
override fun canPickupItem(player: Player, location: Location): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "RPGHorses"
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package com.willfp.eco.internal.spigot.integrations.customentities
|
||||
|
||||
import com.willfp.eco.core.entities.CustomEntity
|
||||
import com.willfp.eco.core.integrations.customentities.CustomEntitiesWrapper
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
class CustomEntitiesMythicMobs : CustomEntitiesWrapper {
|
||||
override fun registerAllEntities() {
|
||||
@@ -11,7 +11,8 @@ class CustomEntitiesMythicMobs : CustomEntitiesWrapper {
|
||||
val api = MythicMobs.inst().apiHelper
|
||||
|
||||
for (id in mobManager.mobNames) {
|
||||
val key = NamespacedKeyUtils.create("mythicmobs", id.lowercase())
|
||||
val key = NamespacedKey.fromString("mythicmobs:${id.lowercase()}")
|
||||
key ?: continue
|
||||
CustomEntity(
|
||||
key,
|
||||
{
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import me.wolfyscript.utilities.util.NamespacedKey
|
||||
import me.wolfyscript.utilities.util.Registry
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.function.Predicate
|
||||
|
||||
class CustomItemsCustomCrafting : CustomItemsWrapper {
|
||||
override fun registerAllItems() {
|
||||
Items.registerItemProvider(CustomCraftingProvider())
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "CustomCrafting"
|
||||
}
|
||||
|
||||
private class CustomCraftingProvider : ItemProvider("customcrafting") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val nKey = key.replace("customcrafting:", "", ignoreCase = true)
|
||||
val itemKey = NamespacedKey("customcrafting", nKey)
|
||||
val item = Registry.CUSTOM_ITEMS.get(itemKey) ?: return null
|
||||
val namespacedKey = NamespacedKeyUtils.create("customcrafting", key)
|
||||
val stack = item.create(1)
|
||||
return CustomItem(
|
||||
namespacedKey,
|
||||
Predicate { test: ItemStack ->
|
||||
val customStack =
|
||||
me.wolfyscript.utilities.api.inventory.custom_items.CustomItem.getByItemStack(test)
|
||||
?: return@Predicate false
|
||||
val iKey = customStack.namespacedKey ?: return@Predicate false
|
||||
iKey.equals(key)
|
||||
},
|
||||
stack
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.ssomar.score.api.ExecutableItemsAPI
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.function.Predicate
|
||||
class CustomItemsExecutableItems: CustomItemsWrapper {
|
||||
override fun registerAllItems() {
|
||||
Items.registerItemProvider(ExecutableItemsProvider())
|
||||
}
|
||||
override fun getPluginName(): String {
|
||||
return "ExecutableItems"
|
||||
}
|
||||
private class ExecutableItemsProvider : ItemProvider("executableitems") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = ExecutableItemsAPI.getExecutableItem(key) ?: return null
|
||||
val namespacedKey = NamespacedKeyUtils.create("executableitems", key)
|
||||
return CustomItem(
|
||||
namespacedKey,
|
||||
Predicate { test: ItemStack ->
|
||||
val customStack = ExecutableItemsAPI.getExecutableItemConfig(test) ?: return@Predicate false
|
||||
customStack.id.equals(key, ignoreCase = true)
|
||||
},
|
||||
item
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customrecipes
|
||||
|
||||
import com.willfp.eco.core.integrations.Integration
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeValidator
|
||||
import me.wolfyscript.customcrafting.CustomCrafting
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class CustomRecipeCustomCrafting : RecipeValidator, Integration {
|
||||
override fun validate(event: GenericCraftEvent): Boolean {
|
||||
val player = event.inventory.viewers.getOrNull(0) as? Player ?: return false
|
||||
return CustomCrafting.inst().craftManager.has(player.uniqueId)
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "CustomCrafting"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.willfp.eco.internal.spigot.math
|
||||
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import org.bukkit.entity.Player
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.data.FastNumberParsing
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
|
||||
private val cache = mutableMapOf<String, CompiledExpression>()
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
fun evaluateExpression(expression: String, player: Player?): Double {
|
||||
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
.map { PlaceholderManager.translatePlaceholders(expression, player) }
|
||||
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = generateExpression(expression)
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
|
||||
private fun generateExpression(expression: String): CompiledExpression {
|
||||
val cached = cache[expression]
|
||||
|
||||
if (cached != null) {
|
||||
return cached
|
||||
}
|
||||
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
|
||||
val compiled = runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
cache[expression] = compiled
|
||||
return compiled
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.willfp.eco.internal.spigot.recipes
|
||||
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe
|
||||
import org.bukkit.Keyed
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.inventory.CraftItemEvent
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent
|
||||
import org.bukkit.inventory.CraftingInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
interface RecipeValidator {
|
||||
fun validate(event: GenericCraftEvent): Boolean
|
||||
}
|
||||
|
||||
interface RecipeListener {
|
||||
fun handle(event: GenericCraftEvent)
|
||||
}
|
||||
|
||||
interface GenericCraftEvent {
|
||||
val inventory: CraftingInventory
|
||||
val recipe: Keyed
|
||||
|
||||
fun allow(recipe: CraftingRecipe)
|
||||
fun deny()
|
||||
}
|
||||
|
||||
class WrappedPrepareItemCraftEvent(
|
||||
private val event: PrepareItemCraftEvent
|
||||
) : GenericCraftEvent {
|
||||
override val inventory: CraftingInventory
|
||||
get() = event.inventory
|
||||
|
||||
override val recipe: Keyed
|
||||
get() = event.recipe as Keyed
|
||||
|
||||
override fun allow(recipe: CraftingRecipe) {
|
||||
this.inventory.result = recipe.output
|
||||
}
|
||||
|
||||
override fun deny() {
|
||||
this.inventory.result = ItemStack(Material.AIR)
|
||||
}
|
||||
}
|
||||
|
||||
class WrappedCraftItemEvent(
|
||||
private val event: CraftItemEvent
|
||||
) : GenericCraftEvent {
|
||||
override val inventory: CraftingInventory
|
||||
get() = event.inventory
|
||||
|
||||
override val recipe: Keyed
|
||||
get() = event.recipe as Keyed
|
||||
|
||||
override fun allow(recipe: CraftingRecipe) {
|
||||
this.inventory.result = recipe.output
|
||||
}
|
||||
|
||||
override fun deny() {
|
||||
this.inventory.result = ItemStack(Material.AIR)
|
||||
event.result = Event.Result.DENY
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.willfp.eco.internal.spigot.recipes
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack
|
||||
import org.bukkit.Keyed
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.CraftItemEvent
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent
|
||||
import org.bukkit.event.player.PlayerRecipeDiscoverEvent
|
||||
import org.bukkit.inventory.ShapedRecipe
|
||||
|
||||
class ShapedRecipeListener : Listener {
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
fun stackedRecipeListener(event: CraftItemEvent) {
|
||||
val recipe = event.recipe as? ShapedRecipe ?: return
|
||||
|
||||
if (!EcoPlugin.getPluginNames().contains(recipe.key.namespace)) {
|
||||
return
|
||||
}
|
||||
|
||||
val matrix = event.inventory.matrix
|
||||
|
||||
val wrapped = WrappedCraftItemEvent(event)
|
||||
|
||||
if (validators.any { it.validate(wrapped) }) {
|
||||
return
|
||||
}
|
||||
|
||||
val matched = Recipes.getMatch(matrix)
|
||||
|
||||
if (matched == null) {
|
||||
wrapped.deny()
|
||||
return
|
||||
}
|
||||
|
||||
var isStackedRecipe = false
|
||||
var upperBound = 64
|
||||
for (i in 0..8) {
|
||||
val inMatrix = event.inventory.matrix.getOrNull(i)
|
||||
val inRecipe = matched.parts[i]
|
||||
|
||||
if (inRecipe is TestableStack) {
|
||||
val max = Math.floorDiv(inMatrix!!.amount, inRecipe.amount)
|
||||
if (max < upperBound) {
|
||||
upperBound = max
|
||||
}
|
||||
isStackedRecipe = true
|
||||
} else if (inMatrix != null) {
|
||||
val max = inMatrix.amount
|
||||
if (max < upperBound) {
|
||||
upperBound = max
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStackedRecipe) {
|
||||
return
|
||||
}
|
||||
|
||||
val toGivePerRecipe = event.recipe.result.amount
|
||||
val maxStackSize = event.recipe.result.maxStackSize
|
||||
while (toGivePerRecipe * upperBound > maxStackSize) {
|
||||
upperBound--
|
||||
}
|
||||
|
||||
for (i in 0..8) {
|
||||
val inMatrix = event.inventory.matrix[i]
|
||||
val inRecipe = matched.parts[i]
|
||||
|
||||
if (inRecipe is TestableStack) {
|
||||
if (event.isShiftClick) {
|
||||
var amount = inMatrix.amount + 1
|
||||
for (j in 0..upperBound) {
|
||||
amount -= inRecipe.amount
|
||||
}
|
||||
inMatrix.amount = amount
|
||||
} else {
|
||||
inMatrix.amount = inMatrix.amount - (inRecipe.amount - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.isShiftClick) {
|
||||
val result = event.inventory.result ?: return
|
||||
|
||||
result.amount = result.amount * upperBound
|
||||
event.inventory.result = result
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun preventLearningDisplayedRecipes(event: PlayerRecipeDiscoverEvent) {
|
||||
if (!EcoPlugin.getPluginNames().contains(event.recipe.namespace)) {
|
||||
return
|
||||
}
|
||||
if (event.recipe.key.contains("_displayed")) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun processListeners(event: PrepareItemCraftEvent) {
|
||||
if (event.recipe !is Keyed) {
|
||||
return
|
||||
}
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.handle(WrappedPrepareItemCraftEvent(event))
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun processListeners(event: CraftItemEvent) {
|
||||
if (event.recipe !is Keyed) {
|
||||
return
|
||||
}
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.handle(WrappedCraftItemEvent(event))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val validators = mutableListOf<RecipeValidator>()
|
||||
private val listeners = mutableListOf<RecipeListener>()
|
||||
|
||||
fun registerValidator(validator: RecipeValidator) {
|
||||
validators.add(validator)
|
||||
}
|
||||
|
||||
fun registerListener(listener: RecipeListener) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class ComplexInComplex : RecipeListener {
|
||||
override fun handle(event: GenericCraftEvent) {
|
||||
val recipe = event.recipe
|
||||
|
||||
if (!EcoPlugin.getPluginNames().contains(recipe.key.namespace)) {
|
||||
return
|
||||
}
|
||||
|
||||
val player = event.inventory.viewers.getOrNull(0) as? Player ?: return
|
||||
|
||||
val matrix = event.inventory.matrix
|
||||
|
||||
if (ShapedRecipeListener.validators.any { it.validate(event) }) {
|
||||
return
|
||||
}
|
||||
|
||||
val matched = Recipes.getMatch(matrix)
|
||||
|
||||
if (matched == null) {
|
||||
event.deny()
|
||||
return
|
||||
}
|
||||
|
||||
if (matched.test(matrix)) {
|
||||
if (matched.permission != null) {
|
||||
if (player.hasPermission(matched.permission!!)) {
|
||||
event.allow(matched)
|
||||
} else {
|
||||
event.deny()
|
||||
}
|
||||
} else {
|
||||
event.allow(matched)
|
||||
}
|
||||
} else {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.core.recipe.parts.MaterialTestableItem
|
||||
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack
|
||||
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
|
||||
class ComplexInEco : RecipeListener {
|
||||
override fun handle(event: GenericCraftEvent) {
|
||||
val craftingRecipe = Recipes.getRecipe(event.recipe.key)
|
||||
|
||||
if (craftingRecipe !is ShapedCraftingRecipe) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ShapedRecipeListener.validators.any { it.validate(event) }) {
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0..8) {
|
||||
val itemStack = event.inventory.matrix[i]
|
||||
val part = craftingRecipe.parts[i]
|
||||
when (part) {
|
||||
is MaterialTestableItem -> {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
is ModifiedTestableItem -> {
|
||||
if (part.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
is TestableStack -> {
|
||||
if (part.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
|
||||
class ComplexInVanilla : RecipeListener {
|
||||
override fun handle(event: GenericCraftEvent) {
|
||||
if (EcoPlugin.getPluginNames().contains(event.recipe.key.namespace)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ShapedRecipeListener.validators.any { it.validate(event) }) {
|
||||
return
|
||||
}
|
||||
|
||||
for (itemStack in event.inventory.matrix) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,17 @@ use-display-frame: true
|
||||
# that display frames will be cleared / deleted.
|
||||
display-frame-ttl: 17
|
||||
|
||||
# The default bukkit NamespacedKey creation can cause decent amounts of lag under
|
||||
# load due to the use of regex validation in the constructor. eco has its own system
|
||||
# to create NamespacedKeys, however it can be unsafe as it skips most validation checks.
|
||||
# If you encounter any bugs with this, then enable this option - however it will come
|
||||
# at a performance penalty.
|
||||
use-safer-namespacedkey-creation: false
|
||||
|
||||
# If the stack traces of extensions that failed to load should be logged. Disabled by
|
||||
# default to prevent users from reporting bugs. Enable if you're a developer.
|
||||
log-full-extension-errors: false
|
||||
|
||||
# Window items packets have the option to be run asynchronously. This may cause
|
||||
# some bugs and is considered experimental, however it has been tested without
|
||||
# any apparent issues. Enable this if performance is absolutely crucial or if you
|
||||
@@ -64,14 +75,14 @@ async-display:
|
||||
# If emergency async should be used.
|
||||
enabled: true
|
||||
# Below this TPS value, emergency async display will be used.
|
||||
cutoff: 18
|
||||
cutoff: 17
|
||||
|
||||
# If players with a large amount of display packets should have their processing
|
||||
# done asynchronously. This will help if a player is trying to crash the server
|
||||
# by overloading the display system.
|
||||
ratelimit:
|
||||
# If rate limit async display should be used.
|
||||
enabled: true
|
||||
enabled: false
|
||||
# The amount of window items packets per timeframe needed to enable async display
|
||||
# for a specified player.
|
||||
cutoff: 4
|
||||
|
||||
@@ -40,6 +40,9 @@ softdepend:
|
||||
- CrashClaim
|
||||
- DecentHolograms
|
||||
- MythicMobs
|
||||
- CustomCrafting
|
||||
- ExecutableItems
|
||||
- RPGHorses
|
||||
libraries:
|
||||
- 'org.reflections:reflections:0.9.12'
|
||||
- 'org.apache.maven:maven-artifact:3.0.3'
|
||||
@@ -53,4 +56,6 @@ libraries:
|
||||
- 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
|
||||
- 'mysql:mysql-connector-java:8.0.25'
|
||||
- 'com.google.guava:guava:31.0.1-jre'
|
||||
- 'com.zaxxer:HikariCP:5.0.0'
|
||||
- 'com.zaxxer:HikariCP:5.0.0'
|
||||
- 'org.objenesis:objenesis:3.2'
|
||||
- 'com.github.ben-manes.caffeine:caffeine:3.0.5'
|
||||
@@ -1,3 +1,3 @@
|
||||
version = 6.18.1
|
||||
version = 6.23.0
|
||||
plugin-name = eco
|
||||
kotlin.code.style = official
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user