Compare commits

...

67 Commits

Author SHA1 Message Date
Auxilor
aa1ce34cbc Updated to 6.24.4 2022-02-16 14:21:49 +00:00
Auxilor
47772c3ff7 Reverted Shaped Recipe changes 2022-02-16 14:21:03 +00:00
Auxilor
dfcac5d527 PR Changes 2022-02-14 13:28:37 +00:00
Auxilor
40f88f0b59 Revert "refactor(nms): Change checking if value is initialized to a lazy val"
This reverts commit 6361c0e8e9.
2022-02-14 13:28:25 +00:00
Auxilor
105355d967 Updated to 6.24.3 2022-02-14 13:15:55 +00:00
Will FP
3cddff22b8 Merge pull request #73
Bump com.github.johnrengelman.shadow from 7.1.0 to 7.1.2
2022-02-14 13:15:39 +00:00
Will FP
f8e930d29e Merge pull request #91
Update ShapedRecipeListener.kt
2022-02-14 13:15:28 +00:00
Will FP
9dbe088e66 Merge pull request #92
refactor(nms): Change checking if value is initialized to a lazy val
2022-02-14 13:15:17 +00:00
Racci
6361c0e8e9 refactor(nms): Change checking if value is initialized to a lazy val 2022-02-14 17:32:12 +11:00
casper
1135672241 Update ShapedRecipeListener.kt
| ShapedRecipeListener.kt Modified to change matrix at the end of the crafting to prevent duplication of items
2022-02-13 12:55:05 -05:00
Auxilor
80891e4a81 Fixed profile saveAll not working 2022-02-11 10:14:33 +00:00
Auxilor
3e0be3a629 Updated to 6.24.2 2022-02-09 15:20:30 +00:00
Auxilor
17819de2ea Fixed adult/baby parsers 2022-02-09 15:20:21 +00:00
Auxilor
209cdd6b0d Updated to 6.24.1 2022-02-05 17:05:29 +00:00
Auxilor
fbf6b2edd9 Added equipment arg parser 2022-02-05 17:05:18 +00:00
dependabot[bot]
8b9e8589a0 Bump com.github.johnrengelman.shadow from 7.1.0 to 7.1.2
Bumps com.github.johnrengelman.shadow from 7.1.0 to 7.1.2.

---
updated-dependencies:
- dependency-name: com.github.johnrengelman.shadow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-03 18:54:34 +00:00
Auxilor
525cc019ea Updated kotlin gradle plugin 2022-02-03 18:53:19 +00:00
Auxilor
04f2d15783 Fixed missing compileKotlin options 2022-02-03 18:46:36 +00:00
Auxilor
f988b591a4 Updated kotlin 2022-02-03 18:42:53 +00:00
Auxilor
9ebfb124c8 Refactored build logic 2022-02-03 18:42:01 +00:00
Auxilor
b9ab263f67 Updated CONTRIBUTING.md 2022-02-03 17:54:44 +00:00
Auxilor
bb5f68283b Updated empty (default) EcoPlugin constructor 2022-02-03 17:51:54 +00:00
Auxilor
9bbf1cfe36 Added EcoPlugin#mutateProps 2022-02-03 17:49:26 +00:00
Auxilor
19bb5f608c Updated more javadoc 2022-02-03 17:46:31 +00:00
Auxilor
a1c70d2081 Corrected PluginProps javadoc 2022-02-03 17:43:40 +00:00
Auxilor
979ddf0ff0 Safety checks to FastItemStack 2022-02-03 17:41:45 +00:00
Auxilor
232a63c00d Cleaned up FillerMask 2022-02-03 17:22:46 +00:00
Auxilor
e65cf9be2c Added extra methods to Items 2022-02-03 17:17:01 +00:00
Auxilor
fbf56037d4 Deprecated MaskMaterials in favour of MaskItems 2022-02-03 16:54:52 +00:00
Auxilor
aa0c4ee7fa Refactored props name 2022-02-03 16:08:18 +00:00
Auxilor
5f3375bf87 Added props validation 2022-02-03 15:11:15 +00:00
Auxilor
11dc6d0e67 Allowed custom props parameter 2022-02-03 15:06:35 +00:00
Auxilor
9cccbd10ba Removed need to reflectively instantiate props 2022-02-03 15:02:45 +00:00
Auxilor
1f0ad48480 Updated props javadoc 2022-02-03 14:58:12 +00:00
Auxilor
93322dcfa5 Updated props javadoc 2022-02-03 14:56:29 +00:00
Auxilor
e3b630fcb7 Improved props system 2022-02-03 14:54:43 +00:00
Auxilor
8690b75f4c Added namespacedKeyOf 2022-02-03 14:19:59 +00:00
Auxilor
6de792f308 Added more durability utils 2022-02-03 14:17:41 +00:00
Auxilor
e59037635e Removed debug from eco.yml 2022-02-03 13:52:48 +00:00
Auxilor
b9d50e261d Fixed missing javadoc 2022-02-03 13:44:15 +00:00
Auxilor
15173c8369 Finally added eco.yml 2022-02-03 13:38:14 +00:00
Auxilor
4ee0645a4e Codestyle 2022-02-03 12:57:29 +00:00
Auxilor
96bd53c089 Codestyle 2022-02-03 12:36:49 +00:00
Auxilor
e658bf3fa8 Removed redundant suppression 2022-02-03 12:36:14 +00:00
Auxilor
988836b5b9 Deprecated UnsupportedVersionException in favour of UnsupportedVersionError 2022-02-03 12:32:46 +00:00
Auxilor
5688f41b8b Fixed deprecation 2022-02-03 12:27:47 +00:00
Auxilor
4eaa6ab75c Fixed build issue 2022-02-03 12:25:39 +00:00
Auxilor
b29363cdf6 Fixed javadoc 2022-02-03 12:22:05 +00:00
Auxilor
c8648a92f5 Resolved PlayerUtils ambiguity in kotlin 2022-02-03 12:10:29 +00:00
Auxilor
0a59b6a208 ProxyFactory error changes 2022-02-03 12:06:00 +00:00
Auxilor
4e18a0ab78 Updated proxy errors 2022-02-03 12:05:22 +00:00
Auxilor
d49405f839 Updated create2DList method signature 2022-02-03 11:47:26 +00:00
Auxilor
e10566da66 Deprecated TeamUtils#getMaterialColorTeam 2022-02-03 11:45:56 +00:00
Auxilor
0c64cd98e0 Updated to 6.24.0 2022-02-03 11:43:47 +00:00
Auxilor
231af30c61 Deprecated + Marked requirement system for removal 2022-02-03 11:41:58 +00:00
Auxilor
9b5cc1fd9c Added more kotlin utilities 2022-02-03 11:23:07 +00:00
Auxilor
7628c0bbfd Renamed FastItemStack methods 2022-02-03 11:17:29 +00:00
Auxilor
0beedc6b07 Updated kotlin to use kotlin API 2022-02-03 11:09:36 +00:00
Auxilor
f3c69f1c15 Added NumberUtils extensions 2022-02-03 11:08:20 +00:00
Auxilor
a148f667e5 Added kotlin builder for commands and PlayerUtils#runExempted 2022-02-03 11:07:04 +00:00
Auxilor
b2370b4b6e Player only commands now can have non-player only subcommands 2022-02-03 10:41:24 +00:00
Auxilor
525bd5264a Removed checkstyle suppressions 2022-02-03 10:34:43 +00:00
Auxilor
54c27a0379 More CI changes 2022-02-03 10:30:22 +00:00
Auxilor
989dda0a4f Updated CI workflows 2022-02-03 10:25:38 +00:00
Auxilor
1f2bb3341e Suppression 2022-02-02 16:54:09 +00:00
Auxilor
65221bdddf Deprecated SlotModifier, replaced with SlotUpdater 2022-02-02 16:52:52 +00:00
Auxilor
b386f2df1b Updated CONTRIBUTING.md 2022-02-02 16:38:05 +00:00
77 changed files with 1288 additions and 291 deletions

15
.github/workflows/checkstyle.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Check PR Codestyle
on: [ pull_request ]
jobs:
checkstyle:
name: Checkstyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dbelyaev/action-checkstyle@v0.5.1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
level: warning
checkstyle_config: ../../config/checkstyle/checkstyle.xml

View File

@@ -1,6 +1,6 @@
name: Java CI name: Java CI
on: [push] on: [ push, pull_request ]
jobs: jobs:
build: build:

View File

@@ -1,6 +1,6 @@
name: Publish API (Dev) name: Publish API (Dev)
on: [push] on: [ push, pull_request ]
jobs: jobs:
publish-release: publish-release:
@@ -39,4 +39,4 @@ jobs:
NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3) NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3)
echo "New version: ${{ steps.vars.outputs.sha_short }}" echo "New version: ${{ steps.vars.outputs.sha_short }}"
echo "Github username: ${GITHUB_ACTOR}" echo "Github username: ${GITHUB_ACTOR}"
./gradlew -Pversion=${{ steps.vars.outputs.sha_short }} publish ./gradlew -Pversion=dev-${{ steps.vars.outputs.sha_short }} publish

View File

@@ -1,24 +1,38 @@
# How to contribute to eco # How to contribute to eco
## Codestyle ## Codestyle
1. The eco checkstyle is in /config/checkstyle.xml 1. The eco checkstyle is in /config/checkstyle.xml
- The pull request must not have any checkstyle issues. - The pull request must not have any checkstyle issues.
- Every method and field must have a javadoc attached. - Every method and field must have a javadoc attached.
2. Use JetBrains annotations 2. Use JetBrains annotations
- Every parameter should be annotated with @NotNull or @Nullable - Every parameter should be annotated with @NotNull or @Nullable
- Use @NotNull over lombok @NonNull
3. Imports 3. Imports
- No group (*) imports. - No group (*) imports.
- No static imports. - No static imports.
4. Kotlin
- Kotlin should be the only language used in the backend, java should be the only language used in the frontend.
- Kotlin API extensions should only be for creating extension functions and extra niceties that aren't possible in java.
Do not write API components in kotlin.
- Kotlin code should never be called directly from the frontend Java API. Kotlin API extensions should always rely on
java, not the other way round.
## Dependency Injection ## Dependency Injection
- eco uses Dependency Injection - eco uses Dependency Injection
- Any calls to Eco#getHandler#getEcoPlugin are code smells and should never be used unless **absolutely necessary**. - Any calls to Eco#getHandler#getEcoPlugin are code smells and should never be used unless **absolutely necessary**.
- NamespacedKeys, FixedMetadataValues, Runnables, and Schedules should be managed using AbstractEcoPlugin through DI. - NamespacedKeys, FixedMetadataValues, Runnables, and Schedules should be managed using AbstractEcoPlugin through DI.
- Any DI class should extend PluginDependent where possible. If the class extends another, then you **must** store the plugin instance in a private final variable called **plugin** with a private or protected getter. - Any DI class should extend PluginDependent where possible. If the class extends another, then you **must** store the
plugin instance in a private final variable called **plugin** with a private or protected getter.
## Other ## Other
- All drops **must** be sent through a DropQueue - calls to World#dropItem will get your PR rejected. - All drops **must** be sent through a DropQueue - calls to World#dropItem will get your PR rejected.
- eco is built with java 17. - eco is built with java 17.

View File

@@ -1,8 +1,19 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
}
}
plugins { plugins {
id("java-library") id("java-library")
id("com.github.johnrengelman.shadow") version "7.1.0" id("com.github.johnrengelman.shadow") version "7.1.2"
id("maven-publish") id("maven-publish")
id("java") id("java")
kotlin("jvm") version "1.6.10"
} }
dependencies { dependencies {
@@ -20,6 +31,7 @@ allprojects {
apply(plugin = "java-library") apply(plugin = "java-library")
apply(plugin = "maven-publish") apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "kotlin")
repositories { repositories {
mavenCentral() mavenCentral()
@@ -73,10 +85,11 @@ allprojects {
} }
dependencies { dependencies {
compileOnly(kotlin("stdlib", version = "1.6.10"))
compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains:annotations:23.0.0")
// Test // Test
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1") testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
// Adventure // Adventure
@@ -104,6 +117,14 @@ allprojects {
} }
tasks { tasks {
compileKotlin {
kotlinOptions {
jvmTarget = "17"
}
targetCompatibility = "17"
sourceCompatibility = "17"
}
shadowJar { shadowJar {
relocate("org.bstats", "com.willfp.eco.shaded.bstats") relocate("org.bstats", "com.willfp.eco.shaded.bstats")
relocate("net.kyori.adventure.text.minimessage", "com.willfp.eco.shaded.minimessage") relocate("net.kyori.adventure.text.minimessage", "com.willfp.eco.shaded.minimessage")

View File

@@ -32,10 +32,6 @@
--> -->
<module name="Checker"> <module name="Checker">
<module name="SuppressionFilter">
<property name="file" value="config/checkstyle/suppression.xml"/>
</module>
<!-- <!--
If you set the basedir property below, then all reported file If you set the basedir property below, then all reported file
names will be relative to the specified directory. See names will be relative to the specified directory. See

View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<!-- Internals don't need javadoc. -->
<suppress files="[\\/]internal[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]internal[\\/]" checks="JavadocVariable"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]eco[\\/]spigot[\\/]" checks="JavadocVariable"/>
<suppress files="[\\/]eco[\\/]proxy[\\/]" checks="MissingJavadocMethod"/>
<suppress files="[\\/]eco[\\/]proxy[\\/]" checks="JavadocVariable"/>
<!-- Modified version of library -->
<suppress files="ArmorEquipEvent.java" checks="JavadocVariable"/>
<suppress files="ArmorEquipEvent.java" checks="MissingJavadocMethod"/>
<suppress files="ArmorEquipEvent.java" checks="JavadocStyle"/>
<suppress files="ArmorListener.java" checks="JavadocVariable"/>
<suppress files="ArmorListener.java" checks="MissingJavadocMethod"/>
<suppress files="ArmorType.java" checks="JavadocVariable"/>
<suppress files="ArmorType.java" checks="MissingJavadocMethod"/>
</suppressions>

View File

@@ -1,19 +1,4 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
}
}
apply plugin: 'kotlin'
dependencies { dependencies {
// Kotlin
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0'
// Adventure // Adventure
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0' compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT' compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
@@ -25,18 +10,6 @@ dependencies {
compileOnly 'com.google.code.gson:gson:2.8.8' 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' group 'com.willfp'
version rootProject.version version rootProject.version

View File

@@ -152,10 +152,14 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
private final ProxyFactory proxyFactory; private final ProxyFactory proxyFactory;
/** /**
* Create a new plugin without a specified color, proxy support, polymart, or bStats. * Create a new plugin.
* <p>
* Will read from eco.yml (like plugin.yml) to fetch values that would otherwise be passed
* into the constructor. If no eco.yml is present, the plugin will load without extension
* support, without proxy support, with no update-checker or bStats, and with the color white.
*/ */
protected EcoPlugin() { protected EcoPlugin() {
this("&f"); this((PluginProps) null);
} }
/** /**
@@ -236,6 +240,23 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
@NotNull final String proxyPackage, @NotNull final String proxyPackage,
@NotNull final String color, @NotNull final String color,
final boolean supportingExtensions) { final boolean supportingExtensions) {
this(
PluginProps.createSimple(
resourceId,
bStatsId,
proxyPackage,
color,
supportingExtensions
)
);
}
/**
* Create a new plugin.
*
* @param pluginProps The props. If left null, it will read from eco.yml.
*/
protected EcoPlugin(@Nullable final PluginProps pluginProps) {
/* /*
The handler must be initialized before any plugin's constructors The handler must be initialized before any plugin's constructors
are called, as the constructors call Eco#getHandler(). are called, as the constructors call Eco#getHandler().
@@ -253,15 +274,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
a standalone handler class, but then there would be an interface a standalone handler class, but then there would be an interface
left in the API that doesn't really help anything. left in the API that doesn't really help anything.
The other alternative would be do use reflection to get a 'createHandler' The other alternative would be to use reflection to get a 'createHandler'
method that only exists in EcoSpigotPlugin - but that feels really dirty method that only exists in EcoSpigotPlugin - but that feels filthy,
and I'd rather only use reflection where necessary. and I'd rather only use reflection where necessary.
*/ */
if (Eco.getHandler() == null && this instanceof Handler) { if (Eco.getHandler() == null && this instanceof Handler) {
/* /*
This code is only ever called by EcoSpigotPlugin (EcoHandler) This code is only ever called by EcoSpigotPlugin (EcoHandler)
as it's the first plugin to load and it is a handler. as it's the first plugin to load, and it is a handler.
Any other plugins will never call this code as the handler Any other plugins will never call this code as the handler
will have already been initialized. will have already been initialized.
@@ -272,11 +293,16 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
assert Eco.getHandler() != null; assert Eco.getHandler() != null;
this.resourceId = resourceId; PluginProps generatedProps = Eco.getHandler().getProps(pluginProps, this.getClass());
this.bStatsId = bStatsId; generatedProps.validate();
this.proxyPackage = proxyPackage; PluginProps props = this.mutateProps(generatedProps);
this.color = color; props.validate();
this.supportingExtensions = supportingExtensions;
this.resourceId = props.getResourceId();
this.bStatsId = props.getBStatsId();
this.proxyPackage = props.getProxyPackage();
this.color = props.getColor();
this.supportingExtensions = props.isSupportingExtensions();
this.scheduler = Eco.getHandler().createScheduler(this); this.scheduler = Eco.getHandler().createScheduler(this);
this.eventManager = Eco.getHandler().createEventManager(this); this.eventManager = Eco.getHandler().createEventManager(this);
@@ -296,8 +322,8 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
/* /*
The minimum eco version check was moved here because it's very common The minimum eco version check was moved here because it's very common
to add a lot of code in the constructor of plugins; meaning that the plugin to add a lot of code in the constructor of plugins; meaning that the plugin
can throw errors without it being obvious to the user that the reason is can throw errors without it being obvious to the user that the reason is that
because they have an outdated version of eco installed. they have an outdated version of eco installed.
*/ */
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.getHandler().getEcoPlugin().getDescription().getVersion()); DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.getHandler().getEcoPlugin().getDescription().getVersion());
@@ -534,6 +560,21 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
} }
/**
* Mutate the plugin props.
* <p>
* Useful for eco-based plugin libraries to enforce certain properties, such as
* forcing extensions to be enabled.
* <p>
* Props are validated both before and after calling this method.
*
* @param props The props.
* @return The mutated props.
*/
protected PluginProps mutateProps(@NotNull final PluginProps props) {
return props;
}
/** /**
* The plugin-specific integrations to be tested and loaded. * The plugin-specific integrations to be tested and loaded.
* *
@@ -635,7 +676,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
* @return The proxy. * @return The proxy.
*/ */
public final <T> T getProxy(@NotNull final Class<T> proxyClass) { public final <T> T getProxy(@NotNull final Class<T> proxyClass) {
Validate.notNull(proxyFactory, "Plugin does not support proxy!"); Validate.notNull(proxyFactory, "Plugin does not support proxies!");
return proxyFactory.getProxy(proxyClass); return proxyFactory.getProxy(proxyClass);
} }

View File

@@ -15,7 +15,6 @@ import com.willfp.eco.core.gui.GUIFactory;
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration; import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
import com.willfp.eco.core.proxy.Cleaner; import com.willfp.eco.core.proxy.Cleaner;
import com.willfp.eco.core.proxy.ProxyFactory; import com.willfp.eco.core.proxy.ProxyFactory;
import com.willfp.eco.core.requirement.RequirementFactory;
import com.willfp.eco.core.scheduling.Scheduler; import com.willfp.eco.core.scheduling.Scheduler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Location; import org.bukkit.Location;
@@ -33,6 +32,7 @@ import java.util.logging.Logger;
* @see Eco#getHandler() * @see Eco#getHandler()
*/ */
@ApiStatus.Internal @ApiStatus.Internal
@SuppressWarnings("removal")
public interface Handler { public interface Handler {
/** /**
* Create a scheduler. * Create a scheduler.
@@ -210,7 +210,8 @@ public interface Handler {
* @return The factory. * @return The factory.
*/ */
@NotNull @NotNull
RequirementFactory getRequirementFactory(); @Deprecated(forRemoval = true)
com.willfp.eco.core.requirement.RequirementFactory getRequirementFactory();
/** /**
* Get Adventure audiences. * Get Adventure audiences.
@@ -259,4 +260,15 @@ public interface Handler {
@NotNull @NotNull
NamespacedKey createNamespacedKey(@NotNull String namespace, NamespacedKey createNamespacedKey(@NotNull String namespace,
@NotNull String key); @NotNull String key);
/**
* Return or get props for a plugin.
*
* @param existing The existing constructor props.
* @param plugin The plugin.
* @return The props.
*/
@NotNull
PluginProps getProps(@Nullable PluginProps existing,
@NotNull Class<? extends EcoPlugin> plugin);
} }

View File

@@ -0,0 +1,275 @@
package com.willfp.eco.core;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* Plugin props are the arguments related to the plugin that are required on start-up.
* <p>
* This class is complex in how it works intentionally. This is done so that fields can be
* added to the props without breaking API backwards compatibility. Thus, there is no public
* constructor and no way to instantiate props without creating a parser.
*/
public final class PluginProps {
/**
* All registered parsers.
*/
private static final Map<Class<?>, PropsParser<?>> REGISTERED_PARSERS = new HashMap<>();
/**
* The polymart resource ID.
*/
@Nullable
private Integer resourceId;
/**
* The bStats ID.
*/
@Nullable
private Integer bStatsId;
/**
* The proxy package.
*/
@Nullable
private String proxyPackage;
/**
* The color.
*/
@Nullable
private String color;
/**
* If extensions are supported.
*/
@Nullable
private Boolean supportingExtensions;
/**
* Create new blank props.
*/
private PluginProps() {
}
/**
* Get resource ID.
*
* @return The resource ID.
*/
public int getResourceId() {
assert resourceId != null;
return resourceId;
}
/**
* Set resource ID.
*
* @param resourceId The resource ID.
*/
public void setResourceId(final int resourceId) {
this.resourceId = resourceId;
}
/**
* Get bStats ID.
*
* @return The bStats ID.
*/
public int getBStatsId() {
assert bStatsId != null;
return bStatsId;
}
/**
* Set bStats ID.
*
* @param bStatsId The bStats ID.
*/
public void setBStatsId(final int bStatsId) {
this.bStatsId = bStatsId;
}
/**
* Get the proxy package.
*
* @return The package.
*/
@NotNull
public String getProxyPackage() {
assert proxyPackage != null;
return proxyPackage;
}
/**
* Set the proxy package.
*
* @param proxyPackage The proxy package.
*/
public void setProxyPackage(@NotNull final String proxyPackage) {
this.proxyPackage = proxyPackage;
}
/**
* Get color.
*
* @return The color.
*/
@NotNull
public String getColor() {
assert color != null;
return color;
}
/**
* Set the color.
*
* @param color The color.
*/
public void setColor(@NotNull final String color) {
this.color = color;
}
/**
* Get if extensions are supported.
*
* @return If supported.
*/
public boolean isSupportingExtensions() {
assert supportingExtensions != null;
return supportingExtensions;
}
/**
* Set if extensions are supported.
*
* @param supportingExtensions If supported.
*/
public void setSupportingExtensions(final boolean supportingExtensions) {
this.supportingExtensions = supportingExtensions;
}
/**
* Ensure that all required props have been set.
*/
public void validate() {
if (
supportingExtensions == null
|| proxyPackage == null
|| color == null
|| bStatsId == null
|| resourceId == null
) {
throw new IllegalStateException("Missing required props!");
}
}
/**
* Parse props from source.
*
* @param source The source.
* @param sourceClass The source class.
* @param <T> The source type.
* @return The props.
*/
public static <T> PluginProps parse(@NotNull final T source,
@NotNull final Class<? extends T> sourceClass) {
for (Map.Entry<Class<?>, PropsParser<?>> entry : REGISTERED_PARSERS.entrySet()) {
Class<?> clazz = entry.getKey();
if (clazz.equals(sourceClass)) {
@SuppressWarnings("unchecked")
PropsParser<T> parser = (PropsParser<T>) entry.getValue();
return parser.parseFrom(source);
}
}
throw new IllegalArgumentException("No parser exists for class " + sourceClass);
}
/**
* Register a parser for a type.
*
* @param clazz The class.
* @param parser The parser.
* @param <T> The source type.
*/
public static <T> void registerParser(@NotNull final Class<T> clazz,
@NotNull final PropsParser<T> parser) {
REGISTERED_PARSERS.put(clazz, parser);
}
/**
* Get if there is a registered parser for a class.
*
* @param clazz The class.
* @return If there is a parser registered.
*/
public static boolean hasParserFor(@NotNull final Class<?> clazz) {
for (Class<?> test : REGISTERED_PARSERS.keySet()) {
if (test.equals(clazz)) {
return true;
}
}
return false;
}
/**
* Create new props from known values.
*
* Marked as internal as this method will break whenever the properties themselves
* are updated (e.g. if a new property is added) - so to prevent any potential
* backwards-compatibility bugs, this method cannot be invoked outside eco itself.
*
* @param resourceId The ID of the plugin on polymart.
* @param bStatsId The ID of the plugin on bStats.
* @param proxyPackage The package where proxies can be found.
* @param color The primary color of the plugin.
* @param supportsExtensions If the plugin should attempt to look for extensions.
* @return The props.
*/
@ApiStatus.Internal
static PluginProps createSimple(final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage,
@NotNull final String color,
final boolean supportsExtensions) {
PluginProps props = new PluginProps();
props.setResourceId(resourceId);
props.setBStatsId(bStatsId);
props.setProxyPackage(proxyPackage);
props.setColor(color);
props.setSupportingExtensions(supportsExtensions);
return props;
}
/**
* Parse arguments into props for a plugin.
*
* @param <T> The type of source.
*/
public interface PropsParser<T> {
/**
* Parse props from a given source.
*
* @param source The source.
* @return The props.
*/
PluginProps parseFrom(@NotNull T source);
/**
* Get a new, blank props instance.
*
* @return Blank props.
*/
default PluginProps getBlankProps() {
return new PluginProps();
}
}
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.command; package com.willfp.eco.core.command;
import com.willfp.eco.core.EcoPlugin;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -66,6 +67,13 @@ public interface CommandBase {
return new ArrayList<>(); return new ArrayList<>();
} }
/**
* Get the plugin.
*
* @return The plugin.
*/
EcoPlugin getPlugin();
/** /**
* Get the handler. * Get the handler.
* *

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.core.command.impl; package com.willfp.eco.core.command.impl;
import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.command.CommandBase; import com.willfp.eco.core.command.CommandBase;
import com.willfp.eco.core.command.CommandHandler; import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.TabCompleteHandler; import com.willfp.eco.core.command.TabCompleteHandler;
@@ -25,7 +24,12 @@ import java.util.stream.Collectors;
* layer, hence why it's a package-private class. * layer, hence why it's a package-private class.
*/ */
@SuppressWarnings({"DeprecatedIsStillUsed"}) @SuppressWarnings({"DeprecatedIsStillUsed"})
abstract class HandledCommand extends PluginDependent<EcoPlugin> implements CommandBase { abstract class HandledCommand implements CommandBase {
/**
* The plugin.
*/
private final EcoPlugin plugin;
/** /**
* The name of the command. * The name of the command.
*/ */
@@ -78,7 +82,7 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
@NotNull final String name, @NotNull final String name,
@NotNull final String permission, @NotNull final String permission,
final boolean playersOnly) { final boolean playersOnly) {
super(plugin); this.plugin = plugin;
this.name = name; this.name = name;
this.permission = permission; this.permission = permission;
this.playersOnly = playersOnly; this.playersOnly = playersOnly;
@@ -98,6 +102,16 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
return this; return this;
} }
/**
* Get the plugin.
*
* @return The plugin.
*/
@Override
public EcoPlugin getPlugin() {
return this.plugin;
}
/** /**
* Handle the command. * Handle the command.
* *
@@ -124,6 +138,11 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
} }
} }
if (this.isPlayersOnly() && !(sender instanceof Player)) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("not-player"));
return;
}
if (this.getHandler() != null) { if (this.getHandler() != null) {
this.getHandler().onExecute(sender, Arrays.asList(args)); this.getHandler().onExecute(sender, Arrays.asList(args));
} else { } else {
@@ -193,11 +212,6 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
public static boolean canExecute(@NotNull final CommandSender sender, public static boolean canExecute(@NotNull final CommandSender sender,
@NotNull final CommandBase command, @NotNull final CommandBase command,
@NotNull final EcoPlugin plugin) { @NotNull final EcoPlugin plugin) {
if (command.isPlayersOnly() && !(sender instanceof Player)) {
sender.sendMessage(plugin.getLangYml().getMessage("not-player"));
return false;
}
if (!sender.hasPermission(command.getPermission()) && sender instanceof Player) { if (!sender.hasPermission(command.getPermission()) && sender instanceof Player) {
sender.sendMessage(plugin.getLangYml().getNoPermission()); sender.sendMessage(plugin.getLangYml().getNoPermission());
return false; return false;

View File

@@ -5,7 +5,10 @@ import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.config.wrapper.ConfigWrapper; import com.willfp.eco.core.config.wrapper.ConfigWrapper;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map; import java.util.Map;
/** /**
@@ -21,6 +24,15 @@ public class TransientConfig extends ConfigWrapper<Config> {
super(Eco.getHandler().getConfigFactory().createConfig(config)); super(Eco.getHandler().getConfigFactory().createConfig(config));
} }
/**
* @param stream The InputStream.
*/
public TransientConfig(@Nullable final InputStream stream) {
super(stream != null ? Eco.getHandler().getConfigFactory().createConfig(YamlConfiguration.loadConfiguration(
new InputStreamReader(stream)
)) : new TransientConfig());
}
/** /**
* Create a new empty transient config. * Create a new empty transient config.
* *

View File

@@ -235,7 +235,7 @@ public interface Config extends Cloneable {
*/ */
@NotNull @NotNull
default String getString(@NotNull String path) { default String getString(@NotNull String path) {
return getString(path, false); return getString(path, false, StringUtils.FormatOption.WITHOUT_PLACEHOLDERS);
} }
/** /**

View File

@@ -22,8 +22,30 @@ public interface FastItemStack {
* *
* @param checkStored If stored NBT should also be checked. * @param checkStored If stored NBT should also be checked.
* @return A map of all enchantments. * @return A map of all enchantments.
* @deprecated Poorly named method. Use getEnchants instead.
*/ */
Map<Enchantment, Integer> getEnchantmentsOnItem(boolean checkStored); @Deprecated(since = "6.24.0")
default Map<Enchantment, Integer> getEnchantmentsOnItem(boolean checkStored) {
return getEnchants(checkStored);
}
/**
* Get all enchantments on an item.
* Does not account for stored enchants.
*
* @return A map of all enchantments.
*/
default Map<Enchantment, Integer> getEnchants() {
return getEnchants(false);
}
/**
* Get all enchantments on an item.
*
* @param checkStored If stored enchantments should be accounted for.
* @return A map of all enchantments.
*/
Map<Enchantment, Integer> getEnchants(boolean checkStored);
/** /**
* Get the level of an enchantment on an item. * Get the level of an enchantment on an item.

View File

@@ -1,6 +1,8 @@
package com.willfp.eco.core.gui.slot; package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.items.builder.ItemStackBuilder; import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.util.ListUtils; import com.willfp.eco.util.ListUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -38,7 +40,7 @@ public class FillerMask {
*/ */
public FillerMask(@NotNull final Material material, public FillerMask(@NotNull final Material material,
@NotNull final String... pattern) { @NotNull final String... pattern) {
this(new MaskMaterials(material), pattern); this(new MaskItems(new MaterialTestableItem(material)), pattern);
} }
/** /**
@@ -46,17 +48,33 @@ public class FillerMask {
* *
* @param materials The mask materials. * @param materials The mask materials.
* @param pattern The pattern. * @param pattern The pattern.
* @deprecated Use {@link MaskItems} instead.
*/ */
@Deprecated(since = "6.24.0")
public FillerMask(@NotNull final MaskMaterials materials, public FillerMask(@NotNull final MaskMaterials materials,
@NotNull final String... pattern) { @NotNull final String... pattern) {
if (Arrays.stream(materials.materials()).anyMatch(material -> material == Material.AIR)) { this(
throw new IllegalArgumentException("Materials cannot be air!"); materials.toMaskItems(),
pattern
);
}
/**
* Create a new filler mask.
*
* @param items The mask items.
* @param pattern The pattern.
*/
public FillerMask(@NotNull final MaskItems items,
@NotNull final String... pattern) {
if (Arrays.stream(items.items()).anyMatch(item -> item instanceof EmptyTestableItem)) {
throw new IllegalArgumentException("Items cannot be empty!");
} }
mask = ListUtils.create2DList(6, 9); mask = ListUtils.create2DList(6, 9);
for (int i = 0; i < materials.materials().length; i++) { for (int i = 0; i < items.items().length; i++) {
ItemStack itemStack = new ItemStackBuilder(materials.materials()[i]) ItemStack itemStack = new ItemStackBuilder(items.items()[i])
.setDisplayName("&r") .setDisplayName("&r")
.build(); .build();

View File

@@ -0,0 +1,45 @@
package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* Mask materials store a set of items which can be accessed by
* a filler mask.
*
* @param items The items.
*/
public record MaskItems(@NotNull TestableItem... items) {
/**
* Create MaskItems from a list of item names.
*
* @param names The names.
* @return The mask items.
*/
public static MaskItems fromItemNames(@NotNull final Iterable<String> names) {
List<TestableItem> items = new ArrayList<>();
for (String name : names) {
TestableItem item = Items.lookup(name);
if (item instanceof EmptyTestableItem) {
continue;
}
items.add(item);
}
if (items.isEmpty()) {
return new MaskItems(new MaterialTestableItem(Material.BLACK_STAINED_GLASS_PANE));
}
return new MaskItems(items.toArray(new TestableItem[0]));
}
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.gui.slot; package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.items.Items;
import org.bukkit.Material; import org.bukkit.Material;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -8,7 +9,16 @@ import org.jetbrains.annotations.NotNull;
* a filler mask. * a filler mask.
* *
* @param materials The materials. * @param materials The materials.
* @deprecated Use {@link MaskItems} instead.
*/ */
@Deprecated(since = "6.24.0")
public record MaskMaterials(@NotNull Material... materials) { public record MaskMaterials(@NotNull Material... materials) {
/**
* Convert MaskMaterials to MaskItems.
*
* @return The MaskItems.
*/
public MaskItems toMaskItems() {
return new MaskItems(Items.fromMaterials(this.materials()));
}
} }

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.gui.slot;
import com.willfp.eco.core.gui.slot.functional.SlotHandler; import com.willfp.eco.core.gui.slot.functional.SlotHandler;
import com.willfp.eco.core.gui.slot.functional.SlotModifier; import com.willfp.eco.core.gui.slot.functional.SlotModifier;
import com.willfp.eco.core.gui.slot.functional.SlotUpdater;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -106,8 +107,23 @@ public interface SlotBuilder {
* *
* @param modifier The modifier. * @param modifier The modifier.
* @return The builder. * @return The builder.
* @deprecated Use {@link SlotBuilder#setUpdater(SlotUpdater)} instead.
*/ */
SlotBuilder setModifier(@NotNull SlotModifier modifier); @Deprecated
default SlotBuilder setModifier(@NotNull SlotModifier modifier) {
return setUpdater((player, menu, previous) -> {
modifier.modify(player, menu, previous);
return previous;
});
}
/**
* Set the ItemStack updater.
*
* @param updater The updater.
* @return The builder.
*/
SlotBuilder setUpdater(@NotNull SlotUpdater updater);
/** /**
* Set slot to be a captive slot. * Set slot to be a captive slot.

View File

@@ -7,8 +7,11 @@ import org.jetbrains.annotations.NotNull;
/** /**
* Interface to run on slot modify. * Interface to run on slot modify.
*
* @deprecated Use {@link SlotUpdater} instead.
*/ */
@FunctionalInterface @FunctionalInterface
@Deprecated
public interface SlotModifier { public interface SlotModifier {
/** /**
* Performs this operation on the given arguments. * Performs this operation on the given arguments.

View File

@@ -0,0 +1,24 @@
package com.willfp.eco.core.gui.slot.functional;
import com.willfp.eco.core.gui.menu.Menu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Interface to run on slot update.
*/
@FunctionalInterface
public interface SlotUpdater {
/**
* Performs this operation on the given arguments.
*
* @param player The player.
* @param menu The menu.
* @param previous The previous ItemStack.
* @return The new ItemStack.
*/
ItemStack update(@NotNull Player player,
@NotNull Menu menu,
@NotNull ItemStack previous);
}

View File

@@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@@ -344,6 +345,35 @@ public final class Items {
} }
} }
/**
* Convert an array of materials to an array of testable items.
*
* @param materials The materials.
* @return An array of functionally identical testable items.
*/
@NotNull
public static TestableItem[] fromMaterials(@NotNull final Material... materials) {
return Arrays.stream(materials)
.map(MaterialTestableItem::new)
.toArray(MaterialTestableItem[]::new);
}
/**
* Convert a collection of materials into a collection of testable items.
*
* @param materials The materials.
* @return A collection of functionally identical testable items.
*/
@NotNull
public static Collection<TestableItem> fromMaterials(@NotNull final Iterable<Material> materials) {
List<TestableItem> items = new ArrayList<>();
for (Material material : materials) {
items.add(new MaterialTestableItem(material));
}
return items;
}
private Items() { private Items() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
} }

View File

@@ -5,12 +5,25 @@ import org.jetbrains.annotations.NotNull;
/** /**
* Generic error with proxy loading. * Generic error with proxy loading.
*/ */
public class ProxyError extends RuntimeException { public class ProxyError extends Error {
/** /**
* Thrown if there is an error getting a proxy. * Thrown if there is an error getting a proxy.
* *
* @param message The message to send. * @param message The message to send.
* @param cause The cause.
*/ */
public ProxyError(@NotNull final String message,
@NotNull final Throwable cause) {
super(message, cause);
}
/**
* Thrown if there is an error getting a proxy.
*
* @param message The message to send.
* @deprecated Proxy Errors should include a cause.
*/
@Deprecated
public ProxyError(@NotNull final String message) { public ProxyError(@NotNull final String message) {
super(message); super(message);
} }

View File

@@ -0,0 +1,15 @@
package com.willfp.eco.core.proxy.exceptions;
import com.willfp.eco.core.proxy.ProxyConstants;
/**
* Server running an unsupported version.
*/
public class UnsupportedVersionError extends Error {
/**
* Thrown if the server is running an unsupported version.
*/
public UnsupportedVersionError() {
super("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
}
}

View File

@@ -1,17 +1,30 @@
package com.willfp.eco.core.proxy.exceptions; package com.willfp.eco.core.proxy.exceptions;
import com.willfp.eco.core.proxy.ProxyConstants;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Error if the server is running an unsupported version. * Error if the server is running an unsupported version.
*
* @deprecated Poorly named, exception when it's actually an error, contains doubly nested errors.
*/ */
@Deprecated(since = "6.24.0", forRemoval = true)
public class UnsupportedVersionException extends ProxyError { public class UnsupportedVersionException extends ProxyError {
/** /**
* Thrown if the server is running an unsupported NMS version. * Thrown if the server is running an unsupported NMS version.
* *
* @param message The message to send. * @param message The message to send.
* @deprecated Use the default constructor.
*/ */
@Deprecated(since = "6.24.0")
public UnsupportedVersionException(@NotNull final String message) { public UnsupportedVersionException(@NotNull final String message) {
super(message); super(message);
} }
/**
* Thrown if the server is running an unsupported NMS version.
*/
public UnsupportedVersionException() {
super("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION, new IllegalStateException());
}
} }

View File

@@ -18,7 +18,6 @@ import java.util.List;
/** /**
* Utility class to manage and register crafting recipes. * Utility class to manage and register crafting recipes.
*/ */
@SuppressWarnings("deprecation")
public final class Recipes { public final class Recipes {
/** /**
* Registry of all recipes. * Registry of all recipes.

View File

@@ -294,7 +294,7 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
*/ */
public boolean isAir() { public boolean isAir() {
for (TestableItem recipePart : this.recipeParts) { for (TestableItem recipePart : this.recipeParts) {
if (recipePart!= null && !(recipePart instanceof EmptyTestableItem)) { if (recipePart != null && !(recipePart instanceof EmptyTestableItem)) {
return false; return false;
} }
} }

View File

@@ -7,7 +7,11 @@ import java.util.List;
/** /**
* A requirement is a defined goal that a player must meet. * A requirement is a defined goal that a player must meet.
*
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
*/ */
@Deprecated(since = "6.24.0", forRemoval = true)
@SuppressWarnings("DeprecatedIsStillUsed")
public abstract class Requirement { public abstract class Requirement {
/** /**
* Create a new requirement. * Create a new requirement.

View File

@@ -6,9 +6,13 @@ import org.jetbrains.annotations.NotNull;
/** /**
* Interface for internal requirement factory implementations. * Interface for internal requirement factory implementations.
*
* @deprecated See {@link Requirement}.
*/ */
@ApiStatus.Internal @ApiStatus.Internal
@Eco.HandlerComponent @Eco.HandlerComponent
@Deprecated(since = "6.24.0", forRemoval = true)
@SuppressWarnings({"removal", "DeprecatedIsStillUsed"})
public interface RequirementFactory { public interface RequirementFactory {
/** /**
* Create a requirement. * Create a requirement.

View File

@@ -5,7 +5,11 @@ import org.jetbrains.annotations.NotNull;
/** /**
* Contains methods and fields pertaining to requirements. * Contains methods and fields pertaining to requirements.
*
* @deprecated See {@link Requirement}.
*/ */
@Deprecated(since = "6.24.0", forRemoval = true)
@SuppressWarnings("removal")
public final class Requirements { public final class Requirements {
/** /**
* Requires a player to have a permission. * Requires a player to have a permission.

View File

@@ -26,11 +26,26 @@ public final class DurabilityUtils {
* @param item The item to damage. * @param item The item to damage.
* @param damage The amount of damage to deal. * @param damage The amount of damage to deal.
* @param slot The slot in the inventory of the item. * @param slot The slot in the inventory of the item.
* @deprecated The slot is not required.
*/ */
@Deprecated(since = "6.24.0")
public static void damageItem(@NotNull final Player player, public static void damageItem(@NotNull final Player player,
@NotNull final ItemStack item, @NotNull final ItemStack item,
final int damage, final int damage,
final int slot) { final int slot) {
damageItem(player, item, damage);
}
/**
* Damage an item in a player's inventory.
*
* @param player The player.
* @param item The item to damage.
* @param damage The amount of damage to deal.
*/
public static void damageItem(@NotNull final Player player,
@NotNull final ItemStack item,
final int damage) {
if (item.getItemMeta() == null) { if (item.getItemMeta() == null) {
return; return;
} }
@@ -61,7 +76,7 @@ public final class DurabilityUtils {
item.setItemMeta((ItemMeta) meta); item.setItemMeta((ItemMeta) meta);
PlayerItemBreakEvent event = new PlayerItemBreakEvent(player, item); PlayerItemBreakEvent event = new PlayerItemBreakEvent(player, item);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
player.getInventory().clear(slot); item.setType(Material.AIR);
player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, 1, 1); player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, 1, 1);
} else { } else {
item.setItemMeta((ItemMeta) meta); item.setItemMeta((ItemMeta) meta);
@@ -69,6 +84,44 @@ public final class DurabilityUtils {
} }
} }
/**
* Damage an item.
*
* @param item The item to damage.
* @param damage The amount of damage to deal.
*/
public static void damageItem(@NotNull final ItemStack item,
final int damage) {
if (item.getItemMeta() == null) {
return;
}
if (item.getItemMeta().isUnbreakable()) {
return;
}
if (!(item.getItemMeta() instanceof Damageable)) {
return;
}
// Special edge case
if (item.getType() == Material.CARVED_PUMPKIN || item.getType() == Material.PLAYER_HEAD) {
return;
}
Damageable meta = (Damageable) item.getItemMeta();
meta.setDamage(meta.getDamage() + damage);
if (meta.getDamage() >= item.getType().getMaxDurability()) {
meta.setDamage(item.getType().getMaxDurability());
item.setItemMeta((ItemMeta) meta);
item.setType(Material.AIR);
} else {
item.setItemMeta((ItemMeta) meta);
}
}
/** /**
* Damage an item in a player's inventory without breaking it. * Damage an item in a player's inventory without breaking it.
* *

View File

@@ -3,6 +3,9 @@ package com.willfp.eco.util;
import com.willfp.eco.core.Eco; import com.willfp.eco.core.Eco;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/** /**
* Utilities / API methods for {@link NamespacedKey}s. * Utilities / API methods for {@link NamespacedKey}s.
@@ -45,8 +48,25 @@ public final class NamespacedKeyUtils {
*/ */
@NotNull @NotNull
public static NamespacedKey fromString(@NotNull final String string) { public static NamespacedKey fromString(@NotNull final String string) {
return Objects.requireNonNull(NamespacedKeyUtils.fromStringOrNull(string));
}
/**
* Create a NamespacedKey from a string.
* <p>
* Preferred over {@link NamespacedKey#fromString(String)} for performance reasons.
*
* @param string The string.
* @return The key, or null if not a key.
*/
@Nullable
public static NamespacedKey fromStringOrNull(@NotNull final String string) {
int index = string.indexOf(":"); int index = string.indexOf(":");
if (index < 0) {
return null;
}
return NamespacedKeyUtils.create( return NamespacedKeyUtils.create(
string.substring(0, index), string.substring(0, index),
string.substring(index + 1) string.substring(index + 1)

View File

@@ -5,6 +5,7 @@ import com.willfp.eco.core.Prerequisite;
import com.willfp.eco.core.data.PlayerProfile; import com.willfp.eco.core.data.PlayerProfile;
import com.willfp.eco.core.data.keys.PersistentDataKey; import com.willfp.eco.core.data.keys.PersistentDataKey;
import com.willfp.eco.core.data.keys.PersistentDataKeyType; import com.willfp.eco.core.data.keys.PersistentDataKeyType;
import com.willfp.eco.core.integrations.anticheat.AnticheatManager;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@@ -12,6 +13,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
/** /**
* Utilities / API methods for players. * Utilities / API methods for players.
*/ */
@@ -107,6 +110,38 @@ public final class PlayerUtils {
profile.write(PLAYER_NAME_KEY, player.getDisplayName()); profile.write(PLAYER_NAME_KEY, player.getDisplayName());
} }
/**
* Run something with the player exempted.
*
* @param player The player.
* @param action The action.
*/
public static void runExempted(@NotNull final Player player,
@NotNull final Consumer<Player> action) {
try {
AnticheatManager.exemptPlayer(player);
action.accept(player);
} finally {
AnticheatManager.unexemptPlayer(player);
}
}
/**
* Run something with the player exempted.
*
* @param player The player.
* @param action The action.
*/
public static void runExempted(@NotNull final Player player,
@NotNull final Runnable action) {
try {
AnticheatManager.exemptPlayer(player);
action.run();
} finally {
AnticheatManager.unexemptPlayer(player);
}
}
private PlayerUtils() { private PlayerUtils() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
} }

View File

@@ -69,8 +69,10 @@ public final class TeamUtils {
* *
* @param material The material to find the team from. * @param material The material to find the team from.
* @return The team. * @return The team.
* @deprecated Stupid method.
*/ */
@NotNull @NotNull
@Deprecated(since = "6.24.0")
public static Team getMaterialColorTeam(@NotNull final Material material) { public static Team getMaterialColorTeam(@NotNull final Material material) {
return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE)); return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE));
} }

View File

@@ -0,0 +1,142 @@
@file:JvmName("CommandHelperExtensions")
package com.willfp.eco.core.commands
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.CommandBase
import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.eco.core.command.impl.Subcommand
import org.bukkit.command.CommandSender
/**
* Helper class for creating commands with builders.
*
* @param plugin The plugin.
* @param name The command name.
* @param permission The permission.
* @param playersOnly If only players should run the command.
* @param executor The command executor.
* @param tabCompleter The tab completer.
*/
class BuiltPluginCommand internal constructor(
plugin: EcoPlugin,
name: String,
permission: String,
playersOnly: Boolean = false,
var executor: (CommandSender, List<String>) -> Unit,
var tabCompleter: (CommandSender, List<String>) -> List<String>,
) : PluginCommand(plugin, name, permission, playersOnly) {
override fun onExecute(sender: CommandSender, args: List<String>) =
executor(sender, args)
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> =
tabCompleter(sender, args)
}
/**
* Helper class for creating commands with builders.
*
* @param plugin The plugin.
* @param name The command name.
* @param permission The permission.
* @param playersOnly If only players should run the command.
* @param executor The command executor.
* @param tabCompleter The tab completer.
*/
class BuiltSubcommand internal constructor(
plugin: EcoPlugin,
name: String,
permission: String,
playersOnly: Boolean = false,
var executor: (CommandSender, List<String>) -> Unit,
var tabCompleter: (CommandSender, List<String>) -> List<String>,
) : Subcommand(plugin, name, permission, playersOnly) {
internal constructor(
parent: CommandBase,
name: String,
executor: (CommandSender, List<String>) -> Unit,
tabCompleter: (CommandSender, List<String>) -> List<String>,
) : this(parent.plugin, name, parent.permission, parent.isPlayersOnly, executor, tabCompleter)
override fun onExecute(sender: CommandSender, args: List<String>) =
executor(sender, args)
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> =
tabCompleter(sender, args)
}
/**
* Kotlin builder for commands.
*
* @param plugin The plugin.
* @param name The command name.
* @param permission The permission.
* @param playersOnly If only players should execute the command.
* @param init The builder.
*/
fun command(
plugin: EcoPlugin,
name: String,
permission: String,
playersOnly: Boolean = false,
init: BuiltPluginCommand.() -> Unit
): PluginCommand {
val command = BuiltPluginCommand(
plugin,
name,
permission,
playersOnly,
{ _, _ -> },
{ _, _ -> emptyList() }
)
init(command)
return command
}
/**
* Kotlin builder for commands.
*
* @param name The command name.
* @param permission The permission.
* @param playersOnly If only players should execute the command.
* @param init The builder.
*/
fun CommandBase.addSubcommand(
name: String,
permission: String,
playersOnly: Boolean = false,
init: BuiltSubcommand.() -> Unit
): Subcommand {
val command = BuiltSubcommand(
this.plugin,
name,
permission,
playersOnly,
{ _, _ -> },
{ _, _ -> emptyList() }
)
init(command)
return command
}
/**
* Kotlin builder for commands.
* Inherits plugin, permission, players only.
*
* @param name The command name.
* @param init The builder.
*/
fun CommandBase.addSubcommand(
name: String,
init: BuiltSubcommand.() -> Unit
): Subcommand {
val command = BuiltSubcommand(
this,
name,
{ _, _ -> },
{ _, _ -> emptyList() }
)
init(command)
return command
}

View File

@@ -43,9 +43,18 @@ fun SlotBuilder.onMiddleClick(action: (InventoryClickEvent, Slot, Menu) -> Unit)
/** /**
* @see SlotBuilder.setModifier * @see SlotBuilder.setModifier
* @deprecated Use SlotUpdater instead.
*/ */
@Deprecated("Use SlotUpdater instead")
@Suppress("DEPRECATION")
fun SlotBuilder.setModifier(action: (Player, Menu, ItemStack) -> Unit): SlotBuilder = fun SlotBuilder.setModifier(action: (Player, Menu, ItemStack) -> Unit): SlotBuilder =
this.setModifier { a, b, c -> action(a, b, c) } this.setUpdater { a, b, c -> c.apply { action(a, b, c) } }
/**
* @see SlotBuilder.setUpdater
*/
fun SlotBuilder.setUpdater(action: (Player, Menu, ItemStack) -> ItemStack): SlotBuilder =
this.setUpdater { a, b, c -> action(a, b, c) }
/** /**
* Kotlin builder for slots. * Kotlin builder for slots.

View File

@@ -0,0 +1,18 @@
@file:JvmName("DurabilityUtilsExtensions")
package com.willfp.eco.util
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
/**
* @see DurabilityUtils.damageItem
*/
fun ItemStack.damage(damage: Int) =
DurabilityUtils.damageItem(this, damage)
/**
* @see DurabilityUtils.damageItem
*/
fun ItemStack.damage(damage: Int, player: Player) =
DurabilityUtils.damageItem(player, this, damage)

View File

@@ -13,3 +13,9 @@ fun <T> List<T>.toFrequencyMap(): Map<T, Int> =
*/ */
fun Iterable<String>.containsIgnoreCase(element: String): Boolean = fun Iterable<String>.containsIgnoreCase(element: String): Boolean =
ListUtils.containsIgnoreCase(this, element) ListUtils.containsIgnoreCase(this, element)
/**
* @see ListUtils.create2DList
*/
fun <T> create2DList(rows: Int, columns: Int): MutableList<MutableList<T>> =
ListUtils.create2DList(rows, columns)

View File

@@ -0,0 +1,29 @@
@file:JvmName("NamespacedKeyUtilsExtensions")
package com.willfp.eco.util
import com.willfp.eco.core.EcoPlugin
/**
* @see NamespacedKeyUtils.fromString
*/
fun namespacedKeyOf(string: String) =
NamespacedKeyUtils.fromString(string)
/**
* @see NamespacedKeyUtils.fromString
*/
fun safeNamespacedKeyOf(string: String) =
NamespacedKeyUtils.fromStringOrNull(string)
/**
* @see NamespacedKeyUtils.create
*/
fun namespacedKeyOf(namespace: String, key: String) =
NamespacedKeyUtils.create(namespace, key)
/**
* @see EcoPlugin.namespacedKeyFactory
*/
fun namespacedKeyOf(plugin: EcoPlugin, key: String) =
plugin.namespacedKeyFactory.create(key)

View File

@@ -0,0 +1,9 @@
@file:JvmName("NumberUtilsExtensions")
package com.willfp.eco.util
/**
* @see NumberUtils.toNumeral
*/
fun Number.toNumeral(): String =
NumberUtils.toNumeral(this.toInt())

View File

@@ -24,3 +24,9 @@ fun Player.asAudience(): Audience =
*/ */
fun CommandSender.asAudience(): Audience = fun CommandSender.asAudience(): Audience =
PlayerUtils.getAudience(this) PlayerUtils.getAudience(this)
/**
* @see PlayerUtils.runExempted
*/
fun Player.runExempted(action: () -> Unit) =
PlayerUtils.runExempted(this, action)

View File

@@ -35,7 +35,7 @@ fun String.formatEco(
fun List<String>.formatEco( fun List<String>.formatEco(
player: Player? = null, player: Player? = null,
formatPlaceholders: Boolean = false formatPlaceholders: Boolean = false
) = StringUtils.formatList( ): List<String> = StringUtils.formatList(
this, this,
player, player,
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS

View File

@@ -1,29 +1,8 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
}
}
group 'com.willfp' group 'com.willfp'
version rootProject.version version rootProject.version
subprojects { subprojects {
apply plugin: "kotlin"
dependencies { dependencies {
compileOnly project(":eco-api") compileOnly project(":eco-api")
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0'
} }
}
compileKotlin {
kotlinOptions {
jvmTarget = "17"
}
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.eco.internal
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginProps
import com.willfp.eco.core.config.TransientConfig
import com.willfp.eco.core.config.interfaces.Config
object EcoPropsParser : PluginProps.PropsParser<Config> {
override fun parseFrom(config: Config): PluginProps {
val resourceId = config.getIntOrNull("resource-id") ?: 0
val bStatsId = config.getIntOrNull("bstats-id") ?: 0
val proxyPackage = config.getStringOrNull("proxy-package") ?: ""
val color = config.getStringOrNull("color") ?: "&f"
val supportsExtensions = config.getBoolOrNull("supports-extensions") ?: false
return blankProps.apply {
this.resourceId = resourceId
this.bStatsId = bStatsId
this.proxyPackage = proxyPackage
this.color = color
this.isSupportingExtensions = supportsExtensions
}
}
fun parseForPlugin(plugin: Class<out EcoPlugin>): PluginProps {
if (!PluginProps.hasParserFor(Config::class.java)) {
PluginProps.registerParser(Config::class.java, this)
}
return PluginProps.parse(
TransientConfig(plugin.getResourceAsStream("/eco.yml")),
Config::class.java
)
}
}

View File

@@ -15,7 +15,7 @@ import com.willfp.eco.internal.config.yaml.EcoYamlConfigSection
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import java.io.StringReader import java.io.StringReader
class EcoConfigFactory : ConfigFactory { object EcoConfigFactory : ConfigFactory {
override fun createConfig(config: YamlConfiguration): Config { override fun createConfig(config: YamlConfiguration): Config {
return EcoYamlConfigSection(config) return EcoYamlConfigSection(config)
} }

View File

@@ -5,7 +5,7 @@ import com.willfp.eco.core.display.Display
import com.willfp.eco.core.display.DisplayHandler import com.willfp.eco.core.display.DisplayHandler
import com.willfp.eco.core.display.DisplayModule import com.willfp.eco.core.display.DisplayModule
import com.willfp.eco.core.display.DisplayPriority import com.willfp.eco.core.display.DisplayPriority
import com.willfp.eco.core.fast.FastItemStack import com.willfp.eco.core.fast.fast
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
@@ -60,7 +60,7 @@ class EcoDisplayHandler(plugin: EcoPlugin) : DisplayHandler {
Display.unfinalize(itemStack) Display.unfinalize(itemStack)
} }
val fast = FastItemStack.wrap(itemStack) val fast = itemStack.fast()
val lore = fast.lore val lore = fast.lore
if (lore.isNotEmpty() && lore.removeIf { line: String -> if (lore.isNotEmpty() && lore.removeIf { line: String ->

View File

@@ -10,7 +10,6 @@ import org.bukkit.Material
import org.bukkit.entity.EntityType import org.bukkit.entity.EntityType
import org.bukkit.entity.ExperienceOrb import org.bukkit.entity.ExperienceOrb
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.player.PlayerExpChangeEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.util.Vector import org.bukkit.util.Vector

View File

@@ -2,7 +2,7 @@ package com.willfp.eco.internal.entities
import com.willfp.eco.core.entities.args.EntityArgParseResult import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser import com.willfp.eco.core.entities.args.EntityArgParser
import org.bukkit.entity.Animals import org.bukkit.entity.Ageable
class EntityArgParserAdult : EntityArgParser { class EntityArgParserAdult : EntityArgParser {
override fun parseArguments(args: Array<out String>): EntityArgParseResult? { override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
@@ -20,14 +20,14 @@ class EntityArgParserAdult : EntityArgParser {
return EntityArgParseResult( return EntityArgParseResult(
{ {
if (it !is Animals) { if (it !is Ageable) {
return@EntityArgParseResult false return@EntityArgParseResult false
} }
it.isAdult it.isAdult
}, },
{ {
(it as? Animals)?.setAdult() (it as? Ageable)?.setAdult()
} }
) )
} }

View File

@@ -2,7 +2,7 @@ package com.willfp.eco.internal.entities
import com.willfp.eco.core.entities.args.EntityArgParseResult import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser import com.willfp.eco.core.entities.args.EntityArgParser
import org.bukkit.entity.Animals import org.bukkit.entity.Ageable
class EntityArgParserBaby : EntityArgParser { class EntityArgParserBaby : EntityArgParser {
override fun parseArguments(args: Array<out String>): EntityArgParseResult? { override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
@@ -20,14 +20,14 @@ class EntityArgParserBaby : EntityArgParser {
return EntityArgParseResult( return EntityArgParseResult(
{ {
if (it !is Animals) { if (it !is Ageable) {
return@EntityArgParseResult false return@EntityArgParseResult false
} }
!it.isAdult !it.isAdult
}, },
{ {
(it as? Animals)?.setBaby() (it as? Ageable)?.setBaby()
} }
) )
} }

View File

@@ -0,0 +1,62 @@
package com.willfp.eco.internal.entities
import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.TestableItem
import org.bukkit.entity.LivingEntity
import org.bukkit.inventory.EquipmentSlot
class EntityArgParserEquipment : EntityArgParser {
override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
val equipment = mutableMapOf<EquipmentSlot, TestableItem>()
for (arg in args) {
val argSplit = arg.split(":")
for (slot in EquipmentSlot.values()) {
if (!argSplit[0].equals(slot.name, ignoreCase = true)) {
continue
}
if (argSplit.size < 2) {
continue
}
equipment[slot] = Items.lookup(argSplit[1])
}
}
if (equipment.isEmpty()) {
return null
}
return EntityArgParseResult(
{
if (it !is LivingEntity) {
return@EntityArgParseResult false
}
val entityEquipment = it.equipment ?: return@EntityArgParseResult false
for ((slot, item) in equipment) {
if (!item.matches(entityEquipment.getItem(slot))) {
return@EntityArgParseResult false
}
}
return@EntityArgParseResult true
},
{
if (it !is LivingEntity) {
return@EntityArgParseResult
}
val entityEquipment = it.equipment ?: return@EntityArgParseResult
for ((slot, item) in equipment) {
entityEquipment.setItem(slot, item.item, false)
}
}
)
}
}

View File

@@ -2,7 +2,6 @@ package com.willfp.eco.internal.entities
import com.willfp.eco.core.entities.args.EntityArgParseResult import com.willfp.eco.core.entities.args.EntityArgParseResult
import com.willfp.eco.core.entities.args.EntityArgParser import com.willfp.eco.core.entities.args.EntityArgParser
import org.bukkit.entity.Animals
class EntityArgParserSilent : EntityArgParser { class EntityArgParserSilent : EntityArgParser {
override fun parseArguments(args: Array<out String>): EntityArgParseResult? { override fun parseArguments(args: Array<out String>): EntityArgParseResult? {

View File

@@ -12,7 +12,7 @@ class EcoCaptiveSlot(
allowMovingItem, allowMovingItem,
allowMovingItem, allowMovingItem,
allowMovingItem, allowMovingItem,
{ _, _, _ -> } { _, _, prev -> prev }
) { ) {
override fun isCaptive(): Boolean { override fun isCaptive(): Boolean {
return true return true

View File

@@ -9,5 +9,5 @@ class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
{ _, _, _ -> }, { _, _, _ -> },
{ _, _, _ -> }, { _, _, _ -> },
{ _, _, _ -> }, { _, _, _ -> },
{ _, _, _ -> } { _, _, prev -> prev }
) )

View File

@@ -3,8 +3,8 @@ package com.willfp.eco.internal.gui.slot
import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.gui.menu.Menu
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.core.gui.slot.functional.SlotHandler import com.willfp.eco.core.gui.slot.functional.SlotHandler
import com.willfp.eco.core.gui.slot.functional.SlotModifier
import com.willfp.eco.core.gui.slot.functional.SlotProvider import com.willfp.eco.core.gui.slot.functional.SlotProvider
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
import com.willfp.eco.internal.gui.menu.MenuHandler import com.willfp.eco.internal.gui.menu.MenuHandler
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.ClickType
@@ -18,7 +18,7 @@ open class EcoSlot(
private val onShiftLeftClick: SlotHandler, private val onShiftLeftClick: SlotHandler,
private val onShiftRightClick: SlotHandler, private val onShiftRightClick: SlotHandler,
private val onMiddleClick: SlotHandler, private val onMiddleClick: SlotHandler,
private val modifier: SlotModifier private val updater: SlotUpdater
) : Slot { ) : Slot {
fun handleInventoryClick( fun handleInventoryClick(
@@ -38,8 +38,7 @@ open class EcoSlot(
override fun getItemStack(player: Player): ItemStack { override fun getItemStack(player: Player): ItemStack {
val menu = MenuHandler.getMenu(player.openInventory.topInventory)!! val menu = MenuHandler.getMenu(player.openInventory.topInventory)!!
val prev = provider.provide(player, menu) val prev = provider.provide(player, menu)
modifier.modify(player, menu, prev) return updater.update(player, menu, prev)
return prev
} }
fun getItemStack( fun getItemStack(
@@ -47,8 +46,7 @@ open class EcoSlot(
menu: Menu menu: Menu
): ItemStack { ): ItemStack {
val prev = provider.provide(player, menu) val prev = provider.provide(player, menu)
modifier.modify(player, menu, prev) return updater.update(player, menu, prev)
return prev
} }
override fun isCaptive(): Boolean { override fun isCaptive(): Boolean {

View File

@@ -3,12 +3,12 @@ package com.willfp.eco.internal.gui.slot
import com.willfp.eco.core.gui.slot.Slot import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.core.gui.slot.SlotBuilder import com.willfp.eco.core.gui.slot.SlotBuilder
import com.willfp.eco.core.gui.slot.functional.SlotHandler import com.willfp.eco.core.gui.slot.functional.SlotHandler
import com.willfp.eco.core.gui.slot.functional.SlotModifier
import com.willfp.eco.core.gui.slot.functional.SlotProvider import com.willfp.eco.core.gui.slot.functional.SlotProvider
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder { class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
private var captive = false private var captive = false
private var modifier: SlotModifier = SlotModifier { player, menu, _ -> provider.provide(player, menu) } private var updater: SlotUpdater = SlotUpdater { player, menu, _ -> provider.provide(player, menu) }
private var onLeftClick = private var onLeftClick =
SlotHandler { _, _, _ -> run { } } SlotHandler { _, _, _ -> run { } }
@@ -51,8 +51,8 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
return this return this
} }
override fun setModifier(modifier: SlotModifier): SlotBuilder { override fun setUpdater(updater: SlotUpdater): SlotBuilder {
this.modifier = modifier this.updater = updater
return this return this
} }
@@ -60,7 +60,7 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
return if (captive) { return if (captive) {
EcoCaptiveSlot(provider) EcoCaptiveSlot(provider)
} else { } else {
EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick, modifier) EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick, updater)
} }
} }
} }

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.internal.items package com.willfp.eco.internal.items
import com.willfp.eco.core.fast.FastItemStack import com.willfp.eco.core.fast.fast
import com.willfp.eco.core.items.args.LookupArgParser import com.willfp.eco.core.items.args.LookupArgParser
import com.willfp.eco.util.NamespacedKeyUtils import com.willfp.eco.util.NamespacedKeyUtils
import org.bukkit.enchantments.Enchantment import org.bukkit.enchantments.Enchantment
@@ -41,7 +41,7 @@ class ArgParserEnchantment : LookupArgParser {
} }
return Predicate { return Predicate {
val onItem = FastItemStack.wrap(it).getEnchantmentsOnItem(true) val onItem = it.fast().getEnchants(true)
for ((enchant, level) in enchants) { for ((enchant, level) in enchants) {
if ((onItem[enchant] ?: 0) < level) { if ((onItem[enchant] ?: 0) < level) {

View File

@@ -4,7 +4,7 @@ import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.proxy.ProxyConstants import com.willfp.eco.core.proxy.ProxyConstants
import com.willfp.eco.core.proxy.ProxyFactory import com.willfp.eco.core.proxy.ProxyFactory
import com.willfp.eco.core.proxy.exceptions.ProxyError import com.willfp.eco.core.proxy.exceptions.ProxyError
import com.willfp.eco.core.proxy.exceptions.UnsupportedVersionException import com.willfp.eco.core.proxy.exceptions.UnsupportedVersionError
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.IdentityHashMap import java.util.IdentityHashMap
@@ -34,21 +34,26 @@ class EcoProxyFactory(
return proxy return proxy
} }
} catch (e: Exception) { } catch (e: Exception) {
throwError(e) throw proxyErrorFrom(e)
} }
throwError(IllegalArgumentException()) throw proxyErrorFrom(IllegalArgumentException("Class doesn't seem to be a proxy."))
throw RuntimeException("Something went wrong.")
} }
private fun throwError(e: Exception?) { private fun proxyErrorFrom(e: Exception): Throwable {
e?.printStackTrace() plugin.logger.severe("Fatal error with proxies! This plugin can't load.")
if (!SUPPORTED_VERSIONS.contains(ProxyConstants.NMS_VERSION)) { return if (!SUPPORTED_VERSIONS.contains(ProxyConstants.NMS_VERSION)) {
throw UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION) ProxyError(
"Could not initialize proxy.",
UnsupportedVersionError()
)
} else { } else {
throw ProxyError("Error with proxies - here's a stacktrace. Only god can help you now.") ProxyError(
"Could not initialize proxy. If you're seeing this error message"
+ ", something has gone badly wrong. This almost definitely isn't user error, blame the developer.",
e
)
} }
} }

View File

@@ -1,14 +1,17 @@
@file:Suppress("DEPRECATION")
package com.willfp.eco.internal.requirement package com.willfp.eco.internal.requirement
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement import com.willfp.eco.core.requirement.Requirement
import com.willfp.eco.core.requirement.RequirementFactory import com.willfp.eco.core.requirement.RequirementFactory
import com.willfp.eco.internal.requirement.requirements.RequirementHasPermission import org.bukkit.entity.Player
import com.willfp.eco.internal.requirement.requirements.RequirementPlaceholderEquals
import com.willfp.eco.internal.requirement.requirements.RequirementPlaceholderGreaterThan
import com.willfp.eco.internal.requirement.requirements.RequirementPlaceholderLessThan
import com.willfp.eco.internal.requirement.requirements.RequirementTrue
class EcoRequirementFactory: RequirementFactory { @Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
class EcoRequirementFactory : RequirementFactory {
override fun create(name: String): Requirement { override fun create(name: String): Requirement {
return when (name.lowercase()) { return when (name.lowercase()) {
"has-permission" -> RequirementHasPermission() "has-permission" -> RequirementHasPermission()
@@ -18,4 +21,93 @@ class EcoRequirementFactory: RequirementFactory {
else -> RequirementTrue() else -> RequirementTrue()
} }
} }
} }
@Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
class RequirementHasPermission : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.isEmpty()) {
return false
}
val permission = args[0]
return player.hasPermission(permission)
}
}
@Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
class RequirementPlaceholderEquals : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1]
return PlaceholderManager.translatePlaceholders(placeholder, player).equals(equals, ignoreCase = true)
}
}
@Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
@SuppressWarnings("DEPRECATION")
class RequirementPlaceholderGreaterThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return (PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0) >= equals
}
}
@Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
class RequirementPlaceholderLessThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return (PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0) < equals
}
}
@Deprecated(
"Requirement system is marked as for-removal from eco",
level = DeprecationLevel.WARNING
)
class RequirementTrue : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
return true
}
}

View File

@@ -1,18 +0,0 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementHasPermission : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.isEmpty()) {
return false
}
val permission = args[0]
return player.hasPermission(permission)
}
}

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderEquals : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1]
return PlaceholderManager.translatePlaceholders(placeholder, player).equals(equals, ignoreCase = true)
}
}

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderGreaterThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return (PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0) >= equals
}
}

View File

@@ -1,20 +0,0 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderLessThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return (PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0) < equals
}
}

View File

@@ -1,13 +0,0 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementTrue : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
return true
}
}

View File

@@ -8,7 +8,7 @@ import org.bukkit.inventory.MerchantRecipe
import java.lang.reflect.Field import java.lang.reflect.Field
class VillagerTrade : VillagerTradeProxy { class VillagerTrade : VillagerTradeProxy {
private var handle: Field private val handle: Field = CraftMerchantRecipe::class.java.getDeclaredField("handle")
override fun displayTrade( override fun displayTrade(
recipe: MerchantRecipe, recipe: MerchantRecipe,
@@ -35,7 +35,6 @@ class VillagerTrade : VillagerTradeProxy {
} }
init { init {
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
handle.isAccessible = true handle.isAccessible = true
} }
} }

View File

@@ -20,7 +20,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
itemStack.getNMSStack(), itemStack itemStack.getNMSStack(), itemStack
) { ) {
private var loreCache: List<String>? = null private var loreCache: List<String>? = null
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> { override fun getEnchants(checkStored: Boolean): Map<Enchantment, Int> {
val enchantmentNBT = if (checkStored && handle.item === Items.ENCHANTED_BOOK) ItemEnchantedBook.d( val enchantmentNBT = if (checkStored && handle.item === Items.ENCHANTED_BOOK) ItemEnchantedBook.d(
handle handle
) else handle.enchantments ) else handle.enchantments
@@ -29,7 +29,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
val compound = base as NBTTagCompound val compound = base as NBTTagCompound
val key = compound.getString("id") val key = compound.getString("id")
val level: Int = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt() val level: Int = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key)) val found = Enchantment.getByKey(NamespacedKeyUtils.fromStringOrNull(key))
if (found != null) { if (found != null) {
foundEnchantments[found] = level foundEnchantments[found] = level
} }

View File

@@ -21,7 +21,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
) { ) {
private var loreCache: List<String>? = null private var loreCache: List<String>? = null
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> { override fun getEnchants(checkStored: Boolean): Map<Enchantment, Int> {
val enchantmentNBT = val enchantmentNBT =
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments( if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle handle
@@ -31,7 +31,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
val compound = base as CompoundTag val compound = base as CompoundTag
val key = compound.getString("id") val key = compound.getString("id")
val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt() val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key)) val found = Enchantment.getByKey(NamespacedKeyUtils.fromStringOrNull(key))
if (found != null) { if (found != null) {
foundEnchantments[found] = level foundEnchantments[found] = level
} }
@@ -176,6 +176,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
} }
override fun hashCode(): Int { override fun hashCode(): Int {
@Suppress("KotlinDeprecation")
return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.item)) return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.item))
} }

View File

@@ -22,7 +22,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
) { ) {
private var loreCache: List<String>? = null private var loreCache: List<String>? = null
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> { override fun getEnchants(checkStored: Boolean): Map<Enchantment, Int> {
val enchantmentNBT = val enchantmentNBT =
if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments( if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle handle
@@ -32,7 +32,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
val compound = base as CompoundTag val compound = base as CompoundTag
val key = compound.getString("id") val key = compound.getString("id")
val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt() val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
val found = Enchantment.getByKey(NamespacedKeyUtils.fromString(key)) val found = Enchantment.getByKey(NamespacedKeyUtils.fromStringOrNull(key))
if (found != null) { if (found != null) {
foundEnchantments[found] = level foundEnchantments[found] = level
} }

View File

@@ -2,9 +2,11 @@ package com.willfp.eco.internal.spigot
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.Handler import com.willfp.eco.core.Handler
import com.willfp.eco.core.PluginProps
import com.willfp.eco.core.fast.FastItemStack import com.willfp.eco.core.fast.FastItemStack
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration
import com.willfp.eco.internal.EcoCleaner import com.willfp.eco.internal.EcoCleaner
import com.willfp.eco.internal.EcoPropsParser
import com.willfp.eco.internal.Plugins import com.willfp.eco.internal.Plugins
import com.willfp.eco.internal.config.EcoConfigFactory import com.willfp.eco.internal.config.EcoConfigFactory
import com.willfp.eco.internal.config.updating.EcoConfigHandler import com.willfp.eco.internal.config.updating.EcoConfigHandler
@@ -21,12 +23,9 @@ import com.willfp.eco.internal.gui.EcoGUIFactory
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
import com.willfp.eco.internal.logging.EcoLogger import com.willfp.eco.internal.logging.EcoLogger
import com.willfp.eco.internal.proxy.EcoProxyFactory 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.scheduling.EcoScheduler
import com.willfp.eco.internal.spigot.data.EcoKeyRegistry import com.willfp.eco.internal.spigot.data.EcoKeyRegistry
import com.willfp.eco.internal.spigot.data.EcoProfileHandler 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 import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
@@ -40,13 +39,12 @@ import java.util.logging.Logger
@Suppress("UNUSED") @Suppress("UNUSED")
class EcoHandler : EcoSpigotPlugin(), Handler { class EcoHandler : EcoSpigotPlugin(), Handler {
private val cleaner = EcoCleaner() private val cleaner = EcoCleaner()
private val requirementFactory = EcoRequirementFactory()
@Suppress("DEPRECATION")
private val requirementFactory = com.willfp.eco.internal.requirement.EcoRequirementFactory()
private var adventure: BukkitAudiences? = null private var adventure: BukkitAudiences? = null
private val keyRegistry = EcoKeyRegistry(this) private val keyRegistry = EcoKeyRegistry(this)
private val playerProfileHandler = EcoProfileHandler( private val playerProfileHandler = EcoProfileHandler(this.configYml.getBool("mysql.enabled"), this)
if (this.configYml.getBool("mysql.enabled"))
MySQLDataHandler(this) else YamlDataHandler(this)
)
@Suppress("RedundantNullableReturnType") @Suppress("RedundantNullableReturnType")
private val keyFactory: InternalNamespacedKeyFactory? = private val keyFactory: InternalNamespacedKeyFactory? =
@@ -94,7 +92,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
} }
override fun getConfigFactory(): EcoConfigFactory { override fun getConfigFactory(): EcoConfigFactory {
return EcoConfigFactory() return EcoConfigFactory
} }
override fun getDropQueueFactory(): EcoDropQueueFactory { override fun getDropQueueFactory(): EcoDropQueueFactory {
@@ -133,7 +131,8 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
MetricHandler.createMetrics(plugin) MetricHandler.createMetrics(plugin)
} }
override fun getRequirementFactory(): EcoRequirementFactory { @Suppress("DEPRECATION")
override fun getRequirementFactory(): com.willfp.eco.internal.requirement.EcoRequirementFactory {
return requirementFactory return requirementFactory
} }
@@ -161,4 +160,8 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
return keyFactory?.create(namespace, key) ?: NamespacedKey(namespace, key) return keyFactory?.create(namespace, key) ?: NamespacedKey(namespace, key)
} }
override fun getProps(existing: PluginProps?, plugin: Class<out EcoPlugin>): PluginProps {
return existing ?: EcoPropsParser.parseForPlugin(plugin)
}
} }

View File

@@ -24,6 +24,7 @@ import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
import com.willfp.eco.internal.entities.EntityArgParserBaby import com.willfp.eco.internal.entities.EntityArgParserBaby
import com.willfp.eco.internal.entities.EntityArgParserCharged import com.willfp.eco.internal.entities.EntityArgParserCharged
import com.willfp.eco.internal.entities.EntityArgParserEquipment
import com.willfp.eco.internal.entities.EntityArgParserExplosionRadius import com.willfp.eco.internal.entities.EntityArgParserExplosionRadius
import com.willfp.eco.internal.entities.EntityArgParserFlySpeed import com.willfp.eco.internal.entities.EntityArgParserFlySpeed
import com.willfp.eco.internal.entities.EntityArgParserFollowRange import com.willfp.eco.internal.entities.EntityArgParserFollowRange
@@ -120,12 +121,7 @@ import org.bukkit.Material
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
abstract class EcoSpigotPlugin : EcoPlugin( abstract class EcoSpigotPlugin : EcoPlugin() {
773,
10043,
"com.willfp.eco.internal.spigot.proxy",
"&a"
) {
init { init {
Items.registerArgParser(ArgParserEnchantment()) Items.registerArgParser(ArgParserEnchantment())
Items.registerArgParser(ArgParserColor()) Items.registerArgParser(ArgParserColor())
@@ -153,6 +149,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
Entities.registerArgParser(EntityArgParserCharged()) Entities.registerArgParser(EntityArgParserCharged())
Entities.registerArgParser(EntityArgParserExplosionRadius()) Entities.registerArgParser(EntityArgParserExplosionRadius())
Entities.registerArgParser(EntityArgParserSilent()) Entities.registerArgParser(EntityArgParserSilent())
Entities.registerArgParser(EntityArgParserEquipment())
ShapedRecipeListener.registerListener(ComplexInComplex()) ShapedRecipeListener.registerListener(ComplexInComplex())
ShapedRecipeListener.registerListener(ComplexInEco()) ShapedRecipeListener.registerListener(ComplexInEco())

View File

@@ -5,17 +5,23 @@ import com.willfp.eco.core.data.Profile
import com.willfp.eco.core.data.ProfileHandler import com.willfp.eco.core.data.ProfileHandler
import com.willfp.eco.core.data.ServerProfile import com.willfp.eco.core.data.ServerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
import com.willfp.eco.internal.spigot.data.storage.DataHandler import com.willfp.eco.internal.spigot.data.storage.DataHandler
import com.willfp.eco.internal.spigot.data.storage.MySQLDataHandler
import com.willfp.eco.internal.spigot.data.storage.YamlDataHandler
import java.util.UUID import java.util.UUID
val serverProfileUUID = UUID(0, 0) val serverProfileUUID = UUID(0, 0)
class EcoProfileHandler( class EcoProfileHandler(
private val handler: DataHandler useSql: Boolean,
plugin: EcoSpigotPlugin
) : ProfileHandler { ) : ProfileHandler {
private val loaded = mutableMapOf<UUID, Profile>() private val loaded = mutableMapOf<UUID, Profile>()
private val handler: DataHandler = if (useSql) MySQLDataHandler(plugin, this) else
YamlDataHandler(plugin, this)
private fun loadGenericProfile(uuid: UUID): Profile { fun loadGenericProfile(uuid: UUID): Profile {
val found = loaded[uuid] val found = loaded[uuid]
if (found != null) { if (found != null) {
return found return found

View File

@@ -2,10 +2,10 @@ package com.willfp.eco.internal.spigot.data.storage
import com.google.common.util.concurrent.ThreadFactoryBuilder import com.google.common.util.concurrent.ThreadFactoryBuilder
import com.willfp.eco.core.Eco import com.willfp.eco.core.Eco
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.internal.spigot.EcoSpigotPlugin import com.willfp.eco.internal.spigot.EcoSpigotPlugin
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import org.apache.logging.log4j.Level import org.apache.logging.log4j.Level
@@ -30,7 +30,8 @@ import java.util.concurrent.Executors
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class MySQLDataHandler( class MySQLDataHandler(
plugin: EcoSpigotPlugin plugin: EcoSpigotPlugin,
private val handler: EcoProfileHandler
) : DataHandler { ) : DataHandler {
private val columns = mutableMapOf<String, Column<*>>() private val columns = mutableMapOf<String, Column<*>>()
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build() private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
@@ -104,7 +105,7 @@ class MySQLDataHandler(
} }
private fun savePlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) { private fun savePlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
val profile = PlayerProfile.load(uuid) val profile = handler.loadGenericProfile(uuid)
executor.submit { executor.submit {
transaction { transaction {

View File

@@ -2,15 +2,16 @@ package com.willfp.eco.internal.spigot.data.storage
import com.willfp.eco.core.config.BaseConfig import com.willfp.eco.core.config.BaseConfig
import com.willfp.eco.core.config.ConfigType import com.willfp.eco.core.config.ConfigType
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.spigot.EcoSpigotPlugin import com.willfp.eco.internal.spigot.EcoSpigotPlugin
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import java.util.UUID import java.util.UUID
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class YamlDataHandler( class YamlDataHandler(
plugin: EcoSpigotPlugin plugin: EcoSpigotPlugin,
private val handler: EcoProfileHandler
) : DataHandler { ) : DataHandler {
private val dataYml = DataYml(plugin) private val dataYml = DataYml(plugin)
@@ -27,7 +28,7 @@ class YamlDataHandler(
} }
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) { override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
val profile = PlayerProfile.load(uuid) val profile = handler.loadGenericProfile(uuid)
for (key in keys) { for (key in keys) {
write(uuid, key.key, profile.read(key)) write(uuid, key.key, profile.read(key))

View File

@@ -135,4 +135,4 @@ class ShapedRecipeListener : Listener {
listeners.add(listener) listeners.add(listener)
} }
} }
} }

View File

@@ -0,0 +1,5 @@
resource-id: 773
bstats-id: 10043
proxy-package: com.willfp.eco.internal.spigot.proxy
color: '&a'
supports-extensions: false

View File

@@ -46,7 +46,7 @@ softdepend:
libraries: libraries:
- 'org.reflections:reflections:0.9.12' - 'org.reflections:reflections:0.9.12'
- 'org.apache.maven:maven-artifact:3.0.3' - 'org.apache.maven:maven-artifact:3.0.3'
- 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0' - 'org.jetbrains.kotlin:kotlin-stdlib:1.6.10'
- 'net.kyori:adventure-platform-bukkit:4.0.0' - 'net.kyori:adventure-platform-bukkit:4.0.0'
- 'net.kyori:adventure-api:4.9.3' - 'net.kyori:adventure-api:4.9.3'
- 'net.kyori:adventure-text-serializer-gson:4.9.3' - 'net.kyori:adventure-text-serializer-gson:4.9.3'

View File

@@ -1,3 +1,3 @@
version = 6.23.0 version = 6.24.4
plugin-name = eco plugin-name = eco
kotlin.code.style = official kotlin.code.style = official