diff --git a/src/main/java/net/halbear/aotg/custom/GuiScreens/AlloyFurnaceGUIScreen.java b/src/main/java/net/halbear/aotg/custom/GuiScreens/AlloyFurnaceGUIScreen.java index 8a97872..1b381d7 100644 --- a/src/main/java/net/halbear/aotg/custom/GuiScreens/AlloyFurnaceGUIScreen.java +++ b/src/main/java/net/halbear/aotg/custom/GuiScreens/AlloyFurnaceGUIScreen.java @@ -65,13 +65,13 @@ public class AlloyFurnaceGUIScreen extends AbstractContainerScreen 0) guiGraphics.blit(RenderPipelines.GUI_TEXTURED, MOLTEN_FILL_SPRITE, this.leftPos + 100, this.topPos + 36 + (19 - CookProgress), 0, 0, 17, CookProgress, 17, 19); - int FuelProgress = GetMoltenProgress(world,x,y,z,21,0,1); + int FuelProgress = GetMoltenProgress(world,x,y,z,21,0,1,this.menu.getSyncedVariable(4)); if(FuelProgress > 0) guiGraphics.blit(RenderPipelines.GUI_TEXTURED, FLAME_SPRITE, this.leftPos + 47, this.topPos + 54 + (21 - FuelProgress), 0, 21 - FuelProgress, 14, FuelProgress, 14, 21); } - private int GetMoltenProgress(Level world, int x, int y, int z, int FullHeight, int MinimumHeight, int ElementVariable){ + private int GetMoltenProgress(Level world, int x, int y, int z, int FullHeight, int MinimumHeight, int ElementVariable, float MaxValue){ BlockState state = world.getBlockState(new BlockPos(x,y,z)); BlockPos position = new BlockPos(x,y,z); if(state.getBlock().getName().getString().equals(ModBlocks.ALLOY_FURNACE.get().getName().getString())) { @@ -81,7 +81,7 @@ public class AlloyFurnaceGUIScreen extends AbstractContainerScreen implements ModScreens.ScreenAccessor { private final Level world; @@ -26,11 +36,28 @@ public class ForgeWorkbenchGUIScreen extends AbstractContainerScreen previewList = new ArrayList<>(); + set.AlloyRecipes().forEach(forgedAlloyRecipe -> { + previewList.add(new ItemStack(forgedAlloyRecipe.OutcomeItem())); + }); + set.ItemRecipes().forEach(forgedAlloyRecipe -> { + previewList.add(new ItemStack(forgedAlloyRecipe.primaryOutcomeItem())); + }); + this.scrollList.refreshItems(previewList); } @Override public void extractBackground(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) { super.extractBackground(guiGraphics, mouseX, mouseY, partialTicks); guiGraphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, this.imageWidth, this.imageHeight); + } @Override @@ -67,14 +107,51 @@ public class ForgeWorkbenchGUIScreen extends AbstractContainerScreenitemStacks){ + List previewList = new ArrayList<>(); + previewList.addAll(itemStacks); + this.scrollList.refreshItems(previewList); + } + @Override protected void extractLabels(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY) { - guiGraphics.text(this.font, Component.translatable("gui.ageofthegods.forge_workbench.title"), 90, 6, -12829636, false); + guiGraphics.text(this.font, Component.translatable("gui.ageofthegods.forge_workbench.title"), 114, 61, -12829636, false); } @Override public void init() { super.init(); + int listWidth = 66; + int listHeight = 74; + int topOffset = this.topPos; + this.scrollList = new ForgeItemsScrollList(this, this.minecraft, listWidth, listHeight, topOffset, 18); + this.scrollList.setPosition( this.leftPos + 29, topOffset + 6); + + List previewList = new ArrayList<>(); + previewList.add(new ItemStack(ModItems.XIPHOS_SWORD.asItem())); + previewList.add(new ItemStack(ModItems.BRONZE_INGOT.asItem())); + previewList.add(new ItemStack(ModItems.ORICHALCUM_INGOT.asItem())); + previewList.add(new ItemStack(ModItems.ELECTRUM_INGOT.asItem())); + previewList.add(new ItemStack(ModItems.HEPATIZON_INGOT.asItem())); + + this.scrollList.refreshItems(previewList); + this.addRenderableWidget(this.scrollList); + this.addWidget(this.scrollList); + + Blower = new ImageButton( this.leftPos + 100, this.topPos + 56, 47, 22, + new WidgetSprites(Identifier.parse("ageofthegods:textures/screens/forge_button_clear.png"), Identifier.parse("ageofthegods:textures/screens/forge_button_hover.png")), e -> { + int x = ForgeWorkbenchGUIScreen.this.x; + int y = ForgeWorkbenchGUIScreen.this.y; + int z = ForgeWorkbenchGUIScreen.this.z; + ClientPacketDistributor.sendToServer(new ForgeWorkbenchGuiButtonHandler(0, x, y, z)); + ForgeWorkbenchGuiButtonHandler.handleButtonAction(entity, 0, x, y, z); + }) { + @Override + public void extractContents(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) { + guiGraphics.blit(RenderPipelines.GUI_TEXTURED, sprites.get(isActive(), isHoveredOrFocused()), getX(), getY(), 0, 0, width, height, width, height); + } + }; + this.addRenderableWidget(Blower); } } diff --git a/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceBlockEntity.java b/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceBlockEntity.java index a639a1a..54fc191 100644 --- a/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceBlockEntity.java +++ b/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceBlockEntity.java @@ -22,9 +22,11 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.FuelValues; import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.ValueInput; @@ -46,6 +48,7 @@ public class AlloyFurnaceBlockEntity extends RandomizableContainerBlockEntity im private boolean isFormed = false; private float Fuel = 0.0f; private float CookProcess = 0.0f; + private float CurrentFuelTime = 0.0f; private float TemperatureC = 0.0f; private float BellowPush = 0.0f; private boolean AbleToCook = false; @@ -63,6 +66,8 @@ public class AlloyFurnaceBlockEntity extends RandomizableContainerBlockEntity im public void SetFuel(int Fuel){this.Fuel = Fuel ;} public int GetTemperatureC(){return (int) TemperatureC;} public void SetTemperatureC(int Temp){this.TemperatureC = Temp ;} + public int GetCurrentFuelTime(){return (int) CurrentFuelTime;} + public void SetCurrentFuelTime(int Temp){this.CurrentFuelTime = Temp ;} public AlloyFurnaceBlockEntity(BlockPos worldPosition, BlockState blockState) { super(ALLOY_FURNACE_BLOCK_ENTITY.get(), worldPosition, blockState); @@ -119,6 +124,7 @@ public class AlloyFurnaceBlockEntity extends RandomizableContainerBlockEntity im if(blockEntity.pushBellow && blockEntity.BellowPush < MAX_BELLOW){ blockEntity.BellowPush += 1; } else if(blockEntity.pushBellow) blockEntity.pushBellow = false; + blockEntity.Fuel = Math.max(blockEntity.Fuel - 1f, 0); if (level.getGameTime() % 5 == 0) { if (level.getGameTime() % 20 == 0) { blockEntity.isFormed = blockEntity.UpdateCompleteStructure(level,pos,state,blockEntity.checkStructure(level, pos, state)); @@ -141,7 +147,8 @@ public class AlloyFurnaceBlockEntity extends RandomizableContainerBlockEntity im blockEntity.CookProcess = Math.min(blockEntity.CookProcess + 1f + blockEntity.BellowPush,100); } else blockEntity.CookProcess = 0; } else if(!blockEntity.items.get(3).isEmpty() && ((!blockEntity.items.get(0).isEmpty() || !blockEntity.items.get(1).isEmpty() ) && !blockEntity.items.get(2).isEmpty() || (!blockEntity.items.get(5).isEmpty() || !blockEntity.items.get(6).isEmpty() ) && !blockEntity.items.get(7).isEmpty())){ - blockEntity.Fuel = 100f; + blockEntity.Fuel = blockEntity.items.get(3).getBurnTime(RecipeType.SMELTING, level.fuelValues()); + blockEntity.SetCurrentFuelTime((int)blockEntity.Fuel); blockEntity.items.get(3).setCount(Math.max(blockEntity.items.get(3).getCount() - 1,0)); } if (blockEntity.CookProcess >= 100f) { @@ -156,7 +163,6 @@ public class AlloyFurnaceBlockEntity extends RandomizableContainerBlockEntity im } else{ blockEntity.CookProcess = 0f; } - blockEntity.Fuel = Math.max(blockEntity.Fuel - 1f, 0); blockEntity.AbleToCook = blockEntity.items.get(4).isEmpty() ; blockEntity.AbleToStartCooking = blockEntity.items.get(2).getItem().equals(Items.DECORATED_POT) && (!blockEntity.items.get(0).isEmpty()||!blockEntity.items.get(1).isEmpty()); blockEntity.setChanged(); diff --git a/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceGUI.java b/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceGUI.java index 44f3bdd..e15f646 100644 --- a/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceGUI.java +++ b/src/main/java/net/halbear/aotg/custom/blocks/AlloyFurnace/AlloyFurnaceGUI.java @@ -89,12 +89,23 @@ public class AlloyFurnaceGUI extends AbstractContainerMenu implements ModMenus.M private final int slot = 2; private int x = this.x; private int y = this.y; + private final int maxLimit = 1; @Override public boolean mayPlace(ItemStack stack) { return Blocks.DECORATED_POT.asItem() == stack.getItem(); } + @Override + public int getMaxStackSize() { + return this.maxLimit; + } + + @Override + public int getMaxStackSize(ItemStack stack) { + return Math.min(this.maxLimit, super.getMaxStackSize(stack)); + } + })); this.customSlots.put(3, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 3, 64, 58) { private final int slot = 3; @@ -140,6 +151,9 @@ public class AlloyFurnaceGUI extends AbstractContainerMenu implements ModMenus.M case 3: returnVal = alloyFurnaceBlockEntity.GetBellowPush(); break; + case 4: + returnVal = alloyFurnaceBlockEntity.GetCurrentFuelTime(); + break; } return returnVal; } @@ -159,12 +173,15 @@ public class AlloyFurnaceGUI extends AbstractContainerMenu implements ModMenus.M case 3: alloyFurnaceBlockEntity.SetBellowPush(value); break; + case 4: + alloyFurnaceBlockEntity.SetCurrentFuelTime(value); + break; } } @Override public int getCount() { - return 4; + return 5; } }; diff --git a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemRecipe.java b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemRecipe.java new file mode 100644 index 0000000..c273a90 --- /dev/null +++ b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemRecipe.java @@ -0,0 +1,66 @@ +package net.halbear.aotg.custom.blocks.Forge; + +import net.halbear.aotg.registries.ModItems; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.ItemContainerContents; + +import java.util.*; + +import static net.halbear.aotg.custom.blocks.Forge.ForgedAlloyRecipe.GetRecipesContainingMetals; + +public record ForgeItemRecipe(Item primaryOutcomeItem, Item[] RequiredItems, int[] RequiredItemCounts) { + public static final Map FORGE_ITEM_RECIPE_MAP = new HashMap<>(); + public static final Map> ITEM_RECIPE_REVERSE_LOOKUP = new HashMap<>(); + static{ + FORGE_ITEM_RECIPE_MAP.put(ModItems.XIPHOS_SWORD.asItem(),new ForgeItemRecipe(ModItems.XIPHOS_SWORD.asItem(),new Item[]{ModItems.BRONZE_INGOT.asItem(), Items.STICK},new int[]{2,1})); + CompileReverseLookupMap(); + } + + public static void CompileReverseLookupMap(){ + ITEM_RECIPE_REVERSE_LOOKUP.clear(); + FORGE_ITEM_RECIPE_MAP.forEach((name, recipe)->{ + Arrays.stream(recipe.RequiredItems).toList().forEach(item -> { + if(!ITEM_RECIPE_REVERSE_LOOKUP.containsKey(item)){ + ITEM_RECIPE_REVERSE_LOOKUP.put(item, new ArrayList<>()); + } + ITEM_RECIPE_REVERSE_LOOKUP.get(item).add(name); + }); + }); + } + + public static List GetRecipesContainingItem(Item item){ + List Metal1Recipes = ITEM_RECIPE_REVERSE_LOOKUP.get(item); + List overlapping = new ArrayList<>(); + if(Metal1Recipes != null) { + for (int i = 0; i < Metal1Recipes.size(); i++) { + if(Metal1Recipes.get(i) == null) continue; + overlapping.add(FORGE_ITEM_RECIPE_MAP.get(Metal1Recipes.get(i))); + } + } + return overlapping; + } + + public static List GetValidRecipesFromContainer(ItemStack Pot, ItemStack Secondary){ + return GetAllValidRecipesFromContainer(Pot,Secondary).ItemRecipes; + } + + public static RecipeSet GetAllValidRecipesFromContainer(ItemStack Pot, ItemStack Secondary){ + List availableAlloyRecipes = ForgedAlloyRecipe.GetValidRecipesFromContainer(Pot); + List ItemsToSearchWith = new ArrayList<>(); + ItemsToSearchWith.add(Secondary.getItem()); + availableAlloyRecipes.forEach(forgedAlloyRecipe -> { + ItemsToSearchWith.add(forgedAlloyRecipe.OutcomeItem()); + }); + Set ValidRecipeSet = new LinkedHashSet<>(); + ItemsToSearchWith.forEach(item->{ + ValidRecipeSet.addAll(GetRecipesContainingItem(item)); + }); + return new RecipeSet(availableAlloyRecipes, new ArrayList<>(ValidRecipeSet)); + } + + + public record RecipeSet(List AlloyRecipes, List ItemRecipes){} +} diff --git a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemsScrollList.java b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemsScrollList.java new file mode 100644 index 0000000..508559b --- /dev/null +++ b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeItemsScrollList.java @@ -0,0 +1,109 @@ +package net.halbear.aotg.custom.blocks.Forge; + +import net.halbear.aotg.custom.GuiScreens.ForgeWorkbenchGUIScreen; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.ObjectSelectionList; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jspecify.annotations.NonNull; + +import java.util.ArrayList; +import java.util.List; + +public class ForgeItemsScrollList extends ObjectSelectionList { + private final ForgeWorkbenchGUIScreen parent; + public ForgeItemsScrollList(ForgeWorkbenchGUIScreen parent, Minecraft minecraft, int width, int height, int y, int itemHeight) { + super(minecraft, width, height, y, itemHeight); + this.parent = parent; + } + + public void refreshItems(List items) { + this.clearEntries(); + for (ItemStack stack : items) { + this.addEntry(new ItemEntry(this.parent, stack)); + } + } + + @Override + public int getRowWidth() { + return 68 - this.scrollbarWidth(); + } + @Override + public void setSelected(ForgeItemsScrollList.ItemEntry entry) { + super.setSelected(entry); + + if (entry != null) { + this.parent.onItemClicked(entry.getItemStack()); + parent.setSelectedStack(entry.getItemStack()); + } + } + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { + if (parent.scrollList != null && parent.scrollList.mouseScrolled(mouseX, mouseY, scrollX, scrollY)) { + return true; + } + return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY); + } + @Override + protected int scrollBarX() { + return this.getX() + this.getRowWidth(); + } + + public static class ItemEntry extends ObjectSelectionList.Entry implements GuiEventListener { + private final ForgeWorkbenchGUIScreen parent; + private final ItemStack itemStack; + + public ItemEntry(ForgeWorkbenchGUIScreen parent, ItemStack stack) { + this.parent = parent; + this.itemStack = stack; + } + + public ItemStack getItemStack(){return itemStack;} + + @Override + public Component getNarration() { + return this.itemStack.getDisplayName(); + } + + @Override + public void extractContent(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean isHovered, float partialTick) { + int left = this.getX(); + int top = this.getY(); + int rowWidth = this.getWidth(); + int rowHeight = this.getHeight(); + + if (isHovered) { + graphics.fill(left, top, left + rowWidth, top + rowHeight, 0x22FFFFFF); + } + List recipeItems = new ArrayList<>(); + ForgedAlloyRecipe alloy_recipe = ForgedAlloyRecipe.RecipeMap.get(this.itemStack.getItem()); + ForgeItemRecipe item_recipe = ForgeItemRecipe.FORGE_ITEM_RECIPE_MAP.get(this.itemStack.getItem()); + if(alloy_recipe != null){ + recipeItems.add(new ItemStack(alloy_recipe.RequiredMetal1(), alloy_recipe.AlloyRatio() < 1 ? 1 : (int)alloy_recipe.AlloyRatio())); + recipeItems.add(new ItemStack(alloy_recipe.RequiredMetal2(), alloy_recipe.AlloyRatio() < 1 ? 1/(int)alloy_recipe.AlloyRatio() : 1)); + } + if(item_recipe != null){ + for(int i = 0; i < item_recipe.RequiredItems().length; i++){ + recipeItems.add(new ItemStack(item_recipe.RequiredItems()[i], item_recipe.RequiredItemCounts()[i])); + } + } + graphics.fakeItem(this.itemStack, left + 4, top); + graphics.pose().pushMatrix(); + graphics.pose().translate(left + 28, top + 2); + graphics.pose().scale(0.75f, 0.75f); + for(int i = 0; i < recipeItems.size(); i++){ + graphics.fakeItem(recipeItems.get(i), (i * 20),1); + graphics.text(parent.getFont(), "" + recipeItems.get(i).getCount(), (i * 20) + 17 - parent.getFont().width("" + recipeItems.get(i).getCount()), 9, -1, true); + } + graphics.pose().popMatrix(); + + if (isHovered && mouseX >= left && mouseX <= left + rowWidth && mouseY >= top && mouseY <= top + rowHeight) { + this.parent.setHoveredStack(this.itemStack); + } + } + + } +} diff --git a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchBlockEntity.java b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchBlockEntity.java index a9fd56a..063618b 100644 --- a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchBlockEntity.java +++ b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchBlockEntity.java @@ -39,7 +39,7 @@ import static net.halbear.aotg.registries.ModBlockEntities.FORGE_WORKBENCH_BLOCK public class ForgeWorkbenchBlockEntity extends RandomizableContainerBlockEntity implements MenuProvider, WorldlyContainer { private int ForgeLevel = 0; - private NonNullList items = NonNullList.withSize(3, ItemStack.EMPTY); + private NonNullList items = NonNullList.withSize(5, ItemStack.EMPTY); public int GetForgeLevel(){return (int)ForgeLevel;} public void SetForgeLevel(int BellowPush){this.ForgeLevel = BellowPush ;} diff --git a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchGUI.java b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchGUI.java index 31ca700..2c3e428 100644 --- a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchGUI.java +++ b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgeWorkbenchGUI.java @@ -13,12 +13,14 @@ import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.transfer.ResourceHandler; import net.neoforged.neoforge.transfer.item.*; import net.neoforged.neoforge.transfer.transaction.Transaction; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -43,8 +45,9 @@ public class ForgeWorkbenchGUI extends AbstractContainerMenu implements ModMenus private Supplier boundItemMatcher = null; private BlockEntity boundBlockEntity = null; private final ContainerData data; + private ForgeItemRecipe.RecipeSet Recipes = new ForgeItemRecipe.RecipeSet(new ArrayList<>(), new ArrayList<>()); - + public ForgeItemRecipe.RecipeSet GetRecipes(){return Recipes;} public ForgeWorkbenchGUI(int containerId, Inventory playerInv, FriendlyByteBuf buffer) { super(ModMenus.FORGE_WORKBENCH_GUI.get(), containerId); @@ -68,10 +71,71 @@ public class ForgeWorkbenchGUI extends AbstractContainerMenu implements ModMenus this.bound = true; } } - this.customSlots.put(0, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 0, 37, 16) { + ForgeWorkbenchGUI currentGUI = this; + currentGUI.Recipes = ForgeItemRecipe.GetAllValidRecipesFromContainer(currentGUI.getSlot(0).getItem(), currentGUI.getSlot(1).getItem()); + this.customSlots.put(0, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 0, 8, 37) { private final int slot = 0; private int x = this.x; private int y = this.y; + private final int maxLimit = 1; + + @Override + public boolean mayPlace(ItemStack stack) { + return Blocks.DECORATED_POT.asItem() == stack.getItem(); + } + + @Override + public int getMaxStackSize() { + return this.maxLimit; + } + + @Override + public int getMaxStackSize(ItemStack stack) { + return Math.min(this.maxLimit, super.getMaxStackSize(stack)); + } + + @Override + public void setByPlayer(ItemStack newStack, ItemStack oldStack) { + super.setByPlayer(newStack, oldStack); + currentGUI.Recipes = ForgeItemRecipe.GetAllValidRecipesFromContainer(newStack, currentGUI.getSlot(1).getItem()); + } + })); + this.customSlots.put(1, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 1, 8, 63) { + private final int slot = 1; + private int x = this.x; + private int y = this.y; + @Override + public void setByPlayer(ItemStack newStack, ItemStack oldStack) { + super.setByPlayer(newStack, oldStack); + currentGUI.Recipes = ForgeItemRecipe.GetAllValidRecipesFromContainer( currentGUI.getSlot(0).getItem(), newStack); + } + })); + this.customSlots.put(2, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 2, 152, 37) { + private final int slot = 2; + private int x = this.x; + private int y = this.y; + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } + })); + this.customSlots.put(3, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 3, 152, 17) { + private final int slot = 3; + private int x = this.x; + private int y = this.y; + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } + })); + this.customSlots.put(4, this.addSlot(new ResourceHandlerSlot(internal, this::setItemInSlot, 4, 152, 57) { + private final int slot = 4; + private int x = this.x; + private int y = this.y; + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } })); diff --git a/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgedAlloyRecipe.java b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgedAlloyRecipe.java new file mode 100644 index 0000000..2017e01 --- /dev/null +++ b/src/main/java/net/halbear/aotg/custom/blocks/Forge/ForgedAlloyRecipe.java @@ -0,0 +1,94 @@ +package net.halbear.aotg.custom.blocks.Forge; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.registries.ModItems; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.ItemContainerContents; +import net.minecraft.world.level.material.Fluids; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public record ForgedAlloyRecipe(Item OutcomeItem, Item RequiredMetal1, Item RequiredMetal2, float AlloyRatio) { + public static final Map RecipeMap = new HashMap<>(); + public static final Map> ReverseLookupRecipeMap = new HashMap<>(); + static { + RecipeMap.put(ModItems.BRONZE_INGOT.asItem(), new ForgedAlloyRecipe(ModItems.BRONZE_INGOT.asItem(), Items.COPPER_INGOT, ModItems.TIN_INGOT.asItem(),9f)); + RecipeMap.put(ModItems.ELECTRUM_INGOT.asItem(), new ForgedAlloyRecipe(ModItems.ELECTRUM_INGOT.asItem(), Items.GOLD_INGOT, ModItems.SILVER_INGOT.asItem(), 3f)); + RecipeMap.put(ModItems.ORICHALCUM_INGOT.asItem(), new ForgedAlloyRecipe(ModItems.ORICHALCUM_INGOT.asItem(), Items.COPPER_INGOT, ModItems.ZINC_INGOT.asItem(),4f)); + RecipeMap.put(ModItems.HEPATIZON_INGOT.asItem(), new ForgedAlloyRecipe(ModItems.HEPATIZON_INGOT.asItem(), Items.COPPER_INGOT, Items.GOLD_INGOT,9f)); + CompileReverseLookupMap(); + } + + public static void CompileReverseLookupMap(){ + ReverseLookupRecipeMap.clear(); + RecipeMap.forEach((name, recipe)->{ + Item item1 = recipe.RequiredMetal1; + Item item2 = recipe.RequiredMetal2; + if(!ReverseLookupRecipeMap.containsKey(item1)){ + ReverseLookupRecipeMap.put(item1, new ArrayList<>()); + } + if(!ReverseLookupRecipeMap.containsKey(item2)){ + ReverseLookupRecipeMap.put(item2, new ArrayList<>()); + } + ReverseLookupRecipeMap.get(item1).add(name); + ReverseLookupRecipeMap.get(item2).add(name); + }); + } + + public static List GetRecipesContainingMetals(Item Metal1, Item Metal2){ + List Metal1Recipes = ReverseLookupRecipeMap.get(Metal1); + List Metal2Recipes = ReverseLookupRecipeMap.get(Metal2); + List overlapping = new ArrayList<>(); + if(Metal1Recipes != null && Metal2Recipes != null) { + for (Item metal1Recipe : Metal1Recipes) { + if (metal1Recipe == null) continue; + if (Metal2Recipes.contains(metal1Recipe)) overlapping.add(RecipeMap.get(metal1Recipe)); + } + } + return overlapping; + } + + public static List GetValidRecipesFromContainer(ItemStack Pot){ + List availableRecipes = new ArrayList<>(); + List ValidRecipes = new ArrayList<>(); + if(Pot.getItem().equals(Items.DECORATED_POT)){ + ItemContainerContents potContents = Pot.get(DataComponents.CONTAINER); + if (potContents != null) { + boolean hasMarker = potContents.getStackInSlot(0).getItem().equals(ModItems.FLUID_INDICATOR_ITEM.asItem()); + if (hasMarker) { + ItemStack AlloyMetal1 = potContents.getStackInSlot(1); + ItemStack AlloyMetal2 = potContents.getStackInSlot(2); + availableRecipes = GetRecipesContainingMetals(AlloyMetal1.getItem(),AlloyMetal2.getItem()); + availableRecipes.forEach(forgedAlloyRecipe -> { + if(Math.floor((float) AlloyMetal1.getCount() /(float)AlloyMetal2.getCount()) == Math.floor(forgedAlloyRecipe.AlloyRatio)) { + ValidRecipes.add(forgedAlloyRecipe); + } + }); + } + } + } + return ValidRecipes; + } + + public static List GetAvailableRecipesFromContainer(ItemStack Pot){ + List availableRecipes = new ArrayList<>(); + if(Pot.getItem().equals(Items.DECORATED_POT)){ + ItemContainerContents potContents = Pot.get(DataComponents.CONTAINER); + if (potContents != null) { + boolean hasMarker = potContents.getStackInSlot(0).getItem().equals(ModItems.FLUID_INDICATOR_ITEM.asItem()); + if (hasMarker) { + ItemStack AlloyMetal1 = potContents.getStackInSlot(1); + ItemStack AlloyMetal2 = potContents.getStackInSlot(2); + return GetRecipesContainingMetals(AlloyMetal1.getItem(),AlloyMetal2.getItem()); + } + } + } + return availableRecipes; + } +} diff --git a/src/main/java/net/halbear/aotg/registries/ModItems.java b/src/main/java/net/halbear/aotg/registries/ModItems.java index 83a2ae7..760ada8 100644 --- a/src/main/java/net/halbear/aotg/registries/ModItems.java +++ b/src/main/java/net/halbear/aotg/registries/ModItems.java @@ -36,6 +36,7 @@ public class ModItems { public static final DeferredItem ORICHALCUM_INGOT = RegisterItem("orichalcum_ingot", Item::new); public static final DeferredItem HEPATIZON_INGOT = RegisterItem("hepatizon_ingot", Item::new); public static final DeferredItem SILVER_INGOT = RegisterItem("silver_ingot", Item::new); + public static final DeferredItem HARDENED_SLAG = RegisterItem("slag", Item::new); public static final DeferredItem XIPHOS_SWORD = RegisterItem("xiphos", properties -> new Item(properties diff --git a/src/main/java/net/halbear/aotg/registries/ModTabs.java b/src/main/java/net/halbear/aotg/registries/ModTabs.java index 1ae453b..31086c5 100644 --- a/src/main/java/net/halbear/aotg/registries/ModTabs.java +++ b/src/main/java/net/halbear/aotg/registries/ModTabs.java @@ -49,5 +49,6 @@ public class ModTabs { output.accept(ELECTRUM_INGOT.get()); output.accept(HEPATIZON_INGOT.get()); output.accept(ORICHALCUM_INGOT.get()); + output.accept(HARDENED_SLAG.get()); }).build()); } diff --git a/src/main/java/net/halbear/aotg/utility/Networking/ForgeWorkbenchGuiButtonHandler.java b/src/main/java/net/halbear/aotg/utility/Networking/ForgeWorkbenchGuiButtonHandler.java new file mode 100644 index 0000000..3057186 --- /dev/null +++ b/src/main/java/net/halbear/aotg/utility/Networking/ForgeWorkbenchGuiButtonHandler.java @@ -0,0 +1,76 @@ +package net.halbear.aotg.utility.Networking; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceBlockEntity; +import net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceUpdateHandler; +import net.halbear.aotg.registries.ModBlocks; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.PacketFlow; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.Identifier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; + +import static net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceMultiBlock.MODEL_PART; +import static net.halbear.aotg.custom.blocks.AlloyFurnace.AlloyFurnaceMultiBlock.PARENT_BLOCK; + +@EventBusSubscriber +public record ForgeWorkbenchGuiButtonHandler(int buttonID, int x, int y, int z) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "forge_workbench_buttons")); + public static final StreamCodec STREAM_CODEC = StreamCodec.of((RegistryFriendlyByteBuf buffer, ForgeWorkbenchGuiButtonHandler message) -> { + buffer.writeInt(message.buttonID); + buffer.writeInt(message.x); + buffer.writeInt(message.y); + buffer.writeInt(message.z); + }, (RegistryFriendlyByteBuf buffer) -> new ForgeWorkbenchGuiButtonHandler(buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readInt())); + + @Override + public Type type() { + return TYPE; + } + + public static void handleData(final ForgeWorkbenchGuiButtonHandler message, final IPayloadContext context) { + if (context.flow() == PacketFlow.SERVERBOUND) { + context.enqueueWork(() -> handleButtonAction(context.player(), message.buttonID, message.x, message.y, message.z)).exceptionally(e -> { + context.connection().disconnect(Component.literal(e.getMessage())); + return null; + }); + } + } + + public static void handleButtonAction(Player entity, int buttonID, int x, int y, int z) { + Level world = entity.level(); + if (!world.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z))) + return; + if (buttonID == 0) { + + } + } + @SubscribeEvent + public static void registerMessage(final RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1.0.0"); + + registrar.playToServer( + ForgeWorkbenchGuiButtonHandler.TYPE, + ForgeWorkbenchGuiButtonHandler.STREAM_CODEC, + ForgeWorkbenchGuiButtonHandler::handleData + ); + } + @SubscribeEvent + public static void registerMessage(FMLCommonSetupEvent event) { + AgeoftheGods.addNetworkMessage(ForgeWorkbenchGuiButtonHandler.TYPE, ForgeWorkbenchGuiButtonHandler.STREAM_CODEC, ForgeWorkbenchGuiButtonHandler::handleData); + } + +} diff --git a/src/main/resources/assets/ageofthegods/Items/slag.json b/src/main/resources/assets/ageofthegods/Items/slag.json new file mode 100644 index 0000000..56cbad4 --- /dev/null +++ b/src/main/resources/assets/ageofthegods/Items/slag.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "ageofthegods:item/slag" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ageofthegods/lang/en_us.json b/src/main/resources/assets/ageofthegods/lang/en_us.json index c9bd05f..6bc347b 100644 --- a/src/main/resources/assets/ageofthegods/lang/en_us.json +++ b/src/main/resources/assets/ageofthegods/lang/en_us.json @@ -22,6 +22,7 @@ "item.ageofthegods.hepatizon_ingot": "Hepatizon Ingot", "item.ageofthegods.orichalcum_ingot": "Orichalcum Ingot", "item.ageofthegods.fluid_indicator_debug_item": "Molten Alloy Mixture: ", + "item.ageofthegods.slag": "Hardened Slag", "ageofthegods.configuration.title": "Age of the Gods Configs", "ageofthegods.configuration.section.ageofthegods.common.toml": "Age of the Gods Configs", diff --git a/src/main/resources/assets/ageofthegods/models/item/slag.json b/src/main/resources/assets/ageofthegods/models/item/slag.json new file mode 100644 index 0000000..e764f2c --- /dev/null +++ b/src/main/resources/assets/ageofthegods/models/item/slag.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "ageofthegods:item/slag" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ageofthegods/textures/item/slag.png b/src/main/resources/assets/ageofthegods/textures/item/slag.png new file mode 100644 index 0000000..043d021 Binary files /dev/null and b/src/main/resources/assets/ageofthegods/textures/item/slag.png differ diff --git a/src/main/resources/assets/ageofthegods/textures/screens/forge_button_clear.png b/src/main/resources/assets/ageofthegods/textures/screens/forge_button_clear.png new file mode 100644 index 0000000..fc0746d Binary files /dev/null and b/src/main/resources/assets/ageofthegods/textures/screens/forge_button_clear.png differ diff --git a/src/main/resources/assets/ageofthegods/textures/screens/forge_button_hover.png b/src/main/resources/assets/ageofthegods/textures/screens/forge_button_hover.png new file mode 100644 index 0000000..3016df9 Binary files /dev/null and b/src/main/resources/assets/ageofthegods/textures/screens/forge_button_hover.png differ diff --git a/src/main/resources/assets/ageofthegods/textures/screens/forge_gui.png b/src/main/resources/assets/ageofthegods/textures/screens/forge_gui.png new file mode 100644 index 0000000..68640d4 Binary files /dev/null and b/src/main/resources/assets/ageofthegods/textures/screens/forge_gui.png differ