From 67d6f34fcc3882b1631335060ba2035973280353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Tue, 28 Jun 2016 21:38:54 +0200 Subject: [PATCH] Implemented a proper GUI factory --- TODO.txt | 1 - .../tech/base/TBAlloyFurnaceGuiHandler.java | 46 ------ .../tech/base/alloy_furnace/AlloyFurnace.java | 9 +- .../tech/base/alloy_furnace/TBAFBlock.java | 4 +- src/java/mmm/utils/gui/GUIUtils.java | 149 +++++++++++++++++- 5 files changed, 150 insertions(+), 59 deletions(-) delete mode 100644 src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java diff --git a/TODO.txt b/TODO.txt index 6b38f4d..4825086 100644 --- a/TODO.txt +++ b/TODO.txt @@ -47,7 +47,6 @@ tech.base No Alloy furnace -> comparator signal configuration (inventory mode w/ combinations, valid ingredients, burn time, alloying time) - -> code clean-up tech.base No Coke oven ------------------------------------------------------------------------------------------------------- animals ??? Goats diff --git a/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java b/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java deleted file mode 100644 index b844952..0000000 --- a/src/java/mmm/tech/base/TBAlloyFurnaceGuiHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -package mmm.tech.base; - - -import mmm.tech.base.alloy_furnace.TBAFContainer; -import mmm.tech.base.alloy_furnace.TBAFGui; -import mmm.tech.base.alloy_furnace.TBAFTileEntity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.common.network.IGuiHandler; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - - - -public class TBAlloyFurnaceGuiHandler - implements IGuiHandler -{ - - @Override - public Object getServerGuiElement( final int ID , final EntityPlayer player , final World world , final int x , - final int y , final int z ) - { - final BlockPos pos = new BlockPos( x , y , z ); - final TileEntity tileEntity = world.getTileEntity( pos ); - if ( tileEntity instanceof TBAFTileEntity ) { - return new TBAFContainer( player.inventory , (TBAFTileEntity) tileEntity ); - } - return null; - } - - - @Override - @SideOnly( Side.CLIENT ) - public Object getClientGuiElement( final int ID , final EntityPlayer player , final World world , final int x , - final int y , final int z ) - { - final TileEntity tileEntity = world.getTileEntity( new BlockPos( x , y , z ) ); - if ( tileEntity instanceof TBAFTileEntity ) { - return new TBAFGui( player.inventory , (TBAFTileEntity) tileEntity ); - } - return null; - } - -} diff --git a/src/java/mmm/tech/base/alloy_furnace/AlloyFurnace.java b/src/java/mmm/tech/base/alloy_furnace/AlloyFurnace.java index 7eaa5d9..256b0a5 100644 --- a/src/java/mmm/tech/base/alloy_furnace/AlloyFurnace.java +++ b/src/java/mmm/tech/base/alloy_furnace/AlloyFurnace.java @@ -1,13 +1,11 @@ package mmm.tech.base.alloy_furnace; -import mmm.Mmm; -import mmm.tech.base.TBAlloyFurnaceGuiHandler; import mmm.utils.UNetwork; import mmm.utils.URegistry; +import mmm.utils.gui.GUIUtils; import net.minecraft.item.Item; import net.minecraft.item.ItemBlockSpecial; -import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; @@ -33,9 +31,10 @@ public enum AlloyFurnace { URegistry.addBlock( this.INACTIVE , this.ITEM ); URegistry.addBlock( this.ACTIVE , null ); + GameRegistry.registerTileEntity( TBAFTileEntity.class , "mmm:tech/base/alloy_furnace" ); - // FIXME - NetworkRegistry.INSTANCE.registerGuiHandler( Mmm.get( ) , new TBAlloyFurnaceGuiHandler( ) ); + GUIUtils.registerTileEntityGUI( TBAFTileEntity.class , "mmm.tech.base.alloy_furnace.TBAFContainer" , + "mmm.tech.base.alloy_furnace.TBAFGui" ); UNetwork.addServerMessage( TBAFMessage.class ); } diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFBlock.java b/src/java/mmm/tech/base/alloy_furnace/TBAFBlock.java index 895d66f..c016895 100644 --- a/src/java/mmm/tech/base/alloy_furnace/TBAFBlock.java +++ b/src/java/mmm/tech/base/alloy_furnace/TBAFBlock.java @@ -6,10 +6,10 @@ import java.util.Random; import javax.annotation.Nullable; -import mmm.Mmm; import mmm.utils.I_URecipeRegistrar; import mmm.utils.UMaths; import mmm.utils.URegistry; +import mmm.utils.gui.GUIUtils; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.BlockHorizontal; @@ -353,7 +353,7 @@ public class TBAFBlock if ( ! ( te instanceof TBAFTileEntity ) || playerIn.isSneaking( ) ) { return false; } - playerIn.openGui( Mmm.get( ) , 0 , worldIn , pos.getX( ) , pos.getY( ) , pos.getZ( ) ); + GUIUtils.openTileEntityGUI( playerIn , worldIn , pos ); return true; } diff --git a/src/java/mmm/utils/gui/GUIUtils.java b/src/java/mmm/utils/gui/GUIUtils.java index fa4f3e3..2cff43c 100644 --- a/src/java/mmm/utils/gui/GUIUtils.java +++ b/src/java/mmm/utils/gui/GUIUtils.java @@ -1,18 +1,35 @@ package mmm.utils.gui; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.google.common.collect.Maps; + +import mmm.Mmm; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import net.minecraftforge.fml.common.network.IGuiHandler; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.relauncher.FMLLaunchHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; -public class GUIUtils -{ - static final Logger LOGGER = LogManager.getLogger( ); - - public static final ResourceLocation GUI_TEXTURE = new ResourceLocation( "mmm" , "textures/gui/gui-common.png" ); +public enum GUIUtils + implements IGuiHandler { + INSTANCE; public static final int TAB_TEXTURE_X = 0; public static final int TAB_TEXTURE_Y = 0; @@ -30,4 +47,126 @@ public class GUIUtils public static final int TAB_ICON_WIDTH = 16; public static final int TAB_ICON_HEIGHT = 16; + private static final HashMap< Class< ? extends TileEntity > , Constructor< ? > > SERVER_SIDE // + = Maps.newHashMap( ); + private static final HashMap< Class< ? extends TileEntity > , Constructor< ? > > CLIENT_SIDE // + = Maps.newHashMap( ); + + static final Logger LOGGER = LogManager.getLogger( ); + + public static final ResourceLocation GUI_TEXTURE = new ResourceLocation( "mmm" , "textures/gui/gui-common.png" ); + + + public static void registerTileEntityGUI( final Class< ? extends TileEntity > teClass , + final String containerClassName , final String guiClassName ) + { + if ( GUIUtils.SERVER_SIDE.containsKey( teClass ) ) { + throw new IllegalArgumentException( "duplicate GUI registration for tile entity class " + teClass ); + } + + GUIUtils.addTileEntityConstructor( GUIUtils.SERVER_SIDE , teClass , Container.class , containerClassName , + "container" ); + if ( FMLLaunchHandler.side( ) == Side.CLIENT ) { + String clsName = "net.minecraft.client.gui.inventory.GuiContainer"; + if ( FMLDeobfuscatingRemapper.INSTANCE.isRemappedClass( clsName ) ) { + clsName = FMLDeobfuscatingRemapper.INSTANCE.map( clsName ); + } + Class< ? > guiClass; + try { + guiClass = Class.forName( clsName ); + } catch ( final ClassNotFoundException e ) { + throw new IllegalArgumentException( "couldn't find GUI class" , e ); + } + GUIUtils.addTileEntityConstructor( GUIUtils.CLIENT_SIDE , teClass , guiClass , guiClassName , "GUI" ); + } + } + + + public static void openTileEntityGUI( final EntityPlayer player , final World world , final BlockPos pos ) + { + player.openGui( Mmm.get( ) , 0 , world , pos.getX( ) , pos.getY( ) , pos.getZ( ) ); + } + + + private static void addTileEntityConstructor( + final HashMap< Class< ? extends TileEntity > , Constructor< ? > > output , + final Class< ? extends TileEntity > teClass , final Class< ? > parent , final String className , + final String designation ) + { + Class< ? > klass; + try { + klass = Class.forName( className ); + } catch ( final ClassNotFoundException e ) { + throw new IllegalArgumentException( "bad " + designation + " class name" , e ); + } + if ( !parent.isAssignableFrom( klass ) ) { + throw new IllegalArgumentException( "class " + className + " is not a " + designation + " sub-class" ); + } + output.put( teClass , GUIUtils.findConstructor( teClass , klass ) ); + } + + + private static Constructor< ? > findConstructor( final Class< ? > teClass , final Class< ? > klass ) + { + final Constructor< ? >[] allCons = klass.getConstructors( ); + for ( final Constructor< ? > cons : allCons ) { + final Class< ? >[] types = cons.getParameterTypes( ); + if ( ! ( types.length == 2 && types[ 0 ].isAssignableFrom( InventoryPlayer.class ) + && types[ 1 ].isAssignableFrom( teClass ) ) ) { + continue; + } + return cons; + } + throw new IllegalArgumentException( "class " + klass.getName( ) + " does not have a supported constructor" ); + } + + + private GUIUtils( ) + { + NetworkRegistry.INSTANCE.registerGuiHandler( Mmm.get( ) , this ); + } + + + @Override + public Object getServerGuiElement( final int ID , final EntityPlayer player , final World world , final int x , + final int y , final int z ) + { + if ( ID == 0 ) { + return this.getObjectForTE( player , world , x , y , z , GUIUtils.SERVER_SIDE , "container" ); + } + return null; + } + + + @Override + @SideOnly( Side.CLIENT ) + public Object getClientGuiElement( final int ID , final EntityPlayer player , final World world , final int x , + final int y , final int z ) + { + if ( ID == 0 ) { + return this.getObjectForTE( player , world , x , y , z , GUIUtils.CLIENT_SIDE , "GUI" ); + } + return null; + } + + + private Object getObjectForTE( final EntityPlayer player , final World world , final int x , final int y , + final int z , final HashMap< Class< ? extends TileEntity > , Constructor< ? > > constructors , + final String designation ) + { + final BlockPos pos = new BlockPos( x , y , z ); + final TileEntity tileEntity = world.getTileEntity( pos ); + final Constructor< ? > cns = constructors.get( tileEntity.getClass( ) ); + if ( cns == null ) { + return null; + } + try { + return cns.newInstance( player.inventory , tileEntity ); + } catch ( InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e ) { + throw new RuntimeException( "couldn't create tile entity " + designation // + + " for " + tileEntity.getClass( ) ); + } + } + }