From 01502ef97c5293298d11e12c9cc3a77b8653c9d8 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 15 Nov 2024 08:21:10 +0100 Subject: [PATCH 01/16] fix typo --- pom.xml | 10 +++++----- .../craftenhance/crafthandling/RecipeInjector.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 671ed74..e43b70b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ This is a minecraft plugin to enhance crafting. UTF-8 - 21 + 21 21 8 0.111 @@ -77,10 +77,10 @@ jitpack.io https://jitpack.io - + codemc-repo https://repo.codemc.io/repository/maven-public/ diff --git a/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java b/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java index f16a132..e878a78 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()) { From d9543969b7feff84de6763e04c3b9cdb65614d66 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 11:32:08 +0100 Subject: [PATCH 02/16] Sort items after page and slot --- .../gui/guis/viewers/RecipeViewRecipe.java | 17 ++- .../craftenhance/util/PaginatedItems.java | 114 ++++++++++++++++++ 2 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java 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/util/PaginatedItems.java b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java new file mode 100644 index 0000000..a774ceb --- /dev/null +++ b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java @@ -0,0 +1,114 @@ +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() { + for (int i = 0; i < itemList.size(); i++) { + if (itemList.get(i) == null) { + return i; + } + } + return -1; + } + + 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; + } + } +} From fbd1ee87828f8a9472f7a224ceb85e1ee5fa2581 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 11:32:31 +0100 Subject: [PATCH 03/16] Fixed so it remember last page opened --- .../commands/ceh/CreateRecipeCmd.java | 8 +++--- .../craftenhance/commands/ceh/RecipesCmd.java | 8 +++--- .../craftenhance/files/CategoryData.java | 6 ++-- .../craftenhance/gui/guis/CategoryList.java | 4 +-- .../gui/guis/EditorTypeSelector.java | 8 +++--- .../craftenhance/gui/guis/RecipesViewer.java | 23 +++++++-------- .../gui/guis/editors/RecipeEditor.java | 28 +++++++++++-------- .../gui/guis/editors/RecipeEditorBlast.java | 4 +-- .../gui/guis/editors/RecipeEditorFurnace.java | 8 +++--- .../gui/guis/editors/RecipeEditorSmoker.java | 4 +-- .../gui/guis/settings/RecipeSettings.java | 17 ++++++----- .../guis/settings/RecipeSettingsBlast.java | 4 +-- .../guis/settings/RecipeSettingsFurnace.java | 6 ++-- .../guis/settings/RecipeSettingsSmoker.java | 4 +-- .../craftenhance/gui/util/GuiUtil.java | 2 +- .../craftenhance/prompt/HandleChatInput.java | 4 ++- 16 files changed, 75 insertions(+), 63 deletions(-) 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..c1819a7 100644 --- a/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java +++ b/src/main/java/com/dutchjelly/craftenhance/commands/ceh/CreateRecipeCmd.java @@ -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: 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/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/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..da03a06 100644 --- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java +++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java @@ -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..c7d344a 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,getPageNumber(), categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player); + else new RecipeViewRecipe<>(categoryData, 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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData, (FurnaceRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player); + new RecipeViewRecipe<>(categoryData, 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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData, (BlastRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player); + new RecipeViewRecipe<>(categoryData,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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData, (SmokerRecipe) enhancedRecipe, "FurnaceRecipeViewer").menuOpen(player); + new RecipeViewRecipe<>(categoryData, 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..7b54bc4 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; @@ -152,7 +154,7 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe } 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 +170,26 @@ 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) { + System.out.println("this.slot," + this.page); + 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); 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/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/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; From ea4691c99497cd7109a04cf81c0f6aa36abb1a5c Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 11:32:50 +0100 Subject: [PATCH 04/16] update library --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e43b70b..29c2c85 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 CraftEnhance CraftEnhance - 2.5.6.3.2 + 2.5.6.3.3 CraftEnhance This is a minecraft plugin to enhance crafting. @@ -13,7 +13,7 @@ 21 21 8 - 0.111 + 0.116 com.dutchjelly.craftenhance.libs @@ -102,7 +102,7 @@ com.mojang authlib - 3.11.49 + 3.13.56 provided From 1fe1b7413d58b17646c6d95b822cbe25c117fc08 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 15:10:26 +0100 Subject: [PATCH 05/16] clean up the logic --- .../craftenhance/gui/guis/RecipesViewer.java | 16 ++++++++-------- .../gui/guis/editors/RecipeEditor.java | 9 ++++++--- 2 files changed, 14 insertions(+), 11 deletions(-) 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 c7d344a..6d7c007 100644 --- a/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java +++ b/src/main/java/com/dutchjelly/craftenhance/gui/guis/RecipesViewer.java @@ -128,26 +128,26 @@ public FillMenuButton createFillMenuButton() { if (enhancedRecipe instanceof WBRecipe) { if (allowClick) - new RecipeEditor<>((WBRecipe) enhancedRecipe,getPageNumber(), categoryData, null, ButtonType.ChooseWorkbenchType).menuOpen(player); - else new RecipeViewRecipe<>(categoryData, getPageNumber(),(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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); + new RecipeEditorFurnace((FurnaceRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData, getPageNumber(),(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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); + new RecipeEditorBlast((BlastRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData,getPageNumber(), (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, getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); + new RecipeEditorSmoker((SmokerRecipe) enhancedRecipe, this.getPageNumber(),categoryData, null, ButtonType.ChooseFurnaceType, true).menuOpen(player); else - new RecipeViewRecipe<>(categoryData, getPageNumber(),(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 7b54bc4..9dfaab8 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 @@ -146,8 +146,12 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe if (value.isActionTypeEqual(ButtonType.DeleteRecipe.name())) { self().getFm().removeRecipe(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; @@ -184,7 +188,6 @@ public boolean run(final MenuButtonData value, final Inventory menu, final Playe } if (value.isActionTypeEqual(ButtonType.Back.name())) { if (this.categoryData != null) { - System.out.println("this.slot," + this.page); final RecipesViewer recipesViewer = new RecipesViewer(this.categoryData, "", player); recipesViewer.menuOpen(player); if ( this.page > 0) From 5104497d36de93a0d953573d2055015319e4fb0b Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 15:32:39 +0100 Subject: [PATCH 06/16] bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29c2c85..0d08bce 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 CraftEnhance CraftEnhance - 2.5.6.3.3 + 2.5.6.4 CraftEnhance This is a minecraft plugin to enhance crafting. From 956592db04373178496c24177bcf05ea0e25b8f3 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Fri, 21 Feb 2025 15:44:49 +0100 Subject: [PATCH 07/16] update the version support --- src/main/java/com/dutchjelly/bukkitadapter/Adapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"; From b72a12fcf0cb4357f09135d4d7336fba4f06695b Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sat, 22 Feb 2025 17:37:28 +0100 Subject: [PATCH 08/16] fix problem, where fail find correct slot. --- pom.xml | 2 +- .../craftenhance/util/PaginatedItems.java | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 0d08bce..3dee07d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 CraftEnhance CraftEnhance - 2.5.6.4 + 2.5.6.4.1 CraftEnhance This is a minecraft plugin to enhance crafting. diff --git a/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java index a774ceb..c28ad36 100644 --- a/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java +++ b/src/main/java/com/dutchjelly/craftenhance/util/PaginatedItems.java @@ -38,7 +38,6 @@ public List retrieveList(final Player player, final String recip 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; @@ -86,12 +85,14 @@ private int findNextFreeSlotInPage(int page) { } private int findNextFreeSlot() { + int index = 0; for (int i = 0; i < itemList.size(); i++) { + index++; if (itemList.get(i) == null) { return i; } } - return -1; + return index >= itemList.size() - 1 ? itemList.size() : index; } public static class Item { @@ -99,7 +100,6 @@ public static class Item { int page; int slot; - Item(final EnhancedRecipe recipe) { this.enhancedRecipe = recipe; this.page = recipe.getPage(); @@ -110,5 +110,14 @@ public static class Item { public EnhancedRecipe getEnhancedRecipe() { return enhancedRecipe; } + + @Override + public String toString() { + return "Item{" + + "enhancedRecipe=" + enhancedRecipe + + ", page=" + page + + ", slot=" + slot + + '}'; + } } } From 75d6d4a556207c64a25a681db2daecd356a8383f Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sat, 1 Mar 2025 23:35:59 +0100 Subject: [PATCH 09/16] Database fixing --- .../dutchjelly/craftenhance/CraftEnhance.java | 5 + .../crafthandling/recipes/EnhancedRecipe.java | 25 +- .../craftenhance/database/RecipeDatabase.java | 496 ++++++++++++++++++ .../database/RecipeSQLQueries.java | 47 ++ .../craftenhance/messaging/Debug.java | 15 +- 5 files changed, 577 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java create mode 100644 src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java diff --git a/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java b/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java index e02ba85..d1fc811 100644 --- a/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java +++ b/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java @@ -27,6 +27,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; @@ -62,6 +63,8 @@ public static CraftEnhance self() { return plugin; } + @Getter + private RecipeDatabase database; private Metrics metrics; @Getter private FileManager fm; @@ -97,6 +100,7 @@ public void onEnable() { this.ingredientsCache = new IngredientsCache(); saveDefaultConfig(); Debug.init(this); + this.database = new RecipeDatabase(); if (isReloading) Bukkit.getScheduler().runTaskAsynchronously(this, () -> loadPluginData(isReloading)); @@ -124,6 +128,7 @@ public void onEnable() { metrics = new Metrics(this, metricsId); } CraftEnhanceAPI.registerListener(new ExecuteCommand()); + this.database.saveRecipes(); } 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..3b994db 100644 --- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java +++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java @@ -54,7 +54,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 ? oncraftcommand + "" : (String) oncraftcommand; } if (args.containsKey("hidden")) @@ -81,10 +82,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; } @@ -168,11 +170,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=" + type + + ", allowedWorlds=" + allowedWorlds + + ", checkPartialMatch=" + checkPartialMatch + + "} "; } public void setPermission(final String permission) { @@ -222,5 +230,6 @@ public void load() { 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/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java new file mode 100644 index 0000000..eb189f1 --- /dev/null +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -0,0 +1,496 @@ +package com.dutchjelly.craftenhance.database; + +import com.dutchjelly.craftenhance.crafthandling.recipes.EnhancedRecipe; +import com.dutchjelly.craftenhance.crafthandling.recipes.WBRecipe; +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 static com.dutchjelly.craftenhance.CraftEnhance.self; + +public class RecipeDatabase implements RecipeSQLQueries { + private static final String URL = "jdbc:sqlite:" + self().getDataFolder() + "/recipes.db"; + + public void saveRecipes() { + + save(); + } + + private void save() { + try (Connection connection = connect()) { + createTables(connection); + connection.setAutoCommit(false); + try { + for (EnhancedRecipe recipe : self().getFm().getRecipes()) { + saveRecipe(connection, recipe); + + getRecipe(connection, recipe.getKey()); + } + 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); + } + } + + public void saveRecipe(@NonNull final EnhancedRecipe recipe) { + try (Connection connection = connect()) { + connection.setAutoCommit(false); + try { + saveRecipe(connection, recipe); + } 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); + } + } + + @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 String recipeId) { + try (Connection connection = connect()) { + deleteRecipe(connection, recipeId); + } catch (SQLException exception) { + Debug.error("Failed to connect to database", exception); + } + } + + private void removeAllowedWorld(@NonNull final String recipeId, @NonNull final String world) { + try (Connection connection = connect()) { + removeAllowedWorld(connection, recipeId, world); + } catch (SQLException exception) { + Debug.error("Failed to connect to database", exception); + } + } + + public void deleteIngredient(@NonNull final String recipeId, @NonNull final ItemStack itemStack) { + String itemKey = getItemKey(itemStack); + if (itemKey == null) return; + + try (Connection connection = connect()) { + deleteIngredient(connection, recipeId, itemKey); + } catch (SQLException exception) { + Debug.error("Failed to connect to database", exception); + } + } + + private Connection connect() throws SQLException { + return DriverManager.getConnection(URL); + } + + private static void updateSQL(final PreparedStatement updateItemStmt) throws SQLException { + updateItemStmt.executeUpdate(); + } + + // Create tables + public void createTables(Connection conn) { + String createRecipesTable = " CREATE TABLE IF NOT EXISTS recipes ( " + + "id TEXT PRIMARY KEY, " + + "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, " + + "oncraftcommand TEXT, " + + "result_item_id INTEGER NOT NULL, " + + "shapeless BOOLEAN NOT NULL, " + + "FOREIGN KEY (result_item_id) 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, " + + "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);"; + + try (Statement stmt = conn.createStatement()) { + stmt.execute(createItemsTable); + stmt.execute(createRecipesTable); + stmt.execute(createAllowedWorldsTable); + } 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 pstmt = connection.prepareStatement(INSERT_OR_REPLACE_WORLDS_SQL)) { + for (String world : allowedWorlds) { + pstmt.setString(1, recipeId); + pstmt.setString(2, world); + pstmt.addBatch(); + } + updateSQL(pstmt); + }*/ + 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, int resultItemId) { + String sql = "INSERT INTO recipes " + + "(id, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, oncraftcommand, result_item_id, shapeless) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"; + + try (PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setString(1, recipe.getKey()); // Explicitly set the recipe ID + pstmt.setInt(2, recipe.getPage()); + 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.setInt(11, resultItemId); + + + boolean isShapeless = (recipe instanceof WBRecipe) && ((WBRecipe) recipe).isShapeless(); + pstmt.setBoolean(12, 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); + } + } + + public int insertOrUpdateItem(Connection conn, final int slot, final String recipeName, final String itemName, byte[] nbtData) { + if (itemName == null || nbtData == null) return -1; + + // Check if the item already exists by name + 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); + return rs.getInt(1); // Return existing ID + } + } 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); + updateSQL(insertStmt); + + ResultSet insertRs = insertStmt.getGeneratedKeys(); + if (insertRs.next()) { + return insertRs.getInt(1); // Return generated ID + } + } + } + } catch (SQLException e) { + Debug.error("Failed to insert or update the itemstack", e); + } + return -1; + } + + // Retrieve a recipe with its ingredients + public EnhancedRecipe getRecipe(Connection conn, String recipeId) { + + try (PreparedStatement pstmt = conn.prepareStatement(SELECT_RECIPE_JOIN_SQL)) { + pstmt.setString(1, recipeId); + pstmt.setString(2, recipeId); + + ResultSet rs = pstmt.executeQuery(); + + if (!rs.next()) return null; // No recipe found + + // Deserialize result item + 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.getBoolean("oncraftcommand")); + map.put("shapeless", rs.getBoolean("shapeless")); + + EnhancedRecipe recipe = WBRecipe.deserialize(map); + recipe.setResult(resultItem); + recipe.setKey(recipeId); + + List ingredients = getRecipeIngredients(conn, recipeId); + recipe.setContent(ingredients.toArray(new ItemStack[0])); + + Set allowedWorlds = getAllowedWorlds(conn, recipeId); + recipe.setAllowedWorlds(allowedWorlds); + + System.out.println("recipe loaded " + recipe); + return recipe; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private List getRecipeIngredients(Connection conn, String recipeId) throws SQLException { + List ingredients = new ArrayList<>(Collections.nCopies(9, null)); + + try (PreparedStatement pstmt = conn.prepareStatement(SELECT_INGREDIENTS_SQL)) { + pstmt.setString(1, recipeId); + 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 < 9 && 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 conn, String recipeId) throws SQLException { + String sql = "DELETE FROM recipes WHERE id = ?;"; + + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, recipeId); + int rowsAffected = pstmt.executeUpdate(); + if (rowsAffected > 0) { + System.out.println("Recipe " + recipeId + " deleted successfully."); + } else { + System.out.println("Recipe " + recipeId + " not found."); + } + } + } + + private void removeAllowedWorld(Connection conn, String recipeId, String world) throws SQLException { + try (PreparedStatement pstmt = conn.prepareStatement(DELETE_WORLD_SQL)) { + pstmt.setString(1, recipeId); + pstmt.setString(2, world); + pstmt.executeUpdate(); + } + } + + public void deleteIngredient(Connection conn, String recipeId, String itemName) throws SQLException { + String sql = "DELETE FROM ingredients WHERE recipe_id = ? AND item_id = (SELECT slot FROM items WHERE name = ?);"; + + try (PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, recipeId); + pstmt.setString(2, itemName); + int rowsAffected = pstmt.executeUpdate(); + if (rowsAffected > 0) { + System.out.println("Ingredient removed from recipe " + recipeId); + } else { + System.out.println("Ingredient not found in recipe " + recipeId); + } + } + } + + // 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 { + int newItemId = insertNewItem(connection, recipe); + insertRecipe(connection, recipe, newItemId); + } + } + ItemStack[] itemStacks = recipe.getContent(); + for (int i = 0; i < itemStacks.length; i++) { + ItemStack item = itemStacks[i]; + String itemName = getItemKey(item); + insertOrUpdateItem(connection, i, recipeName, itemName, serializeItemStack(new ItemStack[]{item})); + } + 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 { + + int resultItemId = recipeResultSet.getInt("result_item_id"); + + try (PreparedStatement selectItemStmt = connection.prepareStatement(SELECT_ITEM_SQL)) { + selectItemStmt.setString(1, recipe.getKey()); + selectItemStmt.setInt(2, resultItemId); + + try (ResultSet itemResultSet = selectItemStmt.executeQuery()) { + if (itemResultSet.next()) { + try (PreparedStatement updateItemStmt = connection.prepareStatement(UPDATE_ITEM_SQL)) { + updateItemStmt.setBytes(1, serializeItemStack(new ItemStack[]{recipe.getResult()})); + updateItemStmt.setString(2, itemResultSet.getString("recipe_id")); + updateItemStmt.setInt(3, itemResultSet.getInt("slot")); + updateSQL(updateItemStmt); + } + } else { + resultItemId = insertNewItem(connection, recipe); + } + } + } + + try (PreparedStatement pstmt = connection.prepareStatement(UPDATE_RECIPE_SQL)) { + pstmt.setInt(1, recipe.getPage()); + pstmt.setInt(2, recipe.getSlot()); + pstmt.setInt(3, recipe.getResultSlot()); + pstmt.setString(4, recipe.getRecipeCategory()); + pstmt.setString(5, recipe.getPermission()); + pstmt.setString(6, String.valueOf(recipe.getMatchType())); + pstmt.setBoolean(7, recipe.isHidden()); + pstmt.setBoolean(8, recipe.isCheckPartialMatch()); + pstmt.setString(9, recipe.getOnCraftCommand()); + pstmt.setInt(10, resultItemId); + + boolean isShapeless = (recipe instanceof WBRecipe) && ((WBRecipe) recipe).isShapeless(); + pstmt.setBoolean(11, isShapeless); + + pstmt.setString(12, recipeResultSet.getString("id")); + updateSQL(pstmt); + } + } + + + private int insertNewItem(Connection connection, EnhancedRecipe recipe) throws SQLException { + + try (PreparedStatement insertItemStmt = connection.prepareStatement(INSERT_ITEM_SQL, Statement.RETURN_GENERATED_KEYS)) { + insertItemStmt.setString(1, recipe.getKey()); + insertItemStmt.setInt(2, 9); + insertItemStmt.setString(3, getItemKey(recipe.getResult())); + insertItemStmt.setBytes(4, serializeItemStack(new ItemStack[]{recipe.getResult()})); + updateSQL(insertItemStmt); + + return 9; + } + } + + + @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/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java new file mode 100644 index 0000000..5b69bbe --- /dev/null +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -0,0 +1,47 @@ +package com.dutchjelly.craftenhance.database; + +public interface RecipeSQLQueries { + + String SELECT_RECIPE_SQL = "SELECT id, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, oncraftcommand, result_item_id, shapeless FROM recipes WHERE id = ?"; + String CHECK_ITEM_EXISTENCE_SQL = "SELECT slot FROM items WHERE recipe_id = ? AND slot = ?;"; + String CHECK_INGREDIENT_EXISTENCE_SQL = "SELECT 1 FROM ingredients WHERE recipe_id = ? AND item_id = ?"; + String SELECT_ITEM_SQL = "SELECT recipe_id, slot FROM items WHERE recipe_id = ? AND slot = ?;"; + String SELECT_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt " + + "FROM recipes r " + + "JOIN items i ON r.result_item_id = i.slot" + + "WHERE r.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 " + + "ORDER BY i.slot;"; + String SELECT_WORLDS_SQL = "SELECT world FROM allowed_worlds WHERE recipe_id = ?;"; + + + String UPDATE_ITEM_SQL = "UPDATE items SET item_nbt = ? WHERE recipe_id = ? and slot = ?;"; + String UPDATE_INGREDIENT_SQL = "UPDATE ingredients SET item_id = ? WHERE recipe_id = ? AND item_id = ?;"; + String UPDATE_RECIPE_SQL = "UPDATE recipes " + + "SET page = ?, " + + " slot = ?, " + + " result_slot = ?, " + + " category = ?, " + + " permission = ?, " + + " matchtype = ?, " + + " hidden = ?, " + + " check_partial_match = ?, " + + " oncraftcommand = ?, " + + " result_item_id = ?, " + + " shapeless = ? " + + "WHERE id = ?;"; + String UPDATE_WORLDS_SQL = "UPDATE allowed_worlds SET world = ? WHERE recipe_id = ? AND world = ?"; + + + 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) VALUES (?, ?, ?, ?)"; + String INSERT_INGREDIENT_SQL = "INSERT INTO ingredients (recipe_id, item_id) VALUES (?, ?)"; + + 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/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, From b00d8a5749d9992e50f103d2bea0ca190cf3cd7c Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sun, 2 Mar 2025 09:34:28 +0100 Subject: [PATCH 10/16] Fixed problem where it selects all result items --- .../craftenhance/database/RecipeDatabase.java | 85 +++++++++++-------- .../database/RecipeSQLQueries.java | 17 ++-- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index eb189f1..d80f875 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -100,16 +100,24 @@ private void removeAllowedWorld(@NonNull final String recipeId, @NonNull final S } public void deleteIngredient(@NonNull final String recipeId, @NonNull final ItemStack itemStack) { - String itemKey = getItemKey(itemStack); - if (itemKey == null) return; + EnhancedRecipe recipe = self().getFm().getRecipes().stream().filter(enhancedRecipe -> enhancedRecipe.getKey().equals(recipeId)).findFirst().orElse(null); + if (recipe == null) return; + + boolean isResult = recipe.getResult().isSimilar(itemStack); + int slot = recipe.getResultSlot(); + if (!isResult) { + slot = getSlotIngredient(itemStack, recipe, slot); + } + if (slot < 0) return; try (Connection connection = connect()) { - deleteIngredient(connection, recipeId, itemKey); + deleteIngredient(connection, recipeId, slot); } catch (SQLException exception) { Debug.error("Failed to connect to database", exception); } } + private Connection connect() throws SQLException { return DriverManager.getConnection(URL); } @@ -130,16 +138,17 @@ public void createTables(Connection conn) { + "matchtype TEXT NOT NULL, " + "hidden BOOLEAN NOT NULL," + "check_partial_match BOOLEAN NOT NULL, " - + "oncraftcommand TEXT, " - + "result_item_id INTEGER NOT NULL, " + + "on_craft_command TEXT, " + + "result_item_type TEXT NOT NULL, " + "shapeless BOOLEAN NOT NULL, " - + "FOREIGN KEY (result_item_id) REFERENCES items(id));"; + + "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);"; @@ -198,12 +207,9 @@ public void insertAllowedWorlds(Connection connection, String recipeId, Set allowedWorlds = getAllowedWorlds(conn, recipeId); recipe.setAllowedWorlds(allowedWorlds); - System.out.println("recipe loaded " + recipe); return recipe; } catch (SQLException e) { throw new RuntimeException(e); @@ -371,12 +373,12 @@ private void removeAllowedWorld(Connection conn, String recipeId, String world) } } - public void deleteIngredient(Connection conn, String recipeId, String itemName) throws SQLException { - String sql = "DELETE FROM ingredients WHERE recipe_id = ? AND item_id = (SELECT slot FROM items WHERE name = ?);"; + public void deleteIngredient(Connection conn, String recipeId, int slot) throws SQLException { + String sql = "DELETE FROM items WHERE recipe_id = ? AND slot = ?);"; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, recipeId); - pstmt.setString(2, itemName); + pstmt.setInt(2, slot); int rowsAffected = pstmt.executeUpdate(); if (rowsAffected > 0) { System.out.println("Ingredient removed from recipe " + recipeId); @@ -406,7 +408,7 @@ public void saveRecipe(Connection connection, EnhancedRecipe recipe) { if (recipeResultSet.next()) { updateRecipe(connection, recipe, recipeResultSet); } else { - int newItemId = insertNewItem(connection, recipe); + String newItemId = insertNewResultItem(connection, recipe); insertRecipe(connection, recipe, newItemId); } } @@ -429,11 +431,11 @@ public void saveRecipe(Connection connection, EnhancedRecipe recipe) { private void updateRecipe(final Connection connection, final EnhancedRecipe recipe, final ResultSet recipeResultSet) throws SQLException { - int resultItemId = recipeResultSet.getInt("result_item_id"); + String resultItemType = recipeResultSet.getString("result_item_type"); - try (PreparedStatement selectItemStmt = connection.prepareStatement(SELECT_ITEM_SQL)) { + try (PreparedStatement selectItemStmt = connection.prepareStatement(SELECT_ITEM_FROM_RECIPE_SLOT_SQL)) { selectItemStmt.setString(1, recipe.getKey()); - selectItemStmt.setInt(2, resultItemId); + selectItemStmt.setInt(2, 9); try (ResultSet itemResultSet = selectItemStmt.executeQuery()) { if (itemResultSet.next()) { @@ -444,7 +446,7 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci updateSQL(updateItemStmt); } } else { - resultItemId = insertNewItem(connection, recipe); + resultItemType = insertNewResultItem(connection, recipe); } } } @@ -459,7 +461,7 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci pstmt.setBoolean(7, recipe.isHidden()); pstmt.setBoolean(8, recipe.isCheckPartialMatch()); pstmt.setString(9, recipe.getOnCraftCommand()); - pstmt.setInt(10, resultItemId); + pstmt.setString(10, resultItemType); boolean isShapeless = (recipe instanceof WBRecipe) && ((WBRecipe) recipe).isShapeless(); pstmt.setBoolean(11, isShapeless); @@ -470,19 +472,30 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci } - private int insertNewItem(Connection connection, EnhancedRecipe recipe) throws SQLException { + private String insertNewResultItem(Connection connection, EnhancedRecipe recipe) throws SQLException { try (PreparedStatement insertItemStmt = connection.prepareStatement(INSERT_ITEM_SQL, Statement.RETURN_GENERATED_KEYS)) { insertItemStmt.setString(1, recipe.getKey()); insertItemStmt.setInt(2, 9); insertItemStmt.setString(3, getItemKey(recipe.getResult())); insertItemStmt.setBytes(4, serializeItemStack(new ItemStack[]{recipe.getResult()})); + insertItemStmt.setString(5, "RESULT"); updateSQL(insertItemStmt); - - return 9; + return "RESULT"; } } + private int getSlotIngredient(final ItemStack itemStack, final EnhancedRecipe recipe, int slot) { + final ItemStack[] content = recipe.getContent(); + for (int i = 0; i < content.length; i++) { + ItemStack item = content[0]; + if (itemStack.isSimilar(item)) { + slot = i; + break; + } + } + return slot; + } @Nonnull public byte[] serializeItemStack(final ItemStack[] itemStacks) { diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java index 5b69bbe..916c500 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -2,13 +2,14 @@ public interface RecipeSQLQueries { - String SELECT_RECIPE_SQL = "SELECT id, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, oncraftcommand, result_item_id, shapeless FROM recipes WHERE id = ?"; + String SELECT_RECIPE_SQL = "SELECT id, 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 CHECK_INGREDIENT_EXISTENCE_SQL = "SELECT 1 FROM ingredients WHERE recipe_id = ? AND item_id = ?"; - String SELECT_ITEM_SQL = "SELECT recipe_id, 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_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt " + "FROM recipes r " + - "JOIN items i ON r.result_item_id = i.slot" + + "JOIN items i ON r.result_item_type = i.type AND r.id = i.recipe_id " + "WHERE r.id = ?;"; String SELECT_INGREDIENTS_SQL = "SELECT i.item_nbt, i.slot " + "FROM items i " + @@ -29,18 +30,20 @@ public interface RecipeSQLQueries { " matchtype = ?, " + " hidden = ?, " + " check_partial_match = ?, " + - " oncraftcommand = ?, " + - " result_item_id = ?, " + + " 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, 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) VALUES (?, ?, ?, ?)"; + String INSERT_ITEM_SQL = "INSERT INTO items (recipe_id, slot, name, item_nbt, type) VALUES (?, ?, ?, ?, ?)"; String INSERT_INGREDIENT_SQL = "INSERT INTO ingredients (recipe_id, item_id) VALUES (?, ?)"; String DELETE_WORLD_SQL = "DELETE FROM allowed_worlds WHERE recipe_id = ? AND world = ?;"; From 5d69c6b864c9316adcb31987429c8c3d7681c44f Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sun, 2 Mar 2025 11:15:27 +0100 Subject: [PATCH 11/16] clean up the database logic --- .../crafthandling/recipes/EnhancedRecipe.java | 2 +- .../database/IngredientWrapper.java | 52 +++++++ .../craftenhance/database/RecipeDatabase.java | 142 ++++++++---------- .../craftenhance/database/RecipeType.java | 7 + 4 files changed, 124 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java create mode 100644 src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java 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 3b994db..ede6163 100644 --- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java +++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java @@ -124,7 +124,7 @@ protected EnhancedRecipe(final Map args) { private String onCraftCommand; @Getter - private RecipeType type; + private final RecipeType type = RecipeType.WORKBENCH; @Getter @Setter 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..63686b8 --- /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 RecipeType recipeType = RecipeType.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 RecipeType getRecipeType() { + return recipeType; + } + + public void setRecipeType(final RecipeType recipeType) { + this.recipeType = recipeType; + } + } diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index d80f875..00fe247 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import static com.dutchjelly.craftenhance.CraftEnhance.self; @@ -176,15 +177,7 @@ public void createTables(Connection conn) { public void insertAllowedWorlds(Connection connection, String recipeId, Set allowedWorlds) throws SQLException { if (allowedWorlds == null || allowedWorlds.isEmpty()) return; -/* - try (PreparedStatement pstmt = connection.prepareStatement(INSERT_OR_REPLACE_WORLDS_SQL)) { - for (String world : allowedWorlds) { - pstmt.setString(1, recipeId); - pstmt.setString(2, world); - pstmt.addBatch(); - } - updateSQL(pstmt); - }*/ + try (PreparedStatement updateStmt = connection.prepareStatement(UPDATE_WORLDS_SQL); PreparedStatement insertStmt = connection.prepareStatement(INSERT_WORLDS_SQL)) { @@ -207,7 +200,7 @@ public void insertAllowedWorlds(Connection connection, String recipeId, Set allowedWorlds = getAllowedWorlds(conn, recipeId); recipe.setAllowedWorlds(allowedWorlds); - + System.out.println("recipe: " + recipe); return recipe; } catch (SQLException e) { throw new RuntimeException(e); @@ -408,15 +365,28 @@ public void saveRecipe(Connection connection, EnhancedRecipe recipe) { if (recipeResultSet.next()) { updateRecipe(connection, recipe, recipeResultSet); } else { - String newItemId = insertNewResultItem(connection, recipe); - insertRecipe(connection, recipe, newItemId); + insertRecipe(connection, recipe, RecipeType.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(RecipeType.RESULT); + }); } ItemStack[] itemStacks = recipe.getContent(); for (int i = 0; i < itemStacks.length; i++) { ItemStack item = itemStacks[i]; String itemName = getItemKey(item); - insertOrUpdateItem(connection, i, recipeName, itemName, serializeItemStack(new ItemStack[]{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) { @@ -433,24 +403,6 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci String resultItemType = recipeResultSet.getString("result_item_type"); - try (PreparedStatement selectItemStmt = connection.prepareStatement(SELECT_ITEM_FROM_RECIPE_SLOT_SQL)) { - selectItemStmt.setString(1, recipe.getKey()); - selectItemStmt.setInt(2, 9); - - try (ResultSet itemResultSet = selectItemStmt.executeQuery()) { - if (itemResultSet.next()) { - try (PreparedStatement updateItemStmt = connection.prepareStatement(UPDATE_ITEM_SQL)) { - updateItemStmt.setBytes(1, serializeItemStack(new ItemStack[]{recipe.getResult()})); - updateItemStmt.setString(2, itemResultSet.getString("recipe_id")); - updateItemStmt.setInt(3, itemResultSet.getInt("slot")); - updateSQL(updateItemStmt); - } - } else { - resultItemType = insertNewResultItem(connection, recipe); - } - } - } - try (PreparedStatement pstmt = connection.prepareStatement(UPDATE_RECIPE_SQL)) { pstmt.setInt(1, recipe.getPage()); pstmt.setInt(2, recipe.getSlot()); @@ -471,17 +423,50 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci } } + public void insertOrUpdateItem(Connection conn, Consumer callback) { + if (callback == null) return; - private String insertNewResultItem(Connection connection, EnhancedRecipe recipe) throws SQLException { + 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(); + RecipeType recipeType = 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, recipeType.name()); + updateSQL(insertStmt); - try (PreparedStatement insertItemStmt = connection.prepareStatement(INSERT_ITEM_SQL, Statement.RETURN_GENERATED_KEYS)) { - insertItemStmt.setString(1, recipe.getKey()); - insertItemStmt.setInt(2, 9); - insertItemStmt.setString(3, getItemKey(recipe.getResult())); - insertItemStmt.setBytes(4, serializeItemStack(new ItemStack[]{recipe.getResult()})); - insertItemStmt.setString(5, "RESULT"); - updateSQL(insertItemStmt); - return "RESULT"; + ResultSet insertRs = insertStmt.getGeneratedKeys(); + if (insertRs.next()) { + insertRs.getInt(1); + } + } + } + } catch (SQLException e) { + Debug.error("Failed to insert or update the itemstack", e); } } @@ -506,4 +491,5 @@ public byte[] serializeItemStack(final ItemStack[] itemStacks) { public ItemStack[] deserializeItemStack(final byte[] itemStacks) { return RegisterNbtAPI.deserializeItemStack(itemStacks); } + } diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java new file mode 100644 index 0000000..98918fc --- /dev/null +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java @@ -0,0 +1,7 @@ +package com.dutchjelly.craftenhance.database; + +public enum RecipeType { + + RESULT, + INGREDIENT +} From 88283cc3239d16729824d2a05daa0ce6b5a749b0 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sun, 2 Mar 2025 14:16:46 +0100 Subject: [PATCH 12/16] Separate the recipes types --- .../crafthandling/recipes/EnhancedRecipe.java | 6 +- .../recipes/utility/RecipeType.java | 13 +++ .../database/IngredientWrapper.java | 10 +- .../craftenhance/database/RecipeDatabase.java | 91 +++++++++++++------ .../database/RecipeIngredientType.java | 23 +++++ .../database/RecipeSQLQueries.java | 7 +- .../craftenhance/database/RecipeType.java | 7 -- 7 files changed, 112 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/dutchjelly/craftenhance/database/RecipeIngredientType.java delete mode 100644 src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java 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 ede6163..09c7372 100644 --- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java +++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/recipes/EnhancedRecipe.java @@ -177,7 +177,7 @@ public String toString() { ", permission='" + permission + '\'' + ", hidden=" + hidden + ", on_craft_command='" + onCraftCommand + '\'' + - ", type=" + type + + ", type=" + this.getType() + ", allowedWorlds=" + allowedWorlds + ", checkPartialMatch=" + checkPartialMatch + "} "; @@ -223,6 +223,10 @@ public void save() { CraftEnhance.self().getFm().saveRecipe(this); } + public RecipeType getType() { + return type; + } + public void load() { RecipeLoader.getInstance().loadRecipe(this); } 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 index 63686b8..651b0a0 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/IngredientWrapper.java @@ -5,7 +5,7 @@ public class IngredientWrapper { private int slot; private String recipeName; private String itemName; - private RecipeType recipeType = RecipeType.INGREDIENT; + private RecipeIngredientType recipeIngredientType = RecipeIngredientType.INGREDIENT; public IngredientWrapper() { } @@ -42,11 +42,11 @@ public void setItemName(final String itemName) { this.itemName = itemName; } - public RecipeType getRecipeType() { - return recipeType; + public RecipeIngredientType getRecipeType() { + return recipeIngredientType; } - public void setRecipeType(final RecipeType recipeType) { - this.recipeType = recipeType; + 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 index 00fe247..0297816 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -1,7 +1,11 @@ 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; @@ -131,6 +135,7 @@ private static void updateSQL(final PreparedStatement updateItemStmt) throws SQL 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, " @@ -200,24 +205,25 @@ public void insertAllowedWorlds(Connection connection, String recipeId, Set { - ingredients.setSlot( recipe.getResultSlot()); + 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(RecipeType.RESULT); + ingredients.setRecipeType(RecipeIngredientType.RESULT); }); } ItemStack[] itemStacks = recipe.getContent(); @@ -405,20 +437,21 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci try (PreparedStatement pstmt = connection.prepareStatement(UPDATE_RECIPE_SQL)) { pstmt.setInt(1, recipe.getPage()); - pstmt.setInt(2, recipe.getSlot()); - pstmt.setInt(3, recipe.getResultSlot()); - pstmt.setString(4, recipe.getRecipeCategory()); - pstmt.setString(5, recipe.getPermission()); - pstmt.setString(6, String.valueOf(recipe.getMatchType())); - pstmt.setBoolean(7, recipe.isHidden()); - pstmt.setBoolean(8, recipe.isCheckPartialMatch()); - pstmt.setString(9, recipe.getOnCraftCommand()); - pstmt.setString(10, resultItemType); + 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(11, isShapeless); + pstmt.setBoolean(12, isShapeless); - pstmt.setString(12, recipeResultSet.getString("id")); + pstmt.setString(13, recipeResultSet.getString("id")); updateSQL(pstmt); } } @@ -432,7 +465,7 @@ public void insertOrUpdateItem(Connection conn, Consumer call final String recipeName = ingredientWrapper.getRecipeName(); final String itemName = ingredientWrapper.getItemName(); byte[] nbtData = ingredientWrapper.getItemData(); - RecipeType recipeType = ingredientWrapper.getRecipeType(); + RecipeIngredientType recipeIngredientType = ingredientWrapper.getRecipeType(); if (itemName == null || nbtData == null) return; @@ -456,7 +489,7 @@ public void insertOrUpdateItem(Connection conn, Consumer call insertStmt.setInt(2, slot); insertStmt.setString(3, itemName); insertStmt.setBytes(4, nbtData); - insertStmt.setString(5, recipeType.name()); + insertStmt.setString(5, recipeIngredientType.name()); updateSQL(insertStmt); ResultSet insertRs = insertStmt.getGeneratedKeys(); 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 index 916c500..aa38109 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -2,7 +2,7 @@ public interface RecipeSQLQueries { - String SELECT_RECIPE_SQL = "SELECT id, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, on_craft_command, result_item_type, shapeless FROM recipes WHERE id = ?"; + 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 CHECK_INGREDIENT_EXISTENCE_SQL = "SELECT 1 FROM ingredients WHERE recipe_id = ? AND item_id = ?"; String SELECT_ITEM_FROM_RECIPE_SLOT_SQL = "SELECT recipe_id, slot FROM items WHERE recipe_id = ? AND slot = ?;"; @@ -23,6 +23,7 @@ public interface RecipeSQLQueries { String UPDATE_INGREDIENT_SQL = "UPDATE ingredients SET item_id = ? WHERE recipe_id = ? AND item_id = ?;"; String UPDATE_RECIPE_SQL = "UPDATE recipes " + "SET page = ?, " + + " recipe_type = ?, " + " slot = ?, " + " result_slot = ?, " + " category = ?, " + @@ -37,8 +38,8 @@ public interface RecipeSQLQueries { String UPDATE_WORLDS_SQL = "UPDATE allowed_worlds SET world = ? WHERE recipe_id = ? AND world = ?"; String INSERT_RECIPES_SQL = "INSERT INTO recipes " + - "(id, page, slot, result_slot, category, permission, matchtype, hidden, check_partial_match, on_craft_command, result_item_type, shapeless) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"; + "(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;"; diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java deleted file mode 100644 index 98918fc..0000000 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dutchjelly.craftenhance.database; - -public enum RecipeType { - - RESULT, - INGREDIENT -} From 2b014e4c98f4ecd2818f83e894f5c317d69b5e11 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Mon, 3 Mar 2025 00:40:10 +0100 Subject: [PATCH 13/16] added missed type --- .../com/dutchjelly/craftenhance/database/RecipeDatabase.java | 1 + .../com/dutchjelly/craftenhance/database/RecipeSQLQueries.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index 0297816..1983ccb 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -311,6 +311,7 @@ private List getRecipeIngredients(Connection conn, String recipeId) t 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"); diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java index aa38109..906deb6 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -15,6 +15,7 @@ public interface RecipeSQLQueries { "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 = ?;"; From 4b7bd0aff425be8d278dc22b43d9a423fd1c4fbd Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sat, 8 Mar 2025 09:43:00 +0100 Subject: [PATCH 14/16] Implemented the sql save It is now fully implemented. --- .../dutchjelly/craftenhance/CraftEnhance.java | 39 +- .../craftenhance/SaveScheduler.java | 84 +++++ .../craftenhance/cache/CacheRecipes.java | 71 ++++ .../commands/ceh/ChangeKeyCmd.java | 13 +- .../commands/ceh/CleanItemFileCmd.java | 8 +- .../commands/ceh/CreateRecipeCmd.java | 6 +- .../commands/ceh/RemoveRecipeCmd.java | 2 +- .../commands/ceh/SetPermissionCmd.java | 6 +- .../commands/ceh/SpecsCommand.java | 2 +- .../crafthandling/RecipeInjector.java | 1 + .../crafthandling/recipes/EnhancedRecipe.java | 46 ++- .../crafthandling/recipes/FurnaceRecipe.java | 4 +- .../crafthandling/recipes/WBRecipe.java | 6 +- .../recipes/furnace/BlastRecipe.java | 5 + .../recipes/furnace/SmokerRecipe.java | 5 + .../craftenhance/database/RecipeDatabase.java | 348 ++++++++++++------ .../database/RecipeSQLQueries.java | 4 + .../craftenhance/files/FileManager.java | 40 +- .../gui/guis/EditorTypeSelector.java | 4 +- .../gui/guis/editors/RecipeEditor.java | 54 +-- 20 files changed, 542 insertions(+), 206 deletions(-) create mode 100644 src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java create mode 100644 src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java diff --git a/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java b/src/main/java/com/dutchjelly/craftenhance/CraftEnhance.java index d1fc811..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; @@ -41,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; @@ -52,17 +54,21 @@ 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; @@ -92,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); @@ -100,7 +111,7 @@ public void onEnable() { this.ingredientsCache = new IngredientsCache(); saveDefaultConfig(); Debug.init(this); - this.database = new RecipeDatabase(); + if (isReloading) Bukkit.getScheduler().runTaskAsynchronously(this, () -> loadPluginData(isReloading)); @@ -108,6 +119,8 @@ public void onEnable() { this.loadPluginData(false); loadRecipes(); } + if (injector == null) + injector = new RecipeInjector(this); guiManager = new GuiManager(this); Debug.Send("Setting up listeners and commands"); @@ -128,7 +141,7 @@ public void onEnable() { metrics = new Metrics(this, metricsId); } CraftEnhanceAPI.registerListener(new ExecuteCommand()); - this.database.saveRecipes(); + saveScheduler.start(); } @@ -153,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(); } @@ -254,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. @@ -274,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..7574a0b --- /dev/null +++ b/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java @@ -0,0 +1,84 @@ +package com.dutchjelly.craftenhance; + +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) { + System.out.println("saving"); + self().getCacheRecipes().save(); + lastSaveTime = now; + } + + } + + private void executeTask() { + if (taskQueue.isEmpty() || isRunningTask) { + return; + } + System.out.println("can runn " ); + isRunningTask = true; + new BukkitRunnable() { + @Override + public void run() { + int batchSize = 4; + 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..8b4b1b4 --- /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 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(() -> { + System.out.println("recipe shall be removed: " + recipe); + 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 c1819a7..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; } @@ -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/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 e878a78..bf3d568 100644 --- a/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java +++ b/src/main/java/com/dutchjelly/craftenhance/crafthandling/RecipeInjector.java @@ -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 09c7372..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) { @@ -55,7 +67,7 @@ protected EnhancedRecipe(final Map args) { if (args.containsKey("oncraftcommand")) { final Object oncraftcommand = args.get("oncraftcommand"); - onCraftCommand = oncraftcommand instanceof Boolean ? oncraftcommand + "" : (String) oncraftcommand; + onCraftCommand = oncraftcommand instanceof Boolean ? "" : (String) oncraftcommand; } if (args.containsKey("hidden")) @@ -137,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() { @@ -149,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); @@ -219,21 +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 RecipeType getType() { - return type; + 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/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index 1983ccb..efdb0a6 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -29,28 +29,33 @@ 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 void saveRecipes() { + public RecipeDatabase() { + try (Connection connection = connect()) { + createTables(connection); + } catch (SQLException exception) { + Debug.error("Failed to connect to database", exception); + } + } + + public void saveRecipes() { save(); } - private void save() { + public void saveRecipe(@NonNull final EnhancedRecipe recipe) { + Send("Saving recipe '" + recipe.getKey() + "' with data: " + recipe.toString()); try (Connection connection = connect()) { - createTables(connection); connection.setAutoCommit(false); try { - for (EnhancedRecipe recipe : self().getFm().getRecipes()) { - saveRecipe(connection, recipe); - - getRecipe(connection, recipe.getKey()); - } - connection.commit(); + saveRecipe(connection, recipe); } finally { try { + connection.commit(); connection.setAutoCommit(true); } catch (SQLException e) { Debug.error("Could not not reset back the auto commit.", e); @@ -61,21 +66,14 @@ private void save() { } } - public void saveRecipe(@NonNull final EnhancedRecipe recipe) { + @NonNull + public List loadRecipes() { try (Connection connection = connect()) { - connection.setAutoCommit(false); - try { - saveRecipe(connection, recipe); - } finally { - try { - connection.setAutoCommit(true); - } catch (SQLException e) { - Debug.error("Could not not reset back the auto commit.", e); - } - } + return this.getAllRecipe(connection); } catch (SQLException exception) { Debug.error("Failed to connect to database", exception); } + return new ArrayList<>(); } @Nullable @@ -88,35 +86,72 @@ public EnhancedRecipe loadRecipe(@NonNull final String recipeId) { return null; } - public void deleteRecipe(@NonNull final String recipeId) { + public void deleteRecipe(@NonNull final EnhancedRecipe enhancedRecipe) { + try (Connection connection = connect()) { + connection.setAutoCommit(false); + Send("Removing recipe '" + enhancedRecipe.getKey() + "' with data: " + enhancedRecipe.toString()); + 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()) { - deleteRecipe(connection, recipeId); + removeAllowedWorld(connection, enhancedRecipe.getKey(), world); } catch (SQLException exception) { Debug.error("Failed to connect to database", exception); } } - private void removeAllowedWorld(@NonNull final String recipeId, @NonNull final String world) { + public void deleteAllIngredients(@NonNull final EnhancedRecipe enhancedRecipe) { try (Connection connection = connect()) { - removeAllowedWorld(connection, recipeId, world); + 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 deleteIngredient(@NonNull final String recipeId, @NonNull final ItemStack itemStack) { - EnhancedRecipe recipe = self().getFm().getRecipes().stream().filter(enhancedRecipe -> enhancedRecipe.getKey().equals(recipeId)).findFirst().orElse(null); - if (recipe == null) return; - boolean isResult = recipe.getResult().isSimilar(itemStack); - int slot = recipe.getResultSlot(); + 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(itemStack, recipe, slot); + slot = getSlotIngredient(enhancedRecipe, itemStack, slot); } if (slot < 0) return; try (Connection connection = connect()) { - deleteIngredient(connection, recipeId, slot); + this.deleteIngredient(connection, enhancedRecipe.getKey(), slot); } catch (SQLException exception) { Debug.error("Failed to connect to database", exception); } @@ -235,6 +270,27 @@ public void insertRecipe(@NonNull Connection conn, EnhancedRecipe recipe, Recipe } } + 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) { @@ -246,68 +302,90 @@ public EnhancedRecipe getRecipe(Connection conn, String recipeId) { ResultSet rs = pstmt.executeQuery(); if (!rs.next()) return null; - 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]; + 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; + } - 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.getBoolean("on_craft_command")); - map.put("shapeless", rs.getBoolean("shapeless")); - - RecipeType type = RecipeType.getType(rs.getString("recipe_type")); - System.out.println("type " + type); - if (type != null) { - switch (type) { - case FURNACE: - map.put("duration", 2); - map.put("exp", 1.5); - recipe = FurnaceRecipe.deserialize(map); - break; - case BLAST: - map.put("duration", 2); - map.put("exp", 1.5); - recipe = BlastRecipe.deserialize(map); - break; - case SMOKER: - map.put("duration", 2); - map.put("exp", 1.5); - recipe = SmokerRecipe.deserialize(map); - break; - default: - recipe = WBRecipe.deserialize(map); - } - } else { - recipe = WBRecipe.deserialize(map); + 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", 2); + map.put("exp", 1.5); + recipe = FurnaceRecipe.deserialize(map); + break; + case BLAST: + map.put("duration", 2); + map.put("exp", 1.5); + recipe = BlastRecipe.deserialize(map); + break; + case SMOKER: + map.put("duration", 2); + map.put("exp", 1.5); + recipe = SmokerRecipe.deserialize(map); + break; + default: + recipe = WBRecipe.deserialize(map); } + } else { + recipe = WBRecipe.deserialize(map); + } - recipe.setResult(resultItem); - recipe.setKey(recipeId); + recipe.setResult(resultItem); + recipe.setKey(recipeId); - List ingredients = getRecipeIngredients(conn, recipeId); - recipe.setContent(ingredients.toArray(new ItemStack[0])); + 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; - } catch (SQLException e) { - throw new RuntimeException(e); - } + Set allowedWorlds = getAllowedWorlds(conn, recipeId); + recipe.setAllowedWorlds(allowedWorlds); + System.out.println("recipe: " + recipe); + return recipe; } - private List getRecipeIngredients(Connection conn, String recipeId) throws SQLException { - List ingredients = new ArrayList<>(Collections.nCopies(9, null)); + 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); @@ -317,10 +395,8 @@ private List getRecipeIngredients(Connection conn, String recipeId) t byte[] nbtData = rs.getBytes("item_nbt"); ItemStack[] items = deserializeItemStack(nbtData); int slot = rs.getInt("slot"); - - if (slot >= 0 && slot < 9 && items != null && items.length > 0) { + if (slot >= 0 && slot < maxAmount && items != null && items.length > 0) { ingredients.set(slot, items[0]); - } } } @@ -341,39 +417,65 @@ private Set getAllowedWorlds(Connection conn, String recipeId) throws SQ return worlds; } - public void deleteRecipe(Connection conn, String recipeId) throws SQLException { + 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])); - try (PreparedStatement pstmt = conn.prepareStatement(sql)) { - pstmt.setString(1, recipeId); + try (PreparedStatement pstmt = connection.prepareStatement(sql)) { + pstmt.setString(1, enhancedRecipe.getKey()); int rowsAffected = pstmt.executeUpdate(); if (rowsAffected > 0) { - System.out.println("Recipe " + recipeId + " deleted successfully."); + Send("Recipe '" + enhancedRecipe.getKey() + "' deleted successfully."); } else { - System.out.println("Recipe " + recipeId + " not found."); + Send("Recipe '" + enhancedRecipe.getKey() + "' not found."); } } } - private void removeAllowedWorld(Connection conn, String recipeId, String world) throws SQLException { - try (PreparedStatement pstmt = conn.prepareStatement(DELETE_WORLD_SQL)) { - pstmt.setString(1, recipeId); - pstmt.setString(2, world); - pstmt.executeUpdate(); + 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(); + } } } - public void deleteIngredient(Connection conn, String recipeId, int slot) throws SQLException { - String sql = "DELETE FROM items WHERE recipe_id = ? AND slot = ?);"; + 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)) { - pstmt.setString(1, recipeId); - pstmt.setInt(2, slot); - int rowsAffected = pstmt.executeUpdate(); - if (rowsAffected > 0) { - System.out.println("Ingredient removed from recipe " + recipeId); - } else { - System.out.println("Ingredient not found in recipe " + recipeId); + 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); + } } } } @@ -457,6 +559,14 @@ private void updateRecipe(final Connection connection, final EnhancedRecipe reci } } + 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; @@ -504,10 +614,18 @@ public void insertOrUpdateItem(Connection conn, Consumer call } } - private int getSlotIngredient(final ItemStack itemStack, final EnhancedRecipe recipe, int slot) { + 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[0]; + ItemStack item = content[i]; if (itemStack.isSimilar(item)) { slot = i; break; @@ -516,6 +634,18 @@ private int getSlotIngredient(final ItemStack itemStack, final EnhancedRecipe re 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); diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java index 906deb6..38b10bb 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -11,6 +11,10 @@ public interface RecipeSQLQueries { "FROM recipes r " + "JOIN items i ON r.result_item_type = i.type AND r.id = i.recipe_id " + "WHERE r.id = ?;"; + + String SELECT_ALL_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt " + + "FROM recipes r " + + "JOIN items i ON r.result_item_type = i.type AND r.id = i.recipe_id;"; String SELECT_INGREDIENTS_SQL = "SELECT i.item_nbt, i.slot " + "FROM items i " + "WHERE i.recipe_id = ? " + 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/EditorTypeSelector.java b/src/main/java/com/dutchjelly/craftenhance/gui/guis/EditorTypeSelector.java index da03a06..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; 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 9dfaab8..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 @@ -144,7 +144,7 @@ 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) { final RecipesViewer recipesViewer = new RecipesViewer(this.categoryData, "", player); @@ -270,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); @@ -280,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++; @@ -289,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++; @@ -311,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()); From f4e77f44deb6e3ae593c5238ac6427e065ff3d93 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sat, 8 Mar 2025 09:48:35 +0100 Subject: [PATCH 15/16] Improved the logging --- pom.xml | 2 +- .../java/com/dutchjelly/craftenhance/SaveScheduler.java | 6 ++++-- .../com/dutchjelly/craftenhance/cache/CacheRecipes.java | 2 +- .../dutchjelly/craftenhance/database/RecipeDatabase.java | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 3dee07d..d3ebe9b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 CraftEnhance CraftEnhance - 2.5.6.4.1 + 2.5.7.0 CraftEnhance This is a minecraft plugin to enhance crafting. diff --git a/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java b/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java index 7574a0b..73e97e3 100644 --- a/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java +++ b/src/main/java/com/dutchjelly/craftenhance/SaveScheduler.java @@ -1,5 +1,6 @@ package com.dutchjelly.craftenhance; +import com.dutchjelly.craftenhance.messaging.Debug; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -46,7 +47,7 @@ public void run() { } if (now - lastSaveTime >= SAVE_INTERVAL) { - System.out.println("saving"); + Debug.Send("Doing the scheduler save task."); self().getCacheRecipes().save(); lastSaveTime = now; } @@ -57,12 +58,13 @@ private void executeTask() { if (taskQueue.isEmpty() || isRunningTask) { return; } - System.out.println("can runn " ); + 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) { diff --git a/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java b/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java index 8b4b1b4..45bb60d 100644 --- a/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java +++ b/src/main/java/com/dutchjelly/craftenhance/cache/CacheRecipes.java @@ -4,6 +4,7 @@ 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; @@ -46,7 +47,6 @@ public void addAll(List enhancedRecipes) { public void remove(EnhancedRecipe enhancedRecipe) { EnhancedRecipe recipe = enhancedRecipe; saveSchedule.addTask(() -> { - System.out.println("recipe shall be removed: " + recipe); this.database.deleteRecipe(recipe); }); recipes.remove(enhancedRecipe); diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index efdb0a6..f9e70e0 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -87,9 +87,10 @@ public EnhancedRecipe loadRecipe(@NonNull final String recipeId) { } public void deleteRecipe(@NonNull final EnhancedRecipe enhancedRecipe) { + Send("Removing recipe '" + enhancedRecipe.getKey() + "' with data: " + enhancedRecipe.toString()); + try (Connection connection = connect()) { connection.setAutoCommit(false); - Send("Removing recipe '" + enhancedRecipe.getKey() + "' with data: " + enhancedRecipe.toString()); deleteRecipe(connection, enhancedRecipe); try { connection.commit(); From e0b6d9078511ce10f55bfb4a260df017a87f1907 Mon Sep 17 00:00:00 2001 From: broken1arrow Date: Sat, 8 Mar 2025 13:07:06 +0100 Subject: [PATCH 16/16] fix the forgotten parts of the furnace recipe so time and experience get saved. --- .../craftenhance/database/RecipeDatabase.java | 83 ++++++++++++++++--- .../database/RecipeSQLQueries.java | 22 +++-- 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java index f9e70e0..f7b594a 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeDatabase.java @@ -141,6 +141,18 @@ public void deleteAllIngredients(@NonNull final EnhancedRecipe enhancedRecipe) { } } + 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); @@ -163,8 +175,8 @@ private Connection connect() throws SQLException { return DriverManager.getConnection(URL); } - private static void updateSQL(final PreparedStatement updateItemStmt) throws SQLException { - updateItemStmt.executeUpdate(); + private int updateSQL(final PreparedStatement updateItemStmt) throws SQLException { + return updateItemStmt.executeUpdate(); } // Create tables @@ -207,10 +219,19 @@ public void createTables(Connection conn) { + "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.execute(createItemsTable); - stmt.execute(createRecipesTable); - stmt.execute(createAllowedWorldsTable); + 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); } @@ -244,7 +265,7 @@ public void insertAllowedWorlds(Connection connection, String recipeId, Set 0) { Send("Recipe '" + enhancedRecipe.getKey() + "' deleted successfully."); } else { @@ -434,6 +479,16 @@ public void deleteRecipe(Connection connection, EnhancedRecipe enhancedRecipe) t } } + 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; @@ -512,6 +567,8 @@ public void saveRecipe(Connection connection, EnhancedRecipe recipe) { ingredients.setRecipeType(RecipeIngredientType.RESULT); }); } + this.updateFurnaces(connection, recipe); + ItemStack[] itemStacks = recipe.getContent(); for (int i = 0; i < itemStacks.length; i++) { ItemStack item = itemStacks[i]; diff --git a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java index 38b10bb..c935e41 100644 --- a/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java +++ b/src/main/java/com/dutchjelly/craftenhance/database/RecipeSQLQueries.java @@ -4,17 +4,19 @@ 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 CHECK_INGREDIENT_EXISTENCE_SQL = "SELECT 1 FROM ingredients WHERE recipe_id = ? AND item_id = ?"; String SELECT_ITEM_FROM_RECIPE_SLOT_SQL = "SELECT recipe_id, slot FROM items WHERE recipe_id = ? AND slot = ?;"; - - String SELECT_RECIPE_JOIN_SQL = "SELECT r.*, i.item_nbt AS result_nbt " + + 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 " + + 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 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 = ? " + @@ -23,9 +25,9 @@ public interface RecipeSQLQueries { "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_INGREDIENT_SQL = "UPDATE ingredients SET item_id = ? WHERE recipe_id = ? AND item_id = ?;"; + String UPDATE_RECIPE_SQL = "UPDATE recipes " + "SET page = ?, " + " recipe_type = ?, " + @@ -49,8 +51,10 @@ public interface RecipeSQLQueries { "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_INGREDIENT_SQL = "INSERT INTO ingredients (recipe_id, item_id) 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