Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7eb1b917dc | ||
|
|
fdba12082c | ||
|
|
516ecc1c3d | ||
|
|
cfd545c735 | ||
|
|
0ded1fe68b | ||
|
|
4fce11b149 | ||
|
|
2374e8fe03 | ||
|
|
36ccf346d7 | ||
|
|
cb480bd88d | ||
|
|
8cc96cb30e | ||
|
|
736ba0f8b0 | ||
|
|
5b5fefee8e | ||
|
|
8941e3179b | ||
|
|
19ce4c56a9 | ||
|
|
337c5d2b84 | ||
|
|
631c17aedc | ||
|
|
0ff4ac92be | ||
|
|
aa94094078 | ||
|
|
135ddcf331 | ||
|
|
e5d31e0b49 | ||
|
|
448b2e4b3f | ||
|
|
ebb30e3a70 | ||
|
|
fb89415636 | ||
|
|
36c77d81eb | ||
|
|
b6cd56ad15 | ||
|
|
1a524aea94 | ||
|
|
2ebab99a06 | ||
|
|
46663f7edb | ||
|
|
4fad66cd90 | ||
|
|
a9fafeec00 | ||
|
|
0d8308d6cd | ||
|
|
13772002e8 | ||
|
|
c9b84889e7 | ||
|
|
1513578266 | ||
|
|
89d6f2f867 | ||
|
|
8e6d98c997 | ||
|
|
5bc2cb31a4 | ||
|
|
041575a103 | ||
|
|
c88dac56b7 | ||
|
|
00da717f6d | ||
|
|
cc557378cc | ||
|
|
b5c49c79b8 | ||
|
|
28018430e7 | ||
|
|
7b6c8d68a8 | ||
|
|
ad3cb3a620 | ||
|
|
511a7e4830 | ||
|
|
5aeeafc041 | ||
|
|
9a51fb8358 | ||
|
|
eeefb9f40e | ||
|
|
aa1ce34cbc | ||
|
|
47772c3ff7 | ||
|
|
dfcac5d527 | ||
|
|
40f88f0b59 | ||
|
|
105355d967 | ||
|
|
3cddff22b8 | ||
|
|
f8e930d29e | ||
|
|
9dbe088e66 | ||
|
|
6361c0e8e9 | ||
|
|
1135672241 | ||
|
|
80891e4a81 | ||
|
|
3e0be3a629 | ||
|
|
17819de2ea | ||
|
|
8b9e8589a0 |
@@ -29,7 +29,7 @@ and many more.
|
||||
|
||||
# For server owners
|
||||
- Requires ProtocolLib to be installed: get the latest version [here](https://www.spigotmc.org/resources/protocollib.1997/)
|
||||
- Supports 1.16.5+
|
||||
- Supports 1.17+
|
||||
|
||||
## Downloads
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
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("java")
|
||||
kotlin("jvm") version "1.6.10"
|
||||
@@ -21,7 +21,6 @@ dependencies {
|
||||
implementation(project(":eco-core:core-plugin"))
|
||||
implementation(project(":eco-core:core-proxy"))
|
||||
implementation(project(":eco-core:core-backend"))
|
||||
implementation(project(":eco-core:core-nms:v1_16_R3"))
|
||||
implementation(project(path = ":eco-core:core-nms:v1_17_R1", configuration = "reobf"))
|
||||
implementation(project(path = ":eco-core:core-nms:v1_18_R1", configuration = "reobf"))
|
||||
}
|
||||
@@ -116,6 +115,10 @@ allprojects {
|
||||
exclude(group = "com.github.cryptomorin", module = "XSeries")
|
||||
}
|
||||
|
||||
configurations.testImplementation {
|
||||
setExtendsFrom(listOf(configurations.compileOnly.get()))
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
|
||||
@@ -204,15 +204,6 @@ public interface Handler {
|
||||
*/
|
||||
void registerBStats(@NotNull EcoPlugin plugin);
|
||||
|
||||
/**
|
||||
* Get the requirement factory.
|
||||
*
|
||||
* @return The factory.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(forRemoval = true)
|
||||
com.willfp.eco.core.requirement.RequirementFactory getRequirementFactory();
|
||||
|
||||
/**
|
||||
* Get Adventure audiences.
|
||||
*
|
||||
|
||||
@@ -51,7 +51,10 @@ public class Prerequisite {
|
||||
|
||||
/**
|
||||
* Requires the server to be running 1.17.
|
||||
*
|
||||
* @deprecated eco no longer supports versions before 1.17.
|
||||
*/
|
||||
@Deprecated(since = "6.25.2")
|
||||
public static final Prerequisite HAS_1_17 = new Prerequisite(
|
||||
() -> ProxyConstants.NMS_VERSION.contains("17") || HAS_1_18.isMet(),
|
||||
"Requires server to be running 1.17+"
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package com.willfp.eco.core.data.keys;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* API to register persistent data keys.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
public interface KeyRegistry {
|
||||
/**
|
||||
* Register a persistent data key to be stored.
|
||||
@@ -21,4 +27,37 @@ public interface KeyRegistry {
|
||||
* @return The keys.
|
||||
*/
|
||||
Set<PersistentDataKey<?>> getRegisteredKeys();
|
||||
|
||||
/**
|
||||
* Mark key as category.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param category The category.
|
||||
*/
|
||||
void markKeyAs(@NotNull PersistentDataKey<?> key,
|
||||
@NotNull KeyRegistry.KeyCategory category);
|
||||
|
||||
/**
|
||||
* Get persistent data key from namespaced key.
|
||||
*
|
||||
* @param namespacedKey The key.
|
||||
* @return The key, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
PersistentDataKey<?> getKeyFrom(@NotNull NamespacedKey namespacedKey);
|
||||
|
||||
/**
|
||||
* Locations for key categorization.
|
||||
*/
|
||||
enum KeyCategory {
|
||||
/**
|
||||
* Player keys.
|
||||
*/
|
||||
PLAYER,
|
||||
|
||||
/**
|
||||
* Server keys.
|
||||
*/
|
||||
SERVER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.willfp.eco.core.data.keys;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -11,7 +13,7 @@ import java.util.Set;
|
||||
*
|
||||
* @param <T> The type of the data.
|
||||
*/
|
||||
public class PersistentDataKey<T> {
|
||||
public final class PersistentDataKey<T> {
|
||||
/**
|
||||
* The key of the persistent data value.
|
||||
*/
|
||||
@@ -80,6 +82,32 @@ public class PersistentDataKey<T> {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Categorize key as a server key, will register new column to MySQL
|
||||
* database immediately rather than waiting for auto-categorization.
|
||||
* <p>
|
||||
* This will improve performance.
|
||||
*
|
||||
* @return The key.
|
||||
*/
|
||||
public PersistentDataKey<T> server() {
|
||||
Eco.getHandler().getKeyRegistry().markKeyAs(this, KeyRegistry.KeyCategory.SERVER);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Categorize key as a player key, will register new column to MySQL
|
||||
* database immediately rather than waiting for auto-categorization.
|
||||
* <p>
|
||||
* This will improve performance.
|
||||
*
|
||||
* @return The key.
|
||||
*/
|
||||
public PersistentDataKey<T> player() {
|
||||
Eco.getHandler().getKeyRegistry().markKeyAs(this, KeyRegistry.KeyCategory.PLAYER);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all persistent data keys.
|
||||
*
|
||||
@@ -88,4 +116,20 @@ public class PersistentDataKey<T> {
|
||||
public static Set<PersistentDataKey<?>> values() {
|
||||
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof PersistentDataKey that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getKey(), that.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.willfp.eco.core.entities;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
/**
|
||||
* Interface for Dummy Entities in order to filter them using instanceof.
|
||||
*/
|
||||
public interface DummyEntity extends Entity {
|
||||
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import com.willfp.eco.core.entities.impl.EmptyTestableEntity;
|
||||
import com.willfp.eco.core.entities.impl.ModifiedTestableEntity;
|
||||
import com.willfp.eco.core.entities.impl.SimpleTestableEntity;
|
||||
import com.willfp.eco.util.NamespacedKeyUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -37,6 +36,11 @@ public final class Entities {
|
||||
*/
|
||||
private static final List<EntityArgParser> ARG_PARSERS = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The lookup handler.
|
||||
*/
|
||||
private static final EntitiesLookupHandler ENTITIES_LOOKUP_HANDLER = new EntitiesLookupHandler(Entities::doParse);
|
||||
|
||||
/**
|
||||
* Register a new custom item.
|
||||
*
|
||||
@@ -87,20 +91,11 @@ public final class Entities {
|
||||
*/
|
||||
@NotNull
|
||||
public static TestableEntity lookup(@NotNull final String key) {
|
||||
if (key.contains("?")) {
|
||||
String[] options = key.split("\\?");
|
||||
for (String option : options) {
|
||||
TestableEntity lookup = lookup(option);
|
||||
if (!(lookup instanceof EmptyTestableEntity)) {
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyTestableEntity();
|
||||
}
|
||||
|
||||
String[] args = StringUtils.parseTokens(key);
|
||||
return ENTITIES_LOOKUP_HANDLER.parseKey(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TestableEntity doParse(@NotNull final String[] args) {
|
||||
if (args.length == 0) {
|
||||
return new EmptyTestableEntity();
|
||||
}
|
||||
@@ -131,7 +126,6 @@ public final class Entities {
|
||||
entity = part;
|
||||
}
|
||||
|
||||
|
||||
String[] modifierArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
|
||||
List<EntityArgParseResult> parseResults = new ArrayList<>();
|
||||
@@ -172,7 +166,6 @@ public final class Entities {
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Testable Entity from an ItemStack.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.willfp.eco.core.entities;
|
||||
|
||||
import com.willfp.eco.core.entities.impl.EmptyTestableEntity;
|
||||
import com.willfp.eco.core.entities.impl.GroupedTestableEntities;
|
||||
import com.willfp.eco.core.lookup.LookupHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Handle item lookup strings.
|
||||
*/
|
||||
public class EntitiesLookupHandler implements LookupHandler<TestableEntity> {
|
||||
/**
|
||||
* The parser.
|
||||
*/
|
||||
private final Function<String[], @NotNull TestableEntity> parser;
|
||||
|
||||
/**
|
||||
* Create new lookup handler.
|
||||
*
|
||||
* @param parser The parser.
|
||||
*/
|
||||
public EntitiesLookupHandler(@NotNull final Function<String[], @NotNull TestableEntity> parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableEntity parse(@NotNull final String[] args) {
|
||||
return parser.apply(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(@NotNull final TestableEntity object) {
|
||||
return !(object instanceof EmptyTestableEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableEntity getFailsafe() {
|
||||
return new EmptyTestableEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableEntity join(@NotNull final Collection<TestableEntity> options) {
|
||||
return new GroupedTestableEntities(options);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.entities;
|
||||
|
||||
import com.willfp.eco.core.lookup.Testable;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -8,13 +9,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* An item with a test to see if any item is that item.
|
||||
*/
|
||||
public interface TestableEntity {
|
||||
public interface TestableEntity extends Testable<Entity> {
|
||||
/**
|
||||
* If an Entity matches the test.
|
||||
*
|
||||
* @param entity The entity to test.
|
||||
* @return If the entity matches.
|
||||
*/
|
||||
@Override
|
||||
boolean matches(@Nullable Entity entity);
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.willfp.eco.core.entities.impl;
|
||||
|
||||
import com.willfp.eco.core.entities.TestableEntity;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A group of testable entities.
|
||||
*
|
||||
* @see com.willfp.eco.core.entities.CustomEntity
|
||||
*/
|
||||
public class GroupedTestableEntities implements TestableEntity {
|
||||
/**
|
||||
* The children.
|
||||
*/
|
||||
private final Collection<TestableEntity> children;
|
||||
|
||||
/**
|
||||
* Create a new group of testable entities.
|
||||
*
|
||||
* @param children The children.
|
||||
*/
|
||||
public GroupedTestableEntities(@NotNull final Collection<TestableEntity> children) {
|
||||
Validate.isTrue(!children.isEmpty(), "Group must have at least one child!");
|
||||
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the item matches any children.
|
||||
*
|
||||
* @param entity The entity to test.
|
||||
* @return If the entity matches the test of any children.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(@Nullable final Entity entity) {
|
||||
for (TestableEntity child : children) {
|
||||
if (child.matches(entity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawn(@NotNull final Location location) {
|
||||
return new ArrayList<>(children)
|
||||
.get(NumberUtils.randInt(0, children.size() - 1))
|
||||
.spawn(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the children.
|
||||
*
|
||||
* @return The children.
|
||||
*/
|
||||
public Collection<TestableEntity> getChildren() {
|
||||
return new ArrayList<>(children);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,8 @@ public final class AntigriefManager {
|
||||
* @param location The location.
|
||||
* @return If player can pick up item.
|
||||
*/
|
||||
public static boolean canPickupItem(@NotNull final Player player, @NotNull final Location location) {
|
||||
public static boolean canPickupItem(@NotNull final Player player,
|
||||
@NotNull final Location location) {
|
||||
return REGISTERED.stream().allMatch(antigriefWrapper -> antigriefWrapper.canPickupItem(player, location));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import com.willfp.eco.util.NamespacedKeyUtils;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -68,6 +67,11 @@ public final class Items {
|
||||
*/
|
||||
private static final List<LookupArgParser> ARG_PARSERS = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The handler.
|
||||
*/
|
||||
private static final ItemsLookupHandler ITEMS_LOOKUP_HANDLER = new ItemsLookupHandler(Items::doParse);
|
||||
|
||||
/**
|
||||
* Register a new custom item.
|
||||
*
|
||||
@@ -131,20 +135,11 @@ public final class Items {
|
||||
*/
|
||||
@NotNull
|
||||
public static TestableItem lookup(@NotNull final String key) {
|
||||
if (key.contains("?")) {
|
||||
String[] options = key.split("\\?");
|
||||
for (String option : options) {
|
||||
TestableItem lookup = lookup(option);
|
||||
if (!(lookup instanceof EmptyTestableItem)) {
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
String[] args = StringUtils.parseTokens(key);
|
||||
return ITEMS_LOOKUP_HANDLER.parseKey(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TestableItem doParse(@NotNull final String[] args) {
|
||||
if (args.length == 0) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.willfp.eco.core.items;
|
||||
|
||||
import com.willfp.eco.core.lookup.LookupHandler;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.GroupedTestableItems;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Handle item lookup strings.
|
||||
*/
|
||||
public class ItemsLookupHandler implements LookupHandler<TestableItem> {
|
||||
/**
|
||||
* The parser.
|
||||
*/
|
||||
private final Function<String[], @NotNull TestableItem> parser;
|
||||
|
||||
/**
|
||||
* Create new lookup handler.
|
||||
*
|
||||
* @param parser The parser.
|
||||
*/
|
||||
public ItemsLookupHandler(@NotNull final Function<String[], @NotNull TestableItem> parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableItem parse(@NotNull final String[] args) {
|
||||
return parser.apply(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(@NotNull final TestableItem object) {
|
||||
return !(object instanceof EmptyTestableItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableItem getFailsafe() {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TestableItem join(@NotNull final Collection<TestableItem> options) {
|
||||
return new GroupedTestableItems(options);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,20 @@
|
||||
package com.willfp.eco.core.items;
|
||||
|
||||
import com.willfp.eco.core.lookup.Testable;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An item with a test to see if any item is that item.
|
||||
*/
|
||||
public interface TestableItem {
|
||||
public interface TestableItem extends Testable<ItemStack> {
|
||||
/**
|
||||
* If an ItemStack matches the recipe part.
|
||||
*
|
||||
* @param itemStack The item to test.
|
||||
* @return If the item matches.
|
||||
*/
|
||||
@Override
|
||||
boolean matches(@Nullable ItemStack itemStack);
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.willfp.eco.core.lookup;
|
||||
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Handle lookups, used in {@link com.willfp.eco.core.entities.Entities} and {@link com.willfp.eco.core.items.Items}.
|
||||
*
|
||||
* @param <T> The type of testable object, eg {@link com.willfp.eco.core.items.TestableItem}.
|
||||
*/
|
||||
public interface LookupHandler<T extends Testable<?>> {
|
||||
/**
|
||||
* Parse lookup string completely.
|
||||
* <p>
|
||||
* You shouldn't override this method unless you're doing something
|
||||
* technically interesting or weird. This is the entry point for all
|
||||
* lookup parsers, {@link this#parse(String[])} is to specify implementation-specific
|
||||
* parsing.
|
||||
*
|
||||
* @param key The key.
|
||||
* @return The object.
|
||||
*/
|
||||
default T parseKey(@NotNull String key) {
|
||||
for (SegmentParser parser : SegmentParser.values()) {
|
||||
T generated = parser.parse(key, this);
|
||||
|
||||
if (generated != null) {
|
||||
return generated;
|
||||
}
|
||||
}
|
||||
|
||||
String[] args = StringUtils.parseTokens(key);
|
||||
|
||||
return this.parse(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse arguments to an object.
|
||||
*
|
||||
* @param args The arguments.
|
||||
* @return The object.
|
||||
*/
|
||||
@NotNull
|
||||
T parse(@NotNull String[] args);
|
||||
|
||||
/**
|
||||
* Validate an object.
|
||||
*
|
||||
* @param object The object.
|
||||
* @return If validated.
|
||||
*/
|
||||
boolean validate(@NotNull T object);
|
||||
|
||||
/**
|
||||
* Get the failsafe object.
|
||||
* <p>
|
||||
* A failsafe object should never pass {@link this#validate(Testable)}, as this will
|
||||
* cause issues with segment parsers. See {@link com.willfp.eco.core.items.ItemsLookupHandler} and
|
||||
* {@link com.willfp.eco.core.recipe.parts.EmptyTestableItem} for examples.
|
||||
*
|
||||
* @return The failsafe.
|
||||
*/
|
||||
@NotNull
|
||||
T getFailsafe();
|
||||
|
||||
/**
|
||||
* Join several options together.
|
||||
*
|
||||
* @param options The options.
|
||||
* @return The joined object.
|
||||
*/
|
||||
@NotNull
|
||||
T join(@NotNull Collection<T> options);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.willfp.eco.core.lookup;
|
||||
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Parse a key into segments.
|
||||
*/
|
||||
public abstract class SegmentParser {
|
||||
/**
|
||||
* All segment parsers.
|
||||
*/
|
||||
private static final List<SegmentParser> REGISTERED = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The pattern to split keys on.
|
||||
*/
|
||||
private final String pattern;
|
||||
|
||||
/**
|
||||
* Create new lookup segment parser.
|
||||
*
|
||||
* @param pattern The pattern.
|
||||
*/
|
||||
protected SegmentParser(@NotNull final String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the parser.
|
||||
*
|
||||
* @return The parser.
|
||||
*/
|
||||
public SegmentParser register() {
|
||||
REGISTERED.add(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try parse segments from key.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param handler The handler.
|
||||
* @param <T> The object type.
|
||||
* @return Null if no segments were found, or the object generated from the segments.
|
||||
*/
|
||||
@Nullable
|
||||
public <T extends Testable<?>> T parse(@NotNull final String key,
|
||||
@NotNull final LookupHandler<T> handler) {
|
||||
if (!key.contains(" " + pattern + " ")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] segments = StringUtils.splitAround(key, pattern);
|
||||
|
||||
return handleSegments(segments, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle segments from key.
|
||||
*
|
||||
* @param segments The key segments.
|
||||
* @param handler The handler.
|
||||
* @param <T> The object type.
|
||||
* @return The returned object.
|
||||
*/
|
||||
protected abstract <T extends Testable<?>> T handleSegments(@NotNull String[] segments,
|
||||
@NotNull LookupHandler<T> handler);
|
||||
|
||||
/**
|
||||
* Get all segment parsers.
|
||||
*
|
||||
* @return All parsers.
|
||||
*/
|
||||
public static Collection<SegmentParser> values() {
|
||||
return new ArrayList<>(REGISTERED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.core.lookup;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for testing if any object matches another object.
|
||||
*
|
||||
* @param <T> The type of object.
|
||||
*/
|
||||
public interface Testable<T> {
|
||||
/**
|
||||
* If object matches the test.
|
||||
*
|
||||
* @param other The other object.
|
||||
* @return If matches.
|
||||
*/
|
||||
boolean matches(@Nullable T other);
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package com.willfp.eco.core.proxy;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Proxy / NMS constants.
|
||||
*/
|
||||
@@ -11,6 +14,14 @@ public final class ProxyConstants {
|
||||
*/
|
||||
public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
|
||||
/**
|
||||
* All supported NMS versions.
|
||||
*/
|
||||
public static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
|
||||
"v1_17_R1",
|
||||
"v1_18_R1"
|
||||
);
|
||||
|
||||
private ProxyConstants() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.willfp.eco.core.recipe.parts;
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A group of testable items.
|
||||
*
|
||||
* @see com.willfp.eco.core.items.CustomItem
|
||||
*/
|
||||
public class GroupedTestableItems implements TestableItem {
|
||||
/**
|
||||
* The children.
|
||||
*/
|
||||
private final Collection<TestableItem> children;
|
||||
|
||||
/**
|
||||
* Create a new group of testable items.
|
||||
*
|
||||
* @param children The children.
|
||||
*/
|
||||
public GroupedTestableItems(@NotNull final Collection<TestableItem> children) {
|
||||
Validate.isTrue(!children.isEmpty(), "Group must have at least one child!");
|
||||
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the item matches any children.
|
||||
*
|
||||
* @param itemStack The item to test.
|
||||
* @return If the item matches the test of any children..
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(@Nullable final ItemStack itemStack) {
|
||||
for (TestableItem child : children) {
|
||||
if (child.matches(itemStack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem() {
|
||||
for (TestableItem child : children) {
|
||||
return child.getItem();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Empty group of children!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the children.
|
||||
*
|
||||
* @return The children.
|
||||
*/
|
||||
public Collection<TestableItem> getChildren() {
|
||||
return new ArrayList<>(children);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,8 +12,8 @@ import java.util.List;
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
public abstract class Requirement {
|
||||
/**
|
||||
* Create a new requirement.
|
||||
@@ -29,4 +31,9 @@ public abstract class Requirement {
|
||||
*/
|
||||
public abstract boolean doesPlayerMeet(@NotNull Player player,
|
||||
@NotNull List<String> args);
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface for internal requirement factory implementations.
|
||||
*
|
||||
* @deprecated See {@link Requirement}.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Eco.HandlerComponent
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
@SuppressWarnings({"removal", "DeprecatedIsStillUsed"})
|
||||
public interface RequirementFactory {
|
||||
/**
|
||||
* Create a requirement.
|
||||
*
|
||||
* @param name The name.
|
||||
* @return The requirement returned for the name.
|
||||
* Will return a requirement that is always true if not found.
|
||||
*/
|
||||
Requirement create(@NotNull String name);
|
||||
}
|
||||
@@ -1,35 +1,40 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Contains methods and fields pertaining to requirements.
|
||||
*
|
||||
* @deprecated See {@link Requirement}.
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public final class Requirements {
|
||||
/**
|
||||
* Requires a player to have a permission.
|
||||
*/
|
||||
public static final Requirement HAS_PERMISSION = Eco.getHandler().getRequirementFactory().create("has-permission");
|
||||
public static final Requirement HAS_PERMISSION = new com.willfp.eco.core.requirement.impl.RequirementHasPermission();
|
||||
|
||||
/**
|
||||
* Placeholder equals value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_EQUALS = Eco.getHandler().getRequirementFactory().create("placeholder-equals");
|
||||
public static final Requirement PLACEHOLDER_EQUALS = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderEquals();
|
||||
|
||||
/**
|
||||
* Numeric placeholder greater than value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_GREATER_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-greater-than");
|
||||
public static final Requirement PLACEHOLDER_GREATER_THAN = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderGreaterThan();
|
||||
|
||||
/**
|
||||
* Numeric placeholder less than value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_LESS_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-less-than");
|
||||
public static final Requirement PLACEHOLDER_LESS_THAN = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderLessThan();
|
||||
|
||||
/**
|
||||
* Get Requirements matching ID.
|
||||
@@ -38,10 +43,27 @@ public final class Requirements {
|
||||
* @return The matching Requirements.
|
||||
*/
|
||||
public static Requirement getByID(@NotNull final String name) {
|
||||
return Eco.getHandler().getRequirementFactory().create(name);
|
||||
return switch (name.toLowerCase()) {
|
||||
case "has-permission" -> HAS_PERMISSION;
|
||||
case "placeholder-equals" -> PLACEHOLDER_EQUALS;
|
||||
case "placeholder-greater-than" -> PLACEHOLDER_GREATER_THAN;
|
||||
case "placeholder-less-than" -> PLACEHOLDER_LESS_THAN;
|
||||
default -> new Requirement() {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private Requirements() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementHasPermission extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return player.hasPermission(args.get(0));
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderEquals extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PlaceholderManager.translatePlaceholders(args.get(0), player).equalsIgnoreCase(args.get(1));
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderGreaterThan extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double actual;
|
||||
try {
|
||||
actual = Double.parseDouble(PlaceholderManager.translatePlaceholders(args.get(0), player));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double expected;
|
||||
try {
|
||||
expected = Double.parseDouble(args.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return actual >= expected;
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderLessThan extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double actual;
|
||||
try {
|
||||
actual = Double.parseDouble(PlaceholderManager.translatePlaceholders(args.get(0), player));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double expected;
|
||||
try {
|
||||
expected = Double.parseDouble(args.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return actual < expected;
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,14 @@ public final class StringUtils {
|
||||
.put("§k", ChatColor.MAGIC)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Regex map for splitting values.
|
||||
*/
|
||||
private static final LoadingCache<String, Pattern> SPACE_AROUND_CHARACTER = Caffeine.newBuilder()
|
||||
.build(
|
||||
character -> Pattern.compile("( " + Pattern.quote(character) + " )")
|
||||
);
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
@@ -419,9 +427,23 @@ public final class StringUtils {
|
||||
*
|
||||
* @param object The object to convert to string.
|
||||
* @return The object stringified.
|
||||
* @deprecated Poorly named method. Use {@link StringUtils#toNiceString(Object)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public static String internalToString(@Nullable final Object object) {
|
||||
return toNiceString(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal implementation of {@link String#valueOf}.
|
||||
* Formats collections and doubles better.
|
||||
*
|
||||
* @param object The object to convert to string.
|
||||
* @return The object stringified.
|
||||
*/
|
||||
@NotNull
|
||||
public static String toNiceString(@Nullable final Object object) {
|
||||
if (object == null) {
|
||||
return "null";
|
||||
}
|
||||
@@ -433,7 +455,7 @@ public final class StringUtils {
|
||||
} else if (object instanceof Double) {
|
||||
return NumberUtils.format((Double) object);
|
||||
} else if (object instanceof Collection<?> c) {
|
||||
return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", "));
|
||||
return c.stream().map(StringUtils::toNiceString).collect(Collectors.joining(", "));
|
||||
} else {
|
||||
return String.valueOf(object);
|
||||
}
|
||||
@@ -560,6 +582,22 @@ public final class StringUtils {
|
||||
return tokens.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split input string around separator surrounded by spaces.
|
||||
* <p>
|
||||
* e.g. {@code splitAround("hello ? how are you", "?")} will split, but
|
||||
* {@code splitAround("hello? how are you", "?")} will not.
|
||||
*
|
||||
* @param input Input string.
|
||||
* @param separator Separator.
|
||||
* @return The split string.
|
||||
*/
|
||||
@NotNull
|
||||
public static String[] splitAround(@NotNull final String input,
|
||||
@NotNull final String separator) {
|
||||
return SPACE_AROUND_CHARACTER.get(separator).split(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for formatting.
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.willfp.eco.util;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.willfp.eco.core.Prerequisite;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
@@ -91,17 +90,15 @@ public final class TeamUtils {
|
||||
MATERIAL_COLORS.put(Material.EMERALD_ORE, ChatColor.GREEN);
|
||||
MATERIAL_COLORS.put(Material.ANCIENT_DEBRIS, ChatColor.DARK_RED);
|
||||
|
||||
if (Prerequisite.HAS_1_17.isMet()) {
|
||||
MATERIAL_COLORS.put(Material.COPPER_ORE, ChatColor.GOLD);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_COPPER_ORE, ChatColor.GOLD);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_COAL_ORE, ChatColor.BLACK);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_IRON_ORE, ChatColor.GRAY);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_GOLD_ORE, ChatColor.YELLOW);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_LAPIS_ORE, ChatColor.BLUE);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_REDSTONE_ORE, ChatColor.RED);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_DIAMOND_ORE, ChatColor.AQUA);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_EMERALD_ORE, ChatColor.GREEN);
|
||||
}
|
||||
MATERIAL_COLORS.put(Material.COPPER_ORE, ChatColor.GOLD);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_COPPER_ORE, ChatColor.GOLD);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_COAL_ORE, ChatColor.BLACK);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_IRON_ORE, ChatColor.GRAY);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_GOLD_ORE, ChatColor.YELLOW);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_LAPIS_ORE, ChatColor.BLUE);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_REDSTONE_ORE, ChatColor.RED);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_DIAMOND_ORE, ChatColor.AQUA);
|
||||
MATERIAL_COLORS.put(Material.DEEPSLATE_EMERALD_ORE, ChatColor.GREEN);
|
||||
}
|
||||
|
||||
private TeamUtils() {
|
||||
|
||||
@@ -40,3 +40,15 @@ fun List<String>.formatEco(
|
||||
player,
|
||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
||||
)
|
||||
|
||||
/**
|
||||
* @see StringUtils.splitAround
|
||||
*/
|
||||
fun String.splitAround(separator: String): Array<String> =
|
||||
StringUtils.splitAround(this, separator)
|
||||
|
||||
/**
|
||||
* @see StringUtils.toNiceString
|
||||
*/
|
||||
fun Any?.toNiceString(): String =
|
||||
StringUtils.toNiceString(this)
|
||||
|
||||
29
eco-api/src/test/java/StringUtilsTest.java
Normal file
29
eco-api/src/test/java/StringUtilsTest.java
Normal file
@@ -0,0 +1,29 @@
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class StringUtilsTest {
|
||||
@Test
|
||||
public void testSplitAround() {
|
||||
Assertions.assertArrayEquals(
|
||||
new String[]{"one", "two"},
|
||||
StringUtils.splitAround("one ? two", "?")
|
||||
);
|
||||
Assertions.assertArrayEquals(
|
||||
new String[]{"one? two"},
|
||||
StringUtils.splitAround("one? two", "?")
|
||||
);
|
||||
Assertions.assertArrayEquals(
|
||||
new String[]{"one", "two", "three"},
|
||||
StringUtils.splitAround("one ? two ? three", "?")
|
||||
);
|
||||
Assertions.assertArrayEquals(
|
||||
new String[]{"one", "two"},
|
||||
StringUtils.splitAround("one || two", "||")
|
||||
);
|
||||
Assertions.assertArrayEquals(
|
||||
new String[]{"one|| two"},
|
||||
StringUtils.splitAround("one|| two", "||")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.willfp.eco.internal.entities
|
||||
|
||||
import com.willfp.eco.core.entities.DummyEntity
|
||||
import org.bukkit.entity.Entity
|
||||
|
||||
class EcoDummyEntity(private val handle: Entity) : DummyEntity, Entity by handle {
|
||||
override fun toString(): String {
|
||||
return "DummyEntity{id=${this.entityId}}"
|
||||
}
|
||||
}
|
||||
@@ -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.EntityArgParser
|
||||
import org.bukkit.entity.Animals
|
||||
import org.bukkit.entity.Ageable
|
||||
|
||||
class EntityArgParserAdult : EntityArgParser {
|
||||
override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
|
||||
@@ -20,14 +20,14 @@ class EntityArgParserAdult : EntityArgParser {
|
||||
|
||||
return EntityArgParseResult(
|
||||
{
|
||||
if (it !is Animals) {
|
||||
if (it !is Ageable) {
|
||||
return@EntityArgParseResult false
|
||||
}
|
||||
|
||||
it.isAdult
|
||||
},
|
||||
{
|
||||
(it as? Animals)?.setAdult()
|
||||
(it as? Ageable)?.setAdult()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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.EntityArgParser
|
||||
import org.bukkit.entity.Animals
|
||||
import org.bukkit.entity.Ageable
|
||||
|
||||
class EntityArgParserBaby : EntityArgParser {
|
||||
override fun parseArguments(args: Array<out String>): EntityArgParseResult? {
|
||||
@@ -20,14 +20,14 @@ class EntityArgParserBaby : EntityArgParser {
|
||||
|
||||
return EntityArgParseResult(
|
||||
{
|
||||
if (it !is Animals) {
|
||||
if (it !is Ageable) {
|
||||
return@EntityArgParseResult false
|
||||
}
|
||||
|
||||
!it.isAdult
|
||||
},
|
||||
{
|
||||
(it as? Animals)?.setBaby()
|
||||
(it as? Ageable)?.setBaby()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,17 +12,11 @@ class EntityArgParserEquipment : EntityArgParser {
|
||||
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)) {
|
||||
if (!arg.lowercase().startsWith("${slot.name.lowercase()}:")) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (argSplit.size < 2) {
|
||||
continue
|
||||
}
|
||||
|
||||
equipment[slot] = Items.lookup(argSplit[1])
|
||||
equipment[slot] = Items.lookup(arg.substring(slot.name.length + 1, arg.length))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,10 @@ class EntityArgParserName : EntityArgParser {
|
||||
var name: String? = null
|
||||
|
||||
for (arg in args) {
|
||||
val argSplit = arg.split(":")
|
||||
if (!argSplit[0].equals("name", ignoreCase = true)) {
|
||||
if (!arg.lowercase().startsWith("name:")) {
|
||||
continue
|
||||
}
|
||||
if (argSplit.size < 2) {
|
||||
continue
|
||||
}
|
||||
name = argSplit[1]
|
||||
name = arg.substring(5, arg.length)
|
||||
}
|
||||
|
||||
name ?: return null
|
||||
|
||||
@@ -11,20 +11,17 @@ class ArgParserName : LookupArgParser {
|
||||
var name: String? = null
|
||||
|
||||
for (arg in args) {
|
||||
val argSplit = arg.split(":")
|
||||
if (!argSplit[0].equals("name", ignoreCase = true)) {
|
||||
if (!arg.lowercase().startsWith("name:")) {
|
||||
continue
|
||||
}
|
||||
if (argSplit.size < 2) {
|
||||
continue
|
||||
}
|
||||
name = argSplit[1]
|
||||
name = arg.substring(5, arg.length)
|
||||
}
|
||||
|
||||
name ?: return null
|
||||
|
||||
val formatted = StringUtils.format(name)
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
meta.setDisplayName(formatted)
|
||||
|
||||
return Predicate {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.willfp.eco.internal.lookup
|
||||
|
||||
import com.willfp.eco.core.lookup.LookupHandler
|
||||
import com.willfp.eco.core.lookup.SegmentParser
|
||||
import com.willfp.eco.core.lookup.Testable
|
||||
|
||||
class SegmentParserGroup : SegmentParser("||") {
|
||||
override fun <T : Testable<*>> handleSegments(segments: Array<out String>, handler: LookupHandler<T>): T {
|
||||
val possibleOptions = mutableListOf<T>()
|
||||
|
||||
for (option in segments) {
|
||||
val lookup = handler.parseKey(option)
|
||||
if (handler.validate(lookup)) {
|
||||
possibleOptions.add(lookup)
|
||||
}
|
||||
}
|
||||
|
||||
if (possibleOptions.isEmpty()) {
|
||||
return handler.failsafe
|
||||
}
|
||||
|
||||
return handler.join(possibleOptions)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.internal.lookup
|
||||
|
||||
import com.willfp.eco.core.lookup.LookupHandler
|
||||
import com.willfp.eco.core.lookup.SegmentParser
|
||||
import com.willfp.eco.core.lookup.Testable
|
||||
|
||||
class SegmentParserUseIfPresent : SegmentParser("?") {
|
||||
override fun <T : Testable<*>> handleSegments(segments: Array<out String>, handler: LookupHandler<T>): T {
|
||||
for (option in segments) {
|
||||
val lookup = handler.parseKey(option)
|
||||
if (handler.validate(lookup)) {
|
||||
return lookup
|
||||
}
|
||||
}
|
||||
|
||||
return handler.failsafe
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class EcoProxyFactory(
|
||||
private fun proxyErrorFrom(e: Exception): Throwable {
|
||||
plugin.logger.severe("Fatal error with proxies! This plugin can't load.")
|
||||
|
||||
return if (!SUPPORTED_VERSIONS.contains(ProxyConstants.NMS_VERSION)) {
|
||||
return if (!ProxyConstants.SUPPORTED_VERSIONS.contains(ProxyConstants.NMS_VERSION)) {
|
||||
ProxyError(
|
||||
"Could not initialize proxy.",
|
||||
UnsupportedVersionError()
|
||||
@@ -74,12 +74,4 @@ class EcoProxyFactory(
|
||||
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SUPPORTED_VERSIONS = listOf(
|
||||
"v1_16_R3",
|
||||
"v1_17_R1",
|
||||
"v1_18_R1"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
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.RequirementFactory
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
@Deprecated(
|
||||
"Requirement system is marked as for-removal from eco",
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
class EcoRequirementFactory : RequirementFactory {
|
||||
override fun create(name: String): Requirement {
|
||||
return when (name.lowercase()) {
|
||||
"has-permission" -> RequirementHasPermission()
|
||||
"placeholder-equals" -> RequirementPlaceholderEquals()
|
||||
"placeholder-greater-than" -> RequirementPlaceholderGreaterThan()
|
||||
"placeholder-less-than" -> RequirementPlaceholderLessThan()
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT'
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
import com.willfp.eco.internal.spigot.proxy.AutoCraftProxy
|
||||
import net.minecraft.server.v1_16_R3.MinecraftKey
|
||||
import net.minecraft.server.v1_16_R3.PacketPlayOutAutoRecipe
|
||||
|
||||
class AutoCraft : AutoCraftProxy {
|
||||
override fun modifyPacket(packet: Any) {
|
||||
val recipePacket = packet as PacketPlayOutAutoRecipe
|
||||
val fKey = recipePacket.javaClass.getDeclaredField("b")
|
||||
fKey.isAccessible = true
|
||||
val key = fKey[recipePacket] as MinecraftKey
|
||||
fKey[recipePacket] = MinecraftKey(key.namespace, key.key + "_displayed")
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy
|
||||
import net.minecraft.server.v1_16_R3.BlockPosition
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class BlockBreak : BlockBreakProxy {
|
||||
override fun breakBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
) {
|
||||
if (player !is CraftPlayer) {
|
||||
return
|
||||
}
|
||||
player.handle.playerInteractManager.breakBlock(BlockPosition(block.x, block.y, block.z))
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.core.display.Display
|
||||
import com.willfp.eco.internal.spigot.proxy.ChatComponentProxy
|
||||
import net.kyori.adventure.nbt.api.BinaryTagHolder
|
||||
import net.kyori.adventure.text.BuildableComponent
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.TranslatableComponent
|
||||
import net.kyori.adventure.text.event.HoverEvent
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
|
||||
import net.minecraft.server.v1_16_R3.IChatBaseComponent
|
||||
import net.minecraft.server.v1_16_R3.MojangsonParser
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class ChatComponent : ChatComponentProxy {
|
||||
private val gsonComponentSerializer = GsonComponentSerializer.gson()
|
||||
|
||||
override fun modifyComponent(obj: Any, player: Player): Any {
|
||||
if (obj !is IChatBaseComponent) {
|
||||
return obj
|
||||
}
|
||||
|
||||
val component = gsonComponentSerializer.deserialize(
|
||||
IChatBaseComponent.ChatSerializer.a(
|
||||
obj
|
||||
)
|
||||
).asComponent() as BuildableComponent<*, *>
|
||||
|
||||
val newComponent = modifyBaseComponent(component, player)
|
||||
|
||||
return IChatBaseComponent.ChatSerializer.a(
|
||||
gsonComponentSerializer.serialize(newComponent.asComponent())
|
||||
) ?: obj
|
||||
}
|
||||
|
||||
private fun modifyBaseComponent(baseComponent: Component, player: Player): Component {
|
||||
var component = baseComponent
|
||||
|
||||
if (component is TranslatableComponent) {
|
||||
val args = mutableListOf<Component>()
|
||||
for (arg in component.args()) {
|
||||
args.add(modifyBaseComponent(arg, player))
|
||||
}
|
||||
component = component.args(args)
|
||||
}
|
||||
|
||||
val children = mutableListOf<Component>()
|
||||
for (child in component.children()) {
|
||||
children.add(modifyBaseComponent(child, player))
|
||||
}
|
||||
component = component.children(children)
|
||||
|
||||
val hoverEvent: HoverEvent<Any> = component.style().hoverEvent() as HoverEvent<Any>? ?: return component
|
||||
|
||||
val showItem = hoverEvent.value()
|
||||
|
||||
if (showItem !is HoverEvent.ShowItem) {
|
||||
return component
|
||||
}
|
||||
|
||||
val newShowItem = showItem.nbt(
|
||||
BinaryTagHolder.of(
|
||||
CraftItemStack.asNMSCopy(
|
||||
Display.display(
|
||||
CraftItemStack.asBukkitCopy(
|
||||
CraftItemStack.asNMSCopy(
|
||||
org.bukkit.inventory.ItemStack(
|
||||
Material.matchMaterial(
|
||||
showItem.item()
|
||||
.toString()
|
||||
) ?: return component,
|
||||
showItem.count()
|
||||
)
|
||||
).apply {
|
||||
this.tag = MojangsonParser.parse(
|
||||
showItem.nbt()?.string() ?: return component
|
||||
) ?: return component
|
||||
}
|
||||
),
|
||||
player
|
||||
)
|
||||
).orCreateTag.toString()
|
||||
)
|
||||
)
|
||||
|
||||
val newHover = hoverEvent.value(newShowItem)
|
||||
val style = component.style().hoverEvent(newHover)
|
||||
return component.style(style)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.entity.EntityType
|
||||
|
||||
class DummyEntity : DummyEntityProxy {
|
||||
override fun createDummyEntity(location: Location): Entity {
|
||||
val world = location.world as CraftWorld
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
return world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity()
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
import com.willfp.eco.core.fast.FastItemStack
|
||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.v1_16_R3.fast.NMSFastItemStack
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class FastItemStackFactory : FastItemStackFactoryProxy {
|
||||
override fun create(itemStack: ItemStack): FastItemStack {
|
||||
return NMSFastItemStack(itemStack)
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.mojang.authlib.GameProfile
|
||||
import com.mojang.authlib.properties.Property
|
||||
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.util.UUID
|
||||
|
||||
class Skull : SkullProxy {
|
||||
private lateinit var setProfile: Method
|
||||
private lateinit var profile: Field
|
||||
|
||||
override fun setSkullTexture(
|
||||
meta: SkullMeta,
|
||||
base64: String
|
||||
) {
|
||||
if (!this::setProfile.isInitialized) {
|
||||
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
|
||||
setProfile.isAccessible = true
|
||||
}
|
||||
val uuid = UUID(
|
||||
base64.substring(base64.length - 20).hashCode().toLong(),
|
||||
base64.substring(base64.length - 10).hashCode().toLong()
|
||||
)
|
||||
val profile = GameProfile(uuid, "eco")
|
||||
profile.properties.put("textures", Property("textures", base64))
|
||||
setProfile.invoke(meta, profile)
|
||||
}
|
||||
|
||||
override fun getSkullTexture(
|
||||
meta: SkullMeta
|
||||
): String? {
|
||||
if (!this::profile.isInitialized) {
|
||||
profile = meta.javaClass.getDeclaredField("profile")
|
||||
profile.isAccessible = true
|
||||
}
|
||||
val profile = profile[meta] as GameProfile? ?: return null
|
||||
val properties = profile.properties ?: return null
|
||||
val prop = properties["textures"] ?: return null
|
||||
return prop.toMutableList().firstOrNull()?.name
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftServer
|
||||
|
||||
class TPS : TPSProxy {
|
||||
override fun getTPS(): Double {
|
||||
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.core.display.Display
|
||||
import com.willfp.eco.internal.spigot.proxy.VillagerTradeProxy
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.MerchantRecipe
|
||||
import java.lang.reflect.Field
|
||||
|
||||
class VillagerTrade : VillagerTradeProxy {
|
||||
private val handle: Field = CraftMerchantRecipe::class.java.getDeclaredField("handle")
|
||||
|
||||
override fun displayTrade(
|
||||
recipe: MerchantRecipe,
|
||||
player: Player
|
||||
): MerchantRecipe {
|
||||
val oldRecipe = recipe as CraftMerchantRecipe
|
||||
val newRecipe = CraftMerchantRecipe(
|
||||
Display.display(recipe.getResult().clone(), player),
|
||||
recipe.getUses(),
|
||||
recipe.getMaxUses(),
|
||||
recipe.hasExperienceReward(),
|
||||
recipe.getVillagerExperience(),
|
||||
recipe.getPriceMultiplier()
|
||||
)
|
||||
for (ingredient in recipe.getIngredients()) {
|
||||
newRecipe.addIngredient(Display.display(ingredient.clone(), player))
|
||||
}
|
||||
getHandle(newRecipe).specialPrice = getHandle(oldRecipe).specialPrice
|
||||
return newRecipe
|
||||
}
|
||||
|
||||
private fun getHandle(recipe: CraftMerchantRecipe): net.minecraft.server.v1_16_R3.MerchantRecipe {
|
||||
return handle[recipe] as net.minecraft.server.v1_16_R3.MerchantRecipe
|
||||
}
|
||||
|
||||
init {
|
||||
handle.isAccessible = true
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3.fast
|
||||
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.lang.reflect.Field
|
||||
|
||||
private val field: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
|
||||
isAccessible = true
|
||||
}
|
||||
|
||||
fun ItemStack.getNMSStack(): net.minecraft.server.v1_16_R3.ItemStack {
|
||||
return if (this !is CraftItemStack) {
|
||||
CraftItemStack.asNMSCopy(this)
|
||||
} else {
|
||||
field[this] as net.minecraft.server.v1_16_R3.ItemStack? ?: CraftItemStack.asNMSCopy(this)
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_16_R3.fast
|
||||
|
||||
import com.willfp.eco.internal.fast.EcoFastItemStack
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import net.minecraft.server.v1_16_R3.Item
|
||||
import net.minecraft.server.v1_16_R3.ItemEnchantedBook
|
||||
import net.minecraft.server.v1_16_R3.ItemStack
|
||||
import net.minecraft.server.v1_16_R3.Items
|
||||
import net.minecraft.server.v1_16_R3.NBTTagCompound
|
||||
import net.minecraft.server.v1_16_R3.NBTTagList
|
||||
import net.minecraft.server.v1_16_R3.NBTTagString
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
|
||||
import org.bukkit.craftbukkit.v1_16_R3.util.CraftMagicNumbers
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.inventory.ItemFlag
|
||||
import kotlin.experimental.and
|
||||
|
||||
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
|
||||
itemStack.getNMSStack(), itemStack
|
||||
) {
|
||||
private var loreCache: List<String>? = null
|
||||
override fun getEnchants(checkStored: Boolean): Map<Enchantment, Int> {
|
||||
val enchantmentNBT = if (checkStored && handle.item === Items.ENCHANTED_BOOK) ItemEnchantedBook.d(
|
||||
handle
|
||||
) else handle.enchantments
|
||||
val foundEnchantments: MutableMap<Enchantment, Int> = HashMap()
|
||||
for (base in enchantmentNBT) {
|
||||
val compound = base as NBTTagCompound
|
||||
val key = compound.getString("id")
|
||||
val level: Int = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
|
||||
val found = Enchantment.getByKey(NamespacedKeyUtils.fromStringOrNull(key))
|
||||
if (found != null) {
|
||||
foundEnchantments[found] = level
|
||||
}
|
||||
}
|
||||
return foundEnchantments
|
||||
}
|
||||
|
||||
override fun getLevelOnItem(
|
||||
enchantment: Enchantment,
|
||||
checkStored: Boolean
|
||||
): Int {
|
||||
val enchantmentNBT = if (checkStored && handle.item === Items.ENCHANTED_BOOK) ItemEnchantedBook.d(
|
||||
handle
|
||||
) else handle.enchantments
|
||||
for (base in enchantmentNBT) {
|
||||
val compound = base as NBTTagCompound
|
||||
val key = compound.getString("id")
|
||||
if (key != enchantment.key.toString()) {
|
||||
continue
|
||||
}
|
||||
return ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun setLore(lore: List<String>?) {
|
||||
loreCache = null
|
||||
val jsonLore: MutableList<String> = ArrayList()
|
||||
if (lore != null) {
|
||||
for (s in lore) {
|
||||
jsonLore.add(StringUtils.legacyToJson(s))
|
||||
}
|
||||
}
|
||||
val displayTag = handle.a("display")
|
||||
if (!displayTag.hasKey("Lore")) {
|
||||
displayTag["Lore"] = NBTTagList()
|
||||
}
|
||||
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
|
||||
loreTag.clear()
|
||||
for (s in jsonLore) {
|
||||
loreTag.add(NBTTagString.a(s))
|
||||
}
|
||||
apply()
|
||||
}
|
||||
|
||||
override fun getLore(): List<String> {
|
||||
if (loreCache != null) {
|
||||
return loreCache as List<String>
|
||||
}
|
||||
val lore: MutableList<String> = ArrayList()
|
||||
for (s in getLoreJSON()) {
|
||||
lore.add(StringUtils.jsonToLegacy(s))
|
||||
}
|
||||
loreCache = lore
|
||||
return lore
|
||||
}
|
||||
|
||||
private fun getLoreJSON(): List<String> {
|
||||
val displayTag = handle.b("display") ?: return emptyList()
|
||||
return if (displayTag.hasKey("Lore")) {
|
||||
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
|
||||
val lore: MutableList<String> = ArrayList(loreTag.size)
|
||||
for (i in loreTag.indices) {
|
||||
lore.add(loreTag.getString(i))
|
||||
}
|
||||
lore
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun addItemFlags(vararg hideFlags: ItemFlag) {
|
||||
for (flag in hideFlags) {
|
||||
this.flagBits = this.flagBits or getBitModifier(flag)
|
||||
}
|
||||
|
||||
apply()
|
||||
}
|
||||
|
||||
override fun removeItemFlags(vararg hideFlags: ItemFlag) {
|
||||
for (flag in hideFlags) {
|
||||
this.flagBits = this.flagBits and getBitModifier(flag)
|
||||
}
|
||||
|
||||
apply()
|
||||
}
|
||||
|
||||
override fun getItemFlags(): MutableSet<ItemFlag> {
|
||||
val flags = mutableSetOf<ItemFlag>()
|
||||
|
||||
var flagArr: Array<ItemFlag>
|
||||
val size = ItemFlag.values().also { flagArr = it }.size
|
||||
|
||||
for (i in 0 until size) {
|
||||
val flag = flagArr[i]
|
||||
if (this.hasItemFlag(flag)) {
|
||||
flags.add(flag)
|
||||
}
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
override fun hasItemFlag(flag: ItemFlag): Boolean {
|
||||
val bitModifier = getBitModifier(flag)
|
||||
return this.flagBits and bitModifier == bitModifier
|
||||
}
|
||||
|
||||
private var flagBits: Int
|
||||
get() =
|
||||
if (handle.hasTag() && handle.tag!!.hasKeyOfType(
|
||||
"HideFlags",
|
||||
99
|
||||
)
|
||||
) handle.tag!!.getInt("HideFlags") else 0
|
||||
set(value) =
|
||||
handle.orCreateTag.setInt("HideFlags", value)
|
||||
|
||||
override fun getRepairCost(): Int {
|
||||
return handle.repairCost
|
||||
}
|
||||
|
||||
override fun setRepairCost(cost: Int) {
|
||||
handle.repairCost = cost
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is NMSFastItemStack) {
|
||||
return false
|
||||
}
|
||||
|
||||
return other.hashCode() == this.hashCode()
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.item))
|
||||
}
|
||||
|
||||
private fun apply() {
|
||||
if (bukkit !is CraftItemStack) {
|
||||
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_17_R1
|
||||
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
|
||||
import com.willfp.eco.internal.entities.EcoDummyEntity
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.entity.EntityType
|
||||
|
||||
class DummyEntity : DummyEntityProxy {
|
||||
class DummyEntityFactory : DummyEntityFactoryProxy {
|
||||
override fun createDummyEntity(location: Location): Entity {
|
||||
val world = location.world as CraftWorld
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
return world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity()
|
||||
return EcoDummyEntity(world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
|
||||
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
|
||||
import com.willfp.eco.internal.entities.EcoDummyEntity
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.entity.EntityType
|
||||
|
||||
class DummyEntity : DummyEntityProxy {
|
||||
class DummyEntityFactory : DummyEntityFactoryProxy {
|
||||
override fun createDummyEntity(location: Location): Entity {
|
||||
val world = location.world as CraftWorld
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
return world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity()
|
||||
return EcoDummyEntity(world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,17 +26,16 @@ dependencies {
|
||||
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.202'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.10'
|
||||
compileOnly 'com.github.oraxen:oraxen:bd81ace154'
|
||||
compileOnly 'com.github.Ssomar-Developement:ExecutableItems:master-SNAPSHOT'
|
||||
compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0'
|
||||
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
|
||||
compileOnly 'com.arcaniax:HeadDatabase-API:1.3.0'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-core:0.36.2'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-dao:0.36.2'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-core:0.37.3'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-dao:0.37.3'
|
||||
compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.37.3'
|
||||
compileOnly 'mysql:mysql-connector-java:8.0.25'
|
||||
compileOnly 'com.zaxxer:HikariCP:5.0.0'
|
||||
compileOnly 'com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.0'
|
||||
compileOnly 'com.github.EssentialsX:Essentials:2.19.0'
|
||||
compileOnly 'com.github.EssentialsX:Essentials:2.18.2'
|
||||
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:1.8.3'
|
||||
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
|
||||
compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.willfp.eco.internal.spigot
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.PluginProps
|
||||
import com.willfp.eco.core.Handler
|
||||
import com.willfp.eco.core.PluginProps
|
||||
import com.willfp.eco.core.fast.FastItemStack
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration
|
||||
import com.willfp.eco.internal.EcoCleaner
|
||||
@@ -24,12 +24,11 @@ import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
|
||||
import com.willfp.eco.internal.logging.EcoLogger
|
||||
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||
import com.willfp.eco.internal.scheduling.EcoScheduler
|
||||
import com.willfp.eco.internal.spigot.data.DataYml
|
||||
import com.willfp.eco.internal.spigot.data.EcoKeyRegistry
|
||||
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.proxy.DummyEntityProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||
import org.bukkit.Location
|
||||
@@ -40,16 +39,13 @@ import java.util.logging.Logger
|
||||
|
||||
@Suppress("UNUSED")
|
||||
class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
override val dataYml = DataYml(this)
|
||||
|
||||
private val cleaner = EcoCleaner()
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private val requirementFactory = com.willfp.eco.internal.requirement.EcoRequirementFactory()
|
||||
private var adventure: BukkitAudiences? = null
|
||||
private val keyRegistry = EcoKeyRegistry(this)
|
||||
private val playerProfileHandler = EcoProfileHandler(
|
||||
if (this.configYml.getBool("mysql.enabled"))
|
||||
MySQLDataHandler(this) else YamlDataHandler(this)
|
||||
)
|
||||
private val keyRegistry = EcoKeyRegistry()
|
||||
private val playerProfileHandler = EcoProfileHandler(this.configYml.getBool("mysql.enabled"), this)
|
||||
|
||||
@Suppress("RedundantNullableReturnType")
|
||||
private val keyFactory: InternalNamespacedKeyFactory? =
|
||||
@@ -136,11 +132,6 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
MetricHandler.createMetrics(plugin)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getRequirementFactory(): com.willfp.eco.internal.requirement.EcoRequirementFactory {
|
||||
return requirementFactory
|
||||
}
|
||||
|
||||
override fun getAdventure(): BukkitAudiences? {
|
||||
return adventure
|
||||
}
|
||||
@@ -158,7 +149,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
}
|
||||
|
||||
override fun createDummyEntity(location: Location): Entity {
|
||||
return getProxy(DummyEntityProxy::class.java).createDummyEntity(location)
|
||||
return getProxy(DummyEntityFactoryProxy::class.java).createDummyEntity(location)
|
||||
}
|
||||
|
||||
override fun createNamespacedKey(namespace: String, key: String): NamespacedKey {
|
||||
|
||||
@@ -45,8 +45,12 @@ import com.willfp.eco.internal.items.ArgParserFlag
|
||||
import com.willfp.eco.internal.items.ArgParserName
|
||||
import com.willfp.eco.internal.items.ArgParserTexture
|
||||
import com.willfp.eco.internal.items.ArgParserUnbreakable
|
||||
import com.willfp.eco.internal.lookup.SegmentParserGroup
|
||||
import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent
|
||||
import com.willfp.eco.internal.spigot.arrows.ArrowDataListener
|
||||
import com.willfp.eco.internal.spigot.data.DataListener
|
||||
import com.willfp.eco.internal.spigot.data.DataYml
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.PlayerBlockListener
|
||||
import com.willfp.eco.internal.spigot.data.storage.ProfileSaver
|
||||
import com.willfp.eco.internal.spigot.display.PacketAutoRecipe
|
||||
@@ -122,6 +126,8 @@ import org.bukkit.event.Listener
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
abstract val dataYml: DataYml
|
||||
|
||||
init {
|
||||
Items.registerArgParser(ArgParserEnchantment())
|
||||
Items.registerArgParser(ArgParserColor())
|
||||
@@ -155,6 +161,9 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
ShapedRecipeListener.registerListener(ComplexInEco())
|
||||
ShapedRecipeListener.registerListener(ComplexInVanilla())
|
||||
|
||||
SegmentParserGroup().register()
|
||||
SegmentParserUseIfPresent().register()
|
||||
|
||||
val skullProxy = getProxy(SkullProxy::class.java)
|
||||
SkullUtils.initialize(
|
||||
{ meta, base64 -> skullProxy.setSkullTexture(meta, base64) },
|
||||
@@ -183,10 +192,11 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
(Eco.getHandler() as EcoHandler).setAdventure(BukkitAudiences.create(this))
|
||||
}
|
||||
|
||||
this.logger.info("Ignore messages about deprecated events!")
|
||||
|
||||
// Init FIS
|
||||
this.getProxy(FastItemStackFactoryProxy::class.java).create(ItemStack(Material.AIR)).unwrap()
|
||||
|
||||
// Preload categorized persistent data keys
|
||||
(Eco.getHandler().profileHandler as EcoProfileHandler).initialize()
|
||||
}
|
||||
|
||||
override fun handleDisable() {
|
||||
@@ -327,4 +337,4 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
|
||||
return listeners
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.willfp.eco.internal.spigot.data
|
||||
|
||||
import com.willfp.eco.core.config.BaseConfig
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
|
||||
class DataYml(
|
||||
plugin: EcoSpigotPlugin
|
||||
) : BaseConfig(
|
||||
"data",
|
||||
plugin,
|
||||
false,
|
||||
ConfigType.YAML
|
||||
)
|
||||
@@ -4,13 +4,11 @@ import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
class EcoKeyRegistry(
|
||||
private val plugin: EcoSpigotPlugin
|
||||
) : KeyRegistry {
|
||||
class EcoKeyRegistry : KeyRegistry {
|
||||
private val registry = mutableMapOf<NamespacedKey, PersistentDataKey<*>>()
|
||||
private val categories = mutableMapOf<NamespacedKey, KeyRegistry.KeyCategory>()
|
||||
|
||||
override fun registerKey(key: PersistentDataKey<*>) {
|
||||
if (this.registry.containsKey(key.key)) {
|
||||
@@ -20,8 +18,6 @@ class EcoKeyRegistry(
|
||||
validateKey(key)
|
||||
|
||||
this.registry[key.key] = key
|
||||
|
||||
(Eco.getHandler().profileHandler as EcoProfileHandler).updateKeys()
|
||||
}
|
||||
|
||||
override fun getRegisteredKeys(): MutableSet<PersistentDataKey<*>> {
|
||||
@@ -46,4 +42,13 @@ class EcoKeyRegistry(
|
||||
else -> throw NullPointerException("Null value found!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun markKeyAs(key: PersistentDataKey<*>, category: KeyRegistry.KeyCategory) {
|
||||
categories[key.key] = category
|
||||
(Eco.getHandler().profileHandler as EcoProfileHandler).handler.categorize(key, category) // ew
|
||||
}
|
||||
|
||||
override fun getKeyFrom(namespacedKey: NamespacedKey): PersistentDataKey<*>? {
|
||||
return registry[namespacedKey]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +65,4 @@ class EcoServerProfile(
|
||||
override fun toString(): String {
|
||||
return "EcoServerProfile"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,23 @@ import com.willfp.eco.core.data.Profile
|
||||
import com.willfp.eco.core.data.ProfileHandler
|
||||
import com.willfp.eco.core.data.ServerProfile
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
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
|
||||
|
||||
val serverProfileUUID = UUID(0, 0)
|
||||
|
||||
class EcoProfileHandler(
|
||||
private val handler: DataHandler
|
||||
useSql: Boolean,
|
||||
plugin: EcoSpigotPlugin
|
||||
) : ProfileHandler {
|
||||
private val loaded = mutableMapOf<UUID, Profile>()
|
||||
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]
|
||||
if (found != null) {
|
||||
return found
|
||||
@@ -58,7 +64,7 @@ class EcoProfileHandler(
|
||||
handler.save()
|
||||
}
|
||||
|
||||
fun updateKeys() {
|
||||
handler.updateKeys()
|
||||
fun initialize() {
|
||||
handler.initialize()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.willfp.eco.internal.spigot.data
|
||||
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
object KeyHelpers {
|
||||
fun deserializeFromString(serialized: String): PersistentDataKey<*>? {
|
||||
val split = serialized.split(";").toTypedArray()
|
||||
|
||||
if (split.size < 2) {
|
||||
return null
|
||||
}
|
||||
|
||||
val key = NamespacedKeyUtils.fromStringOrNull(split[0]) ?: return null
|
||||
val type = PersistentDataKeyType.valueOf(split[1]) ?: return null
|
||||
return when (type) {
|
||||
PersistentDataKeyType.STRING -> PersistentDataKey(
|
||||
key,
|
||||
type as PersistentDataKeyType<String>,
|
||||
if (split.size >= 3) split.toList().subList(2, split.size).joinToString("") else ""
|
||||
)
|
||||
PersistentDataKeyType.INT -> PersistentDataKey(
|
||||
key,
|
||||
type as PersistentDataKeyType<Int>,
|
||||
split[2].toInt()
|
||||
)
|
||||
PersistentDataKeyType.DOUBLE -> PersistentDataKey(
|
||||
key,
|
||||
type as PersistentDataKeyType<Double>,
|
||||
split[2].toDouble()
|
||||
)
|
||||
PersistentDataKeyType.BOOLEAN -> PersistentDataKey(
|
||||
key,
|
||||
type as PersistentDataKeyType<Boolean>,
|
||||
java.lang.Boolean.parseBoolean(split[2])
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun serializeToString(key: PersistentDataKey<*>): String {
|
||||
return "${key.key};${key.type.name()};${key.defaultValue}"
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,27 @@
|
||||
package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import org.bukkit.NamespacedKey
|
||||
import java.util.UUID
|
||||
|
||||
interface DataHandler {
|
||||
fun save() {
|
||||
fun save()
|
||||
fun saveAll(uuids: Iterable<UUID>)
|
||||
|
||||
fun categorize(key: PersistentDataKey<*>, category: KeyRegistry.KeyCategory) {
|
||||
|
||||
}
|
||||
|
||||
fun saveAll(uuids: Iterable<UUID>)
|
||||
|
||||
fun updateKeys() {
|
||||
fun initialize() {
|
||||
|
||||
}
|
||||
|
||||
fun savePlayer(uuid: UUID) {
|
||||
saveKeysForPlayer(uuid, PersistentDataKey.values())
|
||||
saveKeysFor(uuid, PersistentDataKey.values())
|
||||
}
|
||||
|
||||
fun <T> write(uuid: UUID, key: NamespacedKey, value: T)
|
||||
fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>)
|
||||
fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>)
|
||||
fun <T> read(uuid: UUID, key: NamespacedKey): T?
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.data.PlayerProfile
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.KeyHelpers
|
||||
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import org.apache.logging.log4j.Level
|
||||
@@ -26,15 +31,18 @@ import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MySQLDataHandler(
|
||||
plugin: EcoSpigotPlugin
|
||||
private val plugin: EcoSpigotPlugin,
|
||||
handler: EcoProfileHandler
|
||||
) : DataHandler {
|
||||
private val columns = mutableMapOf<String, Column<*>>()
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
|
||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
||||
private val playerHandler: ImplementedMySQLHandler
|
||||
private val serverHandler: ImplementedMySQLHandler
|
||||
|
||||
init {
|
||||
val config = HikariConfig()
|
||||
@@ -49,11 +57,6 @@ class MySQLDataHandler(
|
||||
|
||||
Database.connect(HikariDataSource(config))
|
||||
|
||||
|
||||
transaction {
|
||||
SchemaUtils.create(Players)
|
||||
}
|
||||
|
||||
// Get Exposed to shut the hell up
|
||||
runCatching {
|
||||
exposedLogger::class.java.getDeclaredField("logger").apply { isAccessible = true }
|
||||
@@ -64,70 +67,205 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
playerHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_players"),
|
||||
plugin,
|
||||
plugin.dataYml.getStrings("categorized-keys.player")
|
||||
.mapNotNull { KeyHelpers.deserializeFromString(it) }
|
||||
)
|
||||
|
||||
serverHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_server"),
|
||||
plugin,
|
||||
plugin.dataYml.getStrings("categorized-keys.server")
|
||||
.mapNotNull { KeyHelpers.deserializeFromString(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun updateKeys() {
|
||||
transaction {
|
||||
for (key in Eco.getHandler().keyRegistry.registeredKeys) {
|
||||
registerColumn(key, Players)
|
||||
}
|
||||
|
||||
SchemaUtils.createMissingTablesAndColumns(Players, withLogs = false)
|
||||
}
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
serverHandler.saveAll(uuids.filter { it == serverProfileUUID })
|
||||
playerHandler.saveAll(uuids.filter { it != serverProfileUUID })
|
||||
}
|
||||
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
getPlayer(uuid)
|
||||
writeAsserted(uuid, key, value)
|
||||
applyFor(uuid) {
|
||||
it.write(uuid, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> writeAsserted(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
val column: Column<T> = getColumn(key.toString()) as Column<T>
|
||||
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
applyFor(uuid) {
|
||||
it.saveKeysForRow(uuid, keys)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
return applyFor(uuid) {
|
||||
it.read(uuid, key)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <R> applyFor(uuid: UUID, function: (ImplementedMySQLHandler) -> R): R {
|
||||
return if (uuid == serverProfileUUID) {
|
||||
function(serverHandler)
|
||||
} else {
|
||||
function(playerHandler)
|
||||
}
|
||||
}
|
||||
|
||||
override fun categorize(key: PersistentDataKey<*>, category: KeyRegistry.KeyCategory) {
|
||||
if (category == KeyRegistry.KeyCategory.SERVER) {
|
||||
serverHandler.ensureKeyRegistration(key.key)
|
||||
} else {
|
||||
playerHandler.ensureKeyRegistration(key.key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
plugin.dataYml.set(
|
||||
"categorized-keys.player",
|
||||
playerHandler.registeredKeys.values
|
||||
.map { KeyHelpers.serializeToString(it) }
|
||||
)
|
||||
plugin.dataYml.set(
|
||||
"categorized-keys.server",
|
||||
serverHandler.registeredKeys.values
|
||||
.map { KeyHelpers.serializeToString(it) }
|
||||
)
|
||||
plugin.dataYml.save()
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
playerHandler.initialize()
|
||||
serverHandler.initialize()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class ImplementedMySQLHandler(
|
||||
private val handler: EcoProfileHandler,
|
||||
private val table: UUIDTable,
|
||||
private val plugin: EcoPlugin,
|
||||
private val knownKeys: Collection<PersistentDataKey<*>>
|
||||
) {
|
||||
private val columns = Caffeine.newBuilder()
|
||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
||||
.build<String, Column<*>>()
|
||||
|
||||
private val rows = Caffeine.newBuilder()
|
||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
||||
.build<UUID, ResultRow>()
|
||||
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
|
||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
||||
val registeredKeys = ConcurrentHashMap<NamespacedKey, PersistentDataKey<*>>()
|
||||
private val currentlyProcessingRegistration = ConcurrentHashMap<NamespacedKey, Future<*>>()
|
||||
|
||||
init {
|
||||
transaction {
|
||||
SchemaUtils.create(table)
|
||||
}
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
transaction {
|
||||
for (key in knownKeys) {
|
||||
registerColumn(key, table)
|
||||
}
|
||||
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
for (key in knownKeys) {
|
||||
registeredKeys[key.key] = key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ensureKeyRegistration(key: NamespacedKey) {
|
||||
if (registeredKeys.contains(key)) {
|
||||
return
|
||||
}
|
||||
|
||||
val persistentKey = Eco.getHandler().keyRegistry.getKeyFrom(key) ?: return
|
||||
|
||||
if (table.columns.any { it.name == key.toString() }) {
|
||||
registeredKeys[key] = persistentKey
|
||||
return
|
||||
}
|
||||
|
||||
val future = currentlyProcessingRegistration[key]
|
||||
|
||||
if (future != null) {
|
||||
future.get()
|
||||
return
|
||||
}
|
||||
|
||||
currentlyProcessingRegistration[key] = executor.submit {
|
||||
transaction {
|
||||
registerColumn(persistentKey, table)
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
}
|
||||
registeredKeys[key] = persistentKey
|
||||
currentlyProcessingRegistration.remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
getOrCreateRow(uuid)
|
||||
doWrite(uuid, key, value)
|
||||
}
|
||||
|
||||
private fun <T> doWrite(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
val column: Column<T> = getColumn(key) as Column<T>
|
||||
|
||||
executor.submit {
|
||||
transaction {
|
||||
Players.update({ Players.id eq uuid }) {
|
||||
table.update({ table.id eq uuid }) {
|
||||
it[column] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
savePlayer(uuid, keys)
|
||||
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
saveRow(uuid, keys)
|
||||
}
|
||||
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
fun saveAll(uuids: Iterable<UUID>) {
|
||||
for (uuid in uuids) {
|
||||
savePlayer(uuid)
|
||||
saveRow(uuid, PersistentDataKey.values())
|
||||
}
|
||||
}
|
||||
|
||||
private fun savePlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = PlayerProfile.load(uuid)
|
||||
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = handler.loadGenericProfile(uuid)
|
||||
|
||||
executor.submit {
|
||||
transaction {
|
||||
getPlayer(uuid)
|
||||
getOrCreateRow(uuid)
|
||||
|
||||
for (key in keys) {
|
||||
writeAsserted(uuid, key.key, profile.read(key))
|
||||
doWrite(uuid, key.key, profile.read(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
val doRead = Callable<T?> {
|
||||
var value: T? = null
|
||||
transaction {
|
||||
val player = getPlayer(uuid)
|
||||
value = player[getColumn(key.toString())] as T?
|
||||
val row = getOrCreateRow(uuid)
|
||||
value = row[getColumn(key)] as T?
|
||||
}
|
||||
|
||||
return@Callable value
|
||||
}
|
||||
|
||||
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
|
||||
|
||||
return if (Eco.getHandler().ecoPlugin.configYml.getBool("mysql.async-reads")) {
|
||||
executor.submit(doRead).get()
|
||||
} else {
|
||||
@@ -135,8 +273,6 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
|
||||
object Players : UUIDTable("eco_players")
|
||||
|
||||
private fun <T> registerColumn(key: PersistentDataKey<T>, table: UUIDTable) {
|
||||
table.apply {
|
||||
if (this.columns.stream().anyMatch { it.name == key.key.toString() }) {
|
||||
@@ -158,28 +294,34 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getColumn(name: String): Column<*> {
|
||||
val cached = columns[name]
|
||||
if (cached != null) {
|
||||
return cached
|
||||
}
|
||||
private fun getColumn(key: NamespacedKey): Column<*> {
|
||||
ensureKeyRegistration(key)
|
||||
|
||||
columns[name] = Players.columns.stream().filter { it.name == name }.findFirst().get()
|
||||
return getColumn(name)
|
||||
val name = key.toString()
|
||||
|
||||
return columns.get(name) {
|
||||
table.columns.first { it.name == name }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPlayer(uuid: UUID): ResultRow {
|
||||
val player = transaction {
|
||||
Players.select { Players.id eq uuid }.limit(1).singleOrNull()
|
||||
}
|
||||
|
||||
return if (player != null) {
|
||||
player
|
||||
} else {
|
||||
transaction {
|
||||
Players.insert { it[id] = uuid }
|
||||
private fun getOrCreateRow(uuid: UUID): ResultRow {
|
||||
fun select(uuid: UUID): ResultRow? {
|
||||
return transaction {
|
||||
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
return rows.get(uuid) {
|
||||
val row = select(uuid)
|
||||
|
||||
return@get if (row != null) {
|
||||
row
|
||||
} else {
|
||||
transaction {
|
||||
table.insert { it[id] = uuid }
|
||||
}
|
||||
select(uuid)
|
||||
}
|
||||
getPlayer(uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.willfp.eco.core.config.BaseConfig
|
||||
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.internal.spigot.EcoSpigotPlugin
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
||||
import org.bukkit.NamespacedKey
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class YamlDataHandler(
|
||||
plugin: EcoSpigotPlugin
|
||||
plugin: EcoSpigotPlugin,
|
||||
private val handler: EcoProfileHandler
|
||||
) : DataHandler {
|
||||
private val dataYml = DataYml(plugin)
|
||||
private val dataYml = plugin.dataYml
|
||||
|
||||
override fun save() {
|
||||
dataYml.save()
|
||||
@@ -26,8 +25,8 @@ class YamlDataHandler(
|
||||
save()
|
||||
}
|
||||
|
||||
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = PlayerProfile.load(uuid)
|
||||
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = handler.loadGenericProfile(uuid)
|
||||
|
||||
for (key in keys) {
|
||||
write(uuid, key.key, profile.read(key))
|
||||
@@ -41,13 +40,4 @@ class YamlDataHandler(
|
||||
override fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
return dataYml.get("player.$uuid.$key") as T?
|
||||
}
|
||||
|
||||
class DataYml(
|
||||
plugin: EcoSpigotPlugin
|
||||
) : BaseConfig(
|
||||
"data",
|
||||
plugin,
|
||||
false,
|
||||
ConfigType.YAML
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,21 +5,17 @@ import com.comphenix.protocol.events.PacketContainer
|
||||
import com.comphenix.protocol.events.PacketEvent
|
||||
import com.willfp.eco.core.AbstractPacketAdapter
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.Prerequisite
|
||||
import com.willfp.eco.core.display.Display
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class PacketHeldWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS, false) {
|
||||
class PacketHeldWindowItems(plugin: EcoPlugin) :
|
||||
AbstractPacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS, false) {
|
||||
override fun onSend(
|
||||
packet: PacketContainer,
|
||||
player: Player,
|
||||
event: PacketEvent
|
||||
) {
|
||||
if (!Prerequisite.HAS_1_17.isMet) {
|
||||
return
|
||||
}
|
||||
|
||||
packet.itemModifier.modify(0) { item: ItemStack? ->
|
||||
Display.display(
|
||||
item!!, player
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.bukkit.entity.Player
|
||||
|
||||
class AntigriefCombatLogXV10 : AntigriefWrapper {
|
||||
private val instance: ICombatLogX = Bukkit.getPluginManager().getPlugin("CombatLogX") as ICombatLogX
|
||||
private var disabled = false
|
||||
|
||||
override fun canBreakBlock(
|
||||
player: Player,
|
||||
@@ -43,16 +44,23 @@ class AntigriefCombatLogXV10 : AntigriefWrapper {
|
||||
return true
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Only run checks if the NewbieHelper expansion is installed on the server.
|
||||
val expansionManager = instance.expansionManager
|
||||
val optionalExpansion = expansionManager.getExpansionByName<Expansion>("NewbieHelper")
|
||||
if (optionalExpansion.isPresent) {
|
||||
val expansion = optionalExpansion.get()
|
||||
val expansion = runCatching { optionalExpansion.get() }
|
||||
.onFailure { disabled = true }
|
||||
.getOrNull() ?: return true
|
||||
val newbieHelper: NewbieHelper = expansion as NewbieHelper
|
||||
val pvpListener: ListenerPVP = newbieHelper.pvpListener
|
||||
return pvpListener.isPVPEnabled(player) && pvpListener.isPVPEnabled(victim)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun canPickupItem(player: Player, location: Location): Boolean {
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.bukkit.entity.Player
|
||||
|
||||
class AntigriefCombatLogXV11 : AntigriefWrapper {
|
||||
private val instance: ICombatLogX = Bukkit.getPluginManager().getPlugin("CombatLogX") as ICombatLogX
|
||||
private var disabled = false
|
||||
|
||||
override fun canBreakBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
@@ -42,12 +44,17 @@ class AntigriefCombatLogXV11 : AntigriefWrapper {
|
||||
return true
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Only run checks if the NewbieHelper expansion is installed on the server.
|
||||
val expansionManager = instance.expansionManager
|
||||
val optionalExpansion = expansionManager.getExpansion("NewbieHelper")
|
||||
if (optionalExpansion.isPresent) {
|
||||
val expansion = optionalExpansion.get()
|
||||
val newbieHelperExpansion: NewbieHelperExpansion = expansion as NewbieHelperExpansion
|
||||
val newbieHelperExpansion = runCatching {
|
||||
optionalExpansion.get() as NewbieHelperExpansion
|
||||
}.onFailure { disabled = true }.getOrNull() ?: return true
|
||||
val protectionManager: ProtectionManager = newbieHelperExpansion.protectionManager
|
||||
val pvpManager: PVPManager = newbieHelperExpansion.pvpManager
|
||||
val victimProtected: Boolean = protectionManager.isProtected(victim)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.ssomar.score.api.ExecutableItemsAPI
|
||||
import com.ssomar.executableitems.api.ExecutableItemsAPI
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.Items
|
||||
@@ -9,13 +9,16 @@ import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.function.Predicate
|
||||
class CustomItemsExecutableItems: CustomItemsWrapper {
|
||||
|
||||
class CustomItemsExecutableItems : CustomItemsWrapper {
|
||||
override fun registerAllItems() {
|
||||
Items.registerItemProvider(ExecutableItemsProvider())
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "ExecutableItems"
|
||||
}
|
||||
|
||||
private class ExecutableItemsProvider : ItemProvider("executableitems") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = ExecutableItemsAPI.getExecutableItem(key) ?: return null
|
||||
@@ -30,4 +33,4 @@ class CustomItemsExecutableItems: CustomItemsWrapper {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,4 +135,4 @@ class ShapedRecipeListener : Listener {
|
||||
listeners.add(listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.core.recipe.parts.GroupedTestableItems
|
||||
import com.willfp.eco.core.recipe.parts.MaterialTestableItem
|
||||
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack
|
||||
@@ -9,6 +11,7 @@ import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class ComplexInEco : RecipeListener {
|
||||
override fun handle(event: GenericCraftEvent) {
|
||||
@@ -25,27 +28,41 @@ class ComplexInEco : RecipeListener {
|
||||
for (i in 0..8) {
|
||||
val itemStack = event.inventory.matrix[i]
|
||||
val part = craftingRecipe.parts[i]
|
||||
when (part) {
|
||||
is MaterialTestableItem -> {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
is ModifiedTestableItem -> {
|
||||
if (part.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
is TestableStack -> {
|
||||
if (part.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (part.isCustomWhenShouldNotBe(itemStack)) {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestableItem.isCustomWhenShouldNotBe(itemStack: ItemStack): Boolean {
|
||||
when (this) {
|
||||
is MaterialTestableItem -> {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
is ModifiedTestableItem -> {
|
||||
if (this.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
is TestableStack -> {
|
||||
if (this.handle is MaterialTestableItem) {
|
||||
if (Items.isCustomItem(itemStack)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
is GroupedTestableItems -> {
|
||||
// This will fail if and only if there is a complex item grouped with a simple item of the same type
|
||||
if (this.children.any { it.isCustomWhenShouldNotBe(itemStack) && it.matches(itemStack) }) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -1 +1,71 @@
|
||||
# For internal storage use only, do not modify.
|
||||
# For internal storage use only, do not modify.
|
||||
|
||||
categorized-keys:
|
||||
# Preloading known keys (as of the release of 6.25.0) for optimal performance.
|
||||
# This is only used when MySQL is enabled as the columns must be added each time a new key is registered.
|
||||
player:
|
||||
- ecoskills:crit_damage;INT;0
|
||||
- ecoskills:strong_impact;INT;0
|
||||
- ecoskills:shamanism;INT;0
|
||||
- ecoskills:reimbursement;INT;0
|
||||
- ecoskills:armory_xp;DOUBLE;0.0
|
||||
- ecoskills:bravery;INT;0
|
||||
- ecoskills:seamless_movement;INT;0
|
||||
- ecoskills:fishing;INT;0
|
||||
- ecoskills:armory;INT;0
|
||||
- ecoskills:accelerated_escape;INT;0
|
||||
- ecoskills:alchemy_xp;DOUBLE;0.0
|
||||
- boosters:2sell_multiplier;INT;0
|
||||
- ecoskills:second_chance;INT;0
|
||||
- ecoskills:health;INT;0
|
||||
- ecoskills:spelunking;INT;0
|
||||
- eco:player_name;STRING;Unknown Player
|
||||
- ecoskills:strength;INT;0
|
||||
- ecoskills:woodcutting_xp;DOUBLE;0.0
|
||||
- ecoskills:versatile_tools;INT;0
|
||||
- boosters:skill_xp;INT;0
|
||||
- ecoskills:infernal_resistance;INT;0
|
||||
- ecoskills:wisdom;INT;0
|
||||
- ecoskills:master_lumberjack;INT;0
|
||||
- ecoskills:defense;INT;0
|
||||
- ecoskills:mystic_resilience;INT;0
|
||||
- ecoskills:gainsound;BOOLEAN;true
|
||||
- ecoskills:golden_yield;INT;0
|
||||
- ecoskills:dazzle;INT;0
|
||||
- ecoskills:dodging;INT;0
|
||||
- ecoskills:efficient_brewing;INT;0
|
||||
- ecoskills:bountiful_harvest;INT;0
|
||||
- ecoskills:actionbar_enabled;BOOLEAN;true
|
||||
- ecoskills:enchanting_xp;DOUBLE;0.0
|
||||
- ecoskills:overcompensation;INT;0
|
||||
- ecoskills:alchemy;INT;0
|
||||
- ecoskills:woodcutting;INT;0
|
||||
- ecoskills:mining;INT;0
|
||||
- ecoskills:magnetic_rod;INT;0
|
||||
- ecoskills:fishing_xp;DOUBLE;0.0
|
||||
- ecoskills:farming_xp;DOUBLE;0.0
|
||||
- ecoskills:speed;INT;0
|
||||
- ecoskills:potionmaster;INT;0
|
||||
- ecoskills:combat_xp;DOUBLE;0.0
|
||||
- ecoskills:eye_of_the_depths;INT;0
|
||||
- ecoskills:ferocity;INT;0
|
||||
- ecoskills:combat;INT;0
|
||||
- ecoskills:mining_xp;DOUBLE;0.0
|
||||
- ecoskills:satiation;INT;0
|
||||
- ecoskills:craftsmanship;INT;0
|
||||
- ecoskills:crit_chance;INT;0
|
||||
- ecoskills:dynamic_mining;INT;0
|
||||
- ecoskills:exploration;INT;0
|
||||
- boosters:1_5sell_multiplier;INT;0
|
||||
- ecoskills:enchanting;INT;0
|
||||
- ecoskills:endangering;INT;0
|
||||
- ecoskills:serrated_strikes;INT;0
|
||||
- ecoskills:exploration_xp;DOUBLE;0.0
|
||||
- ecoskills:farming;INT;0
|
||||
server:
|
||||
- 'talismans:known_points;STRING;'
|
||||
- 'ecoarmor:known_points;STRING;'
|
||||
- 'ecoenchants:known_points;STRING;'
|
||||
- 'ecoitems:known_points;STRING;'
|
||||
- 'boosters:known_points;STRING;'
|
||||
- 'reforges:known_points;STRING;'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: eco
|
||||
version: ${projectVersion}
|
||||
main: com.willfp.eco.internal.spigot.EcoHandler
|
||||
api-version: 1.16
|
||||
api-version: 1.17
|
||||
authors: [ Auxilor ]
|
||||
website: willfp.com
|
||||
load: STARTUP
|
||||
@@ -51,11 +51,11 @@ libraries:
|
||||
- 'net.kyori:adventure-api:4.9.3'
|
||||
- 'net.kyori:adventure-text-serializer-gson:4.9.3'
|
||||
- 'net.kyori:adventure-text-serializer-legacy:4.9.3'
|
||||
- 'org.jetbrains.exposed:exposed-core:0.36.2'
|
||||
- 'org.jetbrains.exposed:exposed-dao:0.36.2'
|
||||
- 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
|
||||
- 'org.jetbrains.exposed:exposed-core:0.37.3'
|
||||
- 'org.jetbrains.exposed:exposed-dao:0.37.3'
|
||||
- 'org.jetbrains.exposed:exposed-jdbc:0.37.3'
|
||||
- 'mysql:mysql-connector-java:8.0.25'
|
||||
- 'com.google.guava:guava:31.0.1-jre'
|
||||
- 'com.zaxxer:HikariCP:5.0.0'
|
||||
- 'org.objenesis:objenesis:3.2'
|
||||
- 'com.github.ben-manes.caffeine:caffeine:3.0.5'
|
||||
- 'com.github.ben-manes.caffeine:caffeine:3.0.5'
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.willfp.eco.internal.spigot.proxy
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.entity.Entity
|
||||
|
||||
interface DummyEntityProxy {
|
||||
interface DummyEntityFactoryProxy {
|
||||
fun createDummyEntity(
|
||||
location: Location
|
||||
): Entity
|
||||
@@ -1,3 +1,3 @@
|
||||
version = 6.24.1
|
||||
version = 6.26.0
|
||||
plugin-name = eco
|
||||
kotlin.code.style = official
|
||||
BIN
lib/ExecutableItems-4.1.3.3.jar
Normal file
BIN
lib/ExecutableItems-4.1.3.3.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
lib/SCore-1.6.4.3.jar
Normal file
BIN
lib/SCore-1.6.4.3.jar
Normal file
Binary file not shown.
@@ -11,7 +11,6 @@ rootProject.name = "eco"
|
||||
include(":eco-api")
|
||||
include(":eco-core")
|
||||
include(":eco-core:core-nms")
|
||||
include(":eco-core:core-nms:v1_16_R3")
|
||||
include(":eco-core:core-nms:v1_17_R1")
|
||||
include(":eco-core:core-nms:v1_18_R1")
|
||||
include(":eco-core:core-proxy")
|
||||
|
||||
Reference in New Issue
Block a user