Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Auxilor
2022-02-28 18:52:18 +00:00
51 changed files with 675 additions and 544 deletions

View File

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

View File

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

View File

@@ -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+"

View File

@@ -5,8 +5,8 @@ import com.willfp.eco.core.entities.args.EntityArgParser;
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.core.lookup.LookupHelper;
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 +37,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 +92,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 LookupHelper.parseWith(key, ENTITIES_LOOKUP_HANDLER);
}
@NotNull
private static TestableEntity doParse(@NotNull final String[] args) {
if (args.length == 0) {
return new EmptyTestableEntity();
}
@@ -131,7 +127,6 @@ public final class Entities {
entity = part;
}
String[] modifierArgs = Arrays.copyOfRange(args, 1, args.length);
List<EntityArgParseResult> parseResults = new ArrayList<>();
@@ -172,7 +167,6 @@ public final class Entities {
return entity;
}
/**
* Get a Testable Entity from an ItemStack.
* <p>

View File

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

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.entities;
import com.willfp.eco.core.lookup.test.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);
/**

View File

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

View File

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

View File

@@ -4,13 +4,13 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.willfp.eco.core.items.args.LookupArgParser;
import com.willfp.eco.core.items.provider.ItemProvider;
import com.willfp.eco.core.lookup.LookupHelper;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.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 +68,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 +136,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 LookupHelper.parseWith(key, ITEMS_LOOKUP_HANDLER);
}
@NotNull
private static TestableItem doParse(@NotNull final String[] args) {
if (args.length == 0) {
return new EmptyTestableItem();
}

View File

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

View File

@@ -1,18 +1,20 @@
package com.willfp.eco.core.items;
import com.willfp.eco.core.lookup.test.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);
/**

View File

@@ -0,0 +1,49 @@
package com.willfp.eco.core.lookup;
import com.willfp.eco.core.lookup.test.Testable;
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 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)}.
*
* @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);
}

View File

@@ -0,0 +1,55 @@
package com.willfp.eco.core.lookup;
import com.willfp.eco.core.lookup.test.Testable;
import com.willfp.eco.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* Helper for lookups.
*/
public final class LookupHelper {
/**
* All segment parsers.
*/
private static final List<SegmentParser> SEGMENT_PARSERS = new ArrayList<>();
/**
* Parse key to object.
*
* @param key The key.
* @param handler The handler.
* @param <T> The object type.
* @return The object.
*/
@NotNull
public static <T extends Testable<?>> T parseWith(@NotNull final String key,
@NotNull final LookupHandler<T> handler) {
for (SegmentParser parser : SEGMENT_PARSERS) {
T generated = parser.parse(key, handler);
if (generated != null) {
return generated;
}
}
String[] args = StringUtils.parseTokens(key);
return handler.parse(args);
}
/**
* Register segment parser.
*
* @param parser The parser.
*/
public static void registerSegmentParser(@NotNull final SegmentParser parser) {
SEGMENT_PARSERS.add(parser);
}
private LookupHelper() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}

View File

@@ -0,0 +1,56 @@
package com.willfp.eco.core.lookup;
import com.willfp.eco.core.lookup.test.Testable;
import com.willfp.eco.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Parse a key into segments.
*/
public abstract class SegmentParser {
/**
* 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;
}
/**
* 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);
/**
* 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);
}
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.core.lookup.test;
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);
}

View File

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

View File

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

View File

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

View File

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

View 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", "||")
);
}
}

View File

@@ -0,0 +1,9 @@
package com.willfp.eco.internal.entities
import org.bukkit.entity.Entity
class DummyEntityDelegate(private val handle: Entity) : Entity by handle {
override fun toString(): String {
return "DummyEntity{id=${this.entityId}}"
}
}

View File

@@ -0,0 +1,25 @@
package com.willfp.eco.internal.lookup
import com.willfp.eco.core.lookup.LookupHandler
import com.willfp.eco.core.lookup.LookupHelper
import com.willfp.eco.core.lookup.SegmentParser
import com.willfp.eco.core.lookup.test.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 = LookupHelper.parseWith(option, handler)
if (handler.validate(lookup)) {
possibleOptions.add(lookup)
}
}
if (possibleOptions.isEmpty()) {
return handler.failsafe
}
return handler.join(possibleOptions)
}
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.internal.lookup
import com.willfp.eco.core.lookup.LookupHandler
import com.willfp.eco.core.lookup.LookupHelper
import com.willfp.eco.core.lookup.SegmentParser
import com.willfp.eco.core.lookup.test.Testable
class SegmentParserUseIfPresent : SegmentParser("?") {
override fun <T : Testable<*>> handleSegments(segments: Array<out String>, handler: LookupHandler<T>): T {
for (option in segments) {
val lookup = LookupHelper.parseWith(option, handler)
if (handler.validate(lookup)) {
return lookup
}
}
return handler.failsafe
}
}

View File

@@ -77,7 +77,6 @@ class EcoProxyFactory(
companion object {
val SUPPORTED_VERSIONS = listOf(
"v1_16_R3",
"v1_17_R1",
"v1_18_R1"
)

View File

@@ -1,6 +0,0 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT'
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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]
}
}

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.internal.spigot.proxy.v1_17_R1
import com.willfp.eco.internal.entities.DummyEntityDelegate
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld
@@ -10,6 +11,6 @@ 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()
return DummyEntityDelegate(world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity())
}
}
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.internal.entities.DummyEntityDelegate
import com.willfp.eco.internal.spigot.proxy.DummyEntityProxy
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld
@@ -10,6 +11,6 @@ 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()
return DummyEntityDelegate(world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity())
}
}
}

View File

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

View File

@@ -45,6 +45,8 @@ 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
@@ -112,6 +114,7 @@ import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInEco
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
import com.willfp.eco.core.lookup.LookupHelper
import com.willfp.eco.util.BlockUtils
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.ServerUtils
@@ -155,6 +158,9 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
Entities.registerArgParser(EntityArgParserSilent())
Entities.registerArgParser(EntityArgParserEquipment())
LookupHelper.registerSegmentParser(SegmentParserGroup())
LookupHelper.registerSegmentParser(SegmentParserUseIfPresent())
ShapedRecipeListener.registerListener(ComplexInComplex())
ShapedRecipeListener.registerListener(ComplexInEco())
ShapedRecipeListener.registerListener(ComplexInVanilla())

View File

@@ -152,11 +152,11 @@ private class ImplementedMySQLHandler(
private val knownKeys: Collection<PersistentDataKey<*>>
) {
private val columns = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.SECONDS)
.expireAfterWrite(3, TimeUnit.SECONDS)
.build<String, Column<*>>()
private val rows = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.SECONDS)
.expireAfterWrite(3, TimeUnit.SECONDS)
.build<UUID, ResultRow>()
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,9 +51,9 @@ 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'

View File

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

Binary file not shown.

Binary file not shown.

BIN
lib/SCore-1.6.4.3.jar Normal file

Binary file not shown.

View File

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