diff --git a/pom.xml b/pom.xml
index 671ed74..d3ebe9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,15 +5,15 @@
4.0.0
CraftEnhance
CraftEnhance
- 2.5.6.3.2
+ 2.5.7.0
CraftEnhance
This is a minecraft plugin to enhance crafting.
UTF-8
- 21
+ 21
21
8
- 0.111
+ 0.116
com.dutchjelly.craftenhance.libs
@@ -77,10 +77,10 @@
jitpack.io
https://jitpack.io
-
+
codemc-repo
https://repo.codemc.io/repository/maven-public/
@@ -102,7 +102,7 @@
com.mojang
authlib
- 3.11.49
+ 3.13.56
provided
diff --git a/src/main/java/com/dutchjelly/bukkitadapter/Adapter.java b/src/main/java/com/dutchjelly/bukkitadapter/Adapter.java
index 1d1c80b..8fd852b 100644
--- a/src/main/java/com/dutchjelly/bukkitadapter/Adapter.java
+++ b/src/main/java/com/dutchjelly/bukkitadapter/Adapter.java
@@ -41,7 +41,7 @@ public class Adapter {
public static List CompatibleVersions() {
- return Arrays.asList("1.9", "1.10", "1.11", "1.12", "1.13", "1.14", "1.15", "1.16", "1.17", "1.18", "1.19", "1.20");
+ return Arrays.asList("1.9", "1.10", "1.11", "1.12", "1.13", "1.14", "1.15", "1.16", "1.17", "1.18", "1.19", "1.20","1.21");
}
public final static String GUI_SKULL_MATERIAL_NAME = "GUI_SKULL_ITEM";
diff --git a/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java b/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java
index e02ba85..4844877 100644
--- a/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java
+++ b/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java
@@ -2,6 +2,7 @@
import com.dutchjelly.bukkitadapter.Adapter;
import com.dutchjelly.craftenhance.api.CraftEnhanceAPI;
+import com.dutchjelly.craftenhance.cache.CacheRecipes;
import com.dutchjelly.craftenhance.commandhandling.CustomCmdHandler;
import com.dutchjelly.craftenhance.commands.ceh.ChangeKeyCmd;
import com.dutchjelly.craftenhance.commands.ceh.CleanItemFileCmd;
@@ -27,6 +28,7 @@
import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.BlastRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.SmokerRecipe;
import com.dutchjelly.craftenhance.crafthandling.util.ItemMatchers;
+import com.dutchjelly.craftenhance.database.RecipeDatabase;
import com.dutchjelly.craftenhance.files.CategoryDataCache;
import com.dutchjelly.craftenhance.files.ConfigFormatter;
import com.dutchjelly.craftenhance.files.FileManager;
@@ -40,6 +42,7 @@
import com.dutchjelly.craftenhance.updatechecking.VersionChecker;
import com.dutchjelly.craftenhance.util.Metrics;
import lombok.Getter;
+import lombok.NonNull;
import org.broken.arrow.menu.library.RegisterMenuAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@@ -51,17 +54,23 @@
import java.io.File;
import java.util.Arrays;
+import java.util.List;
import java.util.stream.Collectors;
public class CraftEnhance extends JavaPlugin {
private static CraftEnhance plugin;
-
-
public static CraftEnhance self() {
return plugin;
}
+
+ @Getter
+ private SaveScheduler saveScheduler;
+ @Getter
+ private CacheRecipes cacheRecipes;
+ @Getter
+ private RecipeDatabase database;
private Metrics metrics;
@Getter
private FileManager fm;
@@ -89,6 +98,11 @@ public static CraftEnhance self() {
@Override
public void onEnable() {
plugin = this;
+
+ this.database = new RecipeDatabase();
+ this.saveScheduler = new SaveScheduler();
+ this.cacheRecipes = new CacheRecipes(this);
+
//The file manager needs serialization, so firstly register the classes.
registerSerialization();
versionChecker = VersionChecker.init(this);
@@ -98,12 +112,15 @@ public void onEnable() {
saveDefaultConfig();
Debug.init(this);
+
if (isReloading)
Bukkit.getScheduler().runTaskAsynchronously(this, () -> loadPluginData(isReloading));
else {
this.loadPluginData(false);
loadRecipes();
}
+ if (injector == null)
+ injector = new RecipeInjector(this);
guiManager = new GuiManager(this);
Debug.Send("Setting up listeners and commands");
@@ -124,6 +141,7 @@ public void onEnable() {
metrics = new Metrics(this, metricsId);
}
CraftEnhanceAPI.registerListener(new ExecuteCommand());
+ saveScheduler.start();
}
@@ -148,7 +166,7 @@ public void onDisable() {
fm.saveContainerOwners(injector.getContainerOwners());
Debug.Send("Saving disabled recipes...");
fm.saveDisabledServerRecipes(RecipeLoader.getInstance().getDisabledServerRecipes().stream().map(x -> Adapter.GetRecipeIdentifier(x)).collect(Collectors.toList()));
- fm.getRecipes().forEach(EnhancedRecipe::save);
+ cacheRecipes.getRecipes().forEach(EnhancedRecipe::save);
categoryDataCache.save();
}
@@ -249,19 +267,24 @@ private void loadRecipes() {
//Most other instances use the file manager, so setup before everything.
Debug.Send("Setting up the file manager for recipes.");
setupFileManager();
-
Debug.Send("Loading recipes");
final RecipeLoader loader = RecipeLoader.getInstance();
- fm.getRecipes().stream().filter(x -> x.validate() == null).forEach((recipe) -> loader.loadRecipe(recipe, isReloading));
- loader.printGroupsDebugInfo();
+ Bukkit.getScheduler().runTaskAsynchronously(this, ()-> {
+ @NonNull List recipes = this.database.loadRecipes();
+ this.cacheRecipes.addAll(recipes);
+ Bukkit.getScheduler().runTask(this, ()->loadingRecipes(loader));
+ });
+ isReloading = false;
+ }
+ private void loadingRecipes(final RecipeLoader loader) {
+ this.cacheRecipes.getRecipes().stream().filter(x -> x.validate() == null).forEach((recipe) -> loader.loadRecipe(recipe, isReloading));
+ loader.printGroupsDebugInfo();
loader.disableServerRecipes(
fm.readDisabledServerRecipes().stream().map(x ->
Adapter.FilterRecipes(loader.getServerRecipes(), x)
).collect(Collectors.toList())
);
- if (injector == null)
- injector = new RecipeInjector(this);
injector.registerContainerOwners(fm.getContainerOwners());
injector.setLoader(loader);
//todo learn recipes are little broken. when you reload it.
@@ -269,7 +292,6 @@ private void loadRecipes() {
if (self().getConfig().getBoolean("learn-recipes"))
for (final Player player : Bukkit.getOnlinePlayers())
Adapter.DiscoverRecipes(player, getCategoryDataCache().getServerRecipes());
- isReloading = false;
}
public void openEnhancedCraftingTable(final Player p) {
diff --git a/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java b/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java
new file mode 100644
index 0000000..73e97e3
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java
@@ -0,0 +1,86 @@
+package com.dutchjelly.craftenhance;
+
+import com.dutchjelly.craftenhance.messaging.Debug;
+import org.bukkit.Bukkit;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import static com.dutchjelly.craftenhance.CraftEnhance.self;
+
+public class SaveScheduler implements Runnable {
+ private static final long SAVE_TASK_INTERVAL = 600 * 4;
+ private static final long SAVE_INTERVAL = 60000 * 8;
+ private int taskId = -1;
+ private long lastSaveTime = 0;
+ private long lastSaveTask = 0;
+ private volatile boolean isRunningTask;
+ private BukkitTask task;
+ private final Queue taskQueue = new ConcurrentLinkedQueue<>();
+
+ public void start() {
+ if (task != null && !task.isCancelled()) {
+ return;
+ }
+
+ this.task = Bukkit.getScheduler().runTaskTimerAsynchronously(self(), this, 20 * 30, 20);
+ taskId = this.task.getTaskId();
+ }
+
+ public void stop() {
+ if (taskId == -1) return;
+
+ if (Bukkit.getScheduler().isCurrentlyRunning(taskId) && Bukkit.getScheduler().isQueued(taskId)) {
+ Bukkit.getScheduler().cancelTask(taskId);
+ }
+ }
+
+ @Override
+ public void run() {
+ long now = System.currentTimeMillis();
+
+ if (now - lastSaveTask >= SAVE_TASK_INTERVAL && !isRunningTask) {
+ executeTask();
+ lastSaveTask = now;
+ }
+
+ if (now - lastSaveTime >= SAVE_INTERVAL) {
+ Debug.Send("Doing the scheduler save task.");
+ self().getCacheRecipes().save();
+ lastSaveTime = now;
+ }
+
+ }
+
+ private void executeTask() {
+ if (taskQueue.isEmpty() || isRunningTask) {
+ return;
+ }
+ Debug.Send("Doing the batch save to the database.");
+ isRunningTask = true;
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ int batchSize = 4;
+ Debug.Send("Working with the batch of: " + taskQueue.size());
+ for (int i = 0; i < batchSize && !taskQueue.isEmpty(); i++) {
+ Runnable nextTask = taskQueue.poll();
+ if (nextTask != null) {
+ nextTask.run();
+ }
+ }
+ if (taskQueue.isEmpty()) {
+ isRunningTask = false;
+ cancel();
+ }
+ }
+ }.runTaskTimerAsynchronously(self(), 1, 5);
+ }
+
+ public void addTask(Runnable task) {
+ taskQueue.add(task);
+ }
+
+}
diff --git a/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java b/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java
new file mode 100644
index 0000000..45bb60d
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java
@@ -0,0 +1,71 @@
+package com.dutchjelly.craftenhance.cache;
+
+import com.dutchjelly.craftenhance.CraftEnhance;
+import com.dutchjelly.craftenhance.SaveScheduler;
+import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
+import com.dutchjelly.craftenhance.database.RecipeDatabase;
+import com.dutchjelly.craftenhance.messaging.Debug;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CacheRecipes {
+
+ private final List recipes = new ArrayList<>();
+ private final RecipeDatabase database;
+ private final SaveScheduler saveSchedule;
+
+ public CacheRecipes(final CraftEnhance craftEnhance) {
+ this.database = craftEnhance.getDatabase();
+ this.saveSchedule = craftEnhance.getSaveScheduler();
+ }
+
+ public List getRecipes() {
+ return Collections.unmodifiableList(recipes);
+ }
+
+ @Nullable
+ public EnhancedRecipe getRecipe(final String recipeName) {
+ for (final EnhancedRecipe recipe : recipes) {
+ if (recipe.getKey().equals(recipeName))
+ return recipe;
+ }
+ return null;
+ }
+
+ public void add(EnhancedRecipe enhancedRecipe) {
+ if (enhancedRecipe == null) return;
+ recipes.add(enhancedRecipe);
+ }
+
+ public void addAll(List enhancedRecipes) {
+ recipes.addAll(enhancedRecipes);
+ }
+
+ public void remove(EnhancedRecipe enhancedRecipe) {
+ EnhancedRecipe recipe = enhancedRecipe;
+ saveSchedule.addTask(() -> {
+ this.database.deleteRecipe(recipe);
+ });
+ recipes.remove(enhancedRecipe);
+ }
+
+ public boolean isUniqueRecipeKey(final String key) {
+ return this.getRecipe(key) == null;
+ }
+ public void clear() {
+ recipes.clear();
+ }
+
+ public void save() {
+ saveSchedule.addTask(this.database::saveRecipes);
+ }
+
+ public void save(EnhancedRecipe enhancedRecipe) {
+ saveSchedule.addTask(() -> this.database.saveRecipe(enhancedRecipe));
+ }
+
+
+}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/ChangeKeyCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/ChangeKeyCmd.java
index 46908ec..1a11b17 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/ChangeKeyCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/ChangeKeyCmd.java
@@ -29,7 +29,7 @@ public void handlePlayerCommand(Player p, String[] args) {
Messenger.MessageFromConfig("messages.commands.few-arguments", p, "2");
return;
}
- EnhancedRecipe recipe = handler.getMain().getFm().getRecipe(args[0]);
+ EnhancedRecipe recipe = handler.getMain().getCacheRecipes().getRecipe(args[0]);
if(recipe == null) {
Messenger.Message("That recipe key doesn't exist", p);
return;
@@ -37,10 +37,10 @@ public void handlePlayerCommand(Player p, String[] args) {
//TODO this method of changing the key changes the order of the recipes, which is a weird side-effect, so resolve this
- handler.getMain().getFm().removeRecipe(recipe);
+ recipe.remove();
RecipeLoader.getInstance().unloadRecipe(recipe);
recipe.setKey(args[1]);
- handler.getMain().getFm().saveRecipe(recipe);
+ recipe.save();
RecipeLoader.getInstance().loadRecipe(recipe);
Messenger.Message("The key has been changed to " + args[1] + ".", p);
}
@@ -51,15 +51,16 @@ public void handleConsoleCommand(CommandSender sender, String[] args) {
Messenger.MessageFromConfig("messages.commands.few-arguments", sender, "2");
return;
}
- EnhancedRecipe recipe = handler.getMain().getFm().getRecipe(args[0]);
+ EnhancedRecipe recipe = handler.getMain().getCacheRecipes().getRecipe(args[0]);
if(recipe == null) {
Messenger.Message("That recipe key doesn't exist", sender);
return;
}
- handler.getMain().getFm().removeRecipe(recipe);
+
+ recipe.remove();
RecipeLoader.getInstance().unloadRecipe(recipe);
recipe.setKey(args[1]);
- handler.getMain().getFm().saveRecipe(recipe);
+ recipe.save();
RecipeLoader.getInstance().loadRecipe(recipe);
Messenger.Message("The key has been changed to " + args[1] + ".", sender);
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CleanItemFileCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CleanItemFileCmd.java
index 1884428..09a4c3d 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CleanItemFileCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CleanItemFileCmd.java
@@ -23,13 +23,13 @@ public String getDescription() {
@Override
public void handlePlayerCommand(Player p, String[] args) {
- handler.getMain().getFm().cleanItemFile();
- Messenger.Message("Successfully cleared all unused items.", p);
+ //handler.getMain().getFm().cleanItemFile();
+ Messenger.Message("Not used any more, as it store items inside a SQL database and not allowing duplicates. But in case it is needed it will stay a little longer.", p);
}
@Override
public void handleConsoleCommand(CommandSender sender, String[] args) {
- handler.getMain().getFm().cleanItemFile();
- Messenger.Message("Successfully cleared all unused items.", sender);
+ //handler.getMain().getFm().cleanItemFile();
+ Messenger.Message("Not used any more, as it store items inside a SQL database and not allowing duplicates. But in case it is needed it will stay a little longer.", sender);
}
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java
index 7942fe8..941252c 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java
@@ -43,7 +43,7 @@ public void handlePlayerCommand(Player p, String[] args) {
//Fill in a unique key and empty permission for the user.
if (args.length == 0) {
int uniqueKeyIndex = 1;
- while (!handler.getMain().getFm().isUniqueRecipeKey("recipe" + uniqueKeyIndex))
+ while (!handler.getMain().getCacheRecipes().isUniqueRecipeKey("recipe" + uniqueKeyIndex))
uniqueKeyIndex++;
/*EditorTypeSelector gui = new EditorTypeSelector(handler.getMain().getGuiManager(), handler.getMain().getGuiTemplatesFile().getTemplate(EditorTypeSelector.class), null, p, "recipe" + uniqueKeyIndex, null);
handler.getMain().getGuiManager().openGUI(p, gui);*/
@@ -55,7 +55,7 @@ public void handlePlayerCommand(Player p, String[] args) {
Messenger.MessageFromConfig("messages.commands.few-arguments", p, "2");
return;
}
- if (!handler.getMain().getFm().isUniqueRecipeKey(args[1])) {
+ if (!handler.getMain().getCacheRecipes().isUniqueRecipeKey(args[1])) {
Messenger.Message("The specified recipe key isn't unique.", p);
return;
}
@@ -74,25 +74,25 @@ private static void openEditor(final Player p, final String[] args) {
case "workbench":
recipe = new WBRecipe(permission , null, new ItemStack[9]);
recipe.setKey(args[1]);
- RecipeEditor recipeEditor = new RecipeEditor<>(recipe, null, null, ButtonType.ChooseWorkbenchType);
+ RecipeEditor recipeEditor = new RecipeEditor<>(recipe,0, null, null, ButtonType.ChooseWorkbenchType);
recipeEditor.menuOpen(p);
break;
case "furnace":
recipe = new FurnaceRecipe(permission , null, new ItemStack[1]);
recipe.setKey(args[1]);
- RecipeEditorFurnace editorFurnace = new RecipeEditorFurnace((FurnaceRecipe) recipe, null, null, ButtonType.ChooseWorkbenchType);
+ RecipeEditorFurnace editorFurnace = new RecipeEditorFurnace((FurnaceRecipe) recipe,0, null, null, ButtonType.ChooseWorkbenchType);
editorFurnace.menuOpen(p);
break;
case "blast":
recipe = new BlastRecipe(permission , null, new ItemStack[1]);
recipe.setKey(args[1]);
- RecipeEditorBlast editorBlast = new RecipeEditorBlast((BlastRecipe) recipe, null, null, ButtonType.ChooseWorkbenchType,true);
+ RecipeEditorBlast editorBlast = new RecipeEditorBlast((BlastRecipe) recipe, 0, null, null, ButtonType.ChooseWorkbenchType,true);
editorBlast.menuOpen(p);
break;
case "smoker":
recipe = new SmokerRecipe(permission , null, new ItemStack[1]);
recipe.setKey(args[1]);
- RecipeEditorSmoker editorSmoker = new RecipeEditorSmoker((SmokerRecipe) recipe, null, null, ButtonType.ChooseWorkbenchType,true);
+ RecipeEditorSmoker editorSmoker = new RecipeEditorSmoker((SmokerRecipe) recipe, 0, null, null, ButtonType.ChooseWorkbenchType,true);
editorSmoker.menuOpen(p);
break;
default:
@@ -119,7 +119,7 @@ public List handleTabCompletion(final CommandSender sender, final String
tab.add("smoker");
}
if (args.length == 3) {
- tab.add("key");
+ tab.add("permission");
}
return tab;
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RecipesCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RecipesCmd.java
index d6e34c3..72c5e37 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RecipesCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RecipesCmd.java
@@ -60,16 +60,16 @@ public void handlePlayerCommand(final Player p, final String[] args) {
final EnhancedRecipe recipe = getRecipe(categoryData.getEnhancedRecipes(), args[2]);
if (recipe instanceof WBRecipe) {
if ( p.hasPermission(PermissionTypes.Edit.getPerm()))
- new RecipeEditor<>((WBRecipe) recipe, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(p);
+ new RecipeEditor<>((WBRecipe) recipe,0, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(p);
else
- new RecipeViewRecipe<>(categoryData, (WBRecipe) recipe, "WBRecipeViewer").menuOpen(p);
+ new RecipeViewRecipe<>(categoryData, 0,(WBRecipe) recipe, "WBRecipeViewer").menuOpen(p);
return;
}
if (recipe instanceof FurnaceRecipe) {
if (p.hasPermission(PermissionTypes.Edit.getPerm()))
- new RecipeEditor<>((FurnaceRecipe) recipe, categoryData,null, ButtonType.ChooseFurnaceType).menuOpen(p);
+ new RecipeEditor<>((FurnaceRecipe) recipe,0, categoryData,null, ButtonType.ChooseFurnaceType).menuOpen(p);
else
- new RecipeViewRecipe<>(categoryData, (FurnaceRecipe) recipe, "FurnaceRecipeViewer").menuOpen(p);
+ new RecipeViewRecipe<>(categoryData, 0,(FurnaceRecipe) recipe, "FurnaceRecipeViewer").menuOpen(p);
return;
}
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RemoveRecipeCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RemoveRecipeCmd.java
index 4a7734a..b638b13 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RemoveRecipeCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/RemoveRecipeCmd.java
@@ -46,7 +46,7 @@ private void removeRecipe(final CommandSender sender, String[] args) {
List enhancedRecipes = RecipeLoader.getInstance().getLoadedRecipes();
for (EnhancedRecipe recipe : enhancedRecipes) {
if (recipe.getKey().equals(args[0])) {
- self().getFm().removeRecipe(recipe);
+ self().getCacheRecipes().remove(recipe);
RecipeLoader.getInstance().unloadRecipe(recipe);
Messenger.Message("The specified recipe is removed " + recipe.getKey(), sender);
return;
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SetPermissionCmd.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SetPermissionCmd.java
index d0f0741..1d75495 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SetPermissionCmd.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SetPermissionCmd.java
@@ -11,7 +11,7 @@
@CommandRoute(cmdPath="ceh.setpermission", perms="perms.recipe-editor")
public class SetPermissionCmd implements ICommand {
- private CustomCmdHandler handler;
+ private final CustomCmdHandler handler;
public SetPermissionCmd(CustomCmdHandler handler){
this.handler = handler;
@@ -28,14 +28,14 @@ public void handlePlayerCommand(Player p, String[] args) {
Messenger.MessageFromConfig("messages.commands.few-arguments", p, "2");
return;
}
- EnhancedRecipe recipe = handler.getMain().getFm().getRecipe(args[0]);
+ EnhancedRecipe recipe = handler.getMain().getCacheRecipes().getRecipe(args[0]);
if(recipe == null) {
Messenger.Message("That recipe key doesn't exist", p);
return;
}
recipe.setPermission(args[1]);
- handler.getMain().getFm().saveRecipe(recipe);
+ recipe.save();
Messenger.Message("Successfully set the permissions of the recipe to " + args[1] + ".", p);
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SpecsCommand.java b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SpecsCommand.java
index 07adbe0..ef87a33 100644
--- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SpecsCommand.java
+++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/SpecsCommand.java
@@ -28,7 +28,7 @@ public void handlePlayerCommand(Player p, String[] args) {
Messenger.MessageFromConfig("messages.commands.few-arguments", p, "1");
return;
}
- EnhancedRecipe recipe = handler.getMain().getFm().getRecipe(args[0]);
+ EnhancedRecipe recipe = handler.getMain().getCacheRecipes().getRecipe(args[0]);
if(recipe == null) {
Messenger.Message("That recipe key doesn't exist", p);
return;
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java
index f16a132..bf3d568 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java
@@ -204,7 +204,7 @@ && isViewersAllowedCraft(viewers, wbRecipe)
}
});
} else {
- Debug.Send(Type.Crafting, () -> "This recipe deosen't contains Modeldata and will be crafted if the recipe is not cancelled.");
+ Debug.Send(Type.Crafting, () -> "This recipe doesn't contains Modeldata and will be crafted if the recipe is not cancelled.");
final BeforeCraftOutputEvent beforeCraftOutputEvent = new BeforeCraftOutputEvent(eRecipe, wbRecipe, wbRecipe.getResult().clone());
if (beforeCraftOutputEvent.isCancelled()) {
@@ -567,6 +567,7 @@ public void furnaceBreak(final BlockBreakEvent e) {
private boolean isCraftingAllowedInWorld(final Location location, final EnhancedRecipe eRecipe) {
final Set allowedWorlds = eRecipe.getAllowedWorlds();
+ //todo Similar recipes could prevent world blocking from working.
if (allowedWorlds == null || allowedWorlds.isEmpty()) return false;
if (location != null) {
if (location.getWorld() == null) return true;
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java
index 6c84167..1f0b439 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java
@@ -3,6 +3,8 @@
import com.dutchjelly.bukkitadapter.Adapter;
import com.dutchjelly.craftenhance.CraftEnhance;
import com.dutchjelly.craftenhance.crafthandling.RecipeLoader;
+import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.BlastRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.SmokerRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.utility.RecipeType;
import com.dutchjelly.craftenhance.crafthandling.util.IMatcher;
import com.dutchjelly.craftenhance.crafthandling.util.ItemMatchers;
@@ -29,7 +31,17 @@
public abstract class EnhancedRecipe extends GuiPlacable implements ConfigurationSerializable, ServerLoadable {
- public EnhancedRecipe() {
+ protected EnhancedRecipe(EnhancedRecipe enhancedRecipe) {
+ this("", null, null);
+ this.key = enhancedRecipe.getKey();
+ this.onCraftCommand = enhancedRecipe.getOnCraftCommand();
+ this.allowedWorlds = enhancedRecipe.getAllowedWorlds();
+ this.checkPartialMatch = enhancedRecipe.isCheckPartialMatch();
+ this.matchType = enhancedRecipe.getMatchType();
+ this.deserialize = enhancedRecipe.getDeserialize();
+ this.id = enhancedRecipe.getId();
+ this.hidden = enhancedRecipe.isHidden();
+ this.serialize = enhancedRecipe.getSerialize();
}
public EnhancedRecipe(final String perm, final ItemStack result, final ItemStack[] content) {
@@ -54,7 +66,8 @@ protected EnhancedRecipe(final Map args) {
}
if (args.containsKey("oncraftcommand")) {
- onCraftCommand = (String) args.get("oncraftcommand");
+ final Object oncraftcommand = args.get("oncraftcommand");
+ onCraftCommand = oncraftcommand instanceof Boolean ? "" : (String) oncraftcommand;
}
if (args.containsKey("hidden"))
@@ -81,10 +94,11 @@ protected EnhancedRecipe(final Map args) {
}
});
this.allowedWorlds = worlds;
-
- setContent(new ItemStack[recipeKeys.size()]);
- for (int i = 0; i < content.length; i++) {
- content[i] = fm.getItem(recipeKeys.get(i));
+ if (recipeKeys != null) {
+ setContent(new ItemStack[recipeKeys.size()]);
+ for (int i = 0; i < content.length; i++) {
+ content[i] = fm.getItem(recipeKeys.get(i));
+ }
}
this.deserialize = args;
}
@@ -122,7 +136,7 @@ protected EnhancedRecipe(final Map args) {
private String onCraftCommand;
@Getter
- private RecipeType type;
+ private final RecipeType type = RecipeType.WORKBENCH;
@Getter
@Setter
@@ -135,6 +149,19 @@ protected EnhancedRecipe(final Map args) {
@Setter
private boolean checkPartialMatch;
+ public EnhancedRecipe copy() {
+ switch (this.getType()) {
+ case FURNACE:
+ return new FurnaceRecipe(this);
+ case BLAST:
+ return new BlastRecipe(this);
+ case SMOKER:
+ return new SmokerRecipe(this);
+ default:
+ return new WBRecipe(this);
+ }
+ }
+
@Nonnull
@Override
public Map serialize() {
@@ -147,7 +174,7 @@ public Map serialize() {
put("check_partial_match", checkPartialMatch);
put("oncraftcommand", onCraftCommand);
put("result", fm.getItemKey(result));
- put("recipe", Arrays.stream(content).map(x -> fm.getItemKey(x)).toArray(String[]::new));
+ put("recipe", Arrays.stream(content).map(fm::getItemKey).toArray(String[]::new));
put("allowed_worlds", allowedWorlds != null ? new ArrayList<>(allowedWorlds) : new ArrayList<>());
if (serialize != null && !serialize.isEmpty())
putAll(serialize);
@@ -168,11 +195,17 @@ public String validate() {
@Override
public String toString() {
return "EnhancedRecipe{" +
- "key='" + key + '\'' +
+ "recipe_name='" + key + '\'' +
", result=" + result +
", content=" + Arrays.toString(content) +
- ", recipe-type=" + type +
- "}";
+ ", matchType=" + matchType +
+ ", permission='" + permission + '\'' +
+ ", hidden=" + hidden +
+ ", on_craft_command='" + onCraftCommand + '\'' +
+ ", type=" + this.getType() +
+ ", allowedWorlds=" + allowedWorlds +
+ ", checkPartialMatch=" + checkPartialMatch +
+ "} ";
}
public void setPermission(final String permission) {
@@ -211,16 +244,28 @@ public ItemStack getDisplayItem() {
}
public void save() {
- if (validate() == null)
- CraftEnhance.self().getFm().saveRecipe(this);
+ if (validate() == null) {
+ CraftEnhance.self().getCacheRecipes().save(this);
+ }
+ }
+
+ public void remove() {
+ CraftEnhance.self().getCacheRecipes().remove(this);
}
public void load() {
RecipeLoader.getInstance().loadRecipe(this);
}
+ public RecipeType getType() {
+ return type;
+ }
+
+
public abstract boolean matches(ItemStack[] content);
public abstract boolean matches(ItemStack[] content, IMatcher matcher);
+
public abstract boolean matchesBlockType(final Material blockSmelting);
+
}
\ No newline at end of file
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/FurnaceRecipe.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/FurnaceRecipe.java
index 0901da6..39adeda 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/FurnaceRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/FurnaceRecipe.java
@@ -39,7 +39,9 @@ protected FurnaceRecipe(final Map args) {
public FurnaceRecipe(final String perm, final ItemStack result, final ItemStack[] content) {
super(perm, result, content);
}
-
+ protected FurnaceRecipe(EnhancedRecipe enhancedRecipe){
+ super(enhancedRecipe);
+ }
public static FurnaceRecipe deserialize(final Map args) {
final FurnaceRecipe recipe = new FurnaceRecipe(args);
recipe.duration = (int) args.get("duration");
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/WBRecipe.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/WBRecipe.java
index 488e995..7c3d8f8 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/WBRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/WBRecipe.java
@@ -36,8 +36,12 @@ private WBRecipe(final Map args){
shapeless = (Boolean) args.get("shapeless");
}
- public WBRecipe(){
+ protected WBRecipe(EnhancedRecipe enhancedRecipe){
+ super(enhancedRecipe);
+ }
+ public WBRecipe() {
+ super("", null, null);
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/BlastRecipe.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/BlastRecipe.java
index 844754e..2871e82 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/BlastRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/BlastRecipe.java
@@ -2,6 +2,7 @@
import com.dutchjelly.bukkitadapter.Adapter;
import com.dutchjelly.craftenhance.CraftEnhance;
+import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.FurnaceRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.utility.RecipeType;
import com.dutchjelly.craftenhance.crafthandling.util.ServerRecipeTranslator;
@@ -27,6 +28,10 @@ public BlastRecipe(final String perm, final ItemStack result, final ItemStack[]
super(perm, result, content);
}
+ public BlastRecipe(final EnhancedRecipe enhancedRecipe) {
+ super(enhancedRecipe);
+ }
+
@Override
public Recipe getServerRecipe() {
return Adapter.getBlastRecipe(CraftEnhance.self(), ServerRecipeTranslator.GetFreeKey(getKey()), getResult(), getContent()[0], 100, getExp());
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/SmokerRecipe.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/SmokerRecipe.java
index 82e4eeb..31e4096 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/SmokerRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/furnace/SmokerRecipe.java
@@ -2,6 +2,7 @@
import com.dutchjelly.bukkitadapter.Adapter;
import com.dutchjelly.craftenhance.CraftEnhance;
+import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.FurnaceRecipe;
import com.dutchjelly.craftenhance.crafthandling.recipes.utility.RecipeType;
import com.dutchjelly.craftenhance.crafthandling.util.ServerRecipeTranslator;
@@ -26,6 +27,10 @@ public SmokerRecipe(final String perm, final ItemStack result, final ItemStack[]
super(perm, result, content);
}
+ public SmokerRecipe(final EnhancedRecipe enhancedRecipe) {
+ super(enhancedRecipe);
+ }
+
@Override
public Recipe getServerRecipe() {
return Adapter.getSmokingRecipe(CraftEnhance.self(), ServerRecipeTranslator.GetFreeKey(getKey()), getResult(), getContent()[0], 100, getExp());
diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/utility/RecipeType.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/utility/RecipeType.java
index 473f5b0..66d4152 100644
--- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/utility/RecipeType.java
+++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/utility/RecipeType.java
@@ -46,5 +46,18 @@ public static RecipeType getType(Block block) {
return null;
}
}
+ public static RecipeType getType(String type) {
+ if (type == null) return WORKBENCH;
+ RecipeType [] recipeTypes = values();
+ String typeUp = type.toUpperCase();
+
+ for (RecipeType recipeType : recipeTypes) {
+ if (recipeType.name().equals(typeUp)) {
+ return recipeType;
+ }
+ }
+
+ return WORKBENCH;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java b/src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java
new file mode 100644
index 0000000..651b0a0
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java
@@ -0,0 +1,52 @@
+package com.dutchjelly.craftenhance.database;
+
+public class IngredientWrapper {
+ private byte[] itemData;
+ private int slot;
+ private String recipeName;
+ private String itemName;
+ private RecipeIngredientType recipeIngredientType = RecipeIngredientType.INGREDIENT;
+
+ public IngredientWrapper() {
+ }
+
+ public byte[] getItemData() {
+ return itemData;
+ }
+
+ public int getSlot() {
+ return slot;
+ }
+
+ public void setItemData(final byte[] itemData) {
+ this.itemData = itemData;
+ }
+
+ public void setSlot(final int slot) {
+ this.slot = slot;
+ }
+
+ public String getRecipeName() {
+ return recipeName;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setRecipeName(final String recipeName) {
+ this.recipeName = recipeName;
+ }
+
+ public void setItemName(final String itemName) {
+ this.itemName = itemName;
+ }
+
+ public RecipeIngredientType getRecipeType() {
+ return recipeIngredientType;
+ }
+
+ public void setRecipeType(final RecipeIngredientType recipeIngredientType) {
+ this.recipeIngredientType = recipeIngredientType;
+ }
+ }
diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java
new file mode 100644
index 0000000..f7b594a
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java
@@ -0,0 +1,717 @@
+package com.dutchjelly.craftenhance.database;
+
+import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.FurnaceRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.WBRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.BlastRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.furnace.SmokerRecipe;
+import com.dutchjelly.craftenhance.crafthandling.recipes.utility.RecipeType;
+import com.dutchjelly.craftenhance.messaging.Debug;
+import lombok.NonNull;
+import org.broken.arrow.nbt.library.RegisterNbtAPI;
+import org.bukkit.inventory.ItemStack;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import static com.dutchjelly.craftenhance.CraftEnhance.self;
+import static com.dutchjelly.craftenhance.messaging.Debug.Send;
+
+public class RecipeDatabase implements RecipeSQLQueries {
+ private static final String URL = "jdbc:sqlite:" + self().getDataFolder() + "/recipes.db";
+
+ public RecipeDatabase() {
+ try (Connection connection = connect()) {
+ createTables(connection);
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+
+ public void saveRecipes() {
+ save();
+ }
+
+ public void saveRecipe(@NonNull final EnhancedRecipe recipe) {
+ Send("Saving recipe '" + recipe.getKey() + "' with data: " + recipe.toString());
+ try (Connection connection = connect()) {
+ connection.setAutoCommit(false);
+ try {
+ saveRecipe(connection, recipe);
+ } finally {
+ try {
+ connection.commit();
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ Debug.error("Could not not reset back the auto commit.", e);
+ }
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ @NonNull
+ public List loadRecipes() {
+ try (Connection connection = connect()) {
+ return this.getAllRecipe(connection);
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ return new ArrayList<>();
+ }
+
+ @Nullable
+ public EnhancedRecipe loadRecipe(@NonNull final String recipeId) {
+ try (Connection connection = connect()) {
+ return this.getRecipe(connection, recipeId);
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ return null;
+ }
+
+ public void deleteRecipe(@NonNull final EnhancedRecipe enhancedRecipe) {
+ Send("Removing recipe '" + enhancedRecipe.getKey() + "' with data: " + enhancedRecipe.toString());
+
+ try (Connection connection = connect()) {
+ connection.setAutoCommit(false);
+ deleteRecipe(connection, enhancedRecipe);
+ try {
+ connection.commit();
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ Debug.error("Could not not reset back the auto commit.", e);
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ public void removeAllowedWorlds(@NonNull final EnhancedRecipe enhancedRecipe) {
+ try (Connection connection = connect()) {
+ connection.setAutoCommit(false);
+ this.removeAllowedWorld(connection, enhancedRecipe.getKey(), enhancedRecipe.getAllowedWorlds().toArray(new String[0]));
+ try {
+ connection.commit();
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ Debug.error("Could not not reset back the auto commit.", e);
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ private void removeAllowedWorld(@NonNull final EnhancedRecipe enhancedRecipe, @NonNull final String world) {
+ try (Connection connection = connect()) {
+ removeAllowedWorld(connection, enhancedRecipe.getKey(), world);
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ public void deleteAllIngredients(@NonNull final EnhancedRecipe enhancedRecipe) {
+ try (Connection connection = connect()) {
+ connection.setAutoCommit(false);
+ this.deleteAllIngredients(connection, enhancedRecipe);
+ try {
+ connection.commit();
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ Debug.error("Could not not reset back the auto commit.", e);
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ public void removeFurnaceData(@NonNull final EnhancedRecipe enhancedRecipe) {
+ try (Connection connection = connect()) {
+ this.removeFurnaceData(connection, enhancedRecipe);
+ try {
+ connection.commit();
+ } catch (SQLException e) {
+ Debug.error("Could not not commit changes.", e);
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+ public void deleteIngredient(@NonNull final EnhancedRecipe enhancedRecipe, @NonNull final ItemStack itemStack) {
+ boolean isResult = enhancedRecipe.getResult().isSimilar(itemStack);
+ int slot = enhancedRecipe.getResultSlot();
+
+ if (!isResult) {
+ slot = getSlotIngredient(enhancedRecipe, itemStack, slot);
+ }
+ if (slot < 0) return;
+
+ try (Connection connection = connect()) {
+ this.deleteIngredient(connection, enhancedRecipe.getKey(), slot);
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+
+ private Connection connect() throws SQLException {
+ return DriverManager.getConnection(URL);
+ }
+
+ private int updateSQL(final PreparedStatement updateItemStmt) throws SQLException {
+ return updateItemStmt.executeUpdate();
+ }
+
+ // Create tables
+ public void createTables(Connection conn) {
+ String createRecipesTable = " CREATE TABLE IF NOT EXISTS recipes ( "
+ + "id TEXT PRIMARY KEY, "
+ + "recipe_type TEXT NOT NULL, "
+ + "page INTEGER NOT NULL, "
+ + "slot INTEGER NOT NULL, "
+ + "result_slot INTEGER NOT NULL, "
+ + "category TEXT NOT NULL, "
+ + "permission TEXT, "
+ + "matchtype TEXT NOT NULL, "
+ + "hidden BOOLEAN NOT NULL,"
+ + "check_partial_match BOOLEAN NOT NULL, "
+ + "on_craft_command TEXT, "
+ + "result_item_type TEXT NOT NULL, "
+ + "shapeless BOOLEAN NOT NULL, "
+ + "FOREIGN KEY (result_item_type) REFERENCES items(id));";
+
+ String createItemsTable = " CREATE TABLE IF NOT EXISTS items ( "
+ + "recipe_id TEXT NOT NULL, "
+ + "slot INTEGER NOT NULL, "
+ + "name TEXT NOT NULL, "
+ + "item_nbt BLOB NOT NULL, "
+ + "type TEXT NOT NULL, "
+ + "PRIMARY KEY (recipe_id, slot), "
+ + "FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE);";
+
+ String createIngredientsTable = " CREATE TABLE IF NOT EXISTS ingredients ("
+ + "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + " recipe_id TEXT NOT NULL,"
+ + " item_id INTEGER NOT NULL,"
+ + " FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE,"
+ + " FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE);";
+
+ String createAllowedWorldsTable = " CREATE TABLE IF NOT EXISTS allowed_worlds ("
+ + "recipe_id TEXT NOT NULL, "
+ + "world TEXT NOT NULL, "
+ + "PRIMARY KEY (recipe_id, world), "
+ + "FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE);";
+
+ String furnaceData = " CREATE TABLE IF NOT EXISTS furnace_data ("
+ + "recipe_id TEXT NOT NULL, "
+ + "duration INTEGER NOT NULL, "
+ + "exp DECIMAL(10,5) NOT NULL, "
+ + "PRIMARY KEY (recipe_id), "
+ + "FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE);";
+
+ try (Statement stmt = conn.createStatement()) {
+ stmt.addBatch(createItemsTable);
+ stmt.addBatch(createRecipesTable);
+ stmt.addBatch(createAllowedWorldsTable);
+ stmt.addBatch(furnaceData);
+ stmt.executeBatch();
+ } catch (SQLException e) {
+ Debug.error("Failed to create one of the tables", e);
+ }
+ }
+
+ public void insertAllowedWorlds(Connection connection, String recipeId, Set allowedWorlds) throws SQLException {
+ if (allowedWorlds == null || allowedWorlds.isEmpty()) return;
+
+ try (PreparedStatement updateStmt = connection.prepareStatement(UPDATE_WORLDS_SQL);
+ PreparedStatement insertStmt = connection.prepareStatement(INSERT_WORLDS_SQL)) {
+
+ for (String world : allowedWorlds) {
+ // First try to update
+ updateStmt.setString(1, world);
+ updateStmt.setString(2, recipeId);
+ updateStmt.setString(3, world);
+ int rowsAffected = updateStmt.executeUpdate();
+
+ // If no rows were updated, insert instead
+ if (rowsAffected == 0) {
+ insertStmt.setString(1, recipeId);
+ insertStmt.setString(2, world);
+ insertStmt.addBatch();
+ }
+ }
+ insertStmt.executeBatch();
+ }
+ }
+
+ // Insert a recipe
+ public void insertRecipe(@NonNull Connection conn, EnhancedRecipe recipe, RecipeIngredientType recipeIngredientType) {
+
+ try (PreparedStatement pstmt = conn.prepareStatement(INSERT_RECIPES_SQL, Statement.RETURN_GENERATED_KEYS)) {
+ pstmt.setString(1, recipe.getKey());
+ pstmt.setString(2, recipe.getType().name());
+ pstmt.setInt(3, recipe.getPage());
+ pstmt.setInt(4, recipe.getSlot());
+ pstmt.setInt(5, recipe.getResultSlot());
+ pstmt.setString(6, recipe.getRecipeCategory());
+ pstmt.setString(7, recipe.getPermission());
+ pstmt.setString(8, String.valueOf(recipe.getMatchType()));
+ pstmt.setBoolean(9, recipe.isHidden());
+ pstmt.setBoolean(10, recipe.isCheckPartialMatch());
+ pstmt.setString(11, recipe.getOnCraftCommand());
+ pstmt.setString(12, recipeIngredientType.name());
+
+
+ boolean isShapeless = (recipe instanceof WBRecipe) && ((WBRecipe) recipe).isShapeless();
+ pstmt.setBoolean(13, isShapeless);
+ try {
+ updateSQL(pstmt);
+ } catch (SQLException e) {
+ Debug.error("Failed to insert recipe: " + recipe.getKey());
+ Debug.error("Recipe data: " + recipe, e);
+ }
+ } catch (SQLException e) {
+ Debug.error("Failed to insert data", e);
+ }
+ }
+
+ private void updateFurnaces(final Connection conn, final EnhancedRecipe recipe) throws SQLException {
+ if (!(recipe instanceof FurnaceRecipe)) return;
+
+ FurnaceRecipe furnaceRecipe = ((FurnaceRecipe) recipe);
+ try (PreparedStatement furnPreparedStatement = conn.prepareStatement(SELECT_FURNACE_DATA_SQL)) {
+ furnPreparedStatement.setString(1, recipe.getKey());
+ ResultSet set = furnPreparedStatement.executeQuery();
+ if (set.next()) {
+ try (PreparedStatement updateFurn = conn.prepareStatement(UPDATE_FURNACE_DATA_SQL)) {
+ updateFurn.setInt(1, furnaceRecipe.getDuration());
+ updateFurn.setFloat(2, furnaceRecipe.getExp());
+ updateFurn.setString(3, recipe.getKey());
+ }
+ } else {
+ try (PreparedStatement insertFurn = conn.prepareStatement(INSERT_FURNACE_DATA_SQL)) {
+ insertFurn.setString(1, recipe.getKey());
+ insertFurn.setInt(2, furnaceRecipe.getDuration());
+ insertFurn.setFloat(3, furnaceRecipe.getExp());
+ }
+ }
+ }
+ }
+
+ private void save() {
+ try (Connection connection = connect()) {
+ connection.setAutoCommit(false);
+ try {
+ List tempList = new ArrayList<>(self().getCacheRecipes().getRecipes());
+ for (EnhancedRecipe recipe : tempList) {
+ saveRecipe(connection, recipe);
+ }
+ connection.commit();
+ } finally {
+ try {
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ Debug.error("Could not not reset back the auto commit.", e);
+ }
+ }
+ } catch (SQLException exception) {
+ Debug.error("Failed to connect to database", exception);
+ }
+ }
+
+
+ // Retrieve a recipe with its ingredients
+ public EnhancedRecipe getRecipe(Connection conn, String recipeId) {
+ EnhancedRecipe recipe;
+
+ try (PreparedStatement pstmt = conn.prepareStatement(SELECT_RECIPE_JOIN_SQL)) {
+
+ pstmt.setString(1, recipeId);
+ ResultSet rs = pstmt.executeQuery();
+ if (!rs.next()) return null;
+
+ recipe = getEnhancedRecipe(conn, recipeId, rs);
+ return recipe;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public List getAllRecipe(Connection conn) {
+ List enhancedRecipes = new ArrayList<>();
+ try (PreparedStatement pstmt = conn.prepareStatement(SELECT_ALL_RECIPE_JOIN_SQL)) {
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ final EnhancedRecipe recipe = getEnhancedRecipe(conn, rs.getString("id"), rs);
+ enhancedRecipes.add(recipe);
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ return enhancedRecipes;
+ }
+
+ private EnhancedRecipe getEnhancedRecipe(final Connection conn, final String recipeId, final ResultSet rs) throws SQLException {
+ EnhancedRecipe recipe;
+ Object resultNbt = rs.getBytes("result_nbt");
+ ItemStack resultItem = null;
+ if (resultNbt != null) {
+ final ItemStack[] itemStacks = deserializeItemStack((byte[]) resultNbt);
+ if (itemStacks != null && itemStacks.length > 0) resultItem = itemStacks[0];
+ }
+
+ Map map = new HashMap<>();
+ map.put("page", rs.getInt("page"));
+ map.put("slot", rs.getInt("slot"));
+ map.put("result_slot", rs.getInt("result_slot"));
+ map.put("category", rs.getString("category"));
+ map.put("permission", rs.getString("permission"));
+ map.put("matchtype", rs.getString("matchtype"));
+ map.put("hidden", rs.getBoolean("hidden"));
+ map.put("check_partial_match", rs.getBoolean("check_partial_match"));
+ map.put("oncraftcommand", rs.getString("on_craft_command"));
+ map.put("shapeless", rs.getBoolean("shapeless"));
+
+ RecipeType type = RecipeType.getType(rs.getString("recipe_type"));
+ if (type != null) {
+ switch (type) {
+ case FURNACE:
+ map.put("duration", rs.getInt("duration"));
+ map.put("exp", rs.getDouble("exp"));
+ recipe = FurnaceRecipe.deserialize(map);
+ break;
+ case BLAST:
+ map.put("duration", rs.getInt("duration"));
+ map.put("exp", rs.getDouble("exp"));
+ recipe = BlastRecipe.deserialize(map);
+ break;
+ case SMOKER:
+ map.put("duration", rs.getInt("duration"));
+ map.put("exp", rs.getDouble("exp"));
+ recipe = SmokerRecipe.deserialize(map);
+ break;
+ default:
+ recipe = WBRecipe.deserialize(map);
+ }
+ } else {
+ recipe = WBRecipe.deserialize(map);
+ }
+
+ recipe.setResult(resultItem);
+ recipe.setKey(recipeId);
+
+ List ingredients = getRecipeIngredients(conn, recipeId, type);
+ recipe.setContent(ingredients.toArray(new ItemStack[0]));
+
+ Set allowedWorlds = getAllowedWorlds(conn, recipeId);
+ recipe.setAllowedWorlds(allowedWorlds);
+ System.out.println("recipe: " + recipe);
+ return recipe;
+ }
+
+ private List getRecipeIngredients(Connection conn, String recipeId, final RecipeType type) throws SQLException {
+ int maxAmount = 9;
+ if (type != RecipeType.WORKBENCH)
+ maxAmount = 1;
+ List ingredients = new ArrayList<>(Collections.nCopies(maxAmount, null));
+
+ try (PreparedStatement pstmt = conn.prepareStatement(SELECT_INGREDIENTS_SQL)) {
+ pstmt.setString(1, recipeId);
+ pstmt.setString(2, RecipeIngredientType.INGREDIENT.name());
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ byte[] nbtData = rs.getBytes("item_nbt");
+ ItemStack[] items = deserializeItemStack(nbtData);
+ int slot = rs.getInt("slot");
+ if (slot >= 0 && slot < maxAmount && items != null && items.length > 0) {
+ ingredients.set(slot, items[0]);
+ }
+ }
+ }
+ return ingredients;
+ }
+
+ private Set getAllowedWorlds(Connection conn, String recipeId) throws SQLException {
+ Set worlds = new HashSet<>();
+
+ try (PreparedStatement pstmt = conn.prepareStatement(SELECT_WORLDS_SQL)) {
+ pstmt.setString(1, recipeId);
+ ResultSet rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ worlds.add(rs.getString("world"));
+ }
+ }
+ return worlds;
+ }
+
+ public void deleteRecipe(Connection connection, EnhancedRecipe enhancedRecipe) throws SQLException {
+ String sql = "DELETE FROM recipes WHERE id = ?;";
+ this.deleteAllIngredients(connection, enhancedRecipe);
+ this.removeAllowedWorld(connection, enhancedRecipe.getKey(), enhancedRecipe.getAllowedWorlds().toArray(new String[0]));
+ this.removeFurnaceData(connection, enhancedRecipe);
+
+ try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
+ pstmt.setString(1, enhancedRecipe.getKey());
+ int rowsAffected = this.updateSQL(pstmt);
+ if (rowsAffected > 0) {
+ Send("Recipe '" + enhancedRecipe.getKey() + "' deleted successfully.");
+ } else {
+ Send("Recipe '" + enhancedRecipe.getKey() + "' not found.");
+ }
+ }
+ }
+
+ private void removeFurnaceData(final Connection connection, final EnhancedRecipe enhancedRecipe) throws SQLException {
+ if (!(enhancedRecipe instanceof FurnaceRecipe)) return;
+
+ try (PreparedStatement pstmt = connection.prepareStatement(DELETE_FURNACE_DATA_SQL)) {
+ pstmt.setString(1, enhancedRecipe.getKey());
+ int rowsAffected = this.updateSQL(pstmt);
+ }
+ }
+
+
+ private void removeAllowedWorld(Connection connection, String recipeId, String... worlds) throws SQLException {
+ if (worlds == null || worlds.length == 0) return;
+ boolean batchMode = worlds.length > 1;
+
+ try (PreparedStatement pstmt = connection.prepareStatement(DELETE_WORLD_SQL)) {
+ for (String world : worlds) {
+ pstmt.setString(1, recipeId);
+ pstmt.setString(2, world);
+ if (batchMode) {
+ pstmt.addBatch();
+ } else {
+ int rowsAffected = pstmt.executeUpdate();
+ }
+ }
+ if (batchMode) {
+ int[] rowsAffected = pstmt.executeBatch();
+ }
+ }
+ }
+
+ private void deleteIngredient(Connection conn, String recipeId, Integer... slots) throws SQLException {
+ if (slots == null || slots.length == 0) return;
+
+ String sql = "DELETE FROM items WHERE recipe_id = ? AND slot = ?;";
+ boolean batchMode = slots.length > 1;
+
+ try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
+ for (int slot : slots) {
+ pstmt.setString(1, recipeId);
+ pstmt.setInt(2, slot);
+
+ if (batchMode) {
+ pstmt.addBatch(); // Add to batch
+ } else {
+ int rowsAffected = pstmt.executeUpdate(); // Execute immediately if not in batch mode
+ logDeletionResult(recipeId, rowsAffected);
+ }
+ }
+ if (batchMode) {
+ int[] results = pstmt.executeBatch();
+ for (int rowsAffected : results) {
+ logDeletionResult(recipeId, rowsAffected);
+ }
+ }
+ }
+ }
+
+ // Example usage
+
+ private String getItemKey(final ItemStack item) {
+ if (item == null) return null;
+ String base = item.getItemMeta() != null && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : item.getType().name();
+ base = base.replaceAll("\\.", "_");
+ return base;
+ }
+
+ public void saveRecipe(Connection connection, EnhancedRecipe recipe) {
+
+ try (PreparedStatement selectRecipeStmt = connection.prepareStatement(SELECT_RECIPE_SQL)) {
+
+ final String recipeName = recipe.getKey();
+ selectRecipeStmt.setString(1, recipeName);
+
+ try (ResultSet recipeResultSet = selectRecipeStmt.executeQuery()) {
+ if (recipeResultSet.next()) {
+ updateRecipe(connection, recipe, recipeResultSet);
+ } else {
+ insertRecipe(connection, recipe, RecipeIngredientType.RESULT);
+ }
+ insertOrUpdateItem(connection, ingredients -> {
+ ingredients.setSlot(recipe.getResultSlot());
+ ingredients.setRecipeName(recipe.getKey());
+ final ItemStack result = recipe.getResult();
+ ingredients.setItemData(serializeItemStack(new ItemStack[]{result}));
+ ingredients.setItemName(this.getItemKey(result));
+ ingredients.setRecipeType(RecipeIngredientType.RESULT);
+ });
+ }
+ this.updateFurnaces(connection, recipe);
+
+ ItemStack[] itemStacks = recipe.getContent();
+ for (int i = 0; i < itemStacks.length; i++) {
+ ItemStack item = itemStacks[i];
+ String itemName = getItemKey(item);
+ final int slot = i;
+ insertOrUpdateItem(connection, ingredients -> {
+ ingredients.setSlot(slot);
+ ingredients.setItemData(serializeItemStack(new ItemStack[]{item}));
+ ingredients.setRecipeName(recipeName);
+ ingredients.setItemName(itemName);
+ });
+ }
+ this.insertAllowedWorlds(connection, recipeName, recipe.getAllowedWorlds());
+ } catch (SQLException e) {
+ try {
+ connection.rollback();
+ } catch (SQLException rollbackEx) {
+ Debug.error("Could not rollback changes to the database", rollbackEx);
+ }
+ Debug.error("Failed to save this recipe " + recipe.getKey() + ". It will now rollback all changes made", e);
+ }
+ }
+
+ private void updateRecipe(final Connection connection, final EnhancedRecipe recipe, final ResultSet recipeResultSet) throws SQLException {
+
+ String resultItemType = recipeResultSet.getString("result_item_type");
+
+ try (PreparedStatement pstmt = connection.prepareStatement(UPDATE_RECIPE_SQL)) {
+ pstmt.setInt(1, recipe.getPage());
+ pstmt.setString(2, recipe.getType().name());
+ pstmt.setInt(3, recipe.getSlot());
+ pstmt.setInt(4, recipe.getResultSlot());
+ pstmt.setString(5, recipe.getRecipeCategory());
+ pstmt.setString(6, recipe.getPermission());
+ pstmt.setString(7, String.valueOf(recipe.getMatchType()));
+ pstmt.setBoolean(8, recipe.isHidden());
+ pstmt.setBoolean(9, recipe.isCheckPartialMatch());
+ pstmt.setString(10, recipe.getOnCraftCommand());
+ pstmt.setString(11, resultItemType);
+
+ boolean isShapeless = (recipe instanceof WBRecipe) && ((WBRecipe) recipe).isShapeless();
+ pstmt.setBoolean(12, isShapeless);
+
+ pstmt.setString(13, recipeResultSet.getString("id"));
+ updateSQL(pstmt);
+ }
+ }
+
+ private void deleteAllIngredients(final Connection connection, final EnhancedRecipe enhancedRecipe) throws SQLException {
+ int resultSlot = enhancedRecipe.getResultSlot();
+ List slots = new ArrayList<>();
+ slots.add(resultSlot);
+ slots.addAll(getAllIngredientSlots(enhancedRecipe));
+ this.deleteIngredient(connection, enhancedRecipe.getKey(), slots.toArray(new Integer[0]));
+ }
+
+ public void insertOrUpdateItem(Connection conn, Consumer callback) {
+ if (callback == null) return;
+
+ IngredientWrapper ingredientWrapper = new IngredientWrapper();
+ callback.accept(ingredientWrapper);
+ final int slot = ingredientWrapper.getSlot();
+ final String recipeName = ingredientWrapper.getRecipeName();
+ final String itemName = ingredientWrapper.getItemName();
+ byte[] nbtData = ingredientWrapper.getItemData();
+ RecipeIngredientType recipeIngredientType = ingredientWrapper.getRecipeType();
+
+
+ if (itemName == null || nbtData == null) return;
+
+ try (PreparedStatement checkStmt = conn.prepareStatement(CHECK_ITEM_EXISTENCE_SQL)) {
+ checkStmt.setString(1, recipeName);
+ checkStmt.setInt(2, slot);
+ ResultSet rs = checkStmt.executeQuery();
+
+ if (rs.next()) {
+ try (PreparedStatement updateStmt = conn.prepareStatement(UPDATE_ITEM_SQL)) {
+ updateStmt.setBytes(1, nbtData);
+ updateStmt.setString(2, recipeName);
+ updateStmt.setInt(3, slot);
+ updateSQL(updateStmt);
+ rs.getInt(1);
+ }
+ } else {
+ try (PreparedStatement insertStmt = conn.prepareStatement(INSERT_ITEM_SQL, Statement.RETURN_GENERATED_KEYS)) {
+ insertStmt.setString(1, recipeName);
+ insertStmt.setInt(2, slot);
+ insertStmt.setString(3, itemName);
+ insertStmt.setBytes(4, nbtData);
+ insertStmt.setString(5, recipeIngredientType.name());
+ updateSQL(insertStmt);
+
+ ResultSet insertRs = insertStmt.getGeneratedKeys();
+ if (insertRs.next()) {
+ insertRs.getInt(1);
+ }
+ }
+ }
+ } catch (SQLException e) {
+ Debug.error("Failed to insert or update the itemstack", e);
+ }
+ }
+
+ private void logDeletionResult(String recipeId, int rowsAffected) {
+ if (rowsAffected > 0) {
+ Send("Ingredient removed from recipe " + recipeId);
+ } else {
+ Send("Ingredient not found in recipe " + recipeId);
+ }
+ }
+
+ private int getSlotIngredient(final EnhancedRecipe recipe, final ItemStack itemStack, int slot) {
+ final ItemStack[] content = recipe.getContent();
+ for (int i = 0; i < content.length; i++) {
+ ItemStack item = content[i];
+ if (itemStack.isSimilar(item)) {
+ slot = i;
+ break;
+ }
+ }
+ return slot;
+ }
+
+ private List getAllIngredientSlots(final EnhancedRecipe recipe) {
+ List slots = new ArrayList<>();
+ final ItemStack[] content = recipe.getContent();
+ for (int i = 0; i < content.length; i++) {
+ ItemStack item = content[i];
+ if (item != null) {
+ slots.add(i);
+ }
+ }
+ return slots;
+ }
+
+ @Nonnull
+ public byte[] serializeItemStack(final ItemStack[] itemStacks) {
+ return RegisterNbtAPI.serializeItemStack(itemStacks);
+ }
+
+ @Nullable
+ public ItemStack[] deserializeItemStack(final byte[] itemStacks) {
+ return RegisterNbtAPI.deserializeItemStack(itemStacks);
+ }
+
+}
diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeIngredientType.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeIngredientType.java
new file mode 100644
index 0000000..c74d54a
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeIngredientType.java
@@ -0,0 +1,23 @@
+package com.dutchjelly.craftenhance.database;
+
+public enum RecipeIngredientType {
+
+ RESULT,
+ INGREDIENT;
+
+
+ public static RecipeIngredientType getType(String type) {
+ if (type == null) return INGREDIENT;
+
+ RecipeIngredientType[] recipeIngredientTypes = values();
+ String typeUp = type.toUpperCase();
+
+ for (RecipeIngredientType recipeIngredientType : recipeIngredientTypes) {
+ if (recipeIngredientType.name().equals(typeUp)) {
+ return recipeIngredientType;
+ }
+ }
+
+ return INGREDIENT;
+ }
+}
diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java
new file mode 100644
index 0000000..c935e41
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java
@@ -0,0 +1,60 @@
+package com.dutchjelly.craftenhance.database;
+
+public interface RecipeSQLQueries {
+
+ String SELECT_RECIPE_SQL = "SELECT id, recipe_type, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, on_craft_command, result_item_type, shapeless FROM recipes WHERE id = ?";
+ String CHECK_ITEM_EXISTENCE_SQL = "SELECT slot FROM items WHERE recipe_id = ? AND slot = ?;";
+ String SELECT_ITEM_FROM_RECIPE_SLOT_SQL = "SELECT recipe_id, slot FROM items WHERE recipe_id = ? AND slot = ?;";
+ String SELECT_FURNACE_DATA_SQL = "SELECT recipe_id, slot FROM items WHERE recipe_id = ?;";
+ String SELECT_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt, furn.duration, furn.exp " +
+ "FROM recipes r " +
+ "JOIN items i ON r.result_item_type = i.type AND r.id = i.recipe_id " +
+ "JOIN furnace_data furn ON r.id = furn.recipe_id" +
+ "WHERE r.id = ?;";
+
+ String SELECT_ALL_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt, furn.duration, furn.exp " +
+ "FROM recipes r " +
+ "JOIN items i ON r.result_item_type = i.type AND r.id = i.recipe_id" +
+ "JOIN furnace_data furn ON r.id = furn.recipe_id" +
+ ";";
+ String SELECT_INGREDIENTS_SQL = "SELECT i.item_nbt, i.slot " +
+ "FROM items i " +
+ "WHERE i.recipe_id = ? " +
+ "AND i.slot BETWEEN 0 AND 8 " +
+ "AND i.type = ? " +
+ "ORDER BY i.slot;";
+ String SELECT_WORLDS_SQL = "SELECT world FROM allowed_worlds WHERE recipe_id = ?;";
+
+ String UPDATE_FURNACE_DATA_SQL = "UPDATE furnace_data SET duration = ?, exp = ? WHERE recipe_id = ?;";
+ String UPDATE_ITEM_SQL = "UPDATE items SET item_nbt = ? WHERE recipe_id = ? and slot = ?;";
+
+ String UPDATE_RECIPE_SQL = "UPDATE recipes " +
+ "SET page = ?, " +
+ " recipe_type = ?, " +
+ " slot = ?, " +
+ " result_slot = ?, " +
+ " category = ?, " +
+ " permission = ?, " +
+ " matchtype = ?, " +
+ " hidden = ?, " +
+ " check_partial_match = ?, " +
+ " on_craft_command = ?, " +
+ " result_item_type = ?, " +
+ " shapeless = ? " +
+ "WHERE id = ?;";
+ String UPDATE_WORLDS_SQL = "UPDATE allowed_worlds SET world = ? WHERE recipe_id = ? AND world = ?";
+
+ String INSERT_RECIPES_SQL = "INSERT INTO recipes " +
+ "(id, recipe_type, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, on_craft_command, result_item_type, shapeless) " +
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+ String INSERT_OR_REPLACE_WORLDS_SQL = "INSERT INTO allowed_worlds (recipe_id, world) VALUES (?, ?) " +
+ "ON CONFLICT(recipe_id, world) DO UPDATE SET world = excluded.world;";
+
+ String INSERT_WORLDS_SQL = "INSERT INTO allowed_worlds (recipe_id, world) VALUES (?, ?);";
+ String INSERT_ITEM_SQL = "INSERT INTO items (recipe_id, slot, name, item_nbt, type) VALUES (?, ?, ?, ?, ?);";
+
+ String INSERT_FURNACE_DATA_SQL = "INSERT INTO furnace_data (recipe_id, duration, exp) VALUES (?, ?, ?);";
+ String DELETE_FURNACE_DATA_SQL = "DELETE FROM furnace_data WHERE recipe_id = ?;";
+
+ String DELETE_WORLD_SQL = "DELETE FROM allowed_worlds WHERE recipe_id = ? AND world = ?;";
+}
\ No newline at end of file
diff --git a/src/main/java/com/dutchjelly/craftenhance/files/CategoryData.java b/src/main/java/com/dutchjelly/craftenhance/files/CategoryData.java
index e637142..6f2b6ea 100644
--- a/src/main/java/com/dutchjelly/craftenhance/files/CategoryData.java
+++ b/src/main/java/com/dutchjelly/craftenhance/files/CategoryData.java
@@ -50,10 +50,10 @@ public ItemStack getRecipeCategoryItem() {
public List getEnhancedRecipes() {
return enhancedRecipes;
}
- public List getEnhancedRecipes(final String recipeSeachFor) {
- if (recipeSeachFor == null || recipeSeachFor.equals(""))
+ public List getEnhancedRecipes(final String recipeSearchFor) {
+ if (recipeSearchFor == null || recipeSearchFor.equals(""))
return enhancedRecipes;
- return enhancedRecipes.stream().filter(x -> x.getKey().contains(recipeSeachFor)).collect(Collectors.toList());
+ return enhancedRecipes.stream().filter(x -> x.getKey().contains(recipeSearchFor)).collect(Collectors.toList());
}
public void addEnhancedRecipes(final EnhancedRecipe enhancedRecipes) {
this.enhancedRecipes.add(enhancedRecipes);
diff --git a/src/main/java/com/dutchjelly/craftenhance/files/FileManager.java b/src/main/java/com/dutchjelly/craftenhance/files/FileManager.java
index 9971827..225e5a5 100644
--- a/src/main/java/com/dutchjelly/craftenhance/files/FileManager.java
+++ b/src/main/java/com/dutchjelly/craftenhance/files/FileManager.java
@@ -1,5 +1,6 @@
package com.dutchjelly.craftenhance.files;
+import com.dutchjelly.craftenhance.cache.CacheRecipes;
import com.dutchjelly.craftenhance.CraftEnhance;
import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
import com.dutchjelly.craftenhance.messaging.Debug;
@@ -49,6 +50,7 @@ public class FileManager {
private Map items;
private List recipes;
+ private CacheRecipes cacheRecipes;
private FileManager(final boolean useJson) {
this.useJson = useJson;
@@ -60,10 +62,11 @@ public static FileManager init(final CraftEnhance main) {
fm.items = new HashMap<>();
fm.recipes = new ArrayList<>();
fm.logger = main.getLogger();
+ fm.cacheRecipes = main.getCacheRecipes();
fm.dataFolder = main.getDataFolder();
fm.dataFolder.mkdir();
- fm.itemsFile = fm.getFile(fm.useJson ? "items.json" : "items.yml");
- fm.recipesFile = fm.getFile("recipes.yml");
+ fm.itemsFile = new File(fm.dataFolder, fm.useJson ? "items.json" : "items.yml");
+ fm.recipesFile = new File(fm.dataFolder,"recipes.yml");
fm.serverRecipeFile = fm.getFile("server-recipes.yml");
fm.containerOwnerFile = fm.getFile("container-owners.yml");
return fm;
@@ -126,6 +129,9 @@ private FileConfiguration getYamlConfig(final File file) {
public void cacheRecipes() {
Debug.Send("The file manager is caching recipes...");
EnhancedRecipe keyValue;
+ if(!recipesFile.exists())
+ return;
+
recipesConfig = getYamlConfig(recipesFile);
recipes.clear();
for (final String key : recipesConfig.getKeys(false)) {
@@ -138,12 +144,18 @@ public void cacheRecipes() {
continue;
}
keyValue.setKey(key);
- recipes.add(keyValue);
+ cacheRecipes.add(keyValue);
+ //recipes.add(keyValue);
}
+
+ cacheRecipes.save();
+ this.recipesFile.renameTo(new File(dataFolder, "recipe_copy.yml"));
}
@SneakyThrows
public void cacheItems() {
+ if(!itemsFile.exists())
+ return;
if (useJson) {
@@ -159,17 +171,19 @@ public void cacheItems() {
final Map> serialized = gson.fromJson(json.toString(), typeToken);
if (serialized != null)
serialized.keySet().forEach(x -> items.put(x, ItemStack.deserialize(serialized.get(x))));
- return;
+ } else {
+ if (itemsConfig == null)
+ itemsConfig = new YamlConfiguration();
+ itemsConfig.load(itemsFile);
+ //itemsConfig = getYamlConfig(itemsFile);
+ items.clear();
+ if (itemsConfig != null)
+ for (final String key : itemsConfig.getKeys(false)) {
+ items.put(key, itemsConfig.getItemStack(key));
+ }
}
- if (itemsConfig == null)
- itemsConfig = new YamlConfiguration();
- itemsConfig.load(itemsFile);
- //itemsConfig = getYamlConfig(itemsFile);
- items.clear();
- if (itemsConfig != null)
- for (final String key : itemsConfig.getKeys(false)) {
- items.put(key, itemsConfig.getItemStack(key));
- }
+
+ this.itemsFile.renameTo(new File(dataFolder, useJson ? "items-copy.json" : "items-copy.yml"));
}
public Map getItems() {
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/CategoryList.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/CategoryList.java
index 9839006..ebe8e4a 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/CategoryList.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/CategoryList.java
@@ -96,7 +96,7 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe
return true;
}
if (value.isActionTypeEqual(ButtonType.Back.name())) {
- new RecipeSettings<>(this.recipe, this.categoryData, null, editorType)
+ new RecipeSettings<>(this.recipe,0 ,this.categoryData, null, editorType)
.menuOpen(player);
//new RecipeEditor<>(this.recipe, this.categoryData, null, editorType).menuOpen(player);
}
@@ -144,7 +144,7 @@ public FillMenuButton createFillMenuButton() {
return ButtonUpdateAction.NONE;
}
}
- new RecipeSettings<>(recipe, categoryData, null, editorType).menuOpen(player);
+ new RecipeSettings<>(recipe, 0,categoryData, null, editorType).menuOpen(player);
}
return ButtonUpdateAction.NONE;
}, (slot, containerData) -> {
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java
index 3977ee2..1b25f87 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java
@@ -47,11 +47,11 @@ public EditorTypeSelector(final String recipeKey, final String permission) {
}
private String getFreshKey(String keySeed) {
- if (keySeed == null || !self().getFm().isUniqueRecipeKey(keySeed)) {
+ if (keySeed == null || !self().getCacheRecipes().isUniqueRecipeKey(keySeed)) {
int uniqueKeyIndex = 1;
keySeed = "recipe";
- while (!self().getFm().isUniqueRecipeKey(keySeed + uniqueKeyIndex)) uniqueKeyIndex++;
+ while (!self().getCacheRecipes().isUniqueRecipeKey(keySeed + uniqueKeyIndex)) uniqueKeyIndex++;
keySeed += uniqueKeyIndex;
}
return keySeed;
@@ -87,7 +87,7 @@ public void run(final MenuButtonData value, final Player player) {
if (value.isActionTypeEqual( ButtonType.ChooseWorkbenchType.name())){
EnhancedRecipe newRecipe = new WBRecipe(permission, null, new ItemStack[9]);
newRecipe.setKey(getFreshKey(recipeKey));
- final RecipeEditor recipeEditor = new RecipeEditor<>(newRecipe, null,permission,
+ final RecipeEditor recipeEditor = new RecipeEditor<>(newRecipe,0, null,permission,
value.isActionTypeEqual(ButtonType.ChooseFurnaceType.name()) ? ButtonType.ChooseFurnaceType: ButtonType.ChooseWorkbenchType);
recipeEditor.menuOpen(player);
return;
@@ -95,19 +95,19 @@ public void run(final MenuButtonData value, final Player player) {
if (value.isActionTypeEqual( ButtonType.ChooseFurnaceType.name())){
FurnaceRecipe furnaceRecipe = new FurnaceRecipe(permission, null, new ItemStack[1]);
furnaceRecipe.setKey(getFreshKey(recipeKey));
- new RecipeEditorFurnace(furnaceRecipe,null,permission,ButtonType.ChooseFurnaceType,true).menuOpen(player);
+ new RecipeEditorFurnace(furnaceRecipe,0,null,permission,ButtonType.ChooseFurnaceType,true).menuOpen(player);
return;
}
if (value.isActionTypeEqual( ButtonType.ChooseBlastType.name())){
BlastRecipe blastRecipe = new BlastRecipe(permission, null, new ItemStack[1]);
blastRecipe.setKey(getFreshKey(recipeKey));
- new RecipeEditorBlast(blastRecipe,null,permission,ButtonType.ChooseBlastType,true).menuOpen(player);
+ new RecipeEditorBlast(blastRecipe,0,null,permission,ButtonType.ChooseBlastType,true).menuOpen(player);
return;
}
if (value.isActionTypeEqual( ButtonType.ChooseSmokerType.name())){
SmokerRecipe blastRecipe = new SmokerRecipe(permission, null, new ItemStack[1]);
blastRecipe.setKey(getFreshKey(recipeKey));
- new RecipeEditorSmoker(blastRecipe,null,permission,ButtonType.ChooseSmokerType,true).menuOpen(player);
+ new RecipeEditorSmoker(blastRecipe,0,null,permission,ButtonType.ChooseSmokerType,true).menuOpen(player);
}
}
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java
index f6d8a0c..6d7c007 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java
@@ -16,6 +16,7 @@
import com.dutchjelly.craftenhance.gui.util.ButtonType;
import com.dutchjelly.craftenhance.gui.util.GuiUtil;
import com.dutchjelly.craftenhance.prompt.HandleChatInput;
+import com.dutchjelly.craftenhance.util.PaginatedItems;
import com.dutchjelly.craftenhance.util.PermissionTypes;
import org.broken.arrow.menu.button.manager.library.utility.MenuButtonData;
import org.broken.arrow.menu.button.manager.library.utility.MenuTemplate;
@@ -33,15 +34,15 @@
import java.util.Map.Entry;
import static com.dutchjelly.craftenhance.CraftEnhance.self;
-import static com.dutchjelly.craftenhance.gui.util.FormatListContents.canSeeRecipes;
public class RecipesViewer extends MenuHolderPage {
private final MenuSettingsCache menuSettingsCache = self().getMenuSettingsCache();
private final MenuTemplate menuTemplate;
private final CategoryData categoryData;
- public RecipesViewer(final CategoryData categoryData, final String recipeSeachFor, final Player player) {
- super(canSeeRecipes(categoryData.getEnhancedRecipes(recipeSeachFor), player));
+ public RecipesViewer(final CategoryData categoryData, final String recipeSearchFor, final Player player) {
+ //super(canSeeRecipes(categoryData.getEnhancedRecipes(recipeSearchFor), player));
+ super(new PaginatedItems(categoryData,self().getMenuSettingsCache().getTemplate("RecipesViewer")).retrieveList(player,recipeSearchFor) );
this.menuTemplate = menuSettingsCache.getTemplate("RecipesViewer");
this.categoryData = categoryData;
setFillSpace(this.menuTemplate.getFillSlots());
@@ -127,26 +128,26 @@ public FillMenuButton createFillMenuButton() {
if (enhancedRecipe instanceof WBRecipe) {
if (allowClick)
- new RecipeEditor<>((WBRecipe) enhancedRecipe, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
- else new RecipeViewRecipe<>(categoryData, (WBRecipe) enhancedRecipe, "WBRecipeViewer").menuOpen(player);
+ new RecipeEditor<>((WBRecipe) enhancedRecipe,this.getPageNumber(), categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
+ else new RecipeViewRecipe<>(categoryData, this.getPageNumber(),(WBRecipe) enhancedRecipe, "WBRecipeViewer").menuOpen(player);
}
if (enhancedRecipe instanceof FurnaceRecipe) {
if (allowClick)
- new RecipeEditorFurnace((FurnaceRecipe) enhancedRecipe, categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
+ new RecipeEditorFurnace((FurnaceRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
else
- new RecipeViewRecipe<>(categoryData, (FurnaceRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
+ new RecipeViewRecipe<>(categoryData, this.getPageNumber(),(FurnaceRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
}
if (enhancedRecipe instanceof BlastRecipe) {
if (allowClick)
- new RecipeEditorBlast((BlastRecipe) enhancedRecipe, categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
+ new RecipeEditorBlast((BlastRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
else
- new RecipeViewRecipe<>(categoryData, (BlastRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
+ new RecipeViewRecipe<>(categoryData,this.getPageNumber(), (BlastRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
}
if (enhancedRecipe instanceof SmokerRecipe) {
if (allowClick)
- new RecipeEditorSmoker((SmokerRecipe) enhancedRecipe, categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
+ new RecipeEditorSmoker((SmokerRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
else
- new RecipeViewRecipe<>(categoryData, (SmokerRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
+ new RecipeViewRecipe<>(categoryData, this.getPageNumber(),(SmokerRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player);
}
return ButtonUpdateAction.NONE;
}, (slot, enhancedRecipe) -> {
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditor.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditor.java
index e760d1d..22124b7 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditor.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditor.java
@@ -49,6 +49,7 @@ public class RecipeEditor extends MenuHolderPage
private final MenuSettingsCache menuSettingsCache = self().getMenuSettingsCache();
private final IngredientsCache ingredientsCache;
private final boolean checkPartialMatch;
+ private final int page;
private String permission;
@Getter
private final RecipeT recipe;
@@ -62,12 +63,13 @@ public class RecipeEditor extends MenuHolderPage
private final ButtonType editorType;
private final CategoryData categoryData;
- public RecipeEditor(final RecipeT recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
- this(recipe, categoryData, permission, editorType, true);
+ public RecipeEditor(final RecipeT recipe, final int page, final CategoryData categoryData, final String permission, final ButtonType editorType) {
+ this(recipe, page, categoryData, permission, editorType, true);
}
- public RecipeEditor(final RecipeT recipe, final CategoryData categoryData, final String permission, final ButtonType editorType, final boolean clearItems) {
+ public RecipeEditor(final RecipeT recipe, final int page, final CategoryData categoryData, final String permission, final ButtonType editorType, final boolean clearItems) {
super(formatRecipes(recipe, self().getIngredientsCache(), !clearItems));
+ this.page = page;
if (permission == null || permission.equals(""))
this.permission = recipe.getPermission();
else this.permission = permission;
@@ -142,17 +144,21 @@ public ItemStack getItem() {
public boolean run(final MenuButtonData value, final Inventory menu, final Player player, final ClickType click) {
if (value.isActionTypeEqual(ButtonType.DeleteRecipe.name())) {
- self().getFm().removeRecipe(recipe);
+ self().getCacheRecipes().remove(recipe);
RecipeLoader.getInstance().unloadRecipe(recipe);
- if (this.categoryData != null)
- new RecipesViewer(this.categoryData, "", player).menuOpen(player);
+ if (this.categoryData != null) {
+ final RecipesViewer recipesViewer = new RecipesViewer(this.categoryData, "", player);
+ recipesViewer.menuOpen(player);
+ if ( this.page > 0)
+ recipesViewer.setPage( this.page);
+ }
else
new EditorTypeSelector(null, permission).menuOpen(player);
return true;
}
if (value.isActionTypeEqual(ButtonType.RecipeSettings.name())) {
if (recipe instanceof WBRecipe)
- new RecipeSettings<>(this.recipe, this.categoryData, this.permission, this.editorType)
+ new RecipeSettings<>(this.recipe, this.page, this.categoryData, this.permission, this.editorType)
.menuOpen(player);
}
@@ -168,22 +174,25 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe
final Map map = checkItemsInsideInventory.getItemsFromSetSlots(menu, player, false);
save(map, player, true);
if (this.recipe instanceof WBRecipe) {
- new RecipeEditor<>((WBRecipe) this.recipe, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
+ new RecipeEditor<>((WBRecipe) this.recipe, this.page, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
}
if (this.recipe instanceof FurnaceRecipe) {
- new RecipeEditorFurnace((FurnaceRecipe) this.recipe, categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
+ new RecipeEditorFurnace((FurnaceRecipe) this.recipe, this.page,categoryData, null, ButtonType.ChooseFurnaceType, false).menuOpen(player);
}
if (this.recipe instanceof BlastRecipe) {
- new RecipeEditorBlast((BlastRecipe) this.recipe, categoryData, null, ButtonType.ChooseBlastType,false).menuOpen(player);
+ new RecipeEditorBlast((BlastRecipe) this.recipe, this.page,categoryData, null, ButtonType.ChooseBlastType, false).menuOpen(player);
}
if (this.recipe instanceof SmokerRecipe) {
- new RecipeEditorSmoker((SmokerRecipe) this.recipe, categoryData, null, ButtonType.ChooseSmokerType,false).menuOpen(player);
+ new RecipeEditorSmoker((SmokerRecipe) this.recipe, this.page,categoryData, null, ButtonType.ChooseSmokerType, false).menuOpen(player);
}
}
if (value.isActionTypeEqual(ButtonType.Back.name())) {
- if (this.categoryData != null)
- new RecipesViewer(this.categoryData, "", player).menuOpen(player);
- else
+ if (this.categoryData != null) {
+ final RecipesViewer recipesViewer = new RecipesViewer(this.categoryData, "", player);
+ recipesViewer.menuOpen(player);
+ if ( this.page > 0)
+ recipesViewer.setPage( this.page);
+ } else
new EditorTypeSelector(null, permission).menuOpen(player);
}
return onPlayerClick(this.recipe, this.categoryData, this.permission, value.getActionType(), player);
@@ -261,9 +270,9 @@ protected boolean onPlayerClick(final RecipeT recipe, final CategoryData categor
@Nullable
private ItemStack[] getIngredients(final Map map, final Player player) {
-
- final int resultSlot = this.menuTemplate.getFillSlots().get(recipe.getContent().length);
- final List arrays = new ArrayList<>(recipe.getContent().length);
+ List fillSlots = this.menuTemplate.getFillSlots();
+ final int resultSlot = fillSlots != null && fillSlots.size() > recipe.getContent().length ? this.menuTemplate.getFillSlots().get(recipe.getContent().length) : fillSlots.size();
+ final List stackList = new ArrayList<>(recipe.getContent().length);
int index = 0;
for (final Integer slot : this.menuTemplate.getFillSlots()) {
final ItemStack itemStack = map.get(slot);
@@ -271,8 +280,10 @@ private ItemStack[] getIngredients(final Map map, final Play
Messenger.Message("Recipes only support amounts of 1 in the content.", player);
itemStack.setAmount(1);
}
+ if(index > stackList.size())
+ break;
if (slot != resultSlot)
- arrays.add(index, itemStack);
+ stackList.add(index, itemStack);
if (slot == resultSlot)
this.recipe.setResultSlot(index);
index++;
@@ -280,12 +291,12 @@ private ItemStack[] getIngredients(final Map map, final Play
}
this.result = map.remove(resultSlot);
- if (!arrays.stream().anyMatch(x -> x != null)) {
+ if (!stackList.stream().anyMatch(x -> x != null)) {
return null;
}
if (recipe instanceof FurnaceRecipe)
- return arrays.toArray(new ItemStack[1]);
- final ItemStack[] itemstacks = arrays.toArray(new ItemStack[0]);
+ return stackList.toArray(new ItemStack[1]);
+ final ItemStack[] itemstacks = stackList.toArray(new ItemStack[0]);
/* for (final ItemStack lastItem : itemstacks){
if (lastItem != null)
lastItemIndex++;
@@ -302,42 +313,6 @@ private ItemStack[] getIngredients(final Map map, final Play
return itemstacks;
}
- public boolean handlePositionChange(final String message) {
- if (message == null || message.trim() == "") return false;
-
- if (message.equals("") || message.equalsIgnoreCase("q") || message.equalsIgnoreCase("cancel") || message.equalsIgnoreCase("quit") || message.equalsIgnoreCase("exit"))
- return false;
-
- final String[] args = message.split(" ");
-
- if (args.length != 2) {
- Messenger.Message("Please specify a page and slot number separated by a space.", getViewer());
- return true;
- }
- int page = 0, slot = 0;
- try {
- page = Integer.parseInt(args[0]);
- } catch (final NumberFormatException e) {
- Messenger.Message("Could not parse the page number.", getViewer());
- return true;
- }
-
- try {
- slot = Integer.parseInt(args[1]);
- } catch (final NumberFormatException e) {
- Messenger.Message("Could not parse the slot number.", getViewer());
- return true;
- }
- recipe.setPage(page);
- recipe.setSlot(slot);
-
- Messenger.Message("Set the page to " + page + ", and the slot to " + slot + ". This will get auto-filled if it's not available.", getViewer());
- self().getFm().saveRecipe(recipe);
-
- //updatePlaceHolders();
- return false;
- }
-
private Map getPlaceholders() {
final Map placeHolders = new HashMap() {{
put(InfoItemPlaceHolders.Key.getPlaceHolder(), recipe.getKey() == null ? "null" : recipe.getKey());
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorBlast.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorBlast.java
index 8b27efc..df27e9f 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorBlast.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorBlast.java
@@ -12,8 +12,8 @@
public class RecipeEditorBlast extends RecipeEditor {
- public RecipeEditorBlast(final BlastRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType,boolean clearItems) {
- super(recipe, categoryData, permission, editorType,clearItems);
+ public RecipeEditorBlast(final BlastRecipe recipe,final int page,final CategoryData categoryData, final String permission, final ButtonType editorType, boolean clearItems) {
+ super(recipe, page, categoryData, permission, editorType, clearItems);
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorFurnace.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorFurnace.java
index 4b6e30d..aaa439f 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorFurnace.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorFurnace.java
@@ -13,12 +13,12 @@
public class RecipeEditorFurnace extends RecipeEditor {
- public RecipeEditorFurnace(final FurnaceRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
- super(recipe, categoryData, permission, editorType, true);
+ public RecipeEditorFurnace(final FurnaceRecipe recipe,final int page, final CategoryData categoryData, final String permission, final ButtonType editorType) {
+ super(recipe, page,categoryData, permission, editorType, true);
}
- public RecipeEditorFurnace(final FurnaceRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType,boolean clearItems) {
- super(recipe, categoryData, permission, editorType, clearItems);
+ public RecipeEditorFurnace(final FurnaceRecipe recipe,final int page, final CategoryData categoryData, final String permission, final ButtonType editorType,boolean clearItems) {
+ super(recipe, page,categoryData, permission, editorType, clearItems);
}
@Override
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorSmoker.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorSmoker.java
index 25f7eb2..7ed7374 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorSmoker.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/editors/RecipeEditorSmoker.java
@@ -12,8 +12,8 @@
public class RecipeEditorSmoker extends RecipeEditor {
- public RecipeEditorSmoker(final SmokerRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType,boolean clearItems) {
- super(recipe, categoryData, permission, editorType, clearItems);
+ public RecipeEditorSmoker(final SmokerRecipe recipe,final int page, final CategoryData categoryData, final String permission, final ButtonType editorType,boolean clearItems) {
+ super(recipe, page,categoryData, permission, editorType, clearItems);
}
@Override
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettings.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettings.java
index 2371160..1c7f728 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettings.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettings.java
@@ -45,6 +45,7 @@
public class RecipeSettings extends MenuHolder {
private final MenuSettingsCache menuSettingsCache = self().getMenuSettingsCache();
+ protected final int page;
private String permission;
private final MenuTemplate menuTemplate;
@Getter
@@ -53,7 +54,8 @@ public class RecipeSettings extends MenuHolder {
private final ButtonType editorType;
private final CategoryData categoryData;
- public RecipeSettings(final RecipeT recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
+ public RecipeSettings(final RecipeT recipe, int pageNumber, final CategoryData categoryData, final String permission, final ButtonType editorType) {
+ page = pageNumber;
if (permission == null || permission.equals("")) this.permission = recipe.getPermission();
else this.permission = permission;
this.editorType = editorType;
@@ -72,7 +74,7 @@ public RecipeSettings(final RecipeT recipe, final CategoryData categoryData, fin
if (menuTemplate != null) {
setMenuSize(GuiUtil.invSize("RecipeSettings", this.menuTemplate.getAmountOfButtons()));
final String title = menuTemplate.getMenuTitle() == null ? "editor" : menuTemplate.getMenuTitle().replace(InfoItemPlaceHolders.Recipe_type.getPlaceHolder(), recipe.getType().name().toLowerCase());
- setTitle(()-> title);
+ setTitle(() -> title);
//setFillSpace(menuTemplate.getFillSlots());
setMenuOpenSound(this.menuTemplate.getSound());
}
@@ -121,12 +123,12 @@ public ItemStack getItem() {
public boolean run(final MenuButtonData value, final Inventory menu, final Player player, final ClickType click) {
if (value.isActionTypeEqual(ButtonType.SetPosition.name())) {
- new HandleChatInput(this, this::handlePositionChange);
+ new HandleChatInput(this, this::handlePositionChange).setMessages("Type specify a page and slot number separated by a space or type q, exit or cancel to close conversion.").start(player);
return true;
}
if (value.isActionTypeEqual(ButtonType.AllowedWorldsCraft.name())) {
if (player.isConversing()) return true;
- if (click.isRightClick() && click.isShiftClick()){
+ if (click.isRightClick() && click.isShiftClick()) {
recipe.getAllowedWorlds().clear();
return true;
}
@@ -194,9 +196,9 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe
}
if (value.isActionTypeEqual(ButtonType.Back.name())) {
if (this.recipe instanceof WBRecipe) {
- new RecipeEditor<>((WBRecipe) this.recipe, categoryData, null, ButtonType.ChooseWorkbenchType,false).menuOpen(player);
+ new RecipeEditor<>((WBRecipe) this.recipe, this.page, this.categoryData, null, ButtonType.ChooseWorkbenchType, false).menuOpen(player);
}
- handleBack(this.recipe,categoryData, player);
+ handleBack(this.recipe, categoryData, player);
}
return onPlayerClick(this.recipe, value.getActionType(), player);
}
@@ -268,8 +270,8 @@ public boolean handlePositionChange(final String message) {
}
recipe.setPage(page);
recipe.setSlot(slot);
-
Messenger.Message("Set the page to " + page + ", and the slot to " + slot + ". This will get auto-filled if it's not available.", getViewer());
+ this.runTask(() -> this.menuOpen(player));
return false;
}
@@ -373,6 +375,7 @@ protected void runTask(final Runnable runnable) {
protected boolean onPlayerClick(final RecipeT recipe, final String buttonAction, final Player player) {
return false;
}
+
protected void handleBack(final RecipeT recipe, final CategoryData categoryData, final Player player) {
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsBlast.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsBlast.java
index b0a8c3c..6cc5578 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsBlast.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsBlast.java
@@ -15,7 +15,7 @@
public class RecipeSettingsBlast extends RecipeSettings{
public RecipeSettingsBlast(final BlastRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
- super(recipe, categoryData, permission, editorType);
+ super(recipe, 0,categoryData, permission, editorType);
}
protected boolean onPlayerClick(final BlastRecipe blastRecipe, final String buttonAction, final Player player) {
@@ -73,7 +73,7 @@ protected boolean onPlayerClick(final BlastRecipe blastRecipe, final String butt
@Override
protected void handleBack(final BlastRecipe recipe, final CategoryData categoryData, final Player player) {
- new RecipeEditorBlast(recipe, categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
+ new RecipeEditorBlast(recipe, this.page,categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
}
@Override
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsFurnace.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsFurnace.java
index d52b0de..e93c570 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsFurnace.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsFurnace.java
@@ -15,7 +15,7 @@
public class RecipeSettingsFurnace extends RecipeSettings {
public RecipeSettingsFurnace(final FurnaceRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
- super(recipe, categoryData, permission, editorType);
+ super(recipe, 0, categoryData, permission, editorType);
}
protected boolean onPlayerClick(final FurnaceRecipe furnaceRecipe, final String buttonAction, final Player player) {
@@ -44,7 +44,7 @@ protected boolean onPlayerClick(final FurnaceRecipe furnaceRecipe, final String
}).setMessages("Please input an exp amount.Type q, exit, cancel to turn it off.").start(getViewer());
return true;
}
- if (buttonAction.equalsIgnoreCase( ButtonType.SetCookTime.name())) {
+ if (buttonAction.equalsIgnoreCase(ButtonType.SetCookTime.name())) {
if (player.isConversing()) return true;
new HandleChatInput(this, (msg) -> {
short parsed;
@@ -73,7 +73,7 @@ protected boolean onPlayerClick(final FurnaceRecipe furnaceRecipe, final String
@Override
protected void handleBack(final FurnaceRecipe recipe, final CategoryData categoryData, final Player player) {
- new RecipeEditorFurnace(recipe, categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
+ new RecipeEditorFurnace(recipe, this.page, categoryData, null, ButtonType.ChooseFurnaceType, false).menuOpen(player);
}
@Override
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsSmoker.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsSmoker.java
index 0b5832d..d0e3e5d 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsSmoker.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/settings/RecipeSettingsSmoker.java
@@ -15,7 +15,7 @@
public class RecipeSettingsSmoker extends RecipeSettings{
public RecipeSettingsSmoker(final SmokerRecipe recipe, final CategoryData categoryData, final String permission, final ButtonType editorType) {
- super(recipe, categoryData, permission, editorType);
+ super(recipe, 0,categoryData, permission, editorType);
}
protected boolean onPlayerClick(final SmokerRecipe furnaceRecipe, final String buttonAction, final Player player) {
if (player.isConversing()) return true;
@@ -72,7 +72,7 @@ protected boolean onPlayerClick(final SmokerRecipe furnaceRecipe, final String b
@Override
protected void handleBack(final SmokerRecipe recipe, final CategoryData categoryData, final Player player) {
- new RecipeEditorSmoker(recipe, categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
+ new RecipeEditorSmoker(recipe, this.page,categoryData, null, ButtonType.ChooseFurnaceType,false).menuOpen(player);
}
@Override
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/guis/viewers/RecipeViewRecipe.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/viewers/RecipeViewRecipe.java
index 53f8634..fbdf958 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/viewers/RecipeViewRecipe.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/viewers/RecipeViewRecipe.java
@@ -42,8 +42,9 @@ public class RecipeViewRecipe extends MenuHolder
private final MenuTemplate menuTemplate;
private final CategoryData categoryData;
private final RecipeT recipe;
+ private final int page;
- public RecipeViewRecipe(final CategoryData categoryData, final RecipeT recipe, final String menuType) {
+ public RecipeViewRecipe(final CategoryData categoryData, final int pageNumber, final RecipeT recipe, final String menuType) {
super(formatRecipes(recipe, null, false));
this.recipe = recipe;
this.categoryData = categoryData;
@@ -53,6 +54,7 @@ public RecipeViewRecipe(final CategoryData categoryData, final RecipeT recipe, f
setMenuSize(27);
this.setUseColorConversion(true);
this.setIgnoreItemCheck(true);
+ this.page = pageNumber;
}
@Override
@@ -109,21 +111,24 @@ public ItemStack getItem() {
public boolean run(final MenuButtonData value, final Inventory menu, final Player player, final ClickType click) {
if (value.isActionTypeEqual(ButtonType.Back.name())) {
- new RecipesViewer(categoryData, "", player).menuOpen(player);
+ final RecipesViewer recipesViewer = new RecipesViewer(this.categoryData, "", player);
+ recipesViewer.menuOpen(player);
+ if ( this.page > 0)
+ recipesViewer.setPage( this.page);
}
if (value.isActionTypeEqual(ButtonType.edit_recipe.name())) {
if (player.hasPermission(PermissionTypes.Edit.getPerm())) {
if (recipe instanceof WBRecipe) {
- new RecipeEditor<>((WBRecipe) recipe, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
+ new RecipeEditor<>((WBRecipe) recipe, this.page, categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player);
}
if (recipe instanceof FurnaceRecipe) {
- new RecipeEditorFurnace((FurnaceRecipe) recipe, categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
+ new RecipeEditorFurnace((FurnaceRecipe) recipe, this.page,categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player);
}
if (recipe instanceof BlastRecipe) {
- new RecipeEditorBlast((BlastRecipe) recipe, categoryData, null, ButtonType.ChooseBlastType, true).menuOpen(player);
+ new RecipeEditorBlast((BlastRecipe) recipe, this.page,categoryData, null, ButtonType.ChooseBlastType, true).menuOpen(player);
}
if (recipe instanceof SmokerRecipe) {
- new RecipeEditorSmoker((SmokerRecipe) recipe, categoryData, null, ButtonType.ChooseSmokerType, true).menuOpen(player);
+ new RecipeEditorSmoker((SmokerRecipe) recipe, this.page,categoryData, null, ButtonType.ChooseSmokerType, true).menuOpen(player);
}
}
return false;
diff --git a/src/main/java/com/dutchjelly/craftenhance/gui/util/GuiUtil.java b/src/main/java/com/dutchjelly/craftenhance/gui/util/GuiUtil.java
index cecdfdb..9054bd9 100644
--- a/src/main/java/com/dutchjelly/craftenhance/gui/util/GuiUtil.java
+++ b/src/main/java/com/dutchjelly/craftenhance/gui/util/GuiUtil.java
@@ -183,7 +183,7 @@ public static int invSize(final String menu, final int size) {
if (size <= 36) return 36;
if (size <= 45) return 45;
if (size > 54)
- Messenger.Error("This menu "+ menu + " has set bigger inventory size an it can handle, your set size " + size + ". will defult to 54.");
+ Messenger.Error("This menu "+ menu + " has set bigger inventory size an it can handle, your set size " + size + ". will default to 54.");
return 54;
}
diff --git a/src/main/java/com/dutchjelly/craftenhance/messaging/Debug.java b/src/main/java/com/dutchjelly/craftenhance/messaging/Debug.java
index 52cf656..8e26f7d 100644
--- a/src/main/java/com/dutchjelly/craftenhance/messaging/Debug.java
+++ b/src/main/java/com/dutchjelly/craftenhance/messaging/Debug.java
@@ -3,6 +3,7 @@
import com.dutchjelly.craftenhance.CraftEnhance;
import java.util.function.Supplier;
+import java.util.logging.Level;
import java.util.logging.Logger;
import static com.dutchjelly.craftenhance.messaging.Debug.Type.Crafting;
@@ -59,13 +60,21 @@ public static void Send(final Object sender, final Object obj) {
public static void Send(final Object[] arr) {
if (arr == null) return;
logger.info(prefix + " ");
- for (int i = 0; i < arr.length; i++) {
- if (arr[i] == null) continue;
- logger.info(arr[i].toString());
+ for (final Object o : arr) {
+ if (o == null) continue;
+ logger.info(o.toString());
}
logger.info("");
}
+ public static void error(final String message) {
+ logger.log(Level.WARNING,prefix + message);
+ }
+ public static void error(final String message,Throwable throwable) {
+ logger.log(Level.WARNING,prefix + message,throwable);
+ }
+
+
public enum Type {
Crafting,
Smelting,
diff --git a/src/main/java/com/dutchjelly/craftenhance/prompt/HandleChatInput.java b/src/main/java/com/dutchjelly/craftenhance/prompt/HandleChatInput.java
index d6dc50b..1a58e47 100644
--- a/src/main/java/com/dutchjelly/craftenhance/prompt/HandleChatInput.java
+++ b/src/main/java/com/dutchjelly/craftenhance/prompt/HandleChatInput.java
@@ -52,7 +52,7 @@ protected void onConversationEnd(final SimpleConversation conversation, final Co
}
@Override
- protected ConversationCanceller getCanceller() {
+ protected ConversationCanceller getCanceller() {
return new SimpleCanceller(" ");
}
@@ -77,6 +77,8 @@ protected String getPrompt(final ConversationContext conversationContext) {
Player player = getPlayer();
if (conversationContext.getForWhom() instanceof Player)
player = getPlayer(conversationContext);
+ if (this.messages.isEmpty()) return "No message set for this conversion: " + this.menuHolder.getTitle();
+
final String lastMessage = this.messages.get(this.messages.size() - 1);
for (final String message : this.messages) {
if (message.equals(lastMessage)) break;
diff --git a/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java
new file mode 100644
index 0000000..c28ad36
--- /dev/null
+++ b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java
@@ -0,0 +1,123 @@
+package com.dutchjelly.craftenhance.util;
+
+import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe;
+import com.dutchjelly.craftenhance.files.CategoryData;
+import org.broken.arrow.menu.button.manager.library.utility.MenuTemplate;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.dutchjelly.craftenhance.gui.util.FormatListContents.canSeeRecipes;
+
+public class PaginatedItems {
+
+ private final CategoryData categoryData;
+ private final int slotsPerPage;
+ private final List- itemList = new ArrayList<>();
+ private final List
- needSortItems = new ArrayList<>();
+
+ public PaginatedItems(final CategoryData categoryData, final MenuTemplate menuTemplate) {
+ this.categoryData = categoryData;
+ this.slotsPerPage = menuTemplate.getFillSlots() != null ? menuTemplate.getFillSlots().size() : 0;
+ }
+
+ public List retrieveList(final Player player, final String recipeSearchFor) {
+ List enhancedRecipes = canSeeRecipes(categoryData.getEnhancedRecipes(recipeSearchFor), player);
+ for (EnhancedRecipe recipe : enhancedRecipes) {
+ addItem(new Item(recipe));
+ }
+ for (Item item : needSortItems) {
+ addDuplicates(item);
+ }
+ return itemList.stream()
+ .map(item -> (item != null) ? item.getEnhancedRecipe() : null)
+ .collect(Collectors.toList());
+ }
+
+ private void addDuplicates(final Item item) {
+ int index = (item.page != -1) ? findNextFreeSlotInPage(item.page) : findNextFreeSlot();
+ if (index == -1) {
+ // No space left, move to a new page
+ item.page = (itemList.size() / slotsPerPage) + 1;
+ item.slot = 0;
+ index = getIndex(item.page, item.slot);
+ }
+ ensureCapacity(index);
+ itemList.set(index, item);
+ }
+
+ private void addItem(Item item) {
+ if (item.page != -1 && item.slot != -1) {
+ // Attempt to place fixed slot item
+ int index = getIndex(item.page, item.slot);
+ ensureCapacity(index);
+ if (itemList.get(index) == null) {
+ itemList.set(index, item);
+ return;
+ }
+ item.slot = -1;
+ }
+ needSortItems.add(item);
+ }
+
+
+ private int getIndex(int page, int slot) {
+ return (page - 1) * slotsPerPage + slot;
+ }
+
+ private void ensureCapacity(int index) {
+ while (itemList.size() <= index) {
+ itemList.add(null);
+ }
+ }
+
+ private int findNextFreeSlotInPage(int page) {
+ int start = getIndex(page, 0);
+ int end = start + slotsPerPage;
+ for (int i = start; i < end; i++) {
+ if (i >= itemList.size() || itemList.get(i) == null) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int findNextFreeSlot() {
+ int index = 0;
+ for (int i = 0; i < itemList.size(); i++) {
+ index++;
+ if (itemList.get(i) == null) {
+ return i;
+ }
+ }
+ return index >= itemList.size() - 1 ? itemList.size() : index;
+ }
+
+ public static class Item {
+ private final EnhancedRecipe enhancedRecipe;
+ int page;
+ int slot;
+
+ Item(final EnhancedRecipe recipe) {
+ this.enhancedRecipe = recipe;
+ this.page = recipe.getPage();
+ this.slot = recipe.getSlot() > 0 ? recipe.getSlot() - 1 : recipe.getSlot();
+ //this.slot = recipe.getSlot();
+ }
+
+ public EnhancedRecipe getEnhancedRecipe() {
+ return enhancedRecipe;
+ }
+
+ @Override
+ public String toString() {
+ return "Item{" +
+ "enhancedRecipe=" + enhancedRecipe +
+ ", page=" + page +
+ ", slot=" + slot +
+ '}';
+ }
+ }
+}