Microblocks

Fixes #300 and #282: Microblock compatibility added.
Fixes #293: Added missing redstone method to level emitter.
Craftable essentia no longer shows in item terminals.
Texture updated: Level Emitter
This commit is contained in:
Chris committed 2016-04-17 18:57:13 -04:00
1 parent 3b7d01e83a
commit 135f765728
13 files changed
+344 -121

No files matched your search

+7 -2
View File
@@ -1,5 +1,10 @@
04/15/2016 1.0.0.4 - Beta
Cleaned up ASM transformer code.
Fixes #300 and #282: Microblock compatibility added.
Fixes #293: Added missing redstone method to level emitter.
Craftable essentia no longer shows in item terminals.
Texture updated: Level Emitter
04/15/2016 1.0.0.4 - Beta
Cleaned up ASM transformer code.
04/14/2016 1.0.0.3 - Beta
Completely moved dev environment to Java 8, Java 7 and earlier is no longer supported.
@@ -1,17 +1,17 @@
package thaumicenergistics.client;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.MinecraftForge;
import thaumicenergistics.client.textures.BlockTextureManager;
import thaumicenergistics.common.CommonProxy;
import thaumicenergistics.common.registries.Renderers;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
/**
* Client side proxy.
*
*
* @author Nividica
*
*
*/
public class ClientProxy
extends CommonProxy
@@ -2,32 +2,9 @@ package thaumicenergistics.client.gui;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import thaumcraft.client.lib.UtilsFX;
import thaumcraft.common.config.Config;
import thaumicenergistics.client.gui.abstraction.GuiConstants_ACT;
import thaumicenergistics.client.gui.buttons.*;
import thaumicenergistics.client.gui.widget.ThEWidget;
import thaumicenergistics.client.gui.widget.WidgetAEItem;
import thaumicenergistics.client.textures.AEStateIconsEnum;
import thaumicenergistics.client.textures.GuiTextureManager;
import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal;
import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal.ArcaneCrafingCost;
import thaumicenergistics.common.integration.tc.MEItemAspectBridgeContainer;
import thaumicenergistics.common.network.packet.server.Packet_S_ArcaneCraftingTerminal;
import thaumicenergistics.common.parts.PartArcaneCraftingTerminal;
import thaumicenergistics.common.registries.ThEStrings;
import thaumicenergistics.common.tiles.TileArcaneAssembler;
import thaumicenergistics.common.utils.ThEUtils;
import appeng.api.config.*;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
@@ -38,12 +15,36 @@ import appeng.core.AEConfig;
import appeng.util.Platform;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import thaumcraft.client.lib.UtilsFX;
import thaumcraft.common.config.Config;
import thaumicenergistics.client.gui.abstraction.GuiConstants_ACT;
import thaumicenergistics.client.gui.buttons.*;
import thaumicenergistics.client.gui.widget.ThEWidget;
import thaumicenergistics.client.gui.widget.WidgetAEItem;
import thaumicenergistics.client.textures.AEStateIconsEnum;
import thaumicenergistics.client.textures.GuiTextureManager;
import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal;
import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal.ArcaneCrafingCost;
import thaumicenergistics.common.integration.AEHooks;
import thaumicenergistics.common.integration.tc.MEItemAspectBridgeContainer;
import thaumicenergistics.common.network.packet.server.Packet_S_ArcaneCraftingTerminal;
import thaumicenergistics.common.parts.PartArcaneCraftingTerminal;
import thaumicenergistics.common.registries.ThEStrings;
import thaumicenergistics.common.tiles.TileArcaneAssembler;
import thaumicenergistics.common.utils.ThEUtils;
/**
* {@link TileArcaneAssembler} GUI
*
*
* @author Nividica
*
*
*/
@SideOnly(Side.CLIENT)
public class GuiArcaneCraftingTerminal
@@ -192,7 +193,7 @@ public class GuiArcaneCraftingTerminal
/**
* Checks if the click was a region deposit.
*
*
* @param mouseX
* @param mouseY
* @return True if click was handled.
@@ -221,7 +222,7 @@ public class GuiArcaneCraftingTerminal
/**
* Checks if the click was inside the search box.
*
*
* @param mouseX
* @param mouseY
* @param mouseButton
@@ -255,7 +256,7 @@ public class GuiArcaneCraftingTerminal
/**
* Checks if the click was inside the widgets.
*
*
* @param mouseX
* @param mouseY
* @param mouseButton
@@ -296,14 +297,14 @@ public class GuiArcaneCraftingTerminal
/**
* Extracts or inserts an item to/from the player held stack based on the
* direction the mouse wheel was scrolled.
*
*
* @param deltaZ
*/
private void doMEWheelAction( final int deltaZ, final int mouseX, final int mouseY )
{
// Is the mouse inside the ME area?
if( ThEGuiHelper.INSTANCE.isPointInGuiRegion( ME_ITEM_POS_Y, ME_ITEM_POS_X,
this.numberOfWidgetRows * ME_ROW_HEIGHT, ME_GRID_WIDTH,
if( ThEGuiHelper.INSTANCE.isPointInGuiRegion( GuiConstants_ACT.ME_ITEM_POS_Y, GuiConstants_ACT.ME_ITEM_POS_X,
this.numberOfWidgetRows * GuiConstants_ACT.ME_ROW_HEIGHT, GuiConstants_ACT.ME_GRID_WIDTH,
mouseX, mouseY, this.guiLeft, this.guiTop ) )
{
// Which direction was the scroll?
@@ -327,7 +328,7 @@ public class GuiArcaneCraftingTerminal
/**
* Draws the crafting aspect's and their costs.
*
*
* @param craftingCost
*/
private void drawCraftingAspects( final List<ArcaneCrafingCost> craftingCost )
@@ -369,7 +370,7 @@ public class GuiArcaneCraftingTerminal
/**
* Draws the AE item widgets.
*
*
* @param mouseX
* @param mouseY
* @return
@@ -409,7 +410,7 @@ public class GuiArcaneCraftingTerminal
/**
* If the user has clicked on an item widget this will inform the server
* so that the item can be extracted from the AE network.
*
*
* @param mouseX
* @param mouseY
* @param mouseButton
@@ -540,7 +541,7 @@ public class GuiArcaneCraftingTerminal
{
IAEItemStack stack = this.repo.getReferenceItem( repoIndex++ );
// Did we get a stack?
// Did we get a stack?
if( stack != null )
{
// Set the item
@@ -702,7 +703,8 @@ public class GuiArcaneCraftingTerminal
}
// Should we force a tooltip update?
boolean forceTooltipUpdate = ( ( System.currentTimeMillis() - this.lastTooltipUpdateTime ) >= GuiConstants_ACT.WIDGET_TOOLTIP_UPDATE_INTERVAL );
boolean forceTooltipUpdate = ( ( System.currentTimeMillis() -
this.lastTooltipUpdateTime ) >= GuiConstants_ACT.WIDGET_TOOLTIP_UPDATE_INTERVAL );
// Has the mouse moved, or timeout reached?
if( forceTooltipUpdate || ( this.previousMouseX != mouseX ) || ( this.previousMouseY != mouseY ) )
@@ -746,7 +748,7 @@ public class GuiArcaneCraftingTerminal
/**
* Returns the scroll bar parameters.
*
*
* @return
*/
@Override
@@ -989,7 +991,7 @@ public class GuiArcaneCraftingTerminal
protected void onMouseWheel( final int deltaZ, final int mouseX, final int mouseY )
{
// Is the mouse inside of, or to the left of, the GUI?
if( mouseX > ( this.guiLeft + GUI_WIDTH ) )
if( mouseX > ( this.guiLeft + GuiConstants_ACT.GUI_WIDTH ) )
{
// Mouse is to the right of the gui
return;
@@ -1112,7 +1114,8 @@ public class GuiArcaneCraftingTerminal
// Create the clear grid button
this.buttonList.add( new GuiButtonClearCraftingGrid( GuiConstants_ACT.BUTTON_CLEAR_GRID_ID, this.guiLeft +
GuiConstants_ACT.BUTTON_CLEAR_GRID_POS_X, this.guiTop + GuiConstants_ACT.BUTTON_CLEAR_GRID_POS_Y +
this.lowerTerminalYOffset, 8, 8, true ) );
this.lowerTerminalYOffset,
8, 8, true ) );
// Add sort order button
this.buttonList.add( this.btnSortingMode = new GuiButtonSortingMode( GuiConstants_ACT.BUTTON_SORT_MODE_ID, this.guiLeft +
@@ -1132,7 +1135,8 @@ public class GuiArcaneCraftingTerminal
// Add swap armor button
this.buttonList.add( new GuiButtonSwapArmor( GuiConstants_ACT.BUTTON_SWAP_ARMOR_ID, this.guiLeft +
GuiConstants_ACT.BUTTON_SWAP_ARMOR_POS_X, this.guiTop + GuiConstants_ACT.BUTTON_SWAP_ARMOR_POS_Y +
this.lowerTerminalYOffset, 8, 8 ) );
this.lowerTerminalYOffset,
8, 8 ) );
// Add search mode button
this.buttonList.add( this.btnSearchMode = new GuiButtonSearchMode( GuiConstants_ACT.BUTTON_SEARCH_MODE_ID, this.guiLeft +
@@ -1167,11 +1171,17 @@ public class GuiArcaneCraftingTerminal
/**
* Called to update the amount of an item in the ME network.
*
*
* @param change
*/
public void onReceiveChange( final IAEItemStack change )
{
// Is the item blacklisted?
if( AEHooks.isItemGUIBlacklisted( change ) )
{
return;
}
// Update the repository
this.repo.postUpdate( change );
@@ -1182,7 +1192,7 @@ public class GuiArcaneCraftingTerminal
/**
* Called when the server sends a full list of all
* items in the AE network in response to our request.
*
*
* @param itemList
*/
public void onReceiveFullList( final IItemList<IAEItemStack> itemList )
@@ -1193,16 +1203,13 @@ public class GuiArcaneCraftingTerminal
// Update the repository
for( IAEItemStack stack : itemList )
{
this.repo.postUpdate( stack );
this.onReceiveChange( stack );
}
// Repo needs update
this.viewNeedsUpdate = true;
}
/**
* Called when the server sends the sorting order and direction.
*
*
* @param order
* @param direction
*/
@@ -19,9 +19,9 @@ import thaumicenergistics.common.storage.AspectStack;
/**
* Base class of Aspect Widgets.
*
*
* @author Nividica
*
*
*/
@SideOnly(Side.CLIENT)
public abstract class AspectWidgetBase
@@ -54,7 +54,6 @@ public abstract class AspectWidgetBase
/**
* Cached footnote of the aspect.
* NOTE: One day I hope to put what mod the aspect is from here, not just its primallity.
*/
protected String aspectFootnote = "";
@@ -85,7 +84,7 @@ public abstract class AspectWidgetBase
/**
* Clears the stack and optionally fires the on stack changed event.
*
*
* @param doUpdate
*/
protected void clearStack( final boolean doUpdate )
@@ -202,7 +201,7 @@ public abstract class AspectWidgetBase
/**
* Gets the stack size.
*
*
* @return
*/
public long getAmount()
@@ -212,7 +211,7 @@ public abstract class AspectWidgetBase
/**
* Gets the aspect stack for this widget.
*
*
* @return
*/
public Aspect getAspect()
@@ -222,7 +221,7 @@ public abstract class AspectWidgetBase
/**
* Gets whether or not the stack is craftable.
*
*
* @return
*/
public boolean getCraftable()
@@ -232,7 +231,7 @@ public abstract class AspectWidgetBase
/**
* Returns the aspect stack.
*
*
* @return
*/
public IAspectStack getStack()
@@ -261,7 +260,7 @@ public abstract class AspectWidgetBase
/**
* Returns true if the widget has an aspect.
*
*
* @return
*/
public boolean hasAspect()
@@ -271,7 +270,7 @@ public abstract class AspectWidgetBase
/**
* Set's the aspect stack based on the passed values.
*
*
* @param aspect
* @param amount
* @param isCraftable
@@ -286,7 +285,7 @@ public abstract class AspectWidgetBase
/**
* Sets the aspect based on the stack
*
*
* @param stack
*/
public void setAspect( final IAspectStack stack )
@@ -0,0 +1,25 @@
package thaumicenergistics.common.integration;
import appeng.api.storage.data.IAEItemStack;
import thaumicenergistics.common.items.ItemCraftingAspect;
public class AEHooks
{
/**
* Hook for AE2s <em>GuiMeMonitorable.postUpdate()</em>.<br>
* Returning true will prevent the item from being displayed in GUI's.
* TODO: Expand this into registration list within the API.
*
* @param is
* @return
*/
public static boolean isItemGUIBlacklisted( final IAEItemStack is )
{
if( is.getItem() instanceof ItemCraftingAspect )
{
return true;
}
return false;
}
}
@@ -1,9 +1,17 @@
package thaumicenergistics.common.parts;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import java.util.Random;
import javax.annotation.Nullable;
import appeng.api.config.RedstoneMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartRenderHelper;
import appeng.api.parts.PartItemStack;
import appeng.util.Platform;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.EntityPlayer;
@@ -24,20 +32,12 @@ import thaumicenergistics.common.integration.tc.EssentiaItemContainerHelper;
import thaumicenergistics.common.network.IAspectSlotPart;
import thaumicenergistics.common.registries.EnumCache;
import thaumicenergistics.common.utils.EffectiveSide;
import appeng.api.config.RedstoneMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartRenderHelper;
import appeng.api.parts.PartItemStack;
import appeng.util.Platform;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Emits redstone signals based on networked essentia levels.
*
*
* @author Nividica
*
*
*/
public class PartEssentiaLevelEmitter
extends ThEPartBase
@@ -59,6 +59,27 @@ public class PartEssentiaLevelEmitter
*/
private static final RedstoneMode DEFAULT_REDSTONE_MODE = RedstoneMode.HIGH_SIGNAL;
/**
* Dimensions and offsets
*/
private static final float Base_XY_Min = 7.0F, Base_XY_Max = 9.0F, Base_Z_Min = 11.0F, Base_Z_Max = 13.0F,
// Head Z's
Head_Z_Min = PartEssentiaLevelEmitter.Base_Z_Max, Head_Z_Max = PartEssentiaLevelEmitter.Head_Z_Min + 2.0F,
// Face Z's
Face_Z_Min = PartEssentiaLevelEmitter.Head_Z_Min - 1.0F, FaceZMax = PartEssentiaLevelEmitter.Head_Z_Max + 1.0F,
// Face offsets
FaceOffset_XH_YV = 0.001F, FaceOffset_XV_YH = 1.0F,
// Horizontal faces XY
Face_XH_Min = PartEssentiaLevelEmitter.Base_XY_Min - PartEssentiaLevelEmitter.FaceOffset_XH_YV,
Face_YH_Min = PartEssentiaLevelEmitter.Base_XY_Min - PartEssentiaLevelEmitter.FaceOffset_XV_YH,
Face_XH_Max = PartEssentiaLevelEmitter.Base_XY_Max + PartEssentiaLevelEmitter.FaceOffset_XH_YV,
Face_YH_Max = PartEssentiaLevelEmitter.Base_XY_Max + PartEssentiaLevelEmitter.FaceOffset_XV_YH,
// Vertical faces XY
Face_XV_Min = PartEssentiaLevelEmitter.Base_XY_Min - PartEssentiaLevelEmitter.FaceOffset_XV_YH,
Face_YV_Min = PartEssentiaLevelEmitter.Base_XY_Min - PartEssentiaLevelEmitter.FaceOffset_XH_YV,
Face_XV_Max = PartEssentiaLevelEmitter.Base_XY_Max + PartEssentiaLevelEmitter.FaceOffset_XV_YH,
Face_YV_Max = PartEssentiaLevelEmitter.Base_XY_Max + PartEssentiaLevelEmitter.FaceOffset_XH_YV;
/**
* Aspect we are watching.
*/
@@ -148,7 +169,7 @@ public class PartEssentiaLevelEmitter
/**
* Sets the current amount in the network, of the aspect
* we are watching/filtering.
*
*
* @param amount
*/
private void setCurrentLevel( final long amount )
@@ -166,7 +187,7 @@ public class PartEssentiaLevelEmitter
/**
* Checks if the emitter should be emitting a redstone signal.
*
*
* @return
*/
private void updateEmittingState()
@@ -227,10 +248,17 @@ public class PartEssentiaLevelEmitter
return 8;
}
@Override
public boolean canConnectRedstone()
{
return true;
}
@Override
public void getBoxes( final IPartCollisionHelper helper )
{
helper.addBox( 7.0D, 7.0D, 11.0D, 9.0D, 9.0D, 16.0D );
helper.addBox( PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Base_Z_Min,
PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Head_Z_Max );
}
@Override
@@ -265,7 +293,7 @@ public class PartEssentiaLevelEmitter
/**
* Returns the redstone mode.
*
*
* @return
*/
public RedstoneMode getRedstoneMode()
@@ -284,7 +312,7 @@ public class PartEssentiaLevelEmitter
/**
* Returns the threshold level.
*
*
* @return
*/
public long getThresholdLevel()
@@ -294,7 +322,7 @@ public class PartEssentiaLevelEmitter
/**
* Returns the aspect being tracked.
*
*
* @return
*/
@Nullable
@@ -324,7 +352,7 @@ public class PartEssentiaLevelEmitter
/**
* Called when a player has adjusted the amount wanted via
* gui buttons.
*
*
* @param adjustmentAmount
* @param player
*/
@@ -335,7 +363,7 @@ public class PartEssentiaLevelEmitter
/**
* Called when a player has pressed the redstone toggle button in the gui.
*
*
* @param player
*/
public void onClientToggleRedstoneMode( final EntityPlayer player )
@@ -371,7 +399,7 @@ public class PartEssentiaLevelEmitter
/**
* Called when a player has changed the wanted amount
*
*
* @param threshold
* @param player
*/
@@ -454,7 +482,7 @@ public class PartEssentiaLevelEmitter
/**
* Called client side when a sync packet has been received.
*
*
* @throws IOException
*/
@SideOnly(Side.CLIENT)
@@ -488,7 +516,6 @@ public class PartEssentiaLevelEmitter
// Set the base texture
helper.setTexture( BlockTextureManager.ESSENTIA_LEVEL_EMITTER.getTextures()[0] );
helper.setBounds( 7.0F, 1.0F, 14.0F, 9.0F, 7.0F, 16.0F );
//helper.setBounds( 7.0F, 7.0F, 11.0F, 9.0F, 9.0F, 14.0F );
helper.renderInventoryBox( renderer );
// Set the active texture
@@ -507,17 +534,36 @@ public class PartEssentiaLevelEmitter
{
// Set the base texture
helper.setTexture( BlockTextureManager.ESSENTIA_LEVEL_EMITTER.getTextures()[0] );
helper.setBounds( 7.0F, 7.0F, 11.0F, 9.0F, 9.0F, 14.0F );
// Set shaft bounds
helper.setBounds( PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Base_Z_Min,
PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Base_Z_Max );
// Render shaft
helper.renderBlock( x, y, z, renderer );
// Is the part emitting?
if( this.isEmitting )
{
// Set the active texture
helper.setTexture( BlockTextureManager.ESSENTIA_LEVEL_EMITTER.getTextures()[1] );
IIcon activeTex = BlockTextureManager.ESSENTIA_LEVEL_EMITTER.getTextures()[1];
helper.setTexture( activeTex );
// Set the brightness
Tessellator.instance.setBrightness( ThEPartBase.ACTIVE_FACE_BRIGHTNESS );
Tessellator.instance.setColorOpaque_F( 1.0F, 1.0F, 1.0F );
Tessellator.instance.setBrightness( 0xD000D0 );
// Render horizontal faces
helper.setBounds( PartEssentiaLevelEmitter.Face_XH_Min, PartEssentiaLevelEmitter.Face_YH_Min, PartEssentiaLevelEmitter.Face_Z_Min,
PartEssentiaLevelEmitter.Face_XH_Max, PartEssentiaLevelEmitter.Face_YH_Max, PartEssentiaLevelEmitter.FaceZMax );
helper.renderFace( x, y, z, activeTex, ForgeDirection.EAST, renderer );
helper.renderFace( x, y, z, activeTex, ForgeDirection.WEST, renderer );
// Render vertical faces
helper.setBounds( PartEssentiaLevelEmitter.Face_XV_Min, PartEssentiaLevelEmitter.Face_YV_Min, PartEssentiaLevelEmitter.Face_Z_Min,
PartEssentiaLevelEmitter.Face_XV_Max, PartEssentiaLevelEmitter.Face_YV_Max, PartEssentiaLevelEmitter.FaceZMax );
helper.renderFace( x, y, z, activeTex, ForgeDirection.UP, renderer );
helper.renderFace( x, y, z, activeTex, ForgeDirection.DOWN, renderer );
}
else
@@ -526,8 +572,11 @@ public class PartEssentiaLevelEmitter
helper.setTexture( BlockTextureManager.ESSENTIA_LEVEL_EMITTER.getTextures()[2] );
}
// Set shaft bounds
helper.setBounds( 7.0F, 7.0F, 14.0F, 9.0F, 9.0F, 16.0F );
// Set head bounds
helper.setBounds( PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Base_XY_Min, PartEssentiaLevelEmitter.Head_Z_Min,
PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Base_XY_Max, PartEssentiaLevelEmitter.Head_Z_Max );
// Render head
helper.renderBlock( x, y, z, renderer );
}
@@ -558,7 +607,7 @@ public class PartEssentiaLevelEmitter
/**
* Called from the container to set the filter based on an itemstack.
*
*
* @param player
* @param itemStack
* @return
@@ -638,7 +687,7 @@ public class PartEssentiaLevelEmitter
/**
* Called when a packet to sync client and server is being created.
*
*
* @throws IOException
*/
@Override
@@ -38,13 +38,14 @@ import thaumicenergistics.client.textures.BlockTextureManager;
import thaumicenergistics.common.ThEGuiHandler;
import thaumicenergistics.common.grid.AEPartGridBlock;
import thaumicenergistics.common.utils.EffectiveSide;
import thaumicenergistics.common.utils.ThELog;
import thaumicenergistics.common.utils.ThEUtils;
/**
* Base class for all ThE cable parts.
*
*
* @author Nividica
*
*
*/
public abstract class ThEPartBase
implements IPart, IGridHost, IActionHost, IPowerChannelState
@@ -115,7 +116,7 @@ public abstract class ThEPartBase
/**
* Creates the part.
*
*
* @param associatedPart
* @param interactionPermissions
* Permissions required to interact with the part.
@@ -178,7 +179,7 @@ public abstract class ThEPartBase
/**
* Checks if the specifies player has clearance for the specified
* permission.
*
*
* @param player
* @param permission
* @return
@@ -207,7 +208,7 @@ public abstract class ThEPartBase
/**
* Checks if the specifies player has clearance for the specified
* permission.
*
*
* @param playerID
* @param permission
* @return
@@ -235,7 +236,7 @@ public abstract class ThEPartBase
/**
* Gets the tile entity the part is facing, if any.
*
*
* @return
*/
protected TileEntity getFacingTile()
@@ -271,13 +272,25 @@ public abstract class ThEPartBase
// Create the node
this.node = AEApi.instance().createGridNode( this.gridBlock );
// Update state
this.node.updateState();
// Set the player id
this.node.setPlayerID( this.ownerID );
this.setPower( null );
// Update state
if( ( this.hostTile != null ) && ( this.host != null ) && ( this.hostTile.getWorldObj() != null ) )
{
try
{
this.node.updateState();
}
catch( Exception e )
{
ThELog.error( e, "Part (%s) was unable to update it's node. The part may not function correctly",
this.associatedItem.getDisplayName() );
}
}
// Update the part
this.updateStatus();
}
@Override
@@ -333,7 +346,7 @@ public abstract class ThEPartBase
/**
* Gets the parts grid block.
*
*
* @return
*/
public AEPartGridBlock getGridBlock()
@@ -360,7 +373,7 @@ public abstract class ThEPartBase
/**
* Gets the host tile entity of this part.
*
*
* @return
*/
public final TileEntity getHostTile()
@@ -406,7 +419,7 @@ public abstract class ThEPartBase
/**
* Gets the location of this part.
*
*
* @return
*/
public final DimensionalCoord getLocation()
@@ -421,7 +434,7 @@ public abstract class ThEPartBase
/**
* Gets the side of the host that this part is attached to.
*
*
* @return
*/
public ForgeDirection getSide()
@@ -431,7 +444,7 @@ public abstract class ThEPartBase
/**
* Gets the unlocalized name of this part.
*
*
* @return
*/
public String getUnlocalizedName()
@@ -441,7 +454,7 @@ public abstract class ThEPartBase
/**
* Checks if the part is active and powered.
*
*
* @return
*/
@Override
@@ -473,7 +486,7 @@ public abstract class ThEPartBase
/**
* Called the player interact with this part?
*
*
* @param player
* @return
*/
@@ -568,7 +581,7 @@ public abstract class ThEPartBase
/**
* Returns true if the part is receiving any level of redstone power.
*
*
* @return
*/
public boolean isReceivingRedstonePower()
@@ -819,7 +832,7 @@ public abstract class ThEPartBase
/**
* Setup the part based on the passed item.
*
*
* @param itemPart
*/
public void setupPartFromItem( final ItemStack itemPart )
@@ -849,7 +862,7 @@ public abstract class ThEPartBase
/**
* Saves NBT data specific to the save type.
*
*
* @param data
* @param saveType
*/
@@ -16,9 +16,9 @@ import thaumicenergistics.common.network.packet.client.Packet_C_Sync;
/**
* Houses commonly used methods.
*
*
* @author Nividica
*
*
*/
public final class ThEUtils
{
@@ -39,22 +39,30 @@ public final class ThEUtils
/**
* Returns true if the tile still exists and the player is within reach range.
*
*
* @param player
* @param tile
* @return
*/
public static final boolean canPlayerInteractWith( @Nonnull final EntityPlayer player, @Nonnull final TileEntity tile )
{
return ( tile.getWorldObj().getTileEntity( tile.xCoord, tile.yCoord, tile.zCoord ) == tile ) &&
( player.getDistanceSq( tile.xCoord + 0.5D, tile.yCoord + 0.5D, tile.zCoord + 0.5D ) <= SQUARED_REACH );
TileEntity tileAtCoords = tile.getWorldObj().getTileEntity( tile.xCoord, tile.yCoord, tile.zCoord );
// Null check
if( tileAtCoords == null )
{
return false;
}
// Range check
return( player.getDistanceSq( tile.xCoord + 0.5D, tile.yCoord + 0.5D, tile.zCoord + 0.5D ) <= ThEUtils.SQUARED_REACH );
}
/**
* Returns true if the item stack is a wand, scepter, or staff if they are
* allowed.
*
*
* @param stack
* @param allowStaves
* @return
@@ -103,7 +111,7 @@ public final class ThEUtils
* Ping pongs a value back and forth from min -> max -> min.
* The base speed of this effect is 1 second per transition, 2 seconds
* total.
*
*
* @param speedReduction
* The higher this value, the slower the effect. The smaller this value, the
* faster the effect.
@@ -144,7 +152,7 @@ public final class ThEUtils
/**
* Plays a sound only the specified player can hear.
*
*
* @param player
* Can be null on client side.
* @param soundLocation
@@ -163,7 +171,7 @@ public final class ThEUtils
ResourceLocation sound = new ResourceLocation( soundLocation );
// Play the sound
playLocalSound( sound );
ThEUtils.playLocalSound( sound );
}
else
{
@@ -1,17 +1,26 @@
package thaumicenergistics.fml;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.logging.log4j.Level;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceMethodVisitor;
import cpw.mods.fml.relauncher.FMLRelaunchLog;
public abstract class AClassTransformer
{
protected static final String InstanceConstructorName = "<init>";
private static Printer asmPrinter = new Textifier();
private static TraceMethodVisitor asmVisitor = new TraceMethodVisitor( AClassTransformer.asmPrinter );
/**
* Canonical name of the class to be transformed.
*/
@@ -84,6 +93,28 @@ public abstract class AClassTransformer
return null;
}
/**
* Finds the next occurrence of the opcode after the specified instruction.
*
* @param fromInstruction
* @param opcode
* @return
*/
protected AbstractInsnNode findNextOpCode( final AbstractInsnNode fromInstruction, final int opcode )
{
AbstractInsnNode nextInsn = fromInstruction;
do
{
if( nextInsn.getOpcode() == opcode )
{
return nextInsn;
}
}
while( ( nextInsn = nextInsn.getNext() ) != null );
return null;
}
/**
* Locates a sequence of instructions.
*
@@ -143,6 +174,24 @@ public abstract class AClassTransformer
FMLRelaunchLog.log( "ThE-Core", Level.INFO, text );
}
protected void logInstructionDetails( final AbstractInsnNode insn )
{
// Visit the instruction
insn.accept( AClassTransformer.asmVisitor );
// Create the string writer
StringWriter sw = new StringWriter();
// Print the details into the writer
AClassTransformer.asmPrinter.print( new PrintWriter( sw ) );
// Clear the printer
AClassTransformer.asmPrinter.getText().clear();
// Log the details
this.log( sw.toString() );
}
/**
* Action to take if the transform fails.
*/
@@ -3,6 +3,7 @@ package thaumicenergistics.fml;
import java.util.HashMap;
import net.minecraft.launchwrapper.IClassTransformer;
import thaumicenergistics.fml.classtransformers.ae.ClassTransformer_CraftingTreeProcess;
import thaumicenergistics.fml.classtransformers.ae.ClassTransformer_GuiMEMonitorable;
import thaumicenergistics.fml.classtransformers.tc.*;
public class ASMTransformer
@@ -28,6 +29,7 @@ public class ASMTransformer
// Add AE transformers
this.addTransformer( new ClassTransformer_CraftingTreeProcess() );
this.addTransformer( new ClassTransformer_GuiMEMonitorable() );
}
/**
@@ -0,0 +1,66 @@
package thaumicenergistics.fml.classtransformers.ae;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import thaumicenergistics.fml.AClassTransformer;
public class ClassTransformer_GuiMEMonitorable
extends AClassTransformer
{
public ClassTransformer_GuiMEMonitorable()
{
super( "appeng.client.gui.implementations.GuiMEMonitorable" );
}
private void transformPostUpdate( final MethodNode method )
{
// Search for:
// for( final IAEItemStack is : list )
int opSequence[] = new int[] { Opcodes.IFEQ, Opcodes.ALOAD, Opcodes.INVOKEINTERFACE, Opcodes.CHECKCAST, Opcodes.ASTORE };
AbstractInsnNode insertionPoint = this.findSequence( method.instructions, opSequence, true );
// Get the end of loop jump
JumpInsnNode EOL_Jump = (JumpInsnNode)this.findNextOpCode( insertionPoint, Opcodes.GOTO );
// Insert hook:
// if( AEHooks.isItemGUIBlacklisted( is ) ) continue;
InsnList instructionList = new InsnList();
// is
instructionList.add( new VarInsnNode( Opcodes.ALOAD, 3 ) );
// Static call: isItemGUIBlacklisted( IAEItemStack )
instructionList.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "thaumicenergistics/common/integration/AEHooks",
"isItemGUIBlacklisted", "(Lappeng/api/storage/data/IAEItemStack;)Z",
false ) );
// continue
instructionList.add( new JumpInsnNode( Opcodes.IFNE, EOL_Jump.label ) );
// Insert into method
method.instructions.insert( insertionPoint, instructionList );
}
@Override
protected void onTransformFailure()
{
// No action required
}
@Override
protected void transform( final ClassNode classNode )
{
// Transform methods
for( MethodNode method : classNode.methods )
{
// Constructor
if( method.name.equals( "postUpdate" ) )
{
this.transformPostUpdate( method );
return; // Stop searching.
}
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB