Forge, Slag, almost forge functionality

This commit is contained in:
Halbear
2026-07-31 02:28:04 +01:00
parent e929455902
commit e416507768
19 changed files with 536 additions and 12 deletions
@@ -65,13 +65,13 @@ public class AlloyFurnaceGUIScreen extends AbstractContainerScreen<AlloyFurnaceG
int bellowPush = this.menu.getSyncedVariable(3);
int blowerSprite = (int)Math.clamp(3 * (float)bellowPush/(float)MAX_BELLOW,0,2);
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, BELLOW_SPRITE_SHEET, this.leftPos + 9, this.topPos + 58, 0, 20 * blowerSprite, 35, 20, 35, 60);
int CookProgress = GetMoltenProgress(world,x,y,z,19,0,0);
int CookProgress = GetMoltenProgress(world,x,y,z,19,0,0,100f);
if(CookProgress > 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<AlloyFurnaceG
// if(position == null) return MinimumHeight;
// }
int cookProgress = this.menu.getSyncedVariable(ElementVariable);
float Multipler = Math.min((float)cookProgress/100.0f,1.0f);
float Multipler = Math.min((float)cookProgress/MaxValue,1.0f);
int TargetHeight = (int)Math.ceil((float)FullHeight*Multipler);
return Math.clamp(TargetHeight,MinimumHeight,FullHeight);
}
@@ -1,9 +1,14 @@
package net.halbear.aotg.custom.GuiScreens;
import com.mojang.blaze3d.platform.InputConstants;
import net.halbear.aotg.custom.blocks.Forge.ForgeItemRecipe;
import net.halbear.aotg.custom.blocks.Forge.ForgeItemsScrollList;
import net.halbear.aotg.custom.blocks.Forge.ForgeWorkbenchGUI;
import net.halbear.aotg.registries.ModBlocks;
import net.halbear.aotg.registries.ModItems;
import net.halbear.aotg.registries.ModScreens;
import net.halbear.aotg.utility.Networking.AlloyFurnaceGuiButtonHandler;
import net.halbear.aotg.utility.Networking.ForgeWorkbenchGuiButtonHandler;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.gui.components.WidgetSprites;
@@ -15,10 +20,15 @@ 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.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.client.network.ClientPacketDistributor;
import java.util.ArrayList;
import java.util.List;
public class ForgeWorkbenchGUIScreen extends AbstractContainerScreen<ForgeWorkbenchGUI> implements ModScreens.ScreenAccessor {
private final Level world;
@@ -26,11 +36,28 @@ public class ForgeWorkbenchGUIScreen extends AbstractContainerScreen<ForgeWorkbe
private final Player entity;
private boolean menuStateUpdateActive = false;
private ImageButton Blower;
private static final Identifier BACKGROUND = Identifier.parse("ageofthegods:textures/screens/alloy_furnace_gui.png");
private static final Identifier BACKGROUND = Identifier.parse("ageofthegods:textures/screens/forge_gui.png");
private static final Identifier BELLOW_SPRITE_SHEET = Identifier.parse("ageofthegods:textures/screens/bellow-sheet.png");
private static final Identifier MOLTEN_FILL_SPRITE = Identifier.parse("ageofthegods:textures/screens/alloy_furnace_molten_element_gui.png");
private static final Identifier FLAME_SPRITE = Identifier.parse("ageofthegods:textures/screens/alloy_furnace_flame_gui.png");
public ForgeItemsScrollList scrollList;
private ItemStack hoveredStack = ItemStack.EMPTY;
private ItemStack selectedStack = ItemStack.EMPTY;
public void setHoveredStack(ItemStack stack) {
this.hoveredStack = stack;
}
public void setSelectedStack(ItemStack stack) {
this.selectedStack = stack;
}
public void onItemClicked(ItemStack clickedStack) {
if (this.minecraft.player != null) {
this.minecraft.player.sendOverlayMessage(
Component.literal("Selected: ").append(clickedStack.getHoverName())
);
}
}
public ForgeWorkbenchGUIScreen(ForgeWorkbenchGUI container, Inventory inventory, Component text) {
super(container, inventory, text, 176, 166);
@@ -49,12 +76,25 @@ public class ForgeWorkbenchGUIScreen extends AbstractContainerScreen<ForgeWorkbe
@Override
public void extractRenderState(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) {
super.extractRenderState(guiGraphics, mouseX, mouseY, partialTicks);
if(selectedStack != ItemStack.EMPTY){
guiGraphics.fakeItem(selectedStack,this.leftPos + 115, this.topPos + 13);
}
ForgeItemRecipe.RecipeSet set = menu.GetRecipes();
List<ItemStack> 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 AbstractContainerScreen<ForgeWorkbe
return super.keyPressed(event);
}
public void SetScrollListItems(List<ItemStack>itemStacks){
List<ItemStack> 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<ItemStack> 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);
}
}
@@ -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();
@@ -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;
}
};
@@ -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<Item, ForgeItemRecipe> FORGE_ITEM_RECIPE_MAP = new HashMap<>();
public static final Map<Item, List<Item>> 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<ForgeItemRecipe> GetRecipesContainingItem(Item item){
List<Item> Metal1Recipes = ITEM_RECIPE_REVERSE_LOOKUP.get(item);
List<ForgeItemRecipe> 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<ForgeItemRecipe> GetValidRecipesFromContainer(ItemStack Pot, ItemStack Secondary){
return GetAllValidRecipesFromContainer(Pot,Secondary).ItemRecipes;
}
public static RecipeSet GetAllValidRecipesFromContainer(ItemStack Pot, ItemStack Secondary){
List<ForgedAlloyRecipe> availableAlloyRecipes = ForgedAlloyRecipe.GetValidRecipesFromContainer(Pot);
List<Item> ItemsToSearchWith = new ArrayList<>();
ItemsToSearchWith.add(Secondary.getItem());
availableAlloyRecipes.forEach(forgedAlloyRecipe -> {
ItemsToSearchWith.add(forgedAlloyRecipe.OutcomeItem());
});
Set<ForgeItemRecipe> ValidRecipeSet = new LinkedHashSet<>();
ItemsToSearchWith.forEach(item->{
ValidRecipeSet.addAll(GetRecipesContainingItem(item));
});
return new RecipeSet(availableAlloyRecipes, new ArrayList<>(ValidRecipeSet));
}
public record RecipeSet(List<ForgedAlloyRecipe> AlloyRecipes, List<ForgeItemRecipe> ItemRecipes){}
}
@@ -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<ForgeItemsScrollList.ItemEntry> {
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<ItemStack> 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<ItemEntry> 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<ItemStack> 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);
}
}
}
}
@@ -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<ItemStack> items = NonNullList.withSize(3, ItemStack.EMPTY);
private NonNullList<ItemStack> items = NonNullList.withSize(5, ItemStack.EMPTY);
public int GetForgeLevel(){return (int)ForgeLevel;}
public void SetForgeLevel(int BellowPush){this.ForgeLevel = BellowPush ;}
@@ -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<Boolean> 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;
}
}));
@@ -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<Item,ForgedAlloyRecipe> RecipeMap = new HashMap<>();
public static final Map<Item, List<Item>> 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<ForgedAlloyRecipe> GetRecipesContainingMetals(Item Metal1, Item Metal2){
List<Item> Metal1Recipes = ReverseLookupRecipeMap.get(Metal1);
List<Item> Metal2Recipes = ReverseLookupRecipeMap.get(Metal2);
List<ForgedAlloyRecipe> 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<ForgedAlloyRecipe> GetValidRecipesFromContainer(ItemStack Pot){
List<ForgedAlloyRecipe> availableRecipes = new ArrayList<>();
List<ForgedAlloyRecipe> 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<ForgedAlloyRecipe> GetAvailableRecipesFromContainer(ItemStack Pot){
List<ForgedAlloyRecipe> 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;
}
}
@@ -36,6 +36,7 @@ public class ModItems {
public static final DeferredItem<Item> ORICHALCUM_INGOT = RegisterItem("orichalcum_ingot", Item::new);
public static final DeferredItem<Item> HEPATIZON_INGOT = RegisterItem("hepatizon_ingot", Item::new);
public static final DeferredItem<Item> SILVER_INGOT = RegisterItem("silver_ingot", Item::new);
public static final DeferredItem<Item> HARDENED_SLAG = RegisterItem("slag", Item::new);
public static final DeferredItem<Item> XIPHOS_SWORD = RegisterItem("xiphos",
properties -> new Item(properties
@@ -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());
}
@@ -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<ForgeWorkbenchGuiButtonHandler> TYPE = new Type<>(Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "forge_workbench_buttons"));
public static final StreamCodec<RegistryFriendlyByteBuf, ForgeWorkbenchGuiButtonHandler> 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<ForgeWorkbenchGuiButtonHandler> 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);
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "ageofthegods:item/slag"
}
}
@@ -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",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "ageofthegods:item/slag"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB