From 66737ba2c3986cf0c529c3cb85b8e9c4ce79bc7f Mon Sep 17 00:00:00 2001 From: AnyaPizza Date: Sat, 28 Feb 2026 18:16:57 -0500 Subject: [PATCH 1/2] Added A Whole lotta stuff includes the Alchemist Workbench --- .../screen/AlchemistsWorkbenchScreen.java | 307 ++++++++++++++++++ .../MineTale/datagen/ModBlockTagProvider.java | 3 +- .../tcm/MineTale/datagen/ModLangProvider.java | 17 + .../datagen/ModLootTableProvider.java | 15 + .../MineTale/datagen/ModModelProvider.java | 3 + .../datagen/recipes/AlchemistRecipes.java | 38 +-- .../datagen/recipes/BlacksmithRecipes.java | 90 ++--- .../datagen/recipes/ForgeRecipes.java | 2 +- .../datagen/recipes/WorkbenchRecipes.java | 204 ++++++------ .../workbenches/AlchemistsWorkbench.java | 94 ++++++ .../entity/AlchemistsWorkbenchEntity.java | 174 ++++++++++ .../menu/AlchemistsWorkbenchMenu.java | 128 ++++++++ .../MineTale/registry/ModBlockEntities.java | 6 + .../com/tcm/MineTale/registry/ModBlocks.java | 9 +- .../com/tcm/MineTale/registry/ModItems.java | 37 ++- .../tcm/MineTale/registry/ModMenuTypes.java | 5 + .../MineTale/registry/ModRecipeDisplay.java | 5 + .../com/tcm/MineTale/registry/ModRecipes.java | 6 + 18 files changed, 966 insertions(+), 177 deletions(-) create mode 100644 src/client/java/com/tcm/MineTale/block/workbenches/screen/AlchemistsWorkbenchScreen.java create mode 100644 src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java create mode 100644 src/main/java/com/tcm/MineTale/block/workbenches/entity/AlchemistsWorkbenchEntity.java create mode 100644 src/main/java/com/tcm/MineTale/block/workbenches/menu/AlchemistsWorkbenchMenu.java diff --git a/src/client/java/com/tcm/MineTale/block/workbenches/screen/AlchemistsWorkbenchScreen.java b/src/client/java/com/tcm/MineTale/block/workbenches/screen/AlchemistsWorkbenchScreen.java new file mode 100644 index 0000000..424df99 --- /dev/null +++ b/src/client/java/com/tcm/MineTale/block/workbenches/screen/AlchemistsWorkbenchScreen.java @@ -0,0 +1,307 @@ +package com.tcm.MineTale.block.workbenches.screen; + +import com.tcm.MineTale.MineTale; +import com.tcm.MineTale.block.workbenches.menu.AbstractWorkbenchContainerMenu; +import com.tcm.MineTale.block.workbenches.menu.AlchemistsWorkbenchMenu; +import com.tcm.MineTale.mixin.client.ClientRecipeBookAccessor; +import com.tcm.MineTale.network.CraftRequestPayload; +import com.tcm.MineTale.recipe.MineTaleRecipeBookComponent; +import com.tcm.MineTale.registry.ModBlocks; +import com.tcm.MineTale.registry.ModRecipeDisplay; +import com.tcm.MineTale.registry.ModRecipes; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.minecraft.client.ClientRecipeBook; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.navigation.ScreenPosition; +import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen; +import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; +import net.minecraft.world.item.crafting.display.RecipeDisplayId; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class AlchemistsWorkbenchScreen extends AbstractRecipeBookScreen { + private static final Identifier TEXTURE = + Identifier.fromNamespaceAndPath(MineTale.MOD_ID, "textures/gui/container/workbench_workbench.png"); + + private final MineTaleRecipeBookComponent mineTaleRecipeBook; + + private RecipeDisplayId lastKnownSelectedId = null; + + private Button craftOneBtn; + private Button craftTenBtn; + private Button craftAllBtn; + + /** + * Initialize a workbench GUI screen using the provided container menu, player inventory, and title. + * + * @param menu the menu supplying slots and synchronized state for this screen + * @param inventory the player's inventory to display and interact with + * @param title the title component shown at the top of the screen + */ + public AlchemistsWorkbenchScreen(AlchemistsWorkbenchMenu menu, Inventory inventory, Component title) { + this(menu, inventory, title, createRecipeBookComponent(menu)); + } + + /** + * Creates a WorkbenchWorkbenchScreen bound to the given menu, player inventory, title, and recipe book component. + * + * @param menu the menu backing this screen + * @param inventory the player's inventory shown in the screen + * @param title the screen title component + * @param recipeBook the MineTaleRecipeBookComponent used to display and manage recipes in this screen + */ + private AlchemistsWorkbenchScreen(AlchemistsWorkbenchMenu menu, Inventory inventory, Component title, MineTaleRecipeBookComponent recipeBook) { + super(menu, recipeBook, inventory, title); + this.mineTaleRecipeBook = recipeBook; + } + + /** + * Create a MineTaleRecipeBookComponent configured for the workbench screen. + * + * @param menu the workbench menu used to initialize the recipe book component + * @return a MineTaleRecipeBookComponent containing the workbench tab and associated recipe category + */ + private static MineTaleRecipeBookComponent createRecipeBookComponent(AlchemistsWorkbenchMenu menu) { + ItemStack tabIcon = new ItemStack(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK.asItem()); + + List tabs = List.of( + new RecipeBookComponent.TabInfo(tabIcon.getItem(), ModRecipeDisplay.ALCHEMISTS_SEARCH) + ); + + return new MineTaleRecipeBookComponent(menu, tabs, ModRecipes.ALCHEMISTS_TYPE); + } + + /** + * Initialises the workbench screen's GUI size and interactive widgets. + * + * Sets the screen image dimensions, delegates remaining setup to the superclass, + * computes default button positions and creates three craft buttons: + * - "Craft" (requests 1), + * - "x10" (requests 10), + * - "All" (requests -1 to indicate all). + */ + @Override + protected void init() { + // Important: Set your GUI size before super.init() + this.imageWidth = 176; + this.imageHeight = 166; + + super.init(); + + int defaultLeft = this.leftPos + 90; + int defaultTop = this.topPos + 25; + + this.craftOneBtn = addRenderableWidget(Button.builder(Component.translatable("gui.minetale.craftbtn"), (button) -> { + handleCraftRequest(1); + }).bounds(defaultLeft, defaultTop, 75, 20).build()); + + this.craftTenBtn = addRenderableWidget(Button.builder(Component.literal("x10"), (button) -> { + handleCraftRequest(10); + }).bounds(defaultLeft, defaultTop + 22, 35, 20).build()); + + this.craftAllBtn = addRenderableWidget(Button.builder(Component.translatable("gui.minetale.allbtn"), (button) -> { + handleCraftRequest(-1); // -1 represents "All" logic + }).bounds(defaultLeft + 40, defaultTop + 22, 35, 20).build()); + } + + /** + * Request crafting for the currently selected recipe from the integrated recipe book. + * + * If a recipe is selected, sends a CraftRequestPayload to the server for that recipe and the + * specified quantity. If no recipe is selected, no request is sent. + * + * @param amount the quantity to craft; use -1 to request crafting of the full available stack ("All") + */ + private void handleCraftRequest(int amount) { + // Look at our "Memory" instead of the component + if (this.lastKnownSelectedId != null) { + ClientRecipeBook book = this.minecraft.player.getRecipeBook(); + RecipeDisplayEntry entry = ((ClientRecipeBookAccessor) book).getKnown().get(this.lastKnownSelectedId); + + if (entry != null) { + List results = entry.resultItems(SlotDisplayContext.fromLevel(this.minecraft.level)); + if (!results.isEmpty()) { + System.out.println("Persistent Selection Success: " + results.get(0)); + ClientPlayNetworking.send(new CraftRequestPayload(results.get(0), amount)); + return; + } + } + } + System.out.println("Request failed: No recipe was ever selected!"); + } + + /** + * Draws the workbench background texture at the screen's current GUI origin. + * + * @param guiGraphics the graphics context used to draw GUI elements + * @param f partial tick time for interpolation + * @param i current mouse x coordinate + * @param j current mouse y coordinate + */ + protected void renderBg(GuiGraphics guiGraphics, float f, int i, int j) { + int k = this.leftPos; + int l = this.topPos; + guiGraphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, k, l, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256); + } + + /** + * Render the screen, remember the current recipe selection and update craft-button availability. + * + * Remembers the recipe selected in the recipe book, resolves that selection against the client's known recipes when possible, + * sets the craft buttons active or inactive according to whether the player has sufficient ingredients for counts of 1, 2 and 10, + * renders the background, the superclass UI and any tooltips. + */ + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + renderBackground(graphics, mouseX, mouseY, delta); + super.render(graphics, mouseX, mouseY, delta); + + // 1. Get the current selection from the book + RecipeDisplayId currentId = this.mineTaleRecipeBook.getSelectedRecipeId(); + + // 2. If it's NOT null, remember it! + if (currentId != null) { + this.lastKnownSelectedId = currentId; + } + + // 3. Use the remembered ID to find the entry for button activation + RecipeDisplayEntry selectedEntry = null; + if (this.lastKnownSelectedId != null && this.minecraft.level != null) { + ClientRecipeBook book = this.minecraft.player.getRecipeBook(); + selectedEntry = ((ClientRecipeBookAccessor) book).getKnown().get(this.lastKnownSelectedId); + } + + // 2. Button Activation Logic + if (selectedEntry != null) { + // We use the entry directly. It contains the 15 ingredients needed! + boolean canCraftOne = canCraft(this.minecraft.player, selectedEntry, 1); + boolean canCraftMoreThanOne = canCraft(this.minecraft.player, selectedEntry, 2); + boolean canCraftTen = canCraft(this.minecraft.player, selectedEntry, 10); + + this.craftOneBtn.active = canCraftOne; + this.craftTenBtn.active = canCraftTen; + this.craftAllBtn.active = canCraftMoreThanOne; + } else { + this.craftOneBtn.active = false; + this.craftTenBtn.active = false; + this.craftAllBtn.active = false; + } + + renderTooltip(graphics, mouseX, mouseY); + } + + /** + * Determines whether the player has enough ingredients to craft the given recipe the specified number of times. + * + * @param player the player whose inventory (and networked nearby items) will be checked; may be null + * @param entry the recipe display entry providing crafting requirements; may be null + * @param craftCount the multiplier for required ingredient quantities (e.g., 1, 10, or -1 is not specially handled here) + * @return `true` if the player has at least the required quantity of each ingredient multiplied by `craftCount`, `false` otherwise (also returns `false` if `player` or `entry` is null or the recipe has no requirements) + */ + private boolean canCraft(Player player, RecipeDisplayEntry entry, int craftCount) { + if (player == null || entry == null) return false; + + Optional> reqs = entry.craftingRequirements(); + if (reqs.isEmpty()) return false; + + // 1. Group ingredients by their underlying Item Holders. + // Using List> as the key ensures structural equality (content-based hashing). + Map>, Integer> aggregatedRequirements = new HashMap<>(); + Map>, Ingredient> holderToIngredient = new HashMap<>(); + + for (Ingredient ing : reqs.get()) { + // Collect holders into a List to get a stable hashCode() and equals() + @SuppressWarnings("deprecation") + List> key = ing.items().toList(); + + // Aggregate the counts (how many of this specific ingredient set are required) + aggregatedRequirements.put(key, aggregatedRequirements.getOrDefault(key, 0) + 1); + + // Map the list back to the original ingredient for use in hasIngredientAmount + holderToIngredient.putIfAbsent(key, ing); + } + + // 2. Check the player's inventory against the aggregated totals + Inventory inv = player.getInventory(); + for (Map.Entry>, Integer> entryReq : aggregatedRequirements.entrySet()) { + List> key = entryReq.getKey(); + int totalNeeded = entryReq.getValue() * craftCount; + + // Retrieve the original Ingredient object associated with this list of holders + Ingredient originalIng = holderToIngredient.get(key); + + if (!hasIngredientAmount(inv, originalIng, totalNeeded)) { + return false; + } + } + + return true; + } + + private boolean hasIngredientAmount(Inventory inventory, Ingredient ingredient, int totalRequired) { + System.out.println("DEBUG: Searching inventory + nearby for " + totalRequired + "..."); + if (totalRequired <= 0) return true; + + int found = 0; + + // 1. Check Player Inventory + for (int i = 0; i < inventory.getContainerSize(); i++) { + ItemStack stack = inventory.getItem(i); + if (!stack.isEmpty() && ingredient.test(stack)) { + found += stack.getCount(); + } + } + + // 2. CHECK THE NETWORKED ITEMS FROM CHESTS + // This is the list we sent via the packet! + if (this.menu instanceof AbstractWorkbenchContainerMenu workbenchMenu) { + for (ItemStack stack : workbenchMenu.getNetworkedNearbyItems()) { + if (!stack.isEmpty() && ingredient.test(stack)) { + found += stack.getCount(); + System.out.println("DEBUG: Found " + stack.getCount() + " in nearby networked list. Total: " + found); + } + } + } + + if (found >= totalRequired) { + System.out.println("DEBUG: Requirement MET with " + found + "/" + totalRequired); + return true; + } + + System.out.println("DEBUG: FAILED. Only found: " + found + "/" + totalRequired); + return false; + } + + /** + * Computes the on-screen position for the recipe book toggle button for this GUI. + * + * @return the screen position placed 5 pixels from the GUI's left edge and 49 pixels above the GUI's vertical center + */ + @Override + protected ScreenPosition getRecipeBookButtonPosition() { + // 1. Calculate the start (left) of your workbench GUI + int guiLeft = (this.width - this.imageWidth) / 2; + + // 2. Calculate the top of your workbench GUI + int guiTop = (this.height - this.imageHeight) / 2; + + // 3. Standard Vanilla positioning: + // Usually 5 pixels in from the left and 49 pixels up from the center + return new ScreenPosition(guiLeft + 5, guiTop + this.imageHeight / 2 - 49); + } +} \ No newline at end of file diff --git a/src/client/java/com/tcm/MineTale/datagen/ModBlockTagProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModBlockTagProvider.java index c7d7a15..619ff28 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModBlockTagProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModBlockTagProvider.java @@ -38,7 +38,8 @@ protected void addTags(HolderLookup.Provider provider) { .add(ModBlocks.FURNACE_WORKBENCH_BLOCK_T2) .add(ModBlocks.ARMORERS_WORKBENCH_BLOCK) .add(ModBlocks.BUILDERS_WORKBENCH_BLOCK) - .add(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK); + .add(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK) + .add(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK); valueLookupBuilder(BlockTags.MINEABLE_WITH_AXE) .add(ModBlocks.CAMPFIRE_WORKBENCH_BLOCK) diff --git a/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java index 847a91b..53e4bc5 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java @@ -26,6 +26,7 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio translationBuilder.add("block.minetale.blacksmiths_workbench", "Blacksmith's Workbench"); translationBuilder.add("block.minetale.builders_workbench", "Builder's Workbench"); translationBuilder.add("block.minetale.furniture_workbench", "Furniture Workbench"); + translationBuilder.add("block.minetale.alchemists_workbench", "Alchemist's Workbench"); translationBuilder.add("block.minetale.woodcutters_block", "Woodcutter's Block"); @@ -261,6 +262,10 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio translationBuilder.add("item.minetale.essence_of_ice", "Essence of Ice"); translationBuilder.add("item.minetale.essence_of_the_void", "Essence of the Void"); translationBuilder.add("item.minetale.void_heart", "Void Heart"); + translationBuilder.add("item.minetale.empty_potion_bottle", "Empty Potion Bottle"); + translationBuilder.add("item.minetale.antitode", "Antidote"); + translationBuilder.add("item.minetale.boom_powder", "Boom Powder"); + translationBuilder.add("item.minetale.popberry_bomb", "Popberry Bomb"); // --- FLORA COMPONENTS --- translationBuilder.add("item.minetale.red_petals", "Red Petals"); @@ -279,6 +284,18 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio //translationBuilder.add("item.minetale.wood_gauntlets", "Wood Gauntlets"); translationBuilder.add("item.minetale.wood_greaves", "Wood Greaves"); translationBuilder.add("item.minetale.copper_mace", "Copper Mace"); + translationBuilder.add("item.minetale.copper_hatchet", "Copper Hatchet"); + translationBuilder.add("item.minetale.copper_battleaxe", "Copper Battleaxe"); + translationBuilder.add("item.minetale.copper_daggers", "Copper Daggers"); + translationBuilder.add("item.minetale.copper_longsword", "Copper Longsword"); + translationBuilder.add("item.minetale.copper_shortbow", "Copper Shortbow"); + translationBuilder.add("item.minetale.crude_longsword", "Crude Longsword"); + translationBuilder.add("item.minetale.crude_builders_hammer", "Crude Builders Hammer"); + translationBuilder.add("item.minetale.crude_hatchet", "Crude Hatchet"); + translationBuilder.add("item.minetale.crude_mace", "Crude Mace"); + translationBuilder.add("item.minetale.crude_daggers", "Crude Daggers"); + translationBuilder.add("item.minetale.crude_shortbow", "Crude Shortbow"); + translationBuilder.add("item.minetale.crude_sword", "Crude Sword"); // --- GUI --- translationBuilder.add("gui.minetale.craftbtn", "Craft"); diff --git a/src/client/java/com/tcm/MineTale/datagen/ModLootTableProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModLootTableProvider.java index cf2b92c..7a07af5 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModLootTableProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModLootTableProvider.java @@ -64,6 +64,21 @@ public void generate() { ) ); + this.add(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK, + LootTable.lootTable() // Use the static factory method to start the builder + .withPool(LootPool.lootPool() + .setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK)) + .when(LootItemBlockStatePropertyCondition.hasBlockStateProperties(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK) + .setProperties(StatePropertiesPredicate.Builder.properties() + .hasProperty(AbstractWorkbench.HALF, DoubleBlockHalf.LOWER) + .hasProperty(AbstractWorkbench.TYPE, ChestType.LEFT) + ) + ) + .when(ExplosionCondition.survivesExplosion()) + ) + ); + this.add(ModBlocks.BUILDERS_WORKBENCH_BLOCK, LootTable.lootTable() // Use the static factory method to start the builder .withPool(LootPool.lootPool() diff --git a/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java index ce5e5fe..a36cab7 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java @@ -131,6 +131,9 @@ public void generateItemModels(ItemModelGenerators itemModelGenerators) { itemModelGenerators.generateFlatItem(ModItems.ONION, ModelTemplates.FLAT_HANDHELD_ITEM); itemModelGenerators.generateFlatItem(ModItems.WOOL_SCRAPS, ModelTemplates.FLAT_HANDHELD_ITEM); itemModelGenerators.generateFlatItem(ModItems.POOP, ModelTemplates.FLAT_HANDHELD_ITEM); + itemModelGenerators.generateFlatItem(ModItems.EMPTY_POTION_BOTTLE, ModelTemplates.FLAT_HANDHELD_ITEM); + itemModelGenerators.generateFlatItem(ModItems.ANTIDOTE, ModelTemplates.FLAT_HANDHELD_ITEM); + itemModelGenerators.generateFlatItem(ModItems.POPBERRY_BOMB, ModelTemplates.FLAT_HANDHELD_ITEM); } } \ No newline at end of file diff --git a/src/client/java/com/tcm/MineTale/datagen/recipes/AlchemistRecipes.java b/src/client/java/com/tcm/MineTale/datagen/recipes/AlchemistRecipes.java index cfb3871..e40e319 100644 --- a/src/client/java/com/tcm/MineTale/datagen/recipes/AlchemistRecipes.java +++ b/src/client/java/com/tcm/MineTale/datagen/recipes/AlchemistRecipes.java @@ -11,25 +11,25 @@ public class AlchemistRecipes { public static void buildRecipes(RecipeProvider provider, RecipeOutput exporter, HolderLookup.Provider lookup) { - //new WorkbenchRecipeBuilder(ModRecipes.ALCHEMIST_TYPE, ModRecipes.ALCHEMIST_SERIALIZER) - // .input(ModItems.EMPTY_POTION_BOTTLE) - // .input(ModItems.PLANT_FIBER, 5) - // .input(ModItems.ESSENCE_OF_LIFE, 2) - // .input(ModItems.VENOM_SACK, 1) - // .output(ModItems.ANTIDOTE) - // .time(1) - // .unlockedBy("has_alchemist_workbench", provider.has(ModBlocks.ALCHEMIST_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.ALCHEMIST_SEARCH) - // .save(exporter, "ANTIDOTE"); + new WorkbenchRecipeBuilder(ModRecipes.ALCHEMISTS_TYPE, ModRecipes.ALCHEMISTS_SERIALIZER) + .input(ModItems.EMPTY_POTION_BOTTLE) + .input(ModItems.PLANT_FIBER, 5) + .input(ModItems.ESSENCE_OF_LIFE, 2) + .input(ModItems.VENOM_SAC, 1) + .output(ModItems.ANTIDOTE) + .time(1) + .unlockedBy("has_alchemists_workbench", provider.has(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.ALCHEMISTS_SEARCH) + .save(exporter, "antidote"); - // new WorkbenchRecipeBuilder(ModRecipes.ALCHEMIST_TYPE, ModRecipes.ALCHEMIST_SERIALIZER) - // .input(ModItems.WILD_BERRY, 6) - // .input(ModItems.BOOM_POWDER, 2) - // .input(ModItems.PLANT_FIBER, 4) - // .output(ModItems.POPBERRY_BOMB, 2) - // .time(0.5) - // .unlockedBy("has_alchemist_workbench", provider.has(ModBlocks.ALCHEMIST_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.ALCHEMIST_SEARCH) - // .save(exporter, "POPBERRY_BOMB"); + new WorkbenchRecipeBuilder(ModRecipes.ALCHEMISTS_TYPE, ModRecipes.ALCHEMISTS_SERIALIZER) + .input(ModItems.WILD_BERRY, 6) + .input(ModItems.BOOM_POWDER, 2) + .input(ModItems.PLANT_FIBER, 4) + .output(ModItems.POPBERRY_BOMB) + .time(0.5f) + .unlockedBy("has_alchemists_workbench", provider.has(ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.ALCHEMISTS_SEARCH) + .save(exporter, "popberry_bomb"); } } diff --git a/src/client/java/com/tcm/MineTale/datagen/recipes/BlacksmithRecipes.java b/src/client/java/com/tcm/MineTale/datagen/recipes/BlacksmithRecipes.java index 46de4d8..880dfca 100644 --- a/src/client/java/com/tcm/MineTale/datagen/recipes/BlacksmithRecipes.java +++ b/src/client/java/com/tcm/MineTale/datagen/recipes/BlacksmithRecipes.java @@ -23,45 +23,45 @@ public static void buildRecipes(RecipeProvider provider, RecipeOutput exporter, .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) .save(exporter, "copper_axe"); - //new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) - // .input(Items.COPPER_INGOT, 6) - // .input(ItemTags.LOGS, lookup, 6) - // .input(ModItems.PLANT_FIBER, 4) - // .output(ModItems.COPPER_BATTLEAXE) - // .time(3) - // .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) - // .save(exporter, "copper_battleaxe"); + new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) + .input(Items.COPPER_INGOT, 6) + .input(ItemTags.LOGS, lookup, 6) + .input(ModItems.PLANT_FIBER, 4) + .output(ModItems.COPPER_BATTLEAXE) + .time(3) + .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) + .save(exporter, "copper_battleaxe"); - // new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) - // .input(Items.COPPER_INGOT, 4) - // .input(ItemTags.LOGS, lookup, 3) - // .input(ModItems.PLANT_FIBER, 3) - // .output(ModItems.COPPER_DAGGERS) - // .time(3) - // .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) - // .save(exporter, "copper_daggers"); + new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) + .input(Items.COPPER_INGOT, 4) + .input(ItemTags.LOGS, lookup, 3) + .input(ModItems.PLANT_FIBER, 3) + .output(ModItems.COPPER_DAGGERS) + .time(3) + .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) + .save(exporter, "copper_daggers"); - // new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) - // .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) - // .input(ItemTags.LOGS, lookup, 2) - // .input(ModItems.PLANT_FIBER, 4) - // .output(ModItems.CRUDE_LONGSWORD) - // .time(3) - // .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) - // .save(exporter, "crude_longsword"); + new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) + .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) + .input(ItemTags.LOGS, lookup, 2) + .input(ModItems.PLANT_FIBER, 4) + .output(ModItems.CRUDE_LONGSWORD) + .time(3) + .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) + .save(exporter, "crude_longsword"); - // new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) - // .input(Items.COPPER_INGOT, 6) - // .input(ItemTags.LOGS, lookup, 2) - // .input(ModItems.PLANT_FIBER, 4) - // .output(ModItems.COPPER_LONGSWORD) - // .time(3) - // .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) - // .save(exporter, "copper_longsword"); + new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) + .input(Items.COPPER_INGOT, 6) + .input(ItemTags.LOGS, lookup, 2) + .input(ModItems.PLANT_FIBER, 4) + .output(ModItems.COPPER_LONGSWORD) + .time(3) + .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) + .save(exporter, "copper_longsword"); new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) .input(Items.COPPER_INGOT, 6) @@ -73,15 +73,15 @@ public static void buildRecipes(RecipeProvider provider, RecipeOutput exporter, .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) .save(exporter, "copper_mace"); - // new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) - // .input(Items.COPPER_INGOT, 4) - // .input(ItemTags.LOGS, lookup, 4) - // .input(ModItems.PLANT_FIBER, 6) - // .output(ModItems.COPPER_SHORTBOW) - // .time(3) - // .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) - // .save(exporter, "copper_shortbow"); + new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) + .input(Items.COPPER_INGOT, 4) + .input(ItemTags.LOGS, lookup, 4) + .input(ModItems.PLANT_FIBER, 6) + .output(ModItems.COPPER_SHORTBOW) + .time(3) + .unlockedBy("has_blacksmiths_workbench", provider.has(ModBlocks.BLACKSMITHS_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.BLACKSMITHS_SEARCH) + .save(exporter, "copper_shortbow"); new WorkbenchRecipeBuilder(ModRecipes.BLACKSMITHS_TYPE, ModRecipes.BLACKSMITHS_SERIALIZER) .input(Items.COPPER_INGOT, 4) diff --git a/src/client/java/com/tcm/MineTale/datagen/recipes/ForgeRecipes.java b/src/client/java/com/tcm/MineTale/datagen/recipes/ForgeRecipes.java index 6b8dda1..48b8550 100644 --- a/src/client/java/com/tcm/MineTale/datagen/recipes/ForgeRecipes.java +++ b/src/client/java/com/tcm/MineTale/datagen/recipes/ForgeRecipes.java @@ -5,7 +5,7 @@ import net.minecraft.data.recipes.RecipeProvider; public class ForgeRecipes { - /// Forge still in development in Hytale + /// FORGE STILL IN DEVELOPMENT IN HYTALE public static void buildRecipes(RecipeProvider provider, RecipeOutput exporter, HolderLookup.Provider lookup) { // new WorkbenchRecipeBuilder(ModRecipes.FORGE_TYPE, ModRecipes.FORGE_SERIALIZER) diff --git a/src/client/java/com/tcm/MineTale/datagen/recipes/WorkbenchRecipes.java b/src/client/java/com/tcm/MineTale/datagen/recipes/WorkbenchRecipes.java index 1938679..16982a4 100644 --- a/src/client/java/com/tcm/MineTale/datagen/recipes/WorkbenchRecipes.java +++ b/src/client/java/com/tcm/MineTale/datagen/recipes/WorkbenchRecipes.java @@ -90,113 +90,103 @@ public static void buildRecipes(RecipeProvider provider, RecipeOutput exporter, .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) .save(exporter, "crude_torch"); - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.RUBBLE, 2) - // .input(ModItems.PLANT_FIBER, 3) - // .input(Items.STICK, 3) - // .time(3) - // .output(ModItems.CRUDE_BUILDERS_HAMMER) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_BUILDERS_HAMMER"); - - // TODO: COPPER_PICKAXE Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.PLANT_FIBER) - // .input(ItemTags.LOGS, lookup, 6) - // .input(Items.COPPER_INGOT, 3) - // .time(3) - // .output(ModItems.COPPER_PICKAXE) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "COPPER_PICKAXE"); - - // TODO: CRUDE_PICKAXE Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.RUBBLE, 2) - // .input(ModItems.PLANT_FIBER, 2) - // .input(Items.STICK, 2) - // .time(3) - // .output(ModItems.CRUDE_PICKAXE) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_PICKAXE"); - - // TODO: CRUDE_HATCHET Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.RUBBLE, 2) - // .input(ModItems.PLANT_FIBER, 2) - // .input(Items.STICK, 2) - // .time(3) - // .output(ModItems.CRUDE_HATCHET) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_HATCHET"); - - // TODO: COPPER_HATCHET Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.PLANT_FIBER, 3) - // .input(ItemTags.LOGS, lookup, 6) - // .input(Items.COPPER_INGOT, 3) - // .time(3) - // .output(ModItems.COPPER_HATCHET) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "COPPER_HATCHET"); - - // TODO: CRUDE_BATTLEAXE Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ItemTags.LOGS, lookup, 3) - // .input(ModItems.PLANT_FIBER, 4) - // .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) - // .time(3) - // .output(ModItems.CRUDE_BATTLEAXE) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_BATTLEAXE"); - - // TODO: CRUDE_MACE Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ItemTags.LOGS, lookup, 3) - // .input(ModItems.PLANT_FIBER, 4) - // .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) - // .time(3) - // .output(ModItems.CRUDE_MACE) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_MACE"); - - // TODO: CRUDE_DAGGERS Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.RUBBLE, 3) - // .input(ModItems.PLANT_FIBER, 2) - // .input(Items.STICK, 2) - // .time(3) - // .output(ModItems.CRUDE_DAGGERS) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_DAGGERS"); - - // TODO: CRUDE_SHORTBOW Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.PLANT_FIBER, 6) - // .input(Items.STICK, 4) - // .time(3) - // .output(ModItems.CRUDE_SHORTBOW) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_SHORTBOW"); - - // TODO: CRUDE_SWORD Not Implemented - // new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) - // .input(ModItems.RUBBLE, 2) - // .input(ModItems.PLANT_FIBER, 2) - // .input(Items.STICK, 2) - // .time(3) - // .output(ModItems.CRUDE_SWORD) - // .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) - // .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) - // .save(exporter, "CRUDE_SWORD"); + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.RUBBLE, 2) + .input(ModItems.PLANT_FIBER, 3) + .input(Items.STICK, 3) + .time(3) + .output(ModItems.CRUDE_BUILDERS_HAMMER) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_builders_hammer"); + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.PLANT_FIBER) + .input(ItemTags.LOGS, lookup, 6) + .input(Items.COPPER_INGOT, 3) + .time(3) + .output(Items.COPPER_PICKAXE) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "copper_pickaxe"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.RUBBLE, 2) + .input(ModItems.PLANT_FIBER, 2) + .input(Items.STICK, 2) + .time(3) + .output(Items.STONE_PICKAXE) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "stone_pickaxe"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.RUBBLE, 2) + .input(ModItems.PLANT_FIBER, 2) + .input(Items.STICK, 2) + .time(3) + .output(ModItems.CRUDE_HATCHET) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_hatchet"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.PLANT_FIBER, 3) + .input(ItemTags.LOGS, lookup, 6) + .input(Items.COPPER_INGOT, 3) + .time(3) + .output(ModItems.COPPER_HATCHET) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "copper_hatchet"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ItemTags.LOGS, lookup, 3) + .input(ModItems.PLANT_FIBER, 4) + .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) + .time(3) + .output(ModItems.CRUDE_BATTLEAXE) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_battleaxe"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ItemTags.LOGS, lookup, 3) + .input(ModItems.PLANT_FIBER, 4) + .input(ItemTags.STONE_TOOL_MATERIALS, lookup, 6) + .time(3) + .output(ModItems.CRUDE_MACE) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_mace"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.RUBBLE, 3) + .input(ModItems.PLANT_FIBER, 2) + .input(Items.STICK, 2) + .time(3) + .output(ModItems.CRUDE_DAGGERS) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_daggers"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.PLANT_FIBER, 6) + .input(Items.STICK, 4) + .time(3) + .output(ModItems.CRUDE_SHORTBOW) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_shortbow"); + + new WorkbenchRecipeBuilder(ModRecipes.WORKBENCH_TYPE, ModRecipes.WORKBENCH_SERIALIZER) + .input(ModItems.RUBBLE, 2) + .input(ModItems.PLANT_FIBER, 2) + .input(Items.STICK, 2) + .time(3) + .output(ModItems.CRUDE_SWORD) + .unlockedBy("has_workbench", provider.has(ModBlocks.WORKBENCH_WORKBENCH_BLOCK.asItem())) + .bookCategory(ModRecipeDisplay.WORKBENCH_SEARCH) + .save(exporter, "crude_sword"); } } diff --git a/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java b/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java new file mode 100644 index 0000000..fc728d8 --- /dev/null +++ b/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java @@ -0,0 +1,94 @@ +package com.tcm.MineTale.block.workbenches; + +import com.mojang.serialization.MapCodec; +import com.tcm.MineTale.block.workbenches.entity.AbstractWorkbenchEntity; +import com.tcm.MineTale.block.workbenches.entity.AlchemistsWorkbenchEntity; +import com.tcm.MineTale.registry.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public class AlchemistsWorkbench extends AbstractWorkbench { + public static final boolean IS_WIDE = true; + public static final boolean IS_TALL = false; + + public static final MapCodec CODEC = simpleCodec(AlchemistsWorkbench::new); + + /** + * Constructs a ArmorersWorkbench that uses the mod's ARMORERS_WORKBENCH block entity type. + * + * @param properties block properties for this workbench + */ + public AlchemistsWorkbench(Properties properties) { + // Hardcode the supplier and sounds here if they never change + super(properties, () -> ModBlockEntities.ALCHEMISTS_WORKBENCH_BE, IS_WIDE, IS_TALL, 1); + } + + /** + * Constructs a ArmorersWorkbench using the provided block properties and block-entity type supplier. + * + * @param properties block properties to apply to this workbench + * @param supplier supplier that provides the BlockEntityType for the ArmorersWorkbenchEntity + */ + public AlchemistsWorkbench(Properties properties, Supplier> supplier) { + super(properties, supplier, IS_WIDE, IS_TALL, 1); + } + + /** + * Provides a ticker for workbench block entities when the supplied block entity type matches this block's entity type. + * + * @param type the block entity type to match against this block's workbench entity type + * @return a BlockEntityTicker that updates matching workbench block entities, or {@code null} if the types do not match + */ + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + // This connects the Level's ticking system to your static tick method + return createTickerHelper(type, ModBlockEntities.ALCHEMISTS_WORKBENCH_BE, AbstractWorkbenchEntity::tick); + } + + /** + * Provides the MapCodec used to serialize and deserialize this workbench. + * + * @return the MapCodec for this ArmorersWorkbench + */ + @Override + protected MapCodec codec() { + return CODEC; + } + + /** + * Specifies that this block is rendered using its block model. + * + * @return RenderShape.MODEL to render the block using its JSON/model representation. + */ + @Override + public RenderShape getRenderShape(BlockState state) { + // BaseEntityBlock defaults to INVISIBLE. + // We set it to MODEL so the JSON model is rendered. + return RenderShape.MODEL; + } + + private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 16, 16); + + /** + * The block's collision and interaction shape as a 1×1 footprint (x 0–16, y 0–16, z 0–16). + * + * @return the voxel shape used for collision and interaction + */ + @Override + public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SHAPE; + } +} \ No newline at end of file diff --git a/src/main/java/com/tcm/MineTale/block/workbenches/entity/AlchemistsWorkbenchEntity.java b/src/main/java/com/tcm/MineTale/block/workbenches/entity/AlchemistsWorkbenchEntity.java new file mode 100644 index 0000000..6b410ed --- /dev/null +++ b/src/main/java/com/tcm/MineTale/block/workbenches/entity/AlchemistsWorkbenchEntity.java @@ -0,0 +1,174 @@ +package com.tcm.MineTale.block.workbenches.entity; + +import com.mojang.serialization.Codec; +import com.tcm.MineTale.block.workbenches.menu.AlchemistsWorkbenchMenu; +import com.tcm.MineTale.recipe.WorkbenchRecipe; +import com.tcm.MineTale.registry.ModBlockEntities; +import com.tcm.MineTale.registry.ModRecipes; +import com.tcm.MineTale.util.Constants; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; +import org.jspecify.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class AlchemistsWorkbenchEntity extends AbstractWorkbenchEntity { + protected final ContainerData data = new ContainerData() { + /** + * Retrieves an internal data value by index for UI synchronization. + * + * @param index There is no cook time or anything for this block as it doesnt use it + * @return the value associated with {@code index}, or 0 for any other index + */ + @Override + public int get(int index) { + return switch (index) { + default -> 0; + }; + } + + /** + * No-op for this workbench; data is server-driven and not set client-side. + * + * `@param` index the data index to set + * `@param` value the value to assign (ignored) + */ + @Override + public void set(int index, int value) { + // Not required on WorkbenchEntity + } + + /** + * The number of data values exposed by this ContainerData. + * + * @return the number of data entries (4) + */ + @Override + public int getCount() { + return 4; + } + }; + + /** + * Creates a ArmorersWorkbenchEntity for the specified world position and block state. + * + * Sets the entity's scanRadius to 0.0 and tier to 1. + * + * @param blockPos the world position of this block entity + * @param blockState the block state for this block entity + */ + public AlchemistsWorkbenchEntity(BlockPos blockPos, BlockState blockState) { + super(ModBlockEntities.ALCHEMISTS_WORKBENCH_BE, blockPos, blockState); + + this.tier = 1; + this.canPullFromNearby = true; + } + + /** + * Persist this workbench's state to the given ValueOutput. + * + * Stores "WorkbenchTier" (int), "ScanRadius" (double), and the full inventory under "Inventory" + * using type-safe Codecs. + * + * @param valueOutput the writer used to serialize this entity's fields + */ + @Override + protected void saveAdditional(ValueOutput valueOutput) { + super.saveAdditional(valueOutput); + // store() uses Codecs for type safety + valueOutput.store("WorkbenchTier", Codec.INT, this.tier); + valueOutput.store("ScanRadius", Codec.DOUBLE, this.scanRadius); + + // Convert the SimpleContainer to a List of ItemStacks for the Codec + // Or use the built-in NBT helper if your framework supports it + List stacks = new ArrayList<>(); + for (int i = 0; i < inventory.getContainerSize(); i++) { + stacks.add(inventory.getItem(i)); + } + + // CHANGE: Use OPTIONAL_CODEC instead of CODEC + valueOutput.store("Inventory", ItemStack.OPTIONAL_CODEC.listOf(), stacks); + } + + /** + * Restores workbench-specific state from persistent storage, applying defaults when keys are absent. + * + * Delegates to the superclass load logic, then: + * - reads "WorkbenchTier" (int) into {@code tier}, defaulting to {@code 1} if missing; + * - reads "ScanRadius" (double) into {@code scanRadius}, defaulting to {@code 0.0} if missing; + * - reads "Inventory" as a list of {@code ItemStack} and populates the internal inventory up to its capacity. + */ + @Override + protected void loadAdditional(ValueInput valueInput) { + super.loadAdditional(valueInput); + // read() returns an Optional + this.tier = valueInput.read("WorkbenchTier", Codec.INT).orElse(1); + this.scanRadius = valueInput.read("ScanRadius", Codec.DOUBLE).orElse(0.0); + + // Read the inventory list back + valueInput.read("Inventory", ItemStack.OPTIONAL_CODEC.listOf()).ifPresent(stacks -> { + for (int i = 0; i < stacks.size() && i < inventory.getContainerSize(); i++) { + inventory.setItem(i, stacks.get(i)); + } + }); + } + + /** + * Creates the server-side container menu for this workbench's UI. + * + * @param syncId the window id used to synchronize the menu with the client + * @param playerInventory the opening player's inventory + * @param player the player who opened the menu + * @return a ArmorersWorkbenchMenu bound to this workbench's inventory and synced data + */ + @Override + public @Nullable AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) { + // 1. Trigger the sync to the client before returning the menu + if (player instanceof ServerPlayer serverPlayer) { + this.syncNearbyToPlayer(serverPlayer); + } + + // // 2. Return the menu as usual + return new AlchemistsWorkbenchMenu(syncId, playerInventory, this.data, this); + } + + /** + * Identifies the recipe type used to find and match recipes for this workbench. + * + * @return the RecipeType for workbench recipes + */ + @Override + public RecipeType getWorkbenchRecipeType() { + return ModRecipes.ALCHEMISTS_TYPE; + } + + /** + * Determines whether the workbench currently has fuel available. + * + * Checks that the entity is in a loaded level and that the configured fuel slot contains an item. + * + * @return `true` if the entity is in a loaded level and the fuel slot contains an item, `false` otherwise. + */ + @Override + protected boolean hasFuel() { + if (this.level == null) return false; + + // Check if block is lit + // BlockState state = this.level.getBlockState(this.worldPosition); + // boolean isLit = state.hasProperty(BlockStateProperties.LIT) && state.getValue(BlockStateProperties.LIT); + + boolean hasFuelItem = !this.getItem(Constants.FUEL_SLOT).isEmpty(); + + return hasFuelItem; + } +} \ No newline at end of file diff --git a/src/main/java/com/tcm/MineTale/block/workbenches/menu/AlchemistsWorkbenchMenu.java b/src/main/java/com/tcm/MineTale/block/workbenches/menu/AlchemistsWorkbenchMenu.java new file mode 100644 index 0000000..43223ee --- /dev/null +++ b/src/main/java/com/tcm/MineTale/block/workbenches/menu/AlchemistsWorkbenchMenu.java @@ -0,0 +1,128 @@ +package com.tcm.MineTale.block.workbenches.menu; + +import com.tcm.MineTale.block.workbenches.entity.AbstractWorkbenchEntity; +import com.tcm.MineTale.recipe.WorkbenchRecipeInput; +import com.tcm.MineTale.registry.ModMenuTypes; +import com.tcm.MineTale.registry.ModRecipes; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.StackedItemContents; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.RecipeBookType; +import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraft.world.item.ItemStack; +import org.jspecify.annotations.Nullable; + +import java.util.List; + +public class AlchemistsWorkbenchMenu extends AbstractWorkbenchContainerMenu { + // No internal inventory needed anymore, but we pass an empty container to the super + private static final int EMPTY_SIZE = 0; + private static final int DATA_SIZE = 0; + + @Nullable + private final AbstractWorkbenchEntity blockEntity; + private final Inventory playerInventory; + + /** + * Creates a client-side menu instance when the workbench UI is opened. + * + * @param syncId the synchronization id used to match this menu with the server + * @param playerInventory the player's inventory bound to this menu + */ + public AlchemistsWorkbenchMenu(int syncId, Inventory playerInventory) { + this(syncId, playerInventory, new SimpleContainerData(EMPTY_SIZE), null); + } + + /** + * Creates a workbench menu bound to the given player inventory and optional block entity. + * + * Uses an empty internal container (size 0) and the class's data size to synchronise numeric state. + * + * @param syncId the synchronisation id for this menu + * @param playerInventory the player's inventory used for slot access and recipe-book integration + * @param data container data used to synchronise numeric state between server and client + * @param blockEntity nullable block entity this menu is bound to, or {@code null} if not bound + */ + public AlchemistsWorkbenchMenu(int syncId, Inventory playerInventory, ContainerData data, @Nullable AbstractWorkbenchEntity blockEntity) { + // Note: The order of arguments depends on your AbstractWorkbenchContainerMenu, + // but the 'expectedSize' parameter MUST be 0. + super( + ModMenuTypes.ALCHEMISTS_WORKBENCH_MENU, + syncId, + new SimpleContainer(EMPTY_SIZE), + data, + DATA_SIZE, + playerInventory, + EMPTY_SIZE, + EMPTY_SIZE, + ModRecipes.ALCHEMISTS_TYPE + ); + this.blockEntity = blockEntity; + this.playerInventory = playerInventory; + } + + /** + * Accesses the block entity bound to this menu, if present. + * + * @return the bound AbstractWorkbenchEntity, or {@code null} if this menu is not bound to a block entity + */ + @Override + public @Nullable AbstractWorkbenchEntity getBlockEntity() { + return this.blockEntity; + } + + /** + * Populates the given StackedItemContents with item stacks relevant to crafting lookups. + * + * Includes stacks from the player's inventory, this menu's internal container slots, and + * nearby item stacks supplied via networked data when available. + * + * @param contents the StackedItemContents to populate with accounted stacks + */ + @Override + public void fillCraftSlotsStackedContents(StackedItemContents contents) { + // 1. Account for items in the player's pockets + this.playerInventory.fillStackedContents(contents); + + // 2. Account for items sitting in the Workbench slots (if any) + for (int i = 0; i < this.container.getContainerSize(); i++) { + contents.accountStack(this.container.getItem(i)); + } + + // 3. THE FIX: Use the list provided by the Packet (Networked Items) + // We stop calling be.getNearbyInventories() here because it returns empty on Client + List nearbyItems = this.getNetworkedNearbyItems(); + + if (!nearbyItems.isEmpty() && this.playerInventory.player.level().isClientSide()) { + System.out.println("DEBUG: Recipe Book is now accounting for " + nearbyItems.size() + " stacks from the packet!"); + } + + for (ItemStack stack : nearbyItems) { + contents.accountStack(stack); + } + } + + /** + * Selects the crafting recipe-book category for this menu. + * + * @return {@code RecipeBookType.CRAFTING} + */ + @Override + public RecipeBookType getRecipeBookType() { + // This keeps the Crafting-style recipe book available on the UI + return RecipeBookType.CRAFTING; + } + + /** + * Create the recipe input used by this menu's crafting UI; this implementation provides an empty input. + * + * @return a WorkbenchRecipeInput with both input stacks set to ItemStack.EMPTY + */ + @Override + public WorkbenchRecipeInput createRecipeInput() { + // Since there are no slots, we return an empty input. + // The actual crafting logic will scan the player inventory directly when a button is clicked. + return new WorkbenchRecipeInput(ItemStack.EMPTY, ItemStack.EMPTY); + } +} \ No newline at end of file diff --git a/src/main/java/com/tcm/MineTale/registry/ModBlockEntities.java b/src/main/java/com/tcm/MineTale/registry/ModBlockEntities.java index 736a04b..5d93d24 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModBlockEntities.java +++ b/src/main/java/com/tcm/MineTale/registry/ModBlockEntities.java @@ -54,6 +54,12 @@ public class ModBlockEntities { ModBlocks.FURNITURE_WORKBENCH_BLOCK ); + public static final BlockEntityType ALCHEMISTS_WORKBENCH_BE = register( + "alchemists_workbench_be", + AlchemistsWorkbenchEntity::new, + ModBlocks.ALCHEMISTS_WORKBENCH_BLOCK + ); + /** * Register a BlockEntityType for the given furnace tier and store it in the tier map. * diff --git a/src/main/java/com/tcm/MineTale/registry/ModBlocks.java b/src/main/java/com/tcm/MineTale/registry/ModBlocks.java index 8b78800..eec8434 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModBlocks.java +++ b/src/main/java/com/tcm/MineTale/registry/ModBlocks.java @@ -104,6 +104,13 @@ public class ModBlocks { true ); + public static final Block ALCHEMISTS_WORKBENCH_BLOCK = register( + "alchemists_workbench", + AlchemistsWorkbench::new, + BlockBehaviour.Properties.of().sound(SoundType.STONE), + true + ); + //Is not usable in Hytale. Can make into workbench later public static final Block WOODCUTTERS_BLOCK = register( "woodcutters_block", @@ -235,7 +242,7 @@ public class ModBlocks { public static final Block HAY_TARGET = register("hay_target", Block::new, BlockBehaviour.Properties.of().sound(SoundType.CHERRY_LEAVES), true); // Bed - //TODO: Fix these little shits + //TODO: These are just deco right now and not functional public static final Block FERAN_BED = registerBed("feran_bed", Block::new, BlockBehaviour.Properties.of().sound(SoundType.WOOD), MapColor.COLOR_ORANGE, true); public static final Block BAMBOO_BED = registerBed("bamboo_bed", Block::new, BlockBehaviour.Properties.of().sound(SoundType.WOOD), MapColor.COLOR_CYAN, true); public static final Block LUMBERJACK_BED = registerBed("lumberjack_bed", Block::new, BlockBehaviour.Properties.of().sound(SoundType.WOOD), MapColor.COLOR_BROWN, true); diff --git a/src/main/java/com/tcm/MineTale/registry/ModItems.java b/src/main/java/com/tcm/MineTale/registry/ModItems.java index 914a6a9..5e103f6 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModItems.java +++ b/src/main/java/com/tcm/MineTale/registry/ModItems.java @@ -9,6 +9,7 @@ import com.tcm.MineTale.item.ModArmorMaterials; import com.tcm.MineTale.item.ModCreativeTab; +import com.tcm.MineTale.util.ModTags; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponents; @@ -131,6 +132,10 @@ public static void initialize() { public static final Item ESSENCE_OF_ICE = register("essence_of_ice", Item::new, new Item.Properties()); public static final Item ESSENCE_OF_THE_VOID = register("essence_of_the_void", Item::new, new Item.Properties()); public static final Item VOID_HEART = register("void_heart", Item::new, new Item.Properties()); + public static final Item EMPTY_POTION_BOTTLE = register("empty_potion_bottle", Item::new, new Item.Properties()); + public static final Item ANTIDOTE = register("antidote", Item::new, new Item.Properties()); + public static final Item BOOM_POWDER = register("boom_powder", Item::new, new Item.Properties()); + public static final Item POPBERRY_BOMB = register("popberry_bomb", Item::new, new Item.Properties()); // --- FLORA COMPONENTS (Non-placeable petals) --- public static final Item RED_PETALS = register("red_petals", Item::new, new Item.Properties()); @@ -173,15 +178,41 @@ public static void initialize() { "copper_mace", MaceItem::new, new Item.Properties() - .rarity(Rarity.EPIC) - .durability(500) + .rarity(Rarity.UNCOMMON) + .durability(300) .component(DataComponents.TOOL, MaceItem.createToolProperties()) .repairable(Items.COPPER_INGOT) .attributes(MaceItem.createAttributes()) - .enchantable(15) + .enchantable(10) .component(DataComponents.WEAPON, new Weapon(1)) ); + public static final Item CRUDE_MACE = register( + "crude_mace", + MaceItem::new, + new Item.Properties() + .rarity(Rarity.COMMON) + .durability(100) + .component(DataComponents.TOOL, MaceItem.createToolProperties()) + .repairable(ItemTags.STONE_TOOL_MATERIALS) + .attributes(MaceItem.createAttributes()) + .enchantable(7) + .component(DataComponents.WEAPON, new Weapon(1)) + ); + + public static final Item CRUDE_BUILDERS_HAMMER = register("crude_builders_hammer", Item::new, new Item.Properties()); + public static final Item CRUDE_HATCHET = register("crude_hatchet", Item::new, new Item.Properties()); + public static final Item CRUDE_BATTLEAXE = register("crude_battleaxe", Item::new, new Item.Properties()); + public static final Item CRUDE_DAGGERS = register("crude_daggers", Item::new, new Item.Properties()); + public static final Item CRUDE_SHORTBOW = register("crude_shortbow", BowItem::new, new Item.Properties()); + public static final Item CRUDE_SWORD = register("crude_sword", Item::new, new Item.Properties()); + public static final Item CRUDE_LONGSWORD = register("crude_longsword", Item::new, new Item.Properties()); + public static final Item COPPER_HATCHET = register("copper_hatchet", Item::new, new Item.Properties()); + public static final Item COPPER_DAGGERS = register("copper_daggers", Item::new, new Item.Properties()); + public static final Item COPPER_BATTLEAXE = register("copper_battleaxe", Item::new, new Item.Properties()); + public static final Item COPPER_LONGSWORD = register("copper_longsword", Item::new, new Item.Properties()); + public static final Item COPPER_SHORTBOW = register("copper_shortbow", BowItem::new, new Item.Properties()); + // --- REGISTRATION LOGIC --- public static GenericItem register(String name, Function itemFactory, Item.Properties settings) { ResourceKey itemKey = ResourceKey.create(Registries.ITEM, Identifier.fromNamespaceAndPath(MineTale.MOD_ID, name)); diff --git a/src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java b/src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java index 0ea0fe6..1c7a2cc 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java +++ b/src/main/java/com/tcm/MineTale/registry/ModMenuTypes.java @@ -51,6 +51,11 @@ public class ModMenuTypes { "furniture_workbench_menu", FurnitureWorkbenchMenu::new ); + + public static final MenuType ALCHEMISTS_WORKBENCH_MENU = register( + "alchemists_workbench_menu", + AlchemistsWorkbenchMenu::new + ); /** * Triggers static registration of the mod's menu types. diff --git a/src/main/java/com/tcm/MineTale/registry/ModRecipeDisplay.java b/src/main/java/com/tcm/MineTale/registry/ModRecipeDisplay.java index 8ede1c4..5022aa0 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModRecipeDisplay.java +++ b/src/main/java/com/tcm/MineTale/registry/ModRecipeDisplay.java @@ -42,6 +42,10 @@ public class ModRecipeDisplay { public static final RecipeDisplay.Type FURNITURE_TYPE = new RecipeDisplay.Type<>(WorkbenchRecipeDisplay.CODEC, STREAM_CODEC); + public static final RecipeDisplay.Type ALCHEMISTS_TYPE = + new RecipeDisplay.Type<>(WorkbenchRecipeDisplay.CODEC, STREAM_CODEC); + + // 1. Declare the fields but don't assign them yet public static final RecipeBookCategory CAMPFIRE_SEARCH = registerCategory("campfire_recipe_book_category"); public static final RecipeBookCategory WORKBENCH_SEARCH = registerCategory("workbench_recipe_book_category"); @@ -51,6 +55,7 @@ public class ModRecipeDisplay { public static final RecipeBookCategory BUILDERS_SEARCH = registerCategory("builders_recipe_book_category"); public static final RecipeBookCategory BLACKSMITHS_SEARCH = registerCategory("blacksmiths_recipe_book_category"); public static final RecipeBookCategory FURNITURE_SEARCH = registerCategory("furniture_recipe_book_category"); + public static final RecipeBookCategory ALCHEMISTS_SEARCH = registerCategory("alchemists_recipe_book_category"); /** * Registers the workbench recipe display type into the built-in recipe display registry. diff --git a/src/main/java/com/tcm/MineTale/registry/ModRecipes.java b/src/main/java/com/tcm/MineTale/registry/ModRecipes.java index ddcbf73..ff4bd70 100644 --- a/src/main/java/com/tcm/MineTale/registry/ModRecipes.java +++ b/src/main/java/com/tcm/MineTale/registry/ModRecipes.java @@ -21,6 +21,7 @@ public class ModRecipes { public static final RecipeType BUILDERS_TYPE = createType("builders_recipe_type"); public static final RecipeType BLACKSMITHS_TYPE = createType("blacksmiths_recipe_type"); public static final RecipeType FURNITURE_TYPE = createType("furniture_recipe_type"); + public static final RecipeType ALCHEMISTS_TYPE = createType("alchemists_recipe_type"); // 2. Define the Serializers (The "How") // We pass the specific Type into the Serializer's constructor @@ -48,6 +49,9 @@ public class ModRecipes { public static final RecipeSerializer FURNITURE_SERIALIZER = new WorkbenchRecipe.Serializer(FURNITURE_TYPE); + public static final RecipeSerializer ALCHEMISTS_SERIALIZER = + new WorkbenchRecipe.Serializer(ALCHEMISTS_TYPE); + /** * Registers the mod's recipe types and their serializers into Minecraft's built-in registries under the mod namespace. * @@ -72,6 +76,8 @@ public static void initialize() { register(BLACKSMITHS_TYPE, BLACKSMITHS_SERIALIZER); register(FURNITURE_TYPE, FURNITURE_SERIALIZER); + + register(ALCHEMISTS_TYPE, ALCHEMISTS_SERIALIZER); } /** From 3ebe2bfad057803d33a3f25e27e747199f9794d7 Mon Sep 17 00:00:00 2001 From: AnyaPizza Date: Wed, 4 Mar 2026 16:35:44 -0500 Subject: [PATCH 2/2] fixed some of #66 problems --- .../java/com/tcm/MineTale/MineTaleClient.java | 1 + .../tcm/MineTale/datagen/ModLangProvider.java | 2 +- .../tcm/MineTale/datagen/ModModelProvider.java | 1 + .../block/workbenches/AlchemistsWorkbench.java | 16 ---------------- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/client/java/com/tcm/MineTale/MineTaleClient.java b/src/client/java/com/tcm/MineTale/MineTaleClient.java index 1af871c..fe20045 100644 --- a/src/client/java/com/tcm/MineTale/MineTaleClient.java +++ b/src/client/java/com/tcm/MineTale/MineTaleClient.java @@ -41,6 +41,7 @@ public void onInitializeClient() { MenuScreens.register(ModMenuTypes.BUILDERS_WORKBENCH_MENU, BuildersWorkbenchScreen::new); MenuScreens.register(ModMenuTypes.BLACKSMITHS_WORKBENCH_MENU, BlacksmithsWorkbenchScreen::new); MenuScreens.register(ModMenuTypes.FURNITURE_WORKBENCH_MENU, FurnitureWorkbenchScreen::new); + MenuScreens.register(ModMenuTypes.ALCHEMISTS_WORKBENCH_MENU, AlchemistsWorkbenchScreen::new); BlockRenderLayerMap.putBlock(ModBlocks.FURNACE_WORKBENCH_BLOCK_T1, ChunkSectionLayer.CUTOUT); BlockRenderLayerMap.putBlock(ModBlocks.FURNACE_WORKBENCH_BLOCK_T2, ChunkSectionLayer.CUTOUT); diff --git a/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java index ffa014c..b3642b7 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModLangProvider.java @@ -272,7 +272,7 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio translationBuilder.add("item.minetale.essence_of_the_void", "Essence of the Void"); translationBuilder.add("item.minetale.void_heart", "Void Heart"); translationBuilder.add("item.minetale.empty_potion_bottle", "Empty Potion Bottle"); - translationBuilder.add("item.minetale.antitode", "Antidote"); + translationBuilder.add("item.minetale.antidote", "Antidote"); translationBuilder.add("item.minetale.boom_powder", "Boom Powder"); translationBuilder.add("item.minetale.popberry_bomb", "Popberry Bomb"); diff --git a/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java b/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java index 37f060a..470e94c 100644 --- a/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java +++ b/src/client/java/com/tcm/MineTale/datagen/ModModelProvider.java @@ -136,6 +136,7 @@ public void generateItemModels(ItemModelGenerators itemModelGenerators) { itemModelGenerators.generateFlatItem(ModItems.POOP, ModelTemplates.FLAT_HANDHELD_ITEM); itemModelGenerators.generateFlatItem(ModItems.EMPTY_POTION_BOTTLE, ModelTemplates.FLAT_HANDHELD_ITEM); itemModelGenerators.generateFlatItem(ModItems.ANTIDOTE, ModelTemplates.FLAT_HANDHELD_ITEM); + itemModelGenerators.generateFlatItem(ModItems.BOOM_POWDER, ModelTemplates.FLAT_HANDHELD_ITEM); itemModelGenerators.generateFlatItem(ModItems.POPBERRY_BOMB, ModelTemplates.FLAT_HANDHELD_ITEM); } diff --git a/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java b/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java index fc728d8..cf683d4 100644 --- a/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java +++ b/src/main/java/com/tcm/MineTale/block/workbenches/AlchemistsWorkbench.java @@ -25,22 +25,11 @@ public class AlchemistsWorkbench extends AbstractWorkbench CODEC = simpleCodec(AlchemistsWorkbench::new); - /** - * Constructs a ArmorersWorkbench that uses the mod's ARMORERS_WORKBENCH block entity type. - * - * @param properties block properties for this workbench - */ public AlchemistsWorkbench(Properties properties) { // Hardcode the supplier and sounds here if they never change super(properties, () -> ModBlockEntities.ALCHEMISTS_WORKBENCH_BE, IS_WIDE, IS_TALL, 1); } - /** - * Constructs a ArmorersWorkbench using the provided block properties and block-entity type supplier. - * - * @param properties block properties to apply to this workbench - * @param supplier supplier that provides the BlockEntityType for the ArmorersWorkbenchEntity - */ public AlchemistsWorkbench(Properties properties, Supplier> supplier) { super(properties, supplier, IS_WIDE, IS_TALL, 1); } @@ -58,11 +47,6 @@ public BlockEntityTicker getTicker(Level level, Block return createTickerHelper(type, ModBlockEntities.ALCHEMISTS_WORKBENCH_BE, AbstractWorkbenchEntity::tick); } - /** - * Provides the MapCodec used to serialize and deserialize this workbench. - * - * @return the MapCodec for this ArmorersWorkbench - */ @Override protected MapCodec codec() { return CODEC;