From 8a68416361d491a4e1db7cd60c86ffc705e8bfaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 22 Jun 2016 09:22:49 +0200 Subject: [PATCH] Alloy furnace progress + Mostly working GUI + Many new utilities => A lot of this will need clean-up --- alloy-furnace-gui-1.xcf | Bin 44644 -> 43441 bytes alloy-furnace-gui-2.xcf | Bin 32405 -> 31640 bytes src/java/mmm/food/FMilkable.java | 12 +- src/java/mmm/materials/MAlloyRecipe.java | 11 +- .../mmm/materials/MAlloyRecipesRegistry.java | 39 ++-- .../tech/base/TBAlloyFurnaceContainer.java | 99 +++++++--- src/java/mmm/tech/base/TBAlloyFurnaceGui.java | 170 ++++++++++++++++-- .../tech/base/TBAlloyFurnaceGuiHandler.java | 16 +- .../mmm/tech/base/TBAlloyFurnaceMessage.java | 78 ++++++++ .../tech/base/TBAlloyFurnaceTileEntity.java | 36 ++++ src/java/mmm/tech/base/TechBase.java | 7 + src/java/mmm/utils/I_UMessage.java | 9 +- src/java/mmm/utils/UContainers.java | 14 +- src/java/mmm/utils/UInventoryDisplay.java | 159 ++++++++++++++++ ...InventoryGrid.java => UInventoryGrid.java} | 48 ++++- src/java/mmm/utils/UItemId.java | 93 ++++++++++ src/java/mmm/utils/URegistry.java | 4 +- src/java/mmm/utils/slots/USDisplay.java | 35 ++++ src/java/mmm/utils/slots/USFuel.java | 29 +++ src/java/mmm/utils/slots/USOutput.java | 91 ++++++++++ .../utils/slots/USVisibilityController.java | 83 +++++++++ .../mmm/textures/gui/alloy-furnace_2.png | Bin 1938 -> 0 bytes .../mmm/textures/gui/alloy_furnace_1.png | Bin 2117 -> 2169 bytes .../mmm/textures/gui/alloy_furnace_2.png | Bin 0 -> 2070 bytes 24 files changed, 934 insertions(+), 99 deletions(-) create mode 100644 src/java/mmm/tech/base/TBAlloyFurnaceMessage.java create mode 100644 src/java/mmm/utils/UInventoryDisplay.java rename src/java/mmm/utils/{A_UInventoryGrid.java => UInventoryGrid.java} (72%) create mode 100644 src/java/mmm/utils/UItemId.java create mode 100644 src/java/mmm/utils/slots/USDisplay.java create mode 100644 src/java/mmm/utils/slots/USFuel.java create mode 100644 src/java/mmm/utils/slots/USOutput.java create mode 100644 src/java/mmm/utils/slots/USVisibilityController.java delete mode 100644 src/resources/assets/mmm/textures/gui/alloy-furnace_2.png create mode 100644 src/resources/assets/mmm/textures/gui/alloy_furnace_2.png diff --git a/alloy-furnace-gui-1.xcf b/alloy-furnace-gui-1.xcf index 4e8bee10b1ca18b7511aaf90e82c47c5793ff41d..d6135f55b7a310e0bc567b468feccc447445241e 100644 GIT binary patch delta 666 zcmY+CPbg(k9LK-s+;`)?dXIA5m+SJp%@v|~l(M=0)sz(_D~3iXOyjBJ#ewc>Zo5$D$T{(isD@B2G{>ioUrduMzxV$oiE#G3gM z5E})GhXCggC|d{02LSIL@IxS|#M@_4YKgCw$J)eF(S*HA^|1JyPIX0ZCO)F`7dPcG zfX|qWe^a&n#E)K8EKaM_;*k9atsdEVO--E3e&TGCPueu{uk5 zi9lS}Oo`=0ZM_p{kD9khH0OLUnbVp18+WwUoV>|=FFXSbxLNc7 delta 1592 zcmeH{K}b|l6o&uv-m~5l#)%rIndi%CuwEz#5+W8hA_P%{Z5j#+B3uZvH3Z#V~QG?u#;5H_RHsMlfrHg3Us?EI4ow>wZK_ac47Y^s#@1A?!z2}{K);6u3 zZELYWSJs9L)NMZnj!y!KB+ym@GNXVGpyLJ5`2{#z<%t^Np_3C8>v?EBXaJmGt;7MW zDU(^V@{#?PLZ{E<%GbGSGUv9u+|q4Rzo<}}2E>drPM^eRYe#fWJF;?nw5`t8&%%M+ zg2`MyIv*UV*hYI?TL8g|PcBfAK=G-+*U>>Y9(rF;zk|n@sMaqbN?uA#d+uQ+sv+i7 zRH@ixRNHy}FY~tl^(PMYBlZutCtf3OM`_!WmOs`1e@fd(Q<42HJ6&y5ukdtC$i(ax zSw%M0!!?k&?{Ve-7@0c+JJ*f)8}WXbDt zsdd8(v&S@7y-N49tZFlAXqN4f&r)Ry{q+W}bMBZbuK(F&{G3m1K+T0sp@gA_uY`F}q+yGXWIM$HtJu_GS1<7JyBLDyZ diff --git a/alloy-furnace-gui-2.xcf b/alloy-furnace-gui-2.xcf index 23699df96582fd51392d2d8548adbba11f520618..6c21c069c31bd851973297128215c47572fe0c38 100644 GIT binary patch delta 296 zcmbRGmvP2-#tC+e5*zKU89BQd7(}cX7!+XQd&UF z!oa|k3{1_pIeAU0=U&{+Y* zI~W+uR2dj7&oMAKtp?)V3=E;J3=9eX7#IrWfmok`p|pU3q5LnX>FeqQ0+{`$i(R^~8qWEMhCLRNS1_)>X zQd&UF!oa|k4peUh5oUmjGgUJ%@a_eQZB}Pl$GG_c*G9(8S6L+f6NlI+i6J5hC%1{U72?H@B5c38k7MG-^C`^8#P{=9?6c7Wstez9df&#^f zPzFpJ&<4eoK%bmM6;}khPU$d6%;ACEf`1Pd*pg4wqieQXU>D+W%5LJnQxk2eN7zlY z^KqDOSM+awku3^QkH#mBYgc4vUC(mhzs&<+5QHqSCY`9qt;H_H<`ggpd?s2`ld$u# znGXyC>mq9~5s6?@!~%uGtpC6yVGqRMG&T8#!isv8W>7MLBtTFi1SMLP`3wwowLshn z5 MAlloyRecipe.MAX_ALLOY_INPUTS ) { throw new IllegalArgumentException( "invalid alloy recipe" ); } - this.name = name; this.burnTime = burnTime; this.xp = xp; this.output = output; @@ -34,10 +28,9 @@ public class MAlloyRecipe } - @SideOnly( Side.CLIENT ) public String getLocalizedName( ) { - return I18n.format( this.name ); + return this.output.getItem( ).getItemStackDisplayName( this.output ); } } diff --git a/src/java/mmm/materials/MAlloyRecipesRegistry.java b/src/java/mmm/materials/MAlloyRecipesRegistry.java index 5cc10fa..0a0b620 100644 --- a/src/java/mmm/materials/MAlloyRecipesRegistry.java +++ b/src/java/mmm/materials/MAlloyRecipesRegistry.java @@ -2,8 +2,11 @@ package mmm.materials; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Set; +import com.google.common.collect.HashMultimap; + +import mmm.utils.UItemId; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.relauncher.Side; @@ -14,30 +17,16 @@ import net.minecraftforge.fml.relauncher.SideOnly; public enum MAlloyRecipesRegistry { INSTANCE; - private final HashMap< String , MAlloyRecipe > recipes = new HashMap<>( ); + private final HashMultimap< UItemId , MAlloyRecipe > recipes = HashMultimap.create( ); public void addRecipe( final int burnTime , final float xp , final Item output , final Object... params ) { - this.addRecipe( output.getUnlocalizedName( ) , burnTime , xp , new ItemStack( output ) , params ); + this.addRecipe( burnTime , xp , new ItemStack( output ) , params ); } public void addRecipe( final int burnTime , final float xp , final ItemStack output , final Object... params ) - { - this.addRecipe( output.getUnlocalizedName( ) , burnTime , xp , output , params ); - } - - - public void addRecipe( final String name , final int burnTime , final float xp , final Item output , - final Object... params ) - { - this.addRecipe( name , burnTime , xp , new ItemStack( output ) , params ); - } - - - public void addRecipe( final String name , final int burnTime , final float xp , final ItemStack output , - final Object... params ) { final int nParams = params.length; final ItemStack[] inputs = new ItemStack[ nParams ]; @@ -51,24 +40,20 @@ public enum MAlloyRecipesRegistry { throw new IllegalArgumentException( "invalid alloy recipe input type" ); } } - this.addRecipe( name , burnTime , xp , output , inputs ); + this.addRecipe( burnTime , xp , output , inputs ); } - public void addRecipe( final String name , final int burnTime , final float xp , final ItemStack output , - final ItemStack[] inputs ) + public void addRecipe( final int burnTime , final float xp , final ItemStack output , final ItemStack[] inputs ) { - if ( this.recipes.containsKey( name ) ) { - throw new IllegalArgumentException( "duplicate alloy recipe '" + name + "'" ); - } - final MAlloyRecipe recipe = new MAlloyRecipe( name , burnTime , xp , output , inputs ); - this.recipes.put( name , recipe ); + final MAlloyRecipe recipe = new MAlloyRecipe( burnTime , xp , output , inputs ); + this.recipes.put( UItemId.fromItemStack( output ) , recipe ); } - public MAlloyRecipe getRecipe( final String name ) + public Set< MAlloyRecipe > getRecipe( final UItemId item ) { - return this.recipes.get( name ); + return this.recipes.get( item ); } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceContainer.java b/src/java/mmm/tech/base/TBAlloyFurnaceContainer.java index 33a6f2b..0201563 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceContainer.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceContainer.java @@ -1,55 +1,78 @@ package mmm.tech.base; +import java.util.ArrayList; + +import mmm.materials.MAlloyRecipe; +import mmm.materials.MAlloyRecipesRegistry; import mmm.utils.UContainers; +import mmm.utils.UInventoryDisplay; +import mmm.utils.UInventoryGrid; +import mmm.utils.slots.USDisplay; +import mmm.utils.slots.USFuel; +import mmm.utils.slots.USOutput; +import mmm.utils.slots.USVisibilityController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; public class TBAlloyFurnaceContainer extends Container { - private final World world; - private final BlockPos position; + private final ArrayList< MAlloyRecipe > recipes = MAlloyRecipesRegistry.INSTANCE.getSortedRecipes( ); - // public final IInventory input; - // public final IInventory fuel; - // public final IInventory output; + public final TBAlloyFurnaceTileEntity tileEntity; + public final World world; + public final BlockPos position; + + public final USVisibilityController visibilityController; + public final UInventoryGrid input; + public final UInventoryGrid fuel; + public final UInventoryGrid output; + public final UInventoryDisplay recipe; - @SideOnly( Side.CLIENT ) - public TBAlloyFurnaceContainer( final InventoryPlayer playerInv , final World world ) + public TBAlloyFurnaceContainer( final InventoryPlayer playerInv , final TBAlloyFurnaceTileEntity tileEntity ) { - this( playerInv , world , BlockPos.ORIGIN ); - } - - - public TBAlloyFurnaceContainer( final InventoryPlayer playerInv , final World world , final BlockPos blockPos ) - { - this.world = world; - this.position = blockPos; - - // this.input = input; - // this.fuel = fuel; - - // UContainers.addGrid( // - // ( i , x , y ) -> this.addSlotToContainer( new Slot( input , i , x , y ) ) , // - // 3 , 5 , 0 , 11 , 7 ); - - // UContainers.addGrid( // - // ( i , x , y ) -> this.addSlotToContainer( new SlotFurnaceFuel( fuel , i , x , y ) ) , // - // 2 , 2 , 0 , 79 , 61 ); + this.tileEntity = tileEntity; + this.world = tileEntity.getWorld( ); + this.position = tileEntity.getPos( ); + this.visibilityController = new USVisibilityController( this.inventorySlots ); + this.visibilityController.startGroup( ); UContainers.addPlayerInventory( // ( i , x , y ) -> this.addSlotToContainer( new Slot( playerInv , i , x , y ) ) , // - 7 , 111 ); + 8 , 112 ); + + this.visibilityController.startGroup( ); + this.input = tileEntity.input; + UContainers.addGrid( // + ( i , x , y ) -> this.addSlotToContainer( new Slot( this.input , i , x , y ) ) , // + this.input.width , this.input.height , 0 , 12 , 8 ); + this.fuel = tileEntity.fuel; + UContainers.addGrid( // + ( i , x , y ) -> this.addSlotToContainer( new USFuel( this.fuel , i , x , y ) ) , // + this.fuel.width , this.fuel.height , 0 , 80 , 62 ); + this.output = tileEntity.output; + UContainers.addGrid( // + ( i , x , y ) -> { + this.addSlotToContainer( new USOutput( playerInv.player , this.output , i , x , y ) ); + } , this.output.width , this.output.height , 0 , 130 , 8 ); + + this.recipe = new UInventoryDisplay( "Recipe" , 7 ); + this.visibilityController.startGroup( ); + UContainers.addGrid( // + ( i , x , y ) -> this.addSlotToContainer( new USDisplay( this.recipe , i , x , y ) ) , // + 3 , 2 , 0 , 25 , 37 , 8 , 8 ); + this.addSlotToContainer( new USDisplay( this.recipe , 6 , 131 , 49 ) ); + + this.visibilityController.finalizeGroups( ); + this.visibilityController.hideGroup( 2 ); } @@ -61,4 +84,22 @@ public class TBAlloyFurnaceContainer this.position.getZ( ) + .5 ) <= 64.; } + + public void setCurrentRecipe( int index , boolean confirm ) + { + if ( index < 0 || index >= this.recipes.size( ) ) { + // XXX log + return; + } + + MAlloyRecipe recipe = this.recipes.get( index ); + this.recipe.clear( ); + for ( int i = 0 ; i < recipe.inputs.length ; i++ ) { + this.recipe.setInventorySlotContents( i , recipe.inputs[ i ] ); + } + this.recipe.setInventorySlotContents( 6 , recipe.output ); + + // XXX confirm + } + } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceGui.java b/src/java/mmm/tech/base/TBAlloyFurnaceGui.java index f2c27ea..5c4e24f 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceGui.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceGui.java @@ -1,12 +1,17 @@ package mmm.tech.base; +import java.io.IOException; + import mmm.Mmm; +import mmm.materials.MAlloyRecipesRegistry; +import mmm.utils.URegistry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.util.ResourceLocation; -import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -16,18 +21,60 @@ import net.minecraftforge.fml.relauncher.SideOnly; public class TBAlloyFurnaceGui extends GuiContainer { + @SideOnly( Side.CLIENT ) private static enum Tab { - MAIN( 207 , 0 ) , - CONFIG( 191 , 0 ); + MAIN( 207 , 0 , 1 ) , + CONFIG( 191 , 0 , 2 ); public final int iconX; public final int iconY; + public final int slotGroup; - private Tab( final int iconX , final int iconY ) + private Tab( final int iconX , final int iconY , final int slotGroup ) { this.iconX = iconX; this.iconY = iconY; + this.slotGroup = slotGroup; + } + } + + @SideOnly( Side.CLIENT ) + private static class ArrowButton + extends GuiButton + { + private final boolean forward; + + + public ArrowButton( final int buttonID , final int x , final int y , final boolean forward ) + { + super( buttonID , x , y , 12 , 19 , "" ); + this.forward = forward; + } + + + @Override + public void drawButton( final Minecraft mc , final int mouseX , final int mouseY ) + { + if ( this.visible ) { + mc.getTextureManager( ).bindTexture( TBAlloyFurnaceGui.TEXTURES[ 1 ] ); + GlStateManager.color( 1f , 1f , 1f , 1f ); + + int texX = 176; + if ( !this.enabled ) { + texX += this.width * 2; + } else if ( mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width + && mouseY < this.yPosition + this.height ) { + texX += this.width; + } + + int texY = 0; + if ( !this.forward ) { + texY += this.height; + } + + this.drawTexturedModalRect( this.xPosition , this.yPosition , texX , texY , this.width , this.height ); + } } } @@ -41,21 +88,71 @@ public class TBAlloyFurnaceGui private static final int TAB_WIDTH = 26; private static final int TAB_HEIGHT = 26; private static final int TAB_BORDER = 4; - private static final int TABS_X = 176; - private static final int TABS_Y = 45; + private static final int TABS_TEXTURE_X = 176; + private static final int TABS_TEXTURE_Y = 45; private static final int TAB_ICON_X = 5; private static final int TAB_ICON_Y = 5; private static final int TAB_ICON_WIDTH = 16; private static final int TAB_ICON_HEIGHT = 16; - private final TBAlloyFurnaceGui.Tab selectedTab = Tab.MAIN; + private final TBAlloyFurnaceContainer container; + private ArrowButton bPrevious; + private ArrowButton bNext; + private TBAlloyFurnaceGui.Tab selectedTab = Tab.MAIN; + private int currentRecipe = 0; - public TBAlloyFurnaceGui( final InventoryPlayer inventoryPlayer , final World world ) + public TBAlloyFurnaceGui( final InventoryPlayer inventoryPlayer , final TBAlloyFurnaceTileEntity tileEntity ) { - super( new TBAlloyFurnaceContainer( inventoryPlayer , world ) ); + super( new TBAlloyFurnaceContainer( inventoryPlayer , tileEntity ) ); this.xSize = 176; this.ySize = 194; + + this.container = (TBAlloyFurnaceContainer) this.inventorySlots; + for ( final TBAlloyFurnaceGui.Tab tab : TBAlloyFurnaceGui.Tab.values( ) ) { + if ( tab != this.selectedTab ) { + this.container.visibilityController.hideGroup( tab.slotGroup ); + } + } + + this.setRecipe( 0 ); + } + + + @Override + public void initGui( ) + { + super.initGui( ); + + final int x = ( this.width - this.xSize ) / 2; + final int y = ( this.height - this.ySize ) / 2; + + this.bPrevious = new ArrowButton( 1 , 8 + x , 47 + y , false ); + this.bNext = new ArrowButton( 2 , 156 + x , 47 + y , true ); + this.bPrevious.visible = this.bNext.visible = false; + + this.buttonList.add( this.bNext ); + this.buttonList.add( this.bPrevious ); + this.enableConfigButtons( ); + } + + + private void enableConfigButtons( ) + { + if ( this.bNext != null ) { + this.bNext.enabled = this.currentRecipe < MAlloyRecipesRegistry.INSTANCE.getSortedRecipes( ).size( ) - 1; + this.bPrevious.enabled = this.currentRecipe > 0; + } + } + + + private void setRecipe( final int index ) + { + this.container.setCurrentRecipe( index , false ); + URegistry.network.sendToServer( new TBAlloyFurnaceMessage( + ( (TBAlloyFurnaceContainer) this.inventorySlots ).position , index , false ) ); + this.currentRecipe = index; + this.enableConfigButtons( ); } @@ -85,6 +182,42 @@ public class TBAlloyFurnaceGui } + @Override + protected void mouseClicked( final int mouseX , final int mouseY , final int mouseButton ) + throws IOException + { + super.mouseClicked( mouseX , mouseY , mouseButton ); + + for ( final TBAlloyFurnaceGui.Tab tab : TBAlloyFurnaceGui.Tab.values( ) ) { + if ( this.selectedTab == tab ) { + continue; + } + + final int tabOffsetX = tab.ordinal( ) * TBAlloyFurnaceGui.TAB_WIDTH; + final int tabX = this.guiLeft + tabOffsetX + TBAlloyFurnaceGui.TAB_BORDER; + final int tabY = this.guiTop - TBAlloyFurnaceGui.TAB_HEIGHT + TBAlloyFurnaceGui.TAB_BORDER; + + if ( mouseX >= tabX && mouseY >= tabY && mouseX <= tabX + TBAlloyFurnaceGui.TAB_WIDTH + && mouseY <= tabY + TBAlloyFurnaceGui.TAB_HEIGHT ) { + this.selectTab( tab ); + return; + } + } + } + + + @Override + protected void actionPerformed( final GuiButton button ) + throws IOException + { + if ( button == this.bNext ) { + this.setRecipe( this.currentRecipe + 1 ); + } else if ( button == this.bPrevious ) { + this.setRecipe( this.currentRecipe - 1 ); + } + } + + private void drawTab( final TBAlloyFurnaceGui.Tab tab ) { final boolean selected = this.selectedTab == tab; @@ -93,8 +226,8 @@ public class TBAlloyFurnaceGui final int tabY = this.guiTop - TBAlloyFurnaceGui.TAB_HEIGHT + TBAlloyFurnaceGui.TAB_BORDER; this.drawTexturedModalRect( tabX , tabY , // - TBAlloyFurnaceGui.TABS_X + tabOffsetX , - TBAlloyFurnaceGui.TABS_Y + ( selected ? TBAlloyFurnaceGui.TAB_HEIGHT : 0 ) , // + TBAlloyFurnaceGui.TABS_TEXTURE_X , + TBAlloyFurnaceGui.TABS_TEXTURE_Y + ( selected ? TBAlloyFurnaceGui.TAB_HEIGHT : 0 ) , // TBAlloyFurnaceGui.TAB_WIDTH , TBAlloyFurnaceGui.TAB_HEIGHT ); this.zLevel = 100f; @@ -105,4 +238,19 @@ public class TBAlloyFurnaceGui this.zLevel = 0; } + + private void selectTab( final TBAlloyFurnaceGui.Tab tab ) + { + this.container.visibilityController // + .hideGroup( this.selectedTab.slotGroup ) // + .showGroup( tab.slotGroup ); + this.selectedTab = tab; + + this.bNext.visible = tab == Tab.CONFIG; + this.bPrevious.visible = tab == Tab.CONFIG; + if ( tab == Tab.CONFIG ) { + this.bNext.enabled = this.currentRecipe < MAlloyRecipesRegistry.INSTANCE.getSortedRecipes( ).size( ) - 1; + this.bPrevious.enabled = this.currentRecipe > 0; + } + } } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java b/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java index 06c3c95..c6dea30 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java @@ -16,12 +16,13 @@ public class TBAlloyFurnaceGuiHandler { @Override - public Object getServerGuiElement( int ID , EntityPlayer player , World world , int x , int y , int z ) + public Object getServerGuiElement( final int ID , final EntityPlayer player , final World world , final int x , + final int y , final int z ) { - BlockPos pos = new BlockPos( x , y , z ); - TileEntity tileEntity = world.getTileEntity( pos ); + final BlockPos pos = new BlockPos( x , y , z ); + final TileEntity tileEntity = world.getTileEntity( pos ); if ( tileEntity instanceof TBAlloyFurnaceTileEntity ) { - return new TBAlloyFurnaceContainer( player.inventory , world , pos ); + return new TBAlloyFurnaceContainer( player.inventory , (TBAlloyFurnaceTileEntity) tileEntity ); } return null; } @@ -29,11 +30,12 @@ public class TBAlloyFurnaceGuiHandler @Override @SideOnly( Side.CLIENT ) - public Object getClientGuiElement( int ID , EntityPlayer player , World world , int x , int y , int z ) + public Object getClientGuiElement( final int ID , final EntityPlayer player , final World world , final int x , + final int y , final int z ) { - TileEntity tileEntity = world.getTileEntity( new BlockPos( x , y , z ) ); + final TileEntity tileEntity = world.getTileEntity( new BlockPos( x , y , z ) ); if ( tileEntity instanceof TBAlloyFurnaceTileEntity ) { - return new TBAlloyFurnaceGui( player.inventory , world ); + return new TBAlloyFurnaceGui( player.inventory , (TBAlloyFurnaceTileEntity) tileEntity ); } return null; } diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceMessage.java b/src/java/mmm/tech/base/TBAlloyFurnaceMessage.java new file mode 100644 index 0000000..bbbc361 --- /dev/null +++ b/src/java/mmm/tech/base/TBAlloyFurnaceMessage.java @@ -0,0 +1,78 @@ +package mmm.tech.base; + + +import io.netty.buffer.ByteBuf; +import mmm.utils.I_UMessage; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + + + +public class TBAlloyFurnaceMessage + implements I_UMessage +{ + private BlockPos blockPos; + private int selectedIndex; + private boolean confirm; + + + public TBAlloyFurnaceMessage( ) + { + // EMPTY + } + + + public TBAlloyFurnaceMessage( final BlockPos blockPos , final int selectedIndex , final boolean confirm ) + { + this.blockPos = blockPos; + this.selectedIndex = selectedIndex; + this.confirm = confirm; + } + + + @Override + public void fromBytes( final ByteBuf buf ) + { + this.blockPos = new BlockPos( buf.readInt( ) , buf.readInt( ) , buf.readInt( ) ); + this.selectedIndex = buf.readShort( ); + this.confirm = buf.readBoolean( ); + } + + + @Override + public void toBytes( final ByteBuf buf ) + { + buf.writeInt( this.blockPos.getX( ) ); + buf.writeInt( this.blockPos.getY( ) ); + buf.writeInt( this.blockPos.getZ( ) ); + buf.writeShort( this.selectedIndex ); + buf.writeBoolean( this.confirm ); + } + + + @Override + @SideOnly( Side.CLIENT ) + public void handleOnClient( final EntityPlayerSP player ) + { + // TODO Auto-generated method stub + } + + + @Override + public void handleOnServer( final EntityPlayerMP player ) + { + final Container curCont = player.openContainer; + if ( ! ( curCont instanceof TBAlloyFurnaceContainer ) ) { + // XXX log? + return; + } + + final TBAlloyFurnaceContainer container = (TBAlloyFurnaceContainer) curCont; + container.setCurrentRecipe( this.selectedIndex , this.confirm ); + } + +} diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java b/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java index c716a2a..b8d3b47 100644 --- a/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java +++ b/src/java/mmm/tech/base/TBAlloyFurnaceTileEntity.java @@ -1,7 +1,10 @@ package mmm.tech.base; +import mmm.utils.UInventoryGrid; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.Constants.NBT; @@ -9,4 +12,37 @@ public class TBAlloyFurnaceTileEntity extends TileEntity { + public final UInventoryGrid input; + public final UInventoryGrid fuel; + public final UInventoryGrid output; + + + public TBAlloyFurnaceTileEntity( ) + { + this.input = new UInventoryGrid( "Input" , 3 , 5 ); + this.fuel = new UInventoryGrid( "Fuel" , 2 , 2 ); + this.output = new UInventoryGrid( "Output" , 2 , 5 ); + } + + + @Override + public void readFromNBT( NBTTagCompound compound ) + { + super.readFromNBT( compound ); + this.input.deserializeNBT( compound.getTagList( "Input" , NBT.TAG_COMPOUND ) ); + this.fuel.deserializeNBT( compound.getTagList( "Fuel" , NBT.TAG_COMPOUND ) ); + this.output.deserializeNBT( compound.getTagList( "Output" , NBT.TAG_COMPOUND ) ); + } + + + @Override + public NBTTagCompound writeToNBT( NBTTagCompound compound ) + { + super.writeToNBT( compound ); + compound.setTag( "Input" , this.input.serializeNBT( ) ); + compound.setTag( "Fuel" , this.fuel.serializeNBT( ) ); + compound.setTag( "Output" , this.output.serializeNBT( ) ); + return compound; + } + } diff --git a/src/java/mmm/tech/base/TechBase.java b/src/java/mmm/tech/base/TechBase.java index 1a76e55..58d5e84 100644 --- a/src/java/mmm/tech/base/TechBase.java +++ b/src/java/mmm/tech/base/TechBase.java @@ -2,7 +2,9 @@ package mmm.tech.base; import mmm.Mmm; +import mmm.materials.MAlloyRecipesRegistry; import mmm.utils.URegistry; +import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemBlockSpecial; import net.minecraftforge.fml.common.network.NetworkRegistry; @@ -27,6 +29,11 @@ public class TechBase URegistry.addBlock( TechBase.ALLOY_FURNACE_BLOCK_ACTIVE , null ); GameRegistry.registerTileEntity( TBAlloyFurnaceTileEntity.class , "mmm:tech/base/alloy_furnace" ); NetworkRegistry.INSTANCE.registerGuiHandler( Mmm.get( ) , new TBAlloyFurnaceGuiHandler( ) ); + URegistry.addServerMessage( TBAlloyFurnaceMessage.class ); + + // FIXME test, remove this later + MAlloyRecipesRegistry.INSTANCE.addRecipe( 200 , 0.05f , Items.COOKED_CHICKEN , Items.COOKED_BEEF , + Items.COOKED_PORKCHOP ); } diff --git a/src/java/mmm/utils/I_UMessage.java b/src/java/mmm/utils/I_UMessage.java index 2c62562..8a51828 100644 --- a/src/java/mmm/utils/I_UMessage.java +++ b/src/java/mmm/utils/I_UMessage.java @@ -1,7 +1,11 @@ package mmm.utils; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; @@ -9,13 +13,14 @@ public interface I_UMessage extends IMessage { - default void handleOnClient( ) + @SideOnly( Side.CLIENT ) + default void handleOnClient( final EntityPlayerSP player ) { // EMPTY } - default void handleOnServer( ) + default void handleOnServer( final EntityPlayerMP player ) { // EMPTY } diff --git a/src/java/mmm/utils/UContainers.java b/src/java/mmm/utils/UContainers.java index 1641574..1117af1 100644 --- a/src/java/mmm/utils/UContainers.java +++ b/src/java/mmm/utils/UContainers.java @@ -1,5 +1,6 @@ package mmm.utils; + public class UContainers { @@ -26,9 +27,16 @@ public class UContainers public static void addGrid( final UContainers.SlotAdder slotAdder , final int columns , final int rows , final int index , final int x , final int y ) { - for ( int row = 0 ; row < rows ; ++row ) { - for ( int column = 0 ; column < columns ; ++column ) { - slotAdder.addSlot( index + column + row * 9 , x + column * 18 , y + row * 18 ); + addGrid( slotAdder , columns , rows , index , x , y , 2 , 2 ); + } + + + public static void addGrid( final UContainers.SlotAdder slotAdder , final int columns , final int rows , + final int index , final int x , final int y , int xSpacing , int ySpacing ) + { + for ( int row = 0 , i = 0 ; row < rows ; ++row ) { + for ( int column = 0 ; column < columns ; ++column , ++i ) { + slotAdder.addSlot( index + i , x + column * ( 16 + xSpacing ) , y + row * ( 16 + ySpacing ) ); } } } diff --git a/src/java/mmm/utils/UInventoryDisplay.java b/src/java/mmm/utils/UInventoryDisplay.java new file mode 100644 index 0000000..6bbe8b7 --- /dev/null +++ b/src/java/mmm/utils/UInventoryDisplay.java @@ -0,0 +1,159 @@ +package mmm.utils; + + +import java.util.Arrays; + +import javax.annotation.Nullable; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; + + + +public class UInventoryDisplay + implements IInventory +{ + public final String name; + public final int size; + private ItemStack[] contents; + + + public UInventoryDisplay( final String name , final int size ) + { + this.name = name; + this.size = size; + this.contents = new ItemStack[ size ]; + } + + + @Override + public String getName( ) + { + return this.name; + } + + + @Override + public boolean hasCustomName( ) + { + return false; + } + + + @Override + public ITextComponent getDisplayName( ) + { + return new TextComponentTranslation( this.name ); + } + + + @Override + public int getSizeInventory( ) + { + return this.size; + } + + + @Override + @Nullable + public ItemStack getStackInSlot( final int index ) + { + return index >= 0 && index < this.size ? this.contents[ index ] : null; + } + + + @Override + public ItemStack decrStackSize( int index , int count ) + { + return null; + } + + + @Override + public ItemStack removeStackFromSlot( int index ) + { + return null; + } + + + @Override + public void setInventorySlotContents( int index , ItemStack stack ) + { + this.contents[ index ] = stack; + this.markDirty( ); + } + + + @Override + public int getInventoryStackLimit( ) + { + return 64; + } + + + @Override + public boolean isUseableByPlayer( final EntityPlayer player ) + { + return false; + } + + + @Override + public void openInventory( final EntityPlayer player ) + { + // EMPTY + } + + + @Override + public void closeInventory( final EntityPlayer player ) + { + // EMPTY + } + + + @Override + public boolean isItemValidForSlot( final int index , final ItemStack stack ) + { + return true; + } + + + @Override + public int getField( final int id ) + { + return 0; + } + + + @Override + public void setField( final int id , final int value ) + { + // EMPTY + } + + + @Override + public int getFieldCount( ) + { + return 0; + } + + + @Override + public void clear( ) + { + Arrays.fill( this.contents , null ); + } + + + @Override + public void markDirty( ) + { + // EMPTY + } + +} diff --git a/src/java/mmm/utils/A_UInventoryGrid.java b/src/java/mmm/utils/UInventoryGrid.java similarity index 72% rename from src/java/mmm/utils/A_UInventoryGrid.java rename to src/java/mmm/utils/UInventoryGrid.java index 68f4db0..a6eabe8 100644 --- a/src/java/mmm/utils/A_UInventoryGrid.java +++ b/src/java/mmm/utils/UInventoryGrid.java @@ -9,13 +9,16 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ItemStackHelper; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.util.INBTSerializable; -public abstract class A_UInventoryGrid - implements IInventory +public class UInventoryGrid + implements IInventory , INBTSerializable< NBTTagList > { public final String name; public final int width; @@ -24,7 +27,7 @@ public abstract class A_UInventoryGrid private final ItemStack[] inventoryContents; - public A_UInventoryGrid( final String name , final int width , final int height ) + public UInventoryGrid( final String name , final int width , final int height ) { this.name = name; this.width = width; @@ -175,4 +178,43 @@ public abstract class A_UInventoryGrid Arrays.fill( this.inventoryContents , null ); } + + @Override + public void markDirty( ) + { + // EMPTY + } + + + @Override + public NBTTagList serializeNBT( ) + { + final NBTTagList list = new NBTTagList( ); + for ( int i = 0 ; i < this.slotsCount ; i++ ) { + final ItemStack stack = this.inventoryContents[ i ]; + NBTTagCompound tag; + if ( stack == null ) { + tag = new NBTTagCompound( ); + } else { + tag = stack.serializeNBT( ); + } + list.appendTag( tag ); + } + return list; + } + + + @Override + public void deserializeNBT( final NBTTagList nbt ) + { + final int n = Math.min( nbt.tagCount( ) , this.slotsCount ); + Arrays.fill( this.inventoryContents , null ); + for ( int i = 0 ; i < n ; i++ ) { + final NBTTagCompound tag = nbt.getCompoundTagAt( i ); + if ( tag.hasKey( "id" ) ) { + this.inventoryContents[ i ] = ItemStack.loadItemStackFromNBT( tag ); + } + } + } + } diff --git a/src/java/mmm/utils/UItemId.java b/src/java/mmm/utils/UItemId.java new file mode 100644 index 0000000..c806681 --- /dev/null +++ b/src/java/mmm/utils/UItemId.java @@ -0,0 +1,93 @@ +package mmm.utils; + + +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + + + +public class UItemId +{ + private static final ThreadLocal< WeakHashMap< UItemId , WeakReference< UItemId > > > TABLE // + = new ThreadLocal< WeakHashMap< UItemId , WeakReference< UItemId > > >( ) { + @Override + protected WeakHashMap< UItemId , WeakReference< UItemId > > initialValue( ) + { + return new WeakHashMap<>( ); + } + }; + + + public static UItemId fromItemStack( final ItemStack stack ) + { + return UItemId.create( stack.getItem( ) , stack.getItemDamage( ) ); + } + + + public static UItemId create( final Item item ) + { + return UItemId.create( item , 0 ); + } + + + public static UItemId create( final Item item , final int meta ) + { + final UItemId id = new UItemId( item.getRegistryName( ) , meta ); + final WeakHashMap< UItemId , WeakReference< UItemId > > table = UItemId.TABLE.get( ); + if ( table.containsKey( id ) ) { + return table.get( id ).get( ); + } + table.put( id , new WeakReference< UItemId >( id ) ); + return id; + } + + public final ResourceLocation name; + public final int meta; + + + private UItemId( final ResourceLocation name , final int meta ) + { + this.name = name; + this.meta = meta; + } + + + @Override + public int hashCode( ) + { + final int prime = 31; + return prime * ( prime + this.meta ) + ( this.name == null ? 0 : this.name.hashCode( ) ); + } + + + @Override + public boolean equals( final Object obj ) + { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( this.getClass( ) != obj.getClass( ) ) { + return false; + } + final UItemId other = (UItemId) obj; + if ( this.meta != other.meta ) { + return false; + } + if ( this.name == null ) { + if ( other.name != null ) { + return false; + } + } else if ( !this.name.equals( other.name ) ) { + return false; + } + return true; + } + +} diff --git a/src/java/mmm/utils/URegistry.java b/src/java/mmm/utils/URegistry.java index 8626ac6..c2cc5e1 100644 --- a/src/java/mmm/utils/URegistry.java +++ b/src/java/mmm/utils/URegistry.java @@ -209,7 +209,7 @@ public class URegistry URegistry.network.registerMessage( // ( final I_UMessage m , final MessageContext ctx ) -> { final IThreadListener main = Minecraft.getMinecraft( ); - main.addScheduledTask( ( ) -> m.handleOnClient( ) ); + main.addScheduledTask( ( ) -> m.handleOnClient( Minecraft.getMinecraft( ).thePlayer ) ); return null; } , // message , URegistry.nextPacketDiscriminator++ , Side.CLIENT ); @@ -221,7 +221,7 @@ public class URegistry URegistry.network.registerMessage( // ( final I_UMessage m , final MessageContext ctx ) -> { final IThreadListener main = (WorldServer) ctx.getServerHandler( ).playerEntity.worldObj; - main.addScheduledTask( ( ) -> m.handleOnServer( ) ); + main.addScheduledTask( ( ) -> m.handleOnServer( ctx.getServerHandler( ).playerEntity ) ); return null; } , // message , URegistry.nextPacketDiscriminator++ , Side.SERVER ); diff --git a/src/java/mmm/utils/slots/USDisplay.java b/src/java/mmm/utils/slots/USDisplay.java new file mode 100644 index 0000000..9375080 --- /dev/null +++ b/src/java/mmm/utils/slots/USDisplay.java @@ -0,0 +1,35 @@ +package mmm.utils.slots; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + + + +/** An inventory slot that cannot be interacted with */ +public class USDisplay + extends Slot +{ + + public USDisplay( IInventory inventoryIn , int index , int xPosition , int yPosition ) + { + super( inventoryIn , index , xPosition , yPosition ); + } + + + @Override + public boolean isItemValid( ItemStack stack ) + { + return false; + } + + + @Override + public boolean canTakeStack( EntityPlayer playerIn ) + { + return false; + } + +} diff --git a/src/java/mmm/utils/slots/USFuel.java b/src/java/mmm/utils/slots/USFuel.java new file mode 100644 index 0000000..de1981f --- /dev/null +++ b/src/java/mmm/utils/slots/USFuel.java @@ -0,0 +1,29 @@ +package mmm.utils.slots; + + +import javax.annotation.Nullable; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityFurnace; + + + +public class USFuel + extends Slot +{ + + public USFuel( final IInventory inventoryIn , final int slotIndex , final int xPosition , final int yPosition ) + { + super( inventoryIn , slotIndex , xPosition , yPosition ); + } + + + @Override + public boolean isItemValid( @Nullable final ItemStack stack ) + { + return TileEntityFurnace.isItemFuel( stack ); + } + +} diff --git a/src/java/mmm/utils/slots/USOutput.java b/src/java/mmm/utils/slots/USOutput.java new file mode 100644 index 0000000..16359b3 --- /dev/null +++ b/src/java/mmm/utils/slots/USOutput.java @@ -0,0 +1,91 @@ +package mmm.utils.slots; + + +import javax.annotation.Nullable; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + + + +public class USOutput + extends Slot +{ + public static interface I_OutputHandler + { + public void onOutputRemoved( EntityPlayer player , ItemStack stack , int quantity ); + } + + /** Player interacting with this slot */ + private final EntityPlayer player; + /** Output handler */ + @Nullable + private final I_OutputHandler outputHandler; + /** Amount of items removed from the slot */ + private int removed; + + + public USOutput( final EntityPlayer player , final IInventory inventoryIn , final int slotIndex , + final int xPosition , final int yPosition ) + { + this( player , inventoryIn , slotIndex , xPosition , yPosition , null ); + } + + + public USOutput( final EntityPlayer player , final IInventory inventoryIn , final int slotIndex , + final int xPosition , final int yPosition , @Nullable final I_OutputHandler handler ) + { + super( inventoryIn , slotIndex , xPosition , yPosition ); + this.player = player; + this.outputHandler = handler; + this.removed = 0; + } + + + /** Players can't add items to output slots */ + @Override + public boolean isItemValid( @Nullable final ItemStack stack ) + { + return false; + } + + + @Override + public ItemStack decrStackSize( final int amount ) + { + if ( this.getHasStack( ) ) { + this.removed += Math.min( amount , this.getStack( ).stackSize ); + } + return super.decrStackSize( amount ); + } + + + @Override + public void onPickupFromSlot( final EntityPlayer playerIn , final ItemStack stack ) + { + this.onCrafting( stack ); + super.onPickupFromSlot( playerIn , stack ); + } + + + @Override + protected void onCrafting( final ItemStack stack , final int amount ) + { + this.removed += amount; + this.onCrafting( stack ); + } + + + @Override + protected void onCrafting( final ItemStack stack ) + { + stack.onCrafting( this.player.worldObj , this.player , this.removed ); + if ( this.outputHandler != null ) { + this.outputHandler.onOutputRemoved( this.player , stack , this.removed ); + } + this.removed = 0; + } + +} diff --git a/src/java/mmm/utils/slots/USVisibilityController.java b/src/java/mmm/utils/slots/USVisibilityController.java new file mode 100644 index 0000000..1ff51d7 --- /dev/null +++ b/src/java/mmm/utils/slots/USVisibilityController.java @@ -0,0 +1,83 @@ +package mmm.utils.slots; + + +import java.util.List; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.minecraft.inventory.Slot; + + + +public class USVisibilityController +{ + private final List< Slot > slots; + private final IntArrayList firstSlots; + private int[] slotX; + private int[] slotY; + + + public USVisibilityController( final List< Slot > slots ) + { + this.slots = slots; + this.firstSlots = new IntArrayList( ); + } + + + public int startGroup( ) + { + this.firstSlots.add( this.slots.size( ) ); + return this.firstSlots.size( ) - 1; + } + + + public void finalizeGroups( ) + { + final int nSlots = this.slots.size( ); + this.slotX = new int[ nSlots ]; + this.slotY = new int[ nSlots ]; + for ( int i = 0 ; i < nSlots ; i++ ) { + final Slot slot = this.slots.get( i ); + this.slotX[ i ] = slot.xDisplayPosition; + this.slotY[ i ] = slot.yDisplayPosition; + } + } + + + public USVisibilityController showGroup( final int index ) + { + final int first = this.firstSlots.getInt( index ); + final int last; + if ( index == this.firstSlots.size( ) - 1 ) { + last = this.slotX.length; + } else { + last = this.firstSlots.getInt( index + 1 ); + } + + for ( int i = first ; i < last ; i++ ) { + final Slot slot = this.slots.get( i ); + slot.xDisplayPosition = this.slotX[ i ]; + slot.yDisplayPosition = this.slotY[ i ]; + } + + return this; + } + + + public USVisibilityController hideGroup( final int index ) + { + final int first = this.firstSlots.getInt( index ); + final int last; + if ( index == this.firstSlots.size( ) - 1 ) { + last = this.slotX.length; + } else { + last = this.firstSlots.getInt( index + 1 ); + } + + for ( int i = first ; i < last ; i++ ) { + final Slot slot = this.slots.get( i ); + slot.xDisplayPosition = slot.yDisplayPosition = -4000; + } + + return this; + } +} diff --git a/src/resources/assets/mmm/textures/gui/alloy-furnace_2.png b/src/resources/assets/mmm/textures/gui/alloy-furnace_2.png deleted file mode 100644 index a402554d8e5d1a7d13d50018a6a2e5516e589871..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1938 zcmcIlYfuwc7`=DdU;<=VL<+S|TtdJK1}LH}YRW2aLB!$!$}2pCB3KGlK|r#AinN0S zuqsuM@liku#Hu_DC802iGq%A;m8l{R5u#v03SvZ{cd_qIo%*9Yd+&bp?fuR<-`Tsn zIX>QQT%Gwk006FsyYmMCKomm2)<&10#PTQr=4|qCUcE8-$H$$Dt!Dlv`w~KPt=_uZ z&?dx#l7m^-Puta+=DwqQhlP3f%)28LTo?}XDC2)_W14hgBxkB|VaRvxAs!_si@LOI z4!rTCAX2rf|El7CR#webm!|^N)u?m3JRLfG`;|>T<`l4Sw77IQXZd>gl|1q7!tK#r zU8(SV)W-b74fXW_r@Ss|?%$7y5Ajy3&h3g1NuN=xKg@4wX>mD_muGxMb&{Z)%_o=8 zM~@!WjE|4=>+0%M4vvnYmbByh-}etoCL7zbyJj{CrZv3-d0lBUeSLini!%u-?Z9!I zw3C7G-fZ03#>Uvg^jLAR(1`M$c5fqpzF~8`Nt4cdGPprejkBppF>F1h-y6-Fa>9bG z=p)Zo2eVpL*0A;3bWcy%S*%Uv2l(77P_W8q|8@>(kycPiSNqbddb0taxuZ*(6O|dy zJGWTTmKjY(lz>Gf82FqDgR4ZMs&BBi;R#M@HQ*;DC85^_I{pdVKLp+{YJD7?<*<7*J<$Pg?+r%E8ba3akP6pQm1a z>1Q;T-K~(!6y!V@c9dK&H-TwJlpedt``*;EEMYU725jXaF{;8xTmv(Im;k*l$D4%B ziQkstevjw)_ybM2Gzqe)`I}+ntxiI)NU~d4AMYtUHlo=q^97i6A5OSUU%YbpjIjAp zt+>(;?1*T$1jdj<%{Nd6#&e=r6hOu$#*SFh2slKJmCq$n-6dSQ5>}nV%Kc~jIi*dL zp*65C210^HZKe!63Z$6&qPA?vTFC%!qvV(&ZJ(?o8x%H=R#5tw0c|e;ftd!hR{*HR z%@_k3x$eMj1MJYJ!5)Abi`4UQBJC8z3~@X5UsKwnXtPld6x-)I~fju+b)A~iTSyJ z0%nAAVlB-C2FeNd*lW0fn*hBTw8m4DLrIuQS*TCz_Pj zEZL)pdo_j0#eR7u>r&Wa3dTh&)f1)EHWcX~-+2ssyAxs*p{D<1fE1=Mrc?S1joOs1 z&?RTE;FTc)@gs)7 z_EiM1n$ZJp{|orv7%4MM=9|k~iLDDjpS682w=>$)04H&}^DavkSjCfLa<2O6L0%o? z{MzSB8L#YfRtA;FG%jMC7*iwV?I)48zb0u{TwJ$Vw3AgL1I}?ASHMU9%nq(sI@a+u z9x|;miV@+mEgX}L;iKz=Fn;P>^bh>sj&{L}R)goKOFit?q%tHPF5b@7Ys8tq0N>Yc A&;S4c diff --git a/src/resources/assets/mmm/textures/gui/alloy_furnace_1.png b/src/resources/assets/mmm/textures/gui/alloy_furnace_1.png index 2f949de13984bdff5a8d8d5924b16db6ae64bfdc..36cbaad31063b97d94930d2e8e2de8c1235ce700 100644 GIT binary patch literal 2169 zcmbtVdpOkF8eYFKGUbw~7-bBmIVO$ErYWSDFp5elw;~25WK1cAWJcu@c20R@({U-G zEw^158H0AoE{dAtI-#UO#u&G8nadt^&UQM_`R}ZMzV&?TS?~9L@Ap1yU2}HYt-NZ( zDgc18!ydas06?-W1Q07^!7J>3000P*gWWEdh+bZw^(oII8x-CPokWmLJ*n_0>Trlj zdI`2e=^kRAuRFx*@mpJnjL3@H*R6c-+OGZGHQfQ~@o{^aY?5Lfs^ZFZ{_dA#_%L0l zXfOqtzB9yGysa|WTVFdXp4vgFIC19Q;urDAKQ{K|?))<%T!G4W7_G0o_H=WOO+ zQRrLZ&Mtp(z$E8!9)6K(w~gIaTP`B3qube;8j4cWa<@+xGbhbb>^Gj&Nblqe{b@Ag z6<2oMGJbgyDZpVhKSd!1yad11)6dtvKCLrvie1z|3Z9z7t5vWM!VbLO(sZDYow6rq z$cECp_79XaZKhU=nnm22fmdU(D%e5aXU*EheQUeJ7TV$YXAsBR0&H}ABFIVf>S6rT z*cP$5O04<)Su`N(!_{kT1jf-FIr@@xZgH3~r4&Od?;?m8EEdZItwQKK2&%#G%|KmiUOB-7GV4XtkmbFQZ<~JXnVUp{>k*pp}tsUluRIz zl~Keey7_!A26*`hnn!h=YvwW*Oa@U9_~c3az#Qv~-LEb+PV;LBC){4VX1*A4`jeIF z&{;q%oY-iT!^@3v%6sN65fp*d*qCHoC@)oel-Yn!m!KISZ`QlaqcZt--=}?&;{H0@PZcop8pF=hCCUjGM(NV7rAu5bsZj5N# z_zrqhS@#s3W*wu6$K&Vy_B(EViwh33_-Si~<*%M6&sqM=Yo@iu*+}?rc>jEX1y@O& zcaaj}prmj9(rM{C!5=a0Mt5-ue!#bf}L(#q3MPDwi zL;&4(#yH*X*@3AkDwihNLT`Q{)fRm{iBANouvep!+~)}mG3knN9EUba$bwX!53kH> zgNQZ1I5|0GS&wYhpEMKJTX8$jY>LKcV?;)S{d1uog;GnT&^mRFd3M1Os$j7+6A}{Q zv@3&o#GQ3Uim_4Jse*3lL^9uR-N-v0ZCoo`+%X@HkDehv0U9a^aqgEg%g~1l&S!}> zKYm%=F&_~fF%cfpFdw<&$pzv{R%V&>h-Vr%;G(<-GO$1`uo$C?Qa;!j*&lukIn3G3 zIIwYWQ&(q;#?Q59cgFSHf$2e>;+F&Pk7buy8x$uv^tL340U9s077beBci+H(qy|TO zCdb@jdr~4wF_bkN(=V?oOTOVo_fUhfyjxNzMVuqs?`3+Y2O=1Qw9%gmI3@~=K@VoV(5s<}4FuS$uQO4a`dN3m&gU#k5IE4eokS*5$vWJF zrMyNo(D~u24q#M2#A$?Q;2hQ*{6Jf=1~``;sz>7-ZkCMbQe=Z@AY~Pvm@$|Jc}lnI zuICN#7Xx$x{RPapC78+^YOx^+YO(Of;1YxjPwY$9aa3Ls>h~m4b$;vrD!24CEc0d* z>z~@y{xwDk0&3F>Ghgj#xiZAvrOf=+D!C}O_s1^1J$?bl!WB)N6~r;tSnP@`Po~k& zRlhe4Uv7p0DioL1$fAyXYGiwtPsr_SF!Q$TeH?7r7wTTnZwL0RCLwQ&`XhLikF+v= z)r9?9zyE+*P9Xpbz(Kps-Y&WOy~5|Gin4jmIXLV?gBC3IwP78FtiyA;lPyXjEmJE@ z!8A^Tb-qoSymi#(B+};})RqnE$3k$%F>nqXp-lQ`5rxx!|_poBj4uX--iAdmMS<8AwXVS3F2P%OQvn)tuh4MRptoW?@HI)EJ$Ox$#*)b^}Z-y z)w)&w8^sRKC5l6py2~mqxBiz){w1v8aaRh@rC#f$zbhrUxwtWY$#if~`c?91y(jX9 z%r6B&!C!3lUIZ^*zrN1iMg0Z5OA)EGj;#rf8i#@ZXQfZj-S;afP2+kwOE3;(C%ZBm H%H=-+fPj!E literal 2117 zcmbVNYfux$7T&~w7zKg?Dqs@`mqbKRZb3|dL@EuaAc##7Ur{K~LWO`L0ZoEjipV3C zlyU{bW2h4artb$L=?0&-wN{=j`mJ z_;{0a;U;hZfUc*<{v!ZDG!O!Gv^C3#sN2B+=xp%Zzwc=5Ytdj+nCaJ`d7jNC6iASv z+~Dyp^VFTXoQ>GeyUg>T{O-c-Ct)2&JPw+UZ%q8z$Ns#hx#3y;qzwtx2iJNc+I}qT zI)6Z&&`m%+?%`vOWp-8x@ch}C%dT^;`;56BV)>B%j!skl^))TG+x%5{cfdi?PE% zi}(!Vz40m~N){w68#1M|QC;s+`7w-lO#xUY|DuoN}`HO@nk0nht+M{1C z8uZPHzSt&-wwODf!X|JeMb|lcH)rP0z^pI8!G#p!k#Mna<^je^{cr%jgr(d8_Xk7| ziv~p6HJrYli3JbLQs+OsREbDEj6&c~5hLsQWsrY0$_OtEnir;e*Qawh98}FFUS0iX zw9N{!?FL)>CDVK>_9lAN%d=viS@+IyyxftKf>f&Z}JurZ4`!YA~OTGFv7dy^&BawC516H9!LTe7TK<92b!E$ z&UMX}QR8?w_Lw-3o%SW>Ekb?Jl})*oYI1~AZAj5BIW-OsBf`E5{%JXdioLABLLi6)6EhVz&+Bvq zPa-LwFbzK4B$eAW?$eM?URYG)XbZ}$8`%1ej179}jd}0c0PCj@Z`qEN+CAK06e5pRgYty0PE0ODt$`_oRWy3UeM`b71cT4|r&9~K? zb(>WxdR1-hvC!$68BMow#|5pYzM{LFI?2PiZrsv(?yMbwuILw9vEUUJU2gFlNiJ64 z8zfF%uCtw->r#z-P`W!h5(7zaHW&V@Hew;KN$*LrlugizmC9nfSuA)}Ig;=d0vu93 zJup0!o98&KqN*2#R^Aw^2q70hDdOJg-JN-Q9BHk)YJsv9?Jzq9W%5tUUi@@-Ckgyp zVS)N%LP4QGgMEVRlbqdHOh9}@(pZE7sb~NS+%djwfkVUcvG!ajg6%$hW%6!u>OqYW zE#TXMNIjBG;UPN2|DHq_e=lBE&uXY_73kXoGOQR=PP)lvOaOm_+lnxdYGzcLW0dpz zO+^S!>nhc~z&`_8{~6Vb-V0uh|I)Brl^+stuRlBpeeAbTLE5eA`MHsn+S5oU1hdT+ zX1s)}?Y^)lvx?LqIMJ)rAwDB%*$|e#9#JXfYTzT|X03{1j zVd3LKbAeIJ$*`PP=W5ooB-y4UdMDi9o6}rnnn*iT+|;< zj#_LdGQ&QSuClKJ9~&@1NVdV%4VH=eybDE<86;4s9Eu%CiN-r=fxlF8wWO=XK`_xD zop1U9sZ7RhZ*O-Cym+xUCY;+9nqE*r>Cr$u z8Fo!!*nGgDI?x@}`>~gQRq%;8ogIK&T)Axr)ZL6pF3FO}l@D7q655)#|54EreIjqr z*7?&c$t4fAl|b=-o8w1ecVESn!p$_o$YFT0Rt)?@qarhKoD58%0DP|fgD_x%9k#_> zpBxSA3U$oQ)3pwah=^FcJaq#*YglmI^^WGlJ0mV1GaY~9GuUnmUKr=kuz4w>7QLg+4CINEi diff --git a/src/resources/assets/mmm/textures/gui/alloy_furnace_2.png b/src/resources/assets/mmm/textures/gui/alloy_furnace_2.png new file mode 100644 index 0000000000000000000000000000000000000000..52eba1a716229844645836897f3e67e67de2baad GIT binary patch literal 2070 zcmbu9c~DbX7RGO40tg5J1x0OOfEGcNppk?{5+pM0VvB*Wn4nE$6HsIq642I+2q^8= zZ0QjYkR@Ra$`U9Pq>)WPK#W0TUzM$agro!Z%+yTPbahp~f9`wt-1nXH{m!ZT4@ZZ; zZT(edgxf7qq6LH8qC1a!x8Jbb6ySG&EXD==5;@@3s>#59Tich+^%!i4 zUc6jXeOlPvA^A6Le16#Nm$*M5{#KyBAqTN zueyU;G(S%QNOs1tC_;g>Z~43HN)63@HtN(RY@kesH>&XgUtZ1Zw%7>qfs$k_6xa;& z=Qv3y`%lBe-%m=bhmEm0DXw!@GI`HKrtFYXV1H~clhm}l9EyMO!lJG#iMP6d%`u~t zbz-lsAflq8?sFVIz{!VFseXP3l7~5SBPWevuh}4CA;;&UzZ-I*hg!D!4fMD*Dz&xP zSttNOZ&Yw8Z`-QpnMJ7fW3bl`*D_lfUPLh#8#S0T7`0^f#y`|2HFkEMN=r+_=l9&A zlp1}JB_lC9Db$c`m236Zg2mvu_ZD?1d(D=T$E!CRJTFOk%Ybh`3)lJQI3#B8r%z2u z+f%U`LrrQTgJoY5t{P1+nGIH#Q0 zC7=|Be6(Vr?Bnl}*@3(w!378m1ZxI%h?~*;qxQ?E zbUGpb%!D6Brq12RF!jX3Sbki*Wn6-xDC=O|xMZw&l*9JzEdW2mEK{+8eLkA?4rmdI z_#oX!*cpTXL9MFCBCm|jJxPG^*VRO8{pEWSEUUx6oGU7N2*|Y=9p$d3F@o@`3=^-- zN`;FT zNr1JmcdS~mOc5~Pz98gn;DjDlEXabeii-_`6C853`}z3=6B+#~TM6?@xSXz^CZ?*m z0ee+d+b%}4;524O0QIA5hQaKXjcX0y0Dyu=!5`o*j=Uk^jrdBDIdD8z`hgdu@GG_t zDh?t54Ga$S@pxeh2yh(0Xb1pNhYbdMtVM%#2kqzFqBZ9o(17ZHIzdQfiq z8t;P|ZTUkKU$K!PKS^adOiTquJaK@<9X_n^O8INT+F!aYaHnH?bS%=lPRBlb3|?^{ zrN|{hI&lh