Compare commits

..

28 Commits
1.0.1 ... 2.0.0

Author SHA1 Message Date
Auxilor
b8a5fe0031 Fixed EcoShapedRecipe 2021-01-17 10:48:55 +00:00
Auxilor
5603890663 Reworked eco to be a spigot plugin 2021-01-17 10:48:34 +00:00
Auxilor
1a86cc4dbd Fixed shading errors. 2021-01-14 20:06:27 +00:00
Auxilor
734add6dbc Cleaned 2021-01-14 19:25:21 +00:00
Auxilor
5641c0def3 Updated to 1.3.1 2021-01-14 19:24:37 +00:00
Auxilor
b74ab5349a Fixed shading issues 2021-01-14 19:24:13 +00:00
Auxilor
b0971e5124 Renamed LookupUtils to RecipePartUtils 2021-01-14 14:06:50 +00:00
Auxilor
02d8c8c6b6 Updated to 1.3.0 2021-01-14 13:06:32 +00:00
Auxilor
d9bd5257e3 Added custom item registry 2021-01-14 13:06:03 +00:00
Auxilor
c1a214f34e Fixed crafting 2021-01-14 11:31:05 +00:00
Auxilor
64d1fbb9b1 Updated to 1.2.0 2021-01-14 10:57:23 +00:00
Auxilor
a5433fbb3f Added recipe system 2021-01-14 10:55:44 +00:00
Auxilor
2a2aed52e0 Optimised VectorUtils getCircle() 2021-01-12 14:52:36 +00:00
Auxilor
b16266e22a Cleaned up numerals 2021-01-10 20:05:50 +00:00
Auxilor
2c886dc33b Updated to 1.1.2 2021-01-10 18:51:37 +00:00
Auxilor
db9c60cf35 Added fromNumeral method 2021-01-10 18:51:21 +00:00
Auxilor
a34b36daec Updated to 1.1.1 2021-01-08 22:18:17 +00:00
Auxilor
41a35e99fd Call update is now invoked twice 2021-01-08 22:18:00 +00:00
Auxilor
8e12dad247 Added players to packet adapters 2021-01-08 08:02:15 +00:00
Auxilor
72afa1e5cc Updated to 1.1.0 2021-01-08 08:01:21 +00:00
Auxilor
9904553325 Updated to 1.0.6 2021-01-05 14:17:41 +00:00
Auxilor
ad069ab32f Cleaned up loader 2021-01-05 14:17:26 +00:00
Auxilor
b83a3dd548 Fixed TelekinesisUtils and updated to 1.0.5 2021-01-05 09:09:05 +00:00
Auxilor
7f41eab5e4 Fixed compileOnly issues with jitpack 2021-01-04 12:46:00 +00:00
Auxilor
0d1c2364da Fixed telekinesistests registration and updated to 1.0.4 2021-01-04 12:45:05 +00:00
Auxilor
5bca33a9f5 Added protected getter for BaseConfig and updated to 1.0.3 2021-01-02 17:55:22 +00:00
Auxilor
1196fe8004 Updated to 1.0.2 2021-01-01 16:54:05 +00:00
Auxilor
98ae416fa7 Reduced loaded integration verbosity 2021-01-01 16:53:32 +00:00
19 changed files with 831 additions and 26 deletions

View File

@@ -20,7 +20,7 @@ dependencies {
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT' compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd' compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly 'org.jetbrains:annotations:19.0.0' compileOnly 'org.jetbrains:annotations:19.0.0'
compileOnly fileTree(dir: '/lib', include: ['*.jar']) compileOnly fileTree(dir: 'lib', include: ['*.jar'])
// Lombok // Lombok
compileOnly 'org.projectlombok:lombok:1.18.16' compileOnly 'org.projectlombok:lombok:1.18.16'
@@ -98,5 +98,5 @@ build.dependsOn publishToMavenLocal
group = 'com.willfp' group = 'com.willfp'
archivesBaseName = project.name archivesBaseName = project.name
version = '1.0.1' version = '2.0.0'
java.sourceCompatibility = JavaVersion.VERSION_1_8 java.sourceCompatibility = JavaVersion.VERSION_1_8

View File

@@ -0,0 +1,7 @@
package com.willfp.eco.spigot;
import org.bukkit.plugin.java.JavaPlugin;
public class EcoSpigotMain extends JavaPlugin {
}

View File

@@ -1,8 +1,10 @@
package com.willfp.eco.util; package com.willfp.eco.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@@ -85,6 +87,24 @@ public class NumberUtils {
} }
} }
/**
* Get number from roman numeral.
*
* @param numeral The numeral to convert.
* @return The number, converted from a roman numeral.
*/
public static int fromNumeral(@NotNull final String numeral) {
if (numeral.isEmpty()) {
return 0;
}
for (Map.Entry<Integer, String> entry : NUMERALS.entrySet()) {
if (numeral.startsWith(entry.getValue())) {
return entry.getKey() + fromNumeral(numeral.substring(entry.getValue().length()));
}
}
return 0;
}
/** /**
* Generate random integer in range. * Generate random integer in range.
* *

View File

@@ -6,9 +6,16 @@ import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@UtilityClass @UtilityClass
public class VectorUtils { public class VectorUtils {
/**
* Cached circles to prevent many sqrt calls.
*/
private static final Map<Integer, Vector[]> CIRCLE_CACHE = new HashMap<>();
/** /**
* If vector has all components as finite. * If vector has all components as finite.
* *
@@ -66,6 +73,11 @@ public class VectorUtils {
* @return An array of {@link Vector}s. * @return An array of {@link Vector}s.
*/ */
public Vector[] getCircle(final int radius) { public Vector[] getCircle(final int radius) {
Vector[] cached = CIRCLE_CACHE.get(radius);
if (cached != null) {
return cached;
}
ArrayList<Vector> circleVecs = new ArrayList<>(); ArrayList<Vector> circleVecs = new ArrayList<>();
double xoffset = -radius; double xoffset = -radius;
@@ -85,7 +97,9 @@ public class VectorUtils {
zoffset++; zoffset++;
} }
return circleVecs.toArray(new Vector[0]); Vector[] result = circleVecs.toArray(new Vector[0]);
CIRCLE_CACHE.put(radius, result);
return result;
} }
/** /**

View File

@@ -28,6 +28,7 @@ public abstract class BaseConfig extends PluginDependent implements ValueGetter
/** /**
* The physical config file, as stored on disk. * The physical config file, as stored on disk.
*/ */
@Getter(AccessLevel.PROTECTED)
private final File configFile; private final File configFile;
/** /**

View File

@@ -7,14 +7,31 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicePriority;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function; import java.util.function.Function;
@UtilityClass @UtilityClass
public final class TelekinesisUtils { public final class TelekinesisUtils {
/**
* Instance of registered telekinesis utils.
*/
private final Object instance;
/**
* The class of the utils.
*/
private final Class<?> clazz;
/** /**
* The test service registered to bukkit. * The test service registered to bukkit.
*/ */
private final TelekinesisTests tests; private final Method testMethod;
/**
* The register service registered to bukkit.
*/
private final Method registerMethod;
/** /**
* Test the player for telekinesis. * Test the player for telekinesis.
@@ -25,7 +42,13 @@ public final class TelekinesisUtils {
* @return If the player is telekinetic. * @return If the player is telekinetic.
*/ */
public boolean testPlayer(@NotNull final Player player) { public boolean testPlayer(@NotNull final Player player) {
return tests.testPlayer(player); try {
return (boolean) testMethod.invoke(instance, player);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return false;
} }
/** /**
@@ -34,14 +57,35 @@ public final class TelekinesisUtils {
* @param test The test to register, where the boolean output is if the player is telekinetic. * @param test The test to register, where the boolean output is if the player is telekinetic.
*/ */
public void registerTest(@NotNull final Function<Player, Boolean> test) { public void registerTest(@NotNull final Function<Player, Boolean> test) {
tests.registerTest(test); try {
registerMethod.invoke(instance, test);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} }
static { static {
if (!Bukkit.getServicesManager().isProvidedFor(TelekinesisTests.class)) { Method testMethod1;
Method registerMethod1;
if (Bukkit.getServicesManager().getKnownServices().stream().noneMatch(clazz -> clazz.getName().contains("TelekinesisTests"))) {
Bukkit.getServicesManager().register(TelekinesisTests.class, new EcoTelekinesisTests(), AbstractEcoPlugin.getInstance(), ServicePriority.Normal); Bukkit.getServicesManager().register(TelekinesisTests.class, new EcoTelekinesisTests(), AbstractEcoPlugin.getInstance(), ServicePriority.Normal);
} }
tests = Bukkit.getServicesManager().load(TelekinesisTests.class); instance = Bukkit.getServicesManager().load(Bukkit.getServicesManager().getKnownServices().stream().filter(clazz -> clazz.getName().contains("TelekinesisTests")).findFirst().get());
clazz = instance.getClass();
try {
testMethod1 = clazz.getDeclaredMethod("testPlayer", Player.class);
registerMethod1 = clazz.getDeclaredMethod("registerTest", Function.class);
testMethod1.setAccessible(true);
registerMethod1.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
testMethod1 = null;
registerMethod1 = null;
}
testMethod = testMethod1;
registerMethod = registerMethod1;
} }
} }

View File

@@ -39,6 +39,8 @@ import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.util.integrations.placeholder.plugins.PlaceholderIntegrationPAPI; import com.willfp.eco.util.integrations.placeholder.plugins.PlaceholderIntegrationPAPI;
import com.willfp.eco.util.optional.Prerequisite; import com.willfp.eco.util.optional.Prerequisite;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter; import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import com.willfp.eco.util.recipe.RecipeListener;
import com.willfp.eco.util.recipe.RecipeManager;
import com.willfp.eco.util.updater.UpdateChecker; import com.willfp.eco.util.updater.UpdateChecker;
import lombok.Getter; import lombok.Getter;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
@@ -51,6 +53,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -86,6 +89,18 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
@Getter @Getter
private final String proxyPackage; private final String proxyPackage;
/**
* The color of the plugin, used in messages.
*/
@Getter
private final String color;
/**
* Loaded integrations.
*/
@Getter
private final Set<String> loadedIntegrations = new HashSet<>();
/** /**
* Set of external plugin integrations. * Set of external plugin integrations.
*/ */
@@ -132,6 +147,12 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
@Getter @Getter
private final RunnableFactory runnableFactory; private final RunnableFactory runnableFactory;
/**
* Recipe handler for crafting recipes.
*/
@Getter
private final RecipeManager recipeManager;
/** /**
* The loader for all plugin extensions. * The loader for all plugin extensions.
* *
@@ -159,15 +180,18 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
* @param resourceId The spigot resource ID for the plugin. * @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin. * @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored. * @param proxyPackage The package where proxy implementations are stored.
* @param color The color of the plugin (used in messages, such as &a, &b)
*/ */
protected AbstractEcoPlugin(@NotNull final String pluginName, protected AbstractEcoPlugin(@NotNull final String pluginName,
final int resourceId, final int resourceId,
final int bStatsId, final int bStatsId,
@NotNull final String proxyPackage) { @NotNull final String proxyPackage,
@NotNull final String color) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.resourceId = resourceId; this.resourceId = resourceId;
this.bStatsId = bStatsId; this.bStatsId = bStatsId;
this.proxyPackage = proxyPackage; this.proxyPackage = proxyPackage;
this.color = color;
this.log = new EcoLogger(this); this.log = new EcoLogger(this);
this.scheduler = new EcoScheduler(this); this.scheduler = new EcoScheduler(this);
@@ -177,6 +201,7 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
this.runnableFactory = new RunnableFactory(this); this.runnableFactory = new RunnableFactory(this);
this.extensionLoader = new EcoExtensionLoader(this); this.extensionLoader = new EcoExtensionLoader(this);
this.configHandler = new ConfigHandler(this); this.configHandler = new ConfigHandler(this);
this.recipeManager = new RecipeManager(this);
} }
/** /**
@@ -186,18 +211,15 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
public final void onEnable() { public final void onEnable() {
super.onLoad(); super.onLoad();
this.getLog().info("==========================================");
this.getLog().info(""); this.getLog().info("");
this.getLog().info("Loading &a" + this.pluginName); this.getLog().info("Loading " + this.color + this.pluginName);
this.getLog().info("Made by &aAuxilor&f - willfp.com");
this.getLog().info("");
this.getLog().info("==========================================");
this.getEventManager().registerListener(new ArrowDataListener(this)); this.getEventManager().registerListener(new ArrowDataListener(this));
this.getEventManager().registerListener(new NaturalExpGainListeners()); this.getEventManager().registerListener(new NaturalExpGainListeners());
this.getEventManager().registerListener(new ArmorListener()); this.getEventManager().registerListener(new ArmorListener());
this.getEventManager().registerListener(new DispenserArmorListener()); this.getEventManager().registerListener(new DispenserArmorListener());
this.getEventManager().registerListener(new EntityDeathByEntityListeners(this)); this.getEventManager().registerListener(new EntityDeathByEntityListeners(this));
this.getEventManager().registerListener(new RecipeListener(this));
new FastCollatedDropQueue.CollatedRunnable(this); new FastCollatedDropQueue.CollatedRunnable(this);
@@ -219,17 +241,13 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet()); Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
this.getDefaultIntegrations().forEach((integrationLoader -> { this.getDefaultIntegrations().forEach((integrationLoader -> {
StringBuilder infoBuilder = new StringBuilder();
infoBuilder.append(integrationLoader.getPluginName()).append(": ");
if (enabledPlugins.contains(integrationLoader.getPluginName())) { if (enabledPlugins.contains(integrationLoader.getPluginName())) {
this.loadedIntegrations.add(integrationLoader.getPluginName());
integrationLoader.load(); integrationLoader.load();
infoBuilder.append("&aENABLED");
} else {
infoBuilder.append("&9DISABLED");
} }
this.getLog().info(infoBuilder.toString());
})); }));
this.getLog().info("");
this.getLog().info("Loaded integrations: " + String.join(", ", this.getLoadedIntegrations()));
Prerequisite.update(); Prerequisite.update();
@@ -256,6 +274,8 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz)); this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz));
this.enable(); this.enable();
this.getLog().info("");
} }
/** /**
@@ -312,7 +332,7 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
this.reload(); this.reload();
this.getLog().info("Loaded &a" + this.pluginName); this.getLog().info("Loaded " + this.color + this.pluginName);
} }
/** /**
@@ -320,6 +340,7 @@ public abstract class AbstractEcoPlugin extends JavaPlugin {
*/ */
public final void reload() { public final void reload() {
this.getConfigHandler().callUpdate(); this.getConfigHandler().callUpdate();
this.getConfigHandler().callUpdate(); // Call twice to fix issues
this.getScheduler().cancelAll(); this.getScheduler().cancelAll();
new FastCollatedDropQueue.CollatedRunnable(this); new FastCollatedDropQueue.CollatedRunnable(this);

View File

@@ -8,6 +8,7 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin; import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.Getter; import lombok.Getter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collections; import java.util.Collections;
@@ -60,8 +61,10 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
* The code that should be executed once the packet has been received. * The code that should be executed once the packet has been received.
* *
* @param packet The packet. * @param packet The packet.
* @param player The player.
*/ */
public void onReceive(@NotNull final PacketContainer packet) { public void onReceive(@NotNull final PacketContainer packet,
@NotNull final Player player) {
// Empty rather than abstract as implementations don't need both // Empty rather than abstract as implementations don't need both
} }
@@ -69,8 +72,10 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
* THe code that should be executed once the packet has been sent. * THe code that should be executed once the packet has been sent.
* *
* @param packet The packet. * @param packet The packet.
* @param player The player.
*/ */
public void onSend(@NotNull final PacketContainer packet) { public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
// Empty rather than abstract as implementations don't need both // Empty rather than abstract as implementations don't need both
} }
@@ -89,7 +94,7 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
return; return;
} }
onReceive(event.getPacket()); onReceive(event.getPacket(), event.getPlayer());
} }
/** /**
@@ -107,7 +112,7 @@ public abstract class AbstractPacketAdapter extends PacketAdapter {
return; return;
} }
onSend(event.getPacket()); onSend(event.getPacket(), event.getPlayer());
} }
/** /**

View File

@@ -0,0 +1,257 @@
package com.willfp.eco.util.recipe;
import com.willfp.eco.util.interfaces.Registerable;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.recipe.parts.EmptyRecipePart;
import com.willfp.eco.util.recipe.parts.RecipePart;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public final class EcoShapedRecipe extends PluginDependent implements Registerable {
/**
* Recipe parts.
*/
private final RecipePart[] parts;
/**
* The key of the recipe.
*/
@Getter
private final String key;
/**
* The recipe's output.
*/
@Getter
private final ItemStack output;
private EcoShapedRecipe(@NotNull final AbstractEcoPlugin plugin,
@NotNull final String key,
@NotNull final RecipePart[] parts,
@NotNull final ItemStack output) {
super(plugin);
this.parts = parts;
this.key = key;
this.output = output;
}
/**
* Get item material at a specific index.
*
* @param index The index to check.
* @return The material.
*/
public Material getMaterialAtIndex(final int index) {
return parts[index].getDisplayed().getType();
}
/**
* Get "real" item at specific index.
*
* @param index The index to check.
* @return The item.
*/
public ItemStack getDisplayedAtIndex(final int index) {
return parts[index].getDisplayed();
}
/**
* Test matrix against recipe.
*
* @param matrix The matrix to check.
* @return If the recipe matches.
*/
public boolean test(@NotNull final ItemStack[] matrix) {
boolean matches = true;
for (int i = 0; i < 9; i++) {
if (!parts[i].matches(matrix[i])) {
matches = false;
}
}
return matches;
}
/**
* Register the recipe.
*/
@Override
public void register() {
this.getPlugin().getRecipeManager().register(this);
}
@Override
public String toString() {
return "EcoShapedRecipe{"
+ "parts=" + Arrays.toString(parts)
+ ", key='" + key + '\''
+ ", output=" + output
+ '}';
}
/**
* Create a new recipe builder.
*
* @param plugin The plugin that owns the recipe.
* @param key The recipe key.
* @return A new builder.
*/
public static Builder builder(@NotNull final AbstractEcoPlugin plugin,
@NotNull final String key) {
return new Builder(plugin, key);
}
public static final class Builder {
/**
* The recipe parts.
*/
private final RecipePart[] recipeParts = new RecipePart[9];
/**
* The output of the recipe.
*/
private ItemStack output = null;
/**
* The key of the recipe.
*/
private final String key;
/**
* The plugin that created the recipe.
*/
private final AbstractEcoPlugin plugin;
/**
* Create a new recipe builder.
*
* @param plugin The plugin that owns the recipe.
* @param key The recipe key.
*/
private Builder(@NotNull final AbstractEcoPlugin plugin,
@NotNull final String key) {
this.key = key;
this.plugin = plugin;
}
/**
* Set a recipe part.
*
* @param position The position of the recipe within a crafting matrix.
* @param part The part of the recipe.
* @return The builder.
*/
public Builder setRecipePart(@NotNull final RecipePosition position,
@NotNull final RecipePart part) {
this.recipeParts[position.getIndex()] = part;
return this;
}
/**
* Set a recipe part.
*
* @param position The position of the recipe within a crafting matrix.
* @param part The part of the recipe.
* @return The builder.
*/
public Builder setRecipePart(final int position,
@NotNull final RecipePart part) {
this.recipeParts[position] = part;
return this;
}
/**
* Set the output of the recipe.
*
* @param output The output.
* @return The builder.
*/
public Builder setOutput(@NotNull final ItemStack output) {
this.output = output;
return this;
}
/**
* Build the recipe.
*
* @return The built recipe.
*/
public EcoShapedRecipe build() {
for (int i = 0; i < 9; i++) {
if (recipeParts[i] == null) {
recipeParts[i] = new EmptyRecipePart();
}
}
return new EcoShapedRecipe(plugin, key.toLowerCase(), recipeParts, output);
}
}
public enum RecipePosition {
/**
* Top left of matrix.
*/
TOP_LEFT(0),
/**
* Top middle of matrix.
*/
TOP_MIDDLE(1),
/**
* Top right of matrix.
*/
TOP_RIGHT(2),
/**
* Middle left of matrix.
*/
MIDDLE_LEFT(3),
/**
* Middle of matrix.
*/
MIDDLE(4),
/**
* Middle right of matrix.
*/
MIDDLE_RIGHT(5),
/**
* Bottom left of matrix.
*/
BOTTOM_LEFT(6),
/**
* Bottom middle of matrix.
*/
BOTTOM_MIDDLE(7),
/**
* Bottom right of matrix.
*/
BOTTOM_RIGHT(8);
/**
* The index within a crafting table matrix.
*/
@Getter
private final int index;
/**
* Recipe position with crafting table index.
*
* @param index The index.
*/
RecipePosition(final int index) {
this.index = index;
}
}
}

View File

@@ -0,0 +1,89 @@
package com.willfp.eco.util.recipe;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.jetbrains.annotations.NotNull;
public class RecipeListener extends PluginDependent implements Listener {
/**
* Pass an {@link AbstractEcoPlugin} in order to interface with it.
*
* @param plugin The plugin to manage.
*/
public RecipeListener(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Called on item craft.
*
* @param event The event to listen for.
*/
@EventHandler
public void prepareCraftListener(@NotNull final PrepareItemCraftEvent event) {
if (!(event.getRecipe() instanceof ShapedRecipe)) {
return;
}
ShapedRecipe recipe = (ShapedRecipe) event.getRecipe();
if (!recipe.getKey().getNamespace().equals(this.getPlugin().getPluginName().toLowerCase())) {
return;
}
ItemStack[] matrix = event.getInventory().getMatrix();
EcoShapedRecipe matched = this.getPlugin().getRecipeManager().getMatch(matrix);
if (matched == null) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
if (matched.test(matrix)) {
event.getInventory().setResult(matched.getOutput());
} else {
event.getInventory().setResult(new ItemStack(Material.AIR));
}
}
/**
* Called on item craft.
*
* @param event The event to listen for.
*/
@EventHandler
public void craftListener(@NotNull final CraftItemEvent event) {
if (!(event.getRecipe() instanceof ShapedRecipe)) {
return;
}
ShapedRecipe recipe = (ShapedRecipe) event.getRecipe();
if (!recipe.getKey().getNamespace().equals(this.getPlugin().getPluginName().toLowerCase())) {
return;
}
ItemStack[] matrix = event.getInventory().getMatrix();
EcoShapedRecipe matched = this.getPlugin().getRecipeManager().getMatch(matrix);
if (matched == null) {
event.getInventory().setResult(new ItemStack(Material.AIR));
event.setCancelled(true);
return;
}
if (matched.test(matrix)) {
event.getInventory().setResult(matched.getOutput());
} else {
event.getInventory().setResult(new ItemStack(Material.AIR));
event.setCancelled(true);
}
}
}

View File

@@ -0,0 +1,80 @@
package com.willfp.eco.util.recipe;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.ShapedRecipe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public class RecipeManager extends PluginDependent {
/**
* Registry of all recipes.
*/
private final BiMap<String, EcoShapedRecipe> registry = HashBiMap.create();
/**
* Pass an {@link AbstractEcoPlugin} in order to interface with it.
*
* @param plugin The plugin to manage.
*/
public RecipeManager(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
void register(@NotNull final EcoShapedRecipe recipe) {
String key = recipe.getKey();
registry.forcePut(key, recipe);
NamespacedKey baseKey = this.getPlugin().getNamespacedKeyFactory().create(key);
Bukkit.getServer().removeRecipe(baseKey);
NamespacedKey displayedKey = this.getPlugin().getNamespacedKeyFactory().create(key + "_displayed");
Bukkit.getServer().removeRecipe(displayedKey);
ShapedRecipe shapedRecipe = new ShapedRecipe(baseKey, recipe.getOutput());
shapedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) {
char character = String.valueOf(i).toCharArray()[0];
shapedRecipe.setIngredient(character, recipe.getMaterialAtIndex(i));
}
ShapedRecipe displayedRecipe = new ShapedRecipe(displayedKey, recipe.getOutput());
displayedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) {
char character = String.valueOf(i).toCharArray()[0];
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(recipe.getDisplayedAtIndex(i)));
}
Bukkit.getServer().addRecipe(shapedRecipe);
Bukkit.getServer().addRecipe(displayedRecipe);
}
/**
* Get recipe matching matrix.
*
* @param matrix The matrix to test.
* @return The match, or null if not found.
*/
@Nullable
public EcoShapedRecipe getMatch(@NotNull final ItemStack[] matrix) {
return registry.values().stream().filter(recipe -> recipe.test(matrix)).findFirst().orElse(null);
}
/**
* Get shaped recipe by key.
*
* @param key The key.
* @return The shaped recipe, or null if not found.
*/
@Nullable
public EcoShapedRecipe getShapedRecipe(@NotNull final String key) {
return registry.get(key);
}
}

View File

@@ -0,0 +1,39 @@
package com.willfp.eco.util.recipe.lookup;
import com.willfp.eco.util.recipe.parts.EmptyRecipePart;
import com.willfp.eco.util.recipe.parts.RecipePart;
import com.willfp.eco.util.recipe.parts.SimpleRecipePart;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class EcoItemLookup implements ItemLookup {
/**
* Set of tests that return if the player is telekinetic.
*/
private final Map<String, Function<String, RecipePart>> tests = new HashMap<>();
@Override
public void registerLookup(@NotNull final String key,
@NotNull final Function<String, RecipePart> lookup) {
tests.put(key, lookup);
}
@Override
public RecipePart lookup(@NotNull final String key) {
Function<String, RecipePart> lookup = tests.get(key);
if (lookup == null) {
Material material = Material.getMaterial(key.toUpperCase());
if (material == null || material == Material.AIR) {
return new EmptyRecipePart();
}
return new SimpleRecipePart(material);
}
return lookup.apply(key);
}
}

View File

@@ -0,0 +1,25 @@
package com.willfp.eco.util.recipe.lookup;
import com.willfp.eco.util.recipe.parts.RecipePart;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
public interface ItemLookup {
/**
* Register a new lookup.
*
* @param key The key of the lookup.
* @param lookup The lookup to register, where the output is the recipe part generated.
*/
void registerLookup(@NotNull String key,
@NotNull Function<String, RecipePart> lookup);
/**
* Lookup recipe part from string.
*
* @param key The string to test.
* @return The generated recipe part, or null if invalid.
*/
RecipePart lookup(@NotNull String key);
}

View File

@@ -0,0 +1,48 @@
package com.willfp.eco.util.recipe.lookup;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.recipe.parts.RecipePart;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.plugin.ServicePriority;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
@SuppressWarnings("unchecked")
@UtilityClass
public final class RecipePartUtils {
/**
* Item lookup instance.
*/
private static final ItemLookup itemLookup;
/**
* Lookup recipe part from string.
*
* @param key The string to test.
* @return The generated recipe part, or null if invalid.
*/
public RecipePart lookup(@NotNull final String key) {
return itemLookup.lookup(key);
}
/**
* Register a new lookup.
*
* @param key The key of the lookup.
* @param lookup The lookup to register, where the output is the recipe part generated.
*/
public void registerLookup(@NotNull final String key,
@NotNull final Function<String, RecipePart> lookup) {
itemLookup.registerLookup(key, lookup);
}
static {
if (!Bukkit.getServicesManager().isProvidedFor(ItemLookup.class)) {
Bukkit.getServicesManager().register(ItemLookup.class, new EcoItemLookup(), AbstractEcoPlugin.getInstance(), ServicePriority.Normal);
}
itemLookup = Bukkit.getServicesManager().load(ItemLookup.class);
}
}

View File

@@ -0,0 +1,42 @@
package com.willfp.eco.util.recipe.parts;
import lombok.Getter;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
public class ComplexRecipePart implements RecipePart {
/**
* The test for itemstacks to pass.
*/
@Getter
private final Predicate<ItemStack> predicate;
/**
* Displayed itemstack: what the user should see.
*/
private final ItemStack displayed;
/**
* Create a new complex recipe part.
* @param predicate The test.
* @param displayed The example itemstack.
*/
public ComplexRecipePart(@NotNull final Predicate<ItemStack> predicate,
@NotNull final ItemStack displayed) {
this.predicate = predicate;
this.displayed = displayed;
}
@Override
public boolean matches(@Nullable final ItemStack itemStack) {
return predicate.test(itemStack);
}
@Override
public ItemStack getDisplayed() {
return displayed;
}
}

View File

@@ -0,0 +1,30 @@
package com.willfp.eco.util.recipe.parts;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public class EmptyRecipePart implements RecipePart {
/**
* Create a new empty recipe part.
*/
public EmptyRecipePart() {
}
/**
* If the item is empty.
*
* @param itemStack The item to test.
* @return If the item is empty.
*/
@Override
public boolean matches(@Nullable final ItemStack itemStack) {
return itemStack == null || itemStack.getType() == Material.AIR;
}
@Override
public ItemStack getDisplayed() {
return new ItemStack(Material.AIR);
}
}

View File

@@ -0,0 +1,22 @@
package com.willfp.eco.util.recipe.parts;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public interface RecipePart {
/**
* If an ItemStack matches the recipe part.
*
* @param itemStack The item to test.
* @return If the item matches.
*/
boolean matches(@Nullable ItemStack itemStack);
/**
* Get a displayed itemstack, for autocraft.
*
* @return The item, displayed.
*/
ItemStack getDisplayed();
}

View File

@@ -0,0 +1,40 @@
package com.willfp.eco.util.recipe.parts;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class SimpleRecipePart implements RecipePart {
/**
* The material.
*/
@Getter
private final Material material;
/**
* Create a new simple recipe part.
*
* @param material The material.
*/
public SimpleRecipePart(@NotNull final Material material) {
this.material = material;
}
/**
* If the item matches the material.
*
* @param itemStack The item to test.
* @return If the item is of the specified material.
*/
@Override
public boolean matches(@Nullable final ItemStack itemStack) {
return itemStack != null && itemStack.getType() == material;
}
@Override
public ItemStack getDisplayed() {
return new ItemStack(material);
}
}

View File

@@ -0,0 +1,21 @@
name: eco
version: 2.0.0
main: com.willfp.eco.spigot.EcoSpigotMain
api-version: 1.15
authors: [Auxilor]
website: willfp.com
load: STARTUP
depend:
- ProtocolLib
softdepend:
- WorldGuard
- GriefPrevention
- Towny
- FactionsUUID
- Lands
- Kingdoms
- NoCheatPlus
- AAC
- Matrix
- Spartan
- PlaceholderAPI