Bug fixes

Cleaned up some ASM transformation code.
Renamed model and texture of golem Addon to golem Backpack
Fixed bug where storage bus did not work when placed after jar was
placed.
Added wifi backpack for Essentia core.
Fixed GUI based dupe bug.
Fixed multiple issues with the Arcane assembler: GUI desync, invalid
network state.
Golem backpack pearl now responds to out-of-range and if golem is
disabled(Fetter).
Fixed issue where the last pattern on a knowledge core could not be
erased.
This commit is contained in:
Chris committed 2016-01-21 13:47:19 -05:00
1 parent 373415c4c5
commit 823b381034
18 files changed
+721 -243

No files matched your search

+13 -1
View File
@@ -1,4 +1,16 @@
01/18/2016 0.10.0.0 - Beta
01/21/2016 0.10.0.0 - Beta
Fixed multiple issues with the Arcane assembler: GUI desync, invalid network state.
Golem backpack pearl now responds to out-of-range and if golem is disabled(Fetter).
Fixed issue where the last pattern on a knowledge core could not be erased.
01/19/2016 0.10.0.0 - Beta
Cleaned up some ASM transformation code.
Renamed model and texture of golem Addon to golem Backpack
Fixed bug where storage bus did not work when placed after jar was placed.
Added wifi backpack for Essentia core.
Fixed GUI based dupe bug.
01/18/2016 0.10.0.0 - Beta
Fixed bug where DPE would eat item stacks.
Refactored golem network code.
Added wifi backpack for Gather, Decanting, and Fill cores.
@@ -13,10 +13,10 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ModelGolemWifiAddon
public class ModelGolemWifiBackpack
extends ModelBase
{
public static ResourceLocation TEXTURE = new ResourceLocation( ThaumicEnergistics.MOD_ID, "textures/models/golem.wifi.addon.png" );
public static ResourceLocation TEXTURE = new ResourceLocation( ThaumicEnergistics.MOD_ID, "textures/models/golem.wifi.backpack.png" );
/**
* Submodels
@@ -43,11 +43,6 @@ public class ModelGolemWifiAddon
*/
private final float pearl_FaceDistance, pearl_2FD;
/**
* Rotation of the pearls
*/
private float pearlRotation = 0.0f;
/**
* True if the pearl display list is compiled
*/
@@ -58,7 +53,7 @@ public class ModelGolemWifiAddon
*/
private int pearlDispListID = -1;
public ModelGolemWifiAddon()
public ModelGolemWifiBackpack()
{
this.textureWidth = 16;
this.textureHeight = 16;
@@ -153,27 +148,16 @@ public class ModelGolemWifiAddon
tess.draw();
}
private void renderPearl( final float partialElapsedTick, final boolean inRange )
private void renderPearl( final float pearlRotation, final boolean inRange )
{
if( inRange )
if( !inRange )
{
// Apply Y rotation
if( !Minecraft.getMinecraft().isGamePaused() )
{
this.pearlRotation += ( partialElapsedTick * 2.0f );
if( this.pearlRotation >= 360.0f )
{
this.pearlRotation -= 360.0f;
}
}
}
else
{
// Set red
// Set red tint
GL11.glColor3f( 1.0f, 0.0f, 0.0f );
}
GL11.glRotatef( this.pearlRotation, 0.0f, 1.0f, 0.0f );
// Apply Y rotation
GL11.glRotatef( pearlRotation, 0.0f, 1.0f, 0.0f );
// Is the pearl compiled?
if( !this.isPearlCompiled )
@@ -201,13 +185,13 @@ public class ModelGolemWifiAddon
this.render( 0.03f, f5, true );
}
public void render( final float partialElapsedTick, final float f5, final boolean inRange )
public void render( final float pearlRotation, final float f5, final boolean inRange )
{
Minecraft.getMinecraft().renderEngine.bindTexture( ModelGolemWifiAddon.TEXTURE );
Minecraft.getMinecraft().renderEngine.bindTexture( ModelGolemWifiBackpack.TEXTURE );
this.PackBack.render( f5 );
this.PackFront.render( f5 );
this.Antenna.render( f5 );
this.renderPearl( partialElapsedTick, inRange );
this.renderPearl( pearlRotation, inRange );
}
@@ -9,7 +9,6 @@ import thaumcraft.api.IVisDiscountGear;
import thaumicenergistics.common.blocks.BlockArcaneAssembler;
import thaumicenergistics.common.container.slot.SlotArmor;
import thaumicenergistics.common.container.slot.SlotRestrictive;
import thaumicenergistics.common.items.ItemKnowledgeCore;
import thaumicenergistics.common.tiles.TileArcaneAssembler;
import thaumicenergistics.common.utils.EffectiveSide;
import appeng.api.implementations.items.IUpgradeModule;
@@ -62,17 +61,22 @@ public class ContainerArcaneAssembler
/**
* Reference to the arcane assembler
*/
public TileArcaneAssembler assembler;
public final TileArcaneAssembler assembler;
/**
* Knowledge Core slot.
*/
private SlotRestrictive kCoreSlot;
private final SlotRestrictive kCoreSlot;
/**
* Discount armor slots.
*/
private SlotArmor[] discountSlots = new SlotArmor[4];
private final SlotArmor[] discountSlots = new SlotArmor[4];
/**
* Pattern slots
*/
private final SlotInaccessible[] patternSlots = new SlotInaccessible[PATTERN_ROWS * PATTERN_COLS];
public ContainerArcaneAssembler( final EntityPlayer player, final World world, final int X, final int Y, final int Z )
{
@@ -83,7 +87,7 @@ public class ContainerArcaneAssembler
this.assembler = (TileArcaneAssembler)world.getTileEntity( X, Y, Z );
// Get the assemblers inventory
IInventory asmInv = this.assembler.getInternalInventory();
IInventory assemblerInventory = this.assembler.getInternalInventory();
// Bind to the players inventory
this.bindPlayerInventory( player.inventory, ContainerArcaneAssembler.PLAYER_INV_POSITION_Y, ContainerArcaneAssembler.HOTBAR_INV_POSITION_Y );
@@ -92,7 +96,7 @@ public class ContainerArcaneAssembler
this.bindToNetworkTool( player.inventory, this.assembler.getLocation(), 0, 35 );
// Add the kcore slot
this.kCoreSlot = new SlotRestrictive( asmInv, TileArcaneAssembler.KCORE_SLOT_INDEX, ContainerArcaneAssembler.KCORE_SLOT_X,
this.kCoreSlot = new SlotRestrictive( assemblerInventory, TileArcaneAssembler.KCORE_SLOT_INDEX, ContainerArcaneAssembler.KCORE_SLOT_X,
ContainerArcaneAssembler.KCORE_SLOT_Y );
this.addSlotToContainer( this.kCoreSlot );
@@ -102,11 +106,13 @@ public class ContainerArcaneAssembler
for( int col = 0; col < ContainerArcaneAssembler.PATTERN_COLS; col++ )
{
// Calculate the index
int index = TileArcaneAssembler.PATTERN_SLOT_INDEX + ( ( row * ContainerArcaneAssembler.PATTERN_COLS ) + col );
int index = ( row * ContainerArcaneAssembler.PATTERN_COLS ) + col;
int invIndex = TileArcaneAssembler.PATTERN_SLOT_INDEX + index;
// Add the slot
this.addSlotToContainer( new SlotInaccessible( asmInv, index, ContainerArcaneAssembler.PATTERN_SLOT_X + ( 18 * col ),
ContainerArcaneAssembler.PATTERN_SLOT_Y + ( 18 * row ) ) );
this.addSlotToContainer( this.patternSlots[index]
= new SlotInaccessible( assemblerInventory, invIndex, ContainerArcaneAssembler.PATTERN_SLOT_X + ( 18 * col ),
ContainerArcaneAssembler.PATTERN_SLOT_Y + ( 18 * row ) ) );
}
}
@@ -115,15 +121,16 @@ public class ContainerArcaneAssembler
ContainerArcaneAssembler.UPGRADE_SLOT_X, ContainerArcaneAssembler.UPGRADE_SLOT_Y );
// Create the target slot
this.addSlotToContainer( new SlotInaccessible( asmInv, TileArcaneAssembler.TARGET_SLOT_INDEX, ContainerArcaneAssembler.TARGET_SLOT_X,
ContainerArcaneAssembler.TARGET_SLOT_Y ) );
this.addSlotToContainer( new SlotInaccessible( assemblerInventory, TileArcaneAssembler.TARGET_SLOT_INDEX,
ContainerArcaneAssembler.TARGET_SLOT_X, ContainerArcaneAssembler.TARGET_SLOT_Y ) );
// Add armor slots
for( int index = 0; index < ContainerArcaneAssembler.DISCOUNT_ARMOR_COUNT; index++ )
{
this.discountSlots[index] = new SlotArmor( asmInv, TileArcaneAssembler.DISCOUNT_ARMOR_INDEX + index,
ContainerArcaneAssembler.DISCOUNT_ARMOR_SLOT_X, ContainerArcaneAssembler.DISCOUNT_ARMOR_SLOT_Y + ( index * 18 ), index,
true );
this.discountSlots[index] = new SlotArmor( assemblerInventory, TileArcaneAssembler.DISCOUNT_ARMOR_INDEX + index,
ContainerArcaneAssembler.DISCOUNT_ARMOR_SLOT_X,
ContainerArcaneAssembler.DISCOUNT_ARMOR_SLOT_Y + ( index * 18 ),
index, true );
this.addSlotToContainer( this.discountSlots[index] );
}
@@ -206,7 +213,7 @@ public class ContainerArcaneAssembler
if( !( slotStack.getItem() instanceof IUpgradeModule ) )
{
// Attempt to merge with kcore slot
if( slotStack.getItem() instanceof ItemKnowledgeCore )
if( this.kCoreSlot.isItemValid( slotStack ) )
{
didMerge = this.mergeItemStack( slotStack, this.kCoreSlot.slotNumber, this.kCoreSlot.slotNumber + 1, false );
}
@@ -1113,6 +1113,7 @@ public abstract class ContainerEssentiaCellTerminalBase
// Inform the slot its stack changed;
slot.onSlotChanged();
}
this.detectAndSendChanges();
}
}
@@ -88,17 +88,20 @@ public abstract class TheContainerBase
@Override
public void detectAndSendChanges()
{
// Call super
super.detectAndSendChanges();
// MP player?
if( this.playerMP != null )
{
if( this.detectAndSendChangesMP( this.playerMP ) )
{
this.playerMP.isChangingQuantityOnly = false;
// Call super
super.detectAndSendChanges();
}
}
// Call super
super.detectAndSendChanges();
}
/**
@@ -4,7 +4,9 @@ import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.common.entities.golems.EntityGolemBase;
import thaumicenergistics.api.grid.IMEEssentiaMonitor;
import thaumicenergistics.common.grid.WirelessAELink;
import thaumicenergistics.common.integration.tc.GolemUpgradeTypes;
import appeng.api.AEApi;
@@ -21,7 +23,6 @@ public abstract class AIAENetworkGolem
protected class NetworkHandler
extends WirelessAELink
{
/**
* The maximum number of items the golem can inject/extract per update.
*/
@@ -124,6 +125,27 @@ public abstract class AIAENetworkGolem
stack.stackSize -= depositSize;
}
/**
* Extracts essentia from the network.
*
* @param aspect
* @param amount
* @param mode
* @return The amount extracted.
*/
public long extractEssentia( final Aspect aspect, final int amount, final Actionable mode )
{
// Get the essentia monitor
IMEEssentiaMonitor monitor = this.getEssentiaInventory();
if( monitor == null )
{
return 0;
}
return monitor.extractEssentia( aspect, Math.min( amount, this.maxEssentiaRate ), mode, this.actionSource, mode == Actionable.MODULATE );
}
/**
* Extracts fluids from the network.
*
@@ -209,6 +231,29 @@ public abstract class AIAENetworkGolem
return extracted.getItemStack();
}
/**
* Inserts essentia into the network.
*
* @param aspect
* @param amount
* @return Amount injected
*/
public long insertEssentia( final Aspect aspect, final int amount )
{
// Get the essentia monitor
IMEEssentiaMonitor monitor = this.getEssentiaInventory();
if( monitor == null )
{
return 0;
}
int amountToInject = Math.min( amount, this.maxEssentiaRate );
long amountRejected = monitor.injectEssentia( aspect, amountToInject, Actionable.MODULATE, this.actionSource, true );
return amountToInject - amountRejected;
}
/**
* Checks if the network can be interacted with.
*
@@ -224,7 +269,7 @@ public abstract class AIAENetworkGolem
}
private static final int NETWORK_COOLDOWN = 15;
private static final int NETWORK_COOLDOWN = 20;
/**
* How many ticks until the golem can interact with the network again.
@@ -259,11 +304,11 @@ public abstract class AIAENetworkGolem
/**
* <PRE>
* Base 8, 24, 32
* Advanced 16, 48, 64
* Base 4, 12, 16
* Advanced 8, 24, 32
* </PRE>
*/
private static final int[] ESS_RATES = new int[] { 8, 24, 32 };
private static final int[] ESS_RATES = new int[] { 4, 12, 16 };
public AIAENetworkGolem( final EntityGolemBase golem, final WirelessGolemHandler.WirelessServerData wsd )
{
@@ -298,7 +343,7 @@ public abstract class AIAENetworkGolem
*
* @return True if cooled down.
*/
private boolean cooldownTick()
private boolean cooledDown()
{
if( this.actionTimer > 0 )
{
@@ -328,7 +373,7 @@ public abstract class AIAENetworkGolem
public final boolean shouldExecute()
{
// Check the network timer
if( this.cooldownTick() )
if( this.cooledDown() )
{
this.restartNetworkCooldown();
@@ -0,0 +1,340 @@
package thaumicenergistics.common.entities;
import java.util.HashSet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.IEssentiaTransport;
import thaumcraft.common.entities.golems.EntityGolemBase;
import thaumcraft.common.entities.golems.Marker;
import thaumcraft.common.tiles.TileAlembic;
import thaumcraft.common.tiles.TileJarFillable;
import thaumcraft.common.tiles.TileJarFillableVoid;
import thaumicenergistics.common.entities.WirelessGolemHandler.WirelessServerData;
import appeng.api.config.Actionable;
public class AIGolemWifiEssentia
extends AIAENetworkGolem
{
private final HashSet<TileJarFillable> checkedJars = new HashSet<TileJarFillable>();
/**
* The jar the golem plan's to fill up.
*/
private TileJarFillable targetJar = null;
/**
* Distance to the target jar.
*/
private double targetDistance = 0;
/**
* Is the target jar a void jar?
*/
private boolean targetVoid;
/**
* The square range of the golem.
*/
private double golemRange;
/**
* True if the golem is filling up jars, false if the golem is emptying something.
*/
private boolean modeFill;
public AIGolemWifiEssentia( final EntityGolemBase golem, final WirelessServerData wsd )
{
super( golem, wsd );
}
/**
* Checks jars connected to the specified jar for potential targets.
*
* @param world
* @param gHomePos
* @param teJar
*/
private void checkConnectedJars( final World world, final ChunkCoordinates gHomePos, final TileEntity teJar )
{
int x, y, z, setOp;
// Sanity check
if( this.checkedJars.size() >= 200 )
{
return;
}
// Check each direction
for( ForgeDirection side : ForgeDirection.VALID_DIRECTIONS )
{
// Get the position
x = side.offsetX + teJar.xCoord;
y = side.offsetY + teJar.yCoord;
z = side.offsetZ + teJar.zCoord;
// Get the tile entity
TileEntity te = world.getTileEntity( x, y, z );
// Ensure the tile is a jar
if( !( te instanceof TileJarFillable ) )
{
continue;
}
// Set the jar if it is closer
setOp = this.setTargetIfValid( (TileJarFillable)te, gHomePos );
if( setOp > 2 )
{
// Check it's connected jars
this.checkConnectedJars( world, gHomePos, te );
}
}
}
/**
* Locates the nearest valid jar as a target.
*/
private void findClosestValidJar()
{
// Is there a target?
if( this.targetJar != null )
{
// Is the jar still there?
if( this.golem.worldObj.getTileEntity( this.targetJar.xCoord,
this.targetJar.yCoord, this.targetJar.zCoord ) == this.targetJar )
{
// Can it hold more?
Aspect wantedAspect = ( this.targetJar.aspectFilter != null ? this.targetJar.aspectFilter : this.targetJar.aspect );
if( ( wantedAspect != null ) && ( this.targetVoid || ( this.targetJar.amount < this.targetJar.maxAmount ) ) )
{
// Can the wanted aspect be extracted?
if( this.network.extractEssentia( wantedAspect, 1, Actionable.SIMULATE ) > 0 )
{
return;
}
}
}
}
// Reset target jar
this.targetJar = null;
this.targetDistance = Double.MAX_VALUE;
this.targetVoid = false;
// Get the world the golem is in
World world = this.golem.worldObj;
int worldDim = world.provider.dimensionId;
// Calculate the squared range
this.golemRange = this.golem.getRange();
this.golemRange *= this.golemRange;
// Get the golems position
ChunkCoordinates gHomePos = this.golem.getHomePosition();
// Check each of the golems markers
for( Marker marker : this.golem.getMarkers() )
{
// Ensure the marker is in the same dimension
if( marker.dim != worldDim )
{
continue;
}
// Get the tile entity
TileEntity markedTile = world.getTileEntity( marker.x, marker.y, marker.z );
// Ensure the tile is a jar
if( !( markedTile instanceof TileJarFillable ) )
{
continue;
}
// Set the jar if it is closer
this.setTargetIfValid( (TileJarFillable)markedTile, gHomePos );
// Check connected jars
this.checkConnectedJars( world, gHomePos, markedTile );
}
// Reset checked
this.checkedJars.clear();
}
/**
* Sets the target if the jar is valid, closer, and in range.
*
* @param jar
* @param gHomePos
* @return 1 = Jar out of range, 2 = Jar already visited, 3 = Invalid jar, 4 = Set as target
*/
private int setTargetIfValid( final TileJarFillable jar, final ChunkCoordinates gHomePos )
{
if( !this.checkedJars.add( jar ) )
{
return 2;
}
// In range of golem?
double distance = jar.getDistanceFrom( gHomePos.posX, gHomePos.posY, gHomePos.posZ );
if( distance > this.golemRange )
{
return 1;
}
// If the current target is voiding, but the potential target is not,
// then do not bother with the distance check.
boolean isVoid = ( jar instanceof TileJarFillableVoid );
if( !( this.targetVoid && !isVoid ) )
{
// Check distance
if( distance > this.targetDistance )
{
return 1;
}
}
// Check for essentia
if( jar.aspect == null )
{
// Check for label
if( jar.aspectFilter == null )
{
return 3;
}
}
// Check amount
if( !isVoid && ( jar.amount >= jar.maxAmount ) )
{
return 3;
}
// Valid target
this.targetJar = jar;
this.targetDistance = distance;
this.targetVoid = isVoid;
return 4;
}
@Override
protected boolean needsNetworkNow()
{
// Determine the mode
// Get the tile entity at the golems home
ChunkCoordinates gHomePos = this.golem.getHomePosition();
ForgeDirection side = ForgeDirection.getOrientation( this.golem.homeFacing );
TileEntity te = this.golem.worldObj.getTileEntity( gHomePos.posX - side.offsetX,
gHomePos.posY - side.offsetY,
gHomePos.posZ - side.offsetZ );
// Is the tile an essentia transport?
this.modeFill = !( te instanceof IEssentiaTransport );
// If the tile is not valid, check above it for alembic
if( this.modeFill )
{
for( int i = 1; ( i < 6 ) && this.modeFill; ++i )
{
te = this.golem.worldObj.getTileEntity( gHomePos.posX - side.offsetX,
gHomePos.posY - side.offsetY + i,
gHomePos.posZ - side.offsetZ );
this.modeFill = !( te instanceof TileAlembic );
}
}
// Fill mode
if( this.modeFill )
{
// Needs network if the golem is not carrying anything, and there is a target jar
if( this.golem.essentiaAmount > 0 )
{
return false;
}
// Golem is not carrying anything, find a jar
this.findClosestValidJar();
return( this.targetJar != null );
}
// Empty mode
return( this.golem.getNavigator().noPath() && ( this.golem.essentiaAmount > 0 ) );
}
@Override
public void updateTask()
{
// Fill mode
if( this.modeFill )
{
// Get the wanted aspect
Aspect wantedAspect = ( this.targetJar.aspectFilter != null ? this.targetJar.aspectFilter : this.targetJar.aspect );
if( wantedAspect == null )
{
// Jar is invalid now
this.targetJar = null;
return;
}
// Get the capacity of the jar
int amount = this.targetJar.maxAmount;
// Is the jar not voiding
if( !this.targetVoid )
{
// Calculate the max amount to extract
amount -= this.targetJar.amount;
if( amount < 1 )
{
// Jar is full
this.targetJar = null;
return;
}
}
// Attempt extraction
int extractedAmount = (int)this.network.extractEssentia( wantedAspect, amount, Actionable.MODULATE );
if( extractedAmount <= 0 )
{
return;
}
// Set the golems essentia
this.golem.essentia = wantedAspect;
this.golem.essentiaAmount = extractedAmount;
}
else
{
// Mode empty
if( ( this.golem.essentia == null ) || ( this.golem.essentiaAmount <= 0 ) || !this.golem.getNavigator().noPath() )
{
return;
}
// Attempt injection
int injectedAmount = (int)this.network.insertEssentia( this.golem.essentia, this.golem.essentiaAmount );
if( injectedAmount == 0 )
{
return;
}
// Update golem
this.golem.essentiaAmount -= injectedAmount;
if( this.golem.essentiaAmount <= 0 )
{
this.golem.essentia = null;
}
}
this.golem.updateCarried();
}
}
@@ -73,6 +73,7 @@ public class AIGolemWifiLiquid
{
this.golem.fluidCarried = extracted;
}
this.golem.updateCarried();
this.wantedFluid = null;
}
@@ -1,5 +1,6 @@
package thaumicenergistics.common.entities;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -7,7 +8,7 @@ import org.lwjgl.opengl.GL11;
import thaumcraft.common.entities.golems.EntityGolemBase;
import thaumicenergistics.api.entities.IGolemHookHandler;
import thaumicenergistics.api.entities.IGolemHookSyncRegistry;
import thaumicenergistics.client.render.model.ModelGolemWifiAddon;
import thaumicenergistics.client.render.model.ModelGolemWifiBackpack;
import thaumicenergistics.common.integration.tc.GolemCoreType;
import thaumicenergistics.common.items.ItemEnum;
import thaumicenergistics.common.items.ItemGolemWirelessBackpack;
@@ -21,6 +22,7 @@ public class WirelessGolemHandler
public static class WirelessClientData
{
public boolean isInRange = false;
public float pearlRotation = 0.0f;
public WirelessClientData( final boolean inRange )
{
@@ -54,7 +56,7 @@ public class WirelessGolemHandler
SYNCFLAG_NO_WIFI = Character.valueOf( 'n' );
@SideOnly(Side.CLIENT)
private ModelGolemWifiAddon addonModel;
private ModelGolemWifiBackpack addonModel;
/**
* ID of the wifi sync field.
@@ -101,7 +103,7 @@ public class WirelessGolemHandler
@SideOnly(Side.CLIENT)
private void setupModel()
{
this.addonModel = new ModelGolemWifiAddon();
this.addonModel = new ModelGolemWifiBackpack();
}
@Override
@@ -139,17 +141,6 @@ public class WirelessGolemHandler
// Check for backpack
boolean isHoldingBackpack = ( ( heldItem != null ) && ( heldItem.getItem() == this.backpackItem ) );
// Client side?
if( side == Side.CLIENT )
{
if( isHoldingBackpack )
{
//Swing the item
player.swingItem();
}
return false;
}
// Does the golem already have a backpack on?
if( handlerData != null )
{
@@ -168,8 +159,7 @@ public class WirelessGolemHandler
// Unsupported cores
case Butcher:
case Empty:
case Essentia: // TODO, complex no doubt
case Fish: // TODO?
case Fish:
case Guard:
case Harvest:
case Lumber:
@@ -182,9 +172,23 @@ public class WirelessGolemHandler
case Gather:
case Fill:
case Liquid:
return isHoldingBackpack;
case Essentia:
break;
}
// Client side?
if( side == Side.CLIENT )
{
if( isHoldingBackpack )
{
//Swing the item
player.swingItem();
}
return false;
}
return isHoldingBackpack;
}
@Override
@@ -197,6 +201,9 @@ public class WirelessGolemHandler
String encKey = this.backpackItem.getEncryptionKey( heldItem );
if( encKey != null )
{
// Play sound
golem.worldObj.playSoundAtEntity( golem, "thaumcraft:upgrade", 0.5F, 1.0F );
// Take the item
player.inventory.setInventorySlotContents( player.inventory.currentItem, null );
@@ -254,6 +261,7 @@ public class WirelessGolemHandler
{
return;
}
WirelessClientData wcd = (WirelessClientData)clientHandlerData;
if( golem.hurtTime > 0 )
{
@@ -271,15 +279,33 @@ public class WirelessGolemHandler
GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
}
// Is the golem in range and active?
boolean golemActive = wcd.isInRange && !golem.inactive;
// Update the rotation of the pearl
if( golemActive && !Minecraft.getMinecraft().isGamePaused() )
{
wcd.pearlRotation += partialElaspsedTick * 2.0f;
if( wcd.pearlRotation >= 360.0f )
{
wcd.pearlRotation -= 360.0f;
}
}
// Push the matrix
GL11.glPushMatrix();
// Translate to the golem
GL11.glTranslatef( (float)x, (float)y + 0.63f, (float)z );
// Rotate with the golem
// Rotate to face away from the golem
float golemYaw = 270.0f;
// Interpolate the golems rotation
golemYaw -= ( ( golem.renderYawOffset * partialElaspsedTick ) + ( golem.prevRenderYawOffset * ( 1.0f - partialElaspsedTick ) ) );
// Rotate with the golem
GL11.glRotatef( golemYaw, 0.0f, 1.0f, 0.0f );
// Translate just behind the golem
@@ -289,7 +315,7 @@ public class WirelessGolemHandler
GL11.glScalef( 0.8f, 0.8f, 0.8f );
// Render
this.addonModel.render( partialElaspsedTick, 0.0625f, ( (WirelessClientData)clientHandlerData ).isInRange );
this.addonModel.render( wcd.pearlRotation, 0.0625f, golemActive );
// Pop the matrix
GL11.glPopMatrix();
@@ -329,6 +355,11 @@ public class WirelessGolemHandler
// Add liquid AI script
golem.tasks.addTask( 2, new AIGolemWifiLiquid( golem, wsd ) );
break;
case Essentia:
// Add essentia AI script
golem.tasks.addTask( 2, new AIGolemWifiEssentia( golem, wsd ) );
break;
default:
break;
}
@@ -349,7 +380,6 @@ public class WirelessGolemHandler
@Override
public Object spawnGolemFromItemStack( final EntityGolemBase golem, final ItemStack itemGolemPlacer, final Side side )
{
golem.advanced = true;
return null;
}
@@ -109,7 +109,7 @@ public class GolemHooks
/**
* ID of the datawatcher field.
*/
private static final int DATAWATCHER_ID = 4;
private static int DATAWATCHER_ID = -1;
/**
* Default sync values.
@@ -285,8 +285,36 @@ public class GolemHooks
// Get the datawatcher
DataWatcher watcher = golem.getDataWatcher();
// Add datawatcher field.
watcher.addObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
// Has the ID been set?
if( DATAWATCHER_ID == -1 )
{
// Set the ID to the next available
for( int i = 4; i < 31; ++i )
{
try
{
// Add the object
watcher.addObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
// Object was added
DATAWATCHER_ID = i;
return;
}
catch( IllegalArgumentException e )
{
}
}
// If execution makes it this far, there were no available ID's :(
DATAWATCHER_ID = -2;
ThELog.warning( "Golem Hook API is unable to register channel for sync data." );
return;
}
else if( DATAWATCHER_ID > 0 )
{
// Add datawatcher field.
watcher.addObject( DATAWATCHER_ID, localRegistry.mappingsToString() );
}
}
/**
@@ -312,16 +340,24 @@ public class GolemHooks
// Update data watcher
if( syncRegistry.hasChanged() )
{
golem.getDataWatcher().updateObject( DATAWATCHER_ID, syncRegistry.mappingsToString() );
if( DATAWATCHER_ID > 0 )
{
golem.getDataWatcher().updateObject( DATAWATCHER_ID, syncRegistry.mappingsToString() );
}
}
return;
}
if( DATAWATCHER_ID < 0 )
{
return;
}
// Update sync ticks
++syncRegistry.clientSyncTicks;
// Have 20 ticks passed? (Roughly a full second if the game is not lagging)
if( syncRegistry.clientSyncTicks >= 20.0f )
if( syncRegistry.clientSyncTicks >= 30.0f )
{
// Reset the counter
syncRegistry.clientSyncTicks = 0.0f;
@@ -478,6 +514,7 @@ public class GolemHooks
logCaughtException( "renderGolem", handler, e );
}
}
}
/**
@@ -29,14 +29,15 @@ public class VisCraftingHelper
*
* @param inventory
* @param firstSlotIndex
* @param slotCount
* @param aspect
* @return
*/
public float calculateArmorDiscount( final IInventory inventory, final int firstSlotIndex, final Aspect aspect )
public float calculateArmorDiscount( final IInventory inventory, final int firstSlotIndex, final int slotCount, final Aspect aspect )
{
float discount = 0.0F;
for( int index = 0; index < 4; index++ )
for( int index = 0; index < slotCount; index++ )
{
// Get the armor stack
ItemStack armor = inventory.getStackInSlot( firstSlotIndex + index );
@@ -63,13 +64,14 @@ public class VisCraftingHelper
*
* @param inventory
* @param firstSlotIndex
* @param slotCount
* @return
*/
public int calculateArmorWarp( final IInventory inventory, final int firstSlotIndex )
public int calculateArmorWarp( final IInventory inventory, final int firstSlotIndex, final int slotCount )
{
int warp = 0;
for( int index = 0; index < 4; index++ )
for( int index = 0; index < slotCount; index++ )
{
// Get the armor stack
ItemStack armor = inventory.getStackInSlot( firstSlotIndex + index );
@@ -133,6 +133,10 @@ public class HandlerKnowledgeCore
{
data.setTag( NBTKEY_PATTERNS, plist );
}
else
{
data.removeTag( NBTKEY_PATTERNS );
}
}
/**
@@ -68,19 +68,6 @@ public class TheInternalInventory
// Calculate the amount to get
int decAmount = Math.min( amount, slotStack.stackSize );
// Calculate the remaining amount
int remAmount = slotStack.stackSize - decAmount;
// Is there anything remaining in the slot?
if( remAmount > 0 )
{
this.slots[slotIndex].stackSize = remAmount;
}
else
{
this.slots[slotIndex] = null;
}
// Was any amount gotten?
if( decAmount > 0 )
{
@@ -88,7 +75,20 @@ public class TheInternalInventory
resultStack.stackSize = decAmount;
}
this.markDirty();
// Calculate the remaining amount
slotStack.stackSize = slotStack.stackSize - decAmount;
// Is there anything remaining in the slot?
if( slotStack.stackSize > 0 )
{
// Re-set
this.setInventorySlotContents( slotIndex, slotStack );
}
else
{
// Clear
this.setInventorySlotContents( slotIndex, null );
}
return resultStack;
}
@@ -373,7 +373,7 @@ public class PartEssentiaStorageBus
super.onNeighborChanged();
// Send grid update event on server side
if( EffectiveSide.isServerSide() )
if( EffectiveSide.isServerSide() && this.isActive() )
{
// Update the handler
if( this.handler.onNeighborChange() )
@@ -60,7 +60,6 @@ import appeng.tile.TileEvent;
import appeng.tile.events.TileEventType;
import appeng.tile.grid.AENetworkInvTile;
import appeng.tile.inventory.InvOperation;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -69,6 +68,53 @@ public class TileArcaneAssembler
extends AENetworkInvTile
implements ICraftingProvider, IWailaSource
{
private class AAInv
extends TheInternalInventory
{
public AAInv()
{
super( "ArcaneAssemblerInventory", TileArcaneAssembler.SLOT_COUNT, 64 );
}
@Override
public boolean isItemValidForSlot( final int slotIndex, final ItemStack itemStack )
{
if( slotIndex == TileArcaneAssembler.KCORE_SLOT_INDEX )
{
return ( itemStack == null ) || ( itemStack.getItem() instanceof ItemKnowledgeCore );
}
return true;
}
@Override
public void markDirty()
{
TileArcaneAssembler.this.markDirty();
}
@Override
public void setInventorySlotContents( final int slotIndex, final ItemStack itemStack )
{
// Call super
super.setInventorySlotContents( slotIndex, itemStack );
// Core changed?
if( slotIndex == TileArcaneAssembler.KCORE_SLOT_INDEX )
{
TileArcaneAssembler.this.flag_CoreChanged = true;
}
// Armor changed?
if( slotIndex >= DISCOUNT_ARMOR_INDEX )
{
TileArcaneAssembler.this.flag_RecalcVis = true;
}
}
}
/**
* NBT Keys
*/
@@ -118,9 +164,10 @@ public class TileArcaneAssembler
public static double IDLE_POWER = 0.0D, ACTIVE_POWER = 1.5D, WARP_POWER_PERCENT = 0.15;
/**
* Holds the patterns and the kcore
* Holds the patterns and the kcore.
* Saved and loaded by AEInvTile due to getInternalInventory() call.
*/
private final TheInternalInventory internalInventory;
private final AAInv internalInventory;
/**
* Holds the upgrades
@@ -140,7 +187,7 @@ public class TileArcaneAssembler
/**
* Handles interaction with the knowledge core.
*/
private HandlerKnowledgeCore kCoreHandler;
private final HandlerKnowledgeCore kCoreHandler;
/**
* If true the network should be informed of changes to available patterns.
@@ -193,9 +240,14 @@ public class TileArcaneAssembler
private boolean delayedUpdate = false;
/**
* Set true when the tile is ready.
* True when the core has changed.
*/
private boolean isReady = false;
boolean flag_CoreChanged = false;
/**
* True if the vis discount needs to be re-calculated.
*/
boolean flag_RecalcVis = false;
/**
* Creates the assembler and it's inventory.
@@ -203,7 +255,7 @@ public class TileArcaneAssembler
public TileArcaneAssembler()
{
// Create the internal inventory
this.internalInventory = new TheInternalInventory( "ArcaneAssemblerInventory", TileArcaneAssembler.SLOT_COUNT, 64 );
this.internalInventory = new AAInv();
// Create the upgrade inventory
this.upgradeInventory = new BlockUpgradeInventory( ThEApi.instance().blocks().ArcaneAssembler.getBlock(), this,
@@ -217,6 +269,15 @@ public class TileArcaneAssembler
{
this.visDiscount.put( primal, VisCraftingHelper.INSTANCE.getScepterVisModifier( primal ) );
}
// Create the handler
this.kCoreHandler = new HandlerKnowledgeCore();
// Set idle power usage
this.getProxy().setIdlePowerUsage( TileArcaneAssembler.IDLE_POWER );
// Require a channel
this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL );
}
/**
@@ -248,6 +309,7 @@ public class TileArcaneAssembler
*/
private void calculateVisDiscounts()
{
this.flag_RecalcVis = false;
float discount;
for( Aspect primal : TileArcaneAssembler.PRIMALS )
@@ -256,7 +318,8 @@ public class TileArcaneAssembler
discount = VisCraftingHelper.INSTANCE.getScepterVisModifier( primal );
// Factor in the discount armor
discount -= VisCraftingHelper.INSTANCE.calculateArmorDiscount( this.internalInventory, TileArcaneAssembler.DISCOUNT_ARMOR_INDEX, primal );
discount -= VisCraftingHelper.INSTANCE.calculateArmorDiscount( this.internalInventory, DISCOUNT_ARMOR_INDEX, 4,
primal );
this.visDiscount.put( primal, discount );
}
@@ -265,8 +328,8 @@ public class TileArcaneAssembler
this.warpPowerMultiplier = 1.0F;
// Calculate warp power multiplier
this.warpPowerMultiplier += VisCraftingHelper.INSTANCE.calculateArmorWarp( this.internalInventory, TileArcaneAssembler.DISCOUNT_ARMOR_INDEX ) *
TileArcaneAssembler.WARP_POWER_PERCENT;
this.warpPowerMultiplier += VisCraftingHelper.INSTANCE.calculateArmorWarp( this.internalInventory, DISCOUNT_ARMOR_INDEX, 4 ) *
WARP_POWER_PERCENT;
}
private void craftingTick()
@@ -477,22 +540,6 @@ public class TileArcaneAssembler
}
/**
* Configures the Assembler.
*/
private void setupAssemblerTile()
{
// Ignored on client side
if( FMLCommonHandler.instance().getEffectiveSide().isServer() )
{
// Set idle power usage
this.getProxy().setIdlePowerUsage( TileArcaneAssembler.IDLE_POWER );
// Set that we require a channel
this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL );
}
}
/**
* The number of ticks required to craft an item.
*/
@@ -501,6 +548,40 @@ public class TileArcaneAssembler
return TileArcaneAssembler.BASE_TICKS_PER_CRAFT - ( 4 * this.upgradeCount );
}
/**
* Updates the handler to the current core.
*/
private void updateCoreHandler()
{
this.flag_CoreChanged = false;
// Is there a kcore?
ItemStack kCore = this.internalInventory.getStackInSlot( KCORE_SLOT_INDEX );
if( kCore != null )
{
// Is it a new core?
if( !TileArcaneAssembler.this.kCoreHandler.isHandlingCore( kCore ) )
{
// Open the core
TileArcaneAssembler.this.kCoreHandler.open( kCore );
// Update the pattern slots
TileArcaneAssembler.this.updatePatternSlots();
}
}
else
{
// Was there a core?
if( TileArcaneAssembler.this.kCoreHandler.hasCore() )
{
// No more core
TileArcaneAssembler.this.kCoreHandler.close();
// Update the pattern slots
TileArcaneAssembler.this.updatePatternSlots();
}
}
}
/**
* Updates the pattern slots to match the kcore patterns.
*/
@@ -529,6 +610,8 @@ public class TileArcaneAssembler
this.internalInventory.setInventorySlotContents( index, null );
}
}
this.stalePatterns = true;
}
@Override
@@ -763,63 +846,6 @@ public class TileArcaneAssembler
}
}
@Override
public void markDirty()
{
// Call super
super.markDirty();
// Is the tile ready?
if( !this.isReady )
{
// Still in setup phase.
return;
}
// Is there a kcore?
ItemStack kCore = this.internalInventory.getStackInSlot( TileArcaneAssembler.KCORE_SLOT_INDEX );
if( kCore != null )
{
// Is it a new core?
if( ( this.kCoreHandler == null ) || ( !this.kCoreHandler.isHandlingCore( kCore ) ) )
{
// Close the old handler
if( this.kCoreHandler != null )
{
this.kCoreHandler.close();
}
// Create a new handler
this.kCoreHandler = new HandlerKnowledgeCore( kCore );
// Update the pattern slots
this.updatePatternSlots();
// Update the network
this.stalePatterns = true;
}
}
else
{
// Was there a core?
if( this.kCoreHandler != null )
{
// No more core
this.kCoreHandler.close();
this.kCoreHandler = null;
// Update the pattern slots
this.updatePatternSlots();
// Update the network
this.stalePatterns = true;
}
}
//Recalculate the vis discount.
this.calculateVisDiscounts();
}
/**
* Called when the tile entity is about to be destroyed by a block break.
*/
@@ -913,24 +939,18 @@ public class TileArcaneAssembler
// Call super
super.onReady();
// Setup the kcore handler
this.updateCoreHandler();
// Is there a knowledge core?
if( this.internalInventory.getHasStack( KCORE_SLOT_INDEX ) )
{
// Is there a pattern?
if( this.currentPattern != null )
{
// Set the core
// Set the patterns core
this.currentPattern.setKnowledgeCore( this.internalInventory.getStackInSlot( KCORE_SLOT_INDEX ) );
}
// Create the handler
this.kCoreHandler = new HandlerKnowledgeCore( this.internalInventory.getStackInSlot( KCORE_SLOT_INDEX ) );
// Update the pattern slots
this.updatePatternSlots();
// Update the network
this.stalePatterns = true;
}
else if( this.currentPattern != null )
{
@@ -939,14 +959,8 @@ public class TileArcaneAssembler
this.currentPattern = null;
}
// Setup the assembler
this.setupAssemblerTile();
// Recalculate the vis discounts
this.calculateVisDiscounts();
// Set ready
this.isReady = true;
}
@TileEvent(TileEventType.NETWORK_READ)
@@ -1014,7 +1028,12 @@ public class TileArcaneAssembler
@TileEvent(TileEventType.TICK)
public void onTick()
{
// Ignored on client side.
// Vis discounts need to be updated?
if( this.flag_RecalcVis )
{
this.calculateVisDiscounts();
}
if( EffectiveSide.isClientSide() )
{
if( ( this.isCrafting ) && ( this.craftTickCounter < TileArcaneAssembler.BASE_TICKS_PER_CRAFT ) )
@@ -1022,9 +1041,16 @@ public class TileArcaneAssembler
this.craftTickCounter++ ;
}
// Ignore the rest on client side.
return;
}
// Core changed?
if( this.flag_CoreChanged )
{
this.updateCoreHandler();
}
// Ensure the assembler is active
if( !this.isActive() )
{
@@ -45,6 +45,11 @@ public abstract class TileEVCBase
*/
public static final int MAX_ESSENTIA_STORED = 64;
/**
* Maximum reciprocal
*/
public static final float MAX_ESSENTIA_STORED_RECIPROCAL = 1.0f / MAX_ESSENTIA_STORED;
/**
* Stored Essentia
*/
@@ -236,50 +241,38 @@ public abstract class TileEVCBase
@Override
public int getSuctionAmount( final ForgeDirection side )
{
int suction = 0;
// Suction is based on how full the chamber is, as it fills up suction drops
// Is there anything stored?
if( this.storedEssentia != null )
// Get how much is stored
float stored = ( this.storedEssentia == null ? 0.0f : this.storedEssentia.getStackSize() );
if( stored == MAX_ESSENTIA_STORED )
{
// Not Full?
if( this.storedEssentia.getStackSize() < TileEVCBase.MAX_ESSENTIA_STORED )
{
// Full suction when stored but not full.
suction = 128;
}
}
else
{
// Less suction when nothing stored.
suction = 100;
return 0;
}
return suction;
// Calculate the ratio, minimum of 25%, and multiply against maximum suction
return (int)( 128 * ( 1.0f - ( ( stored * 0.75f ) * MAX_ESSENTIA_STORED_RECIPROCAL ) ) );
}
@Override
public Aspect getSuctionType( final ForgeDirection side )
{
// Default to Ignis
Aspect suction = Aspect.FIRE;
// Is there anything stored?
if( this.hasStoredEssentia() )
{
// Suction type must match what is stored
suction = this.storedEssentia.getAspect();
}
else
{
// Rotate into Potentia?
if( ( MinecraftServer.getServer().getTickCounter() % 200 ) > 100 )
{
// Set to Potentia
suction = Aspect.ENERGY;
}
return this.storedEssentia.getAspect();
}
return suction;
// Rotate into Potentia?
if( ( MinecraftServer.getServer().getTickCounter() % 200 ) > 100 )
{
// Set to Potentia
return Aspect.ENERGY;
}
// Default to Ignis
return Aspect.FIRE;
}
@Override
@@ -50,7 +50,7 @@ public class ASMTransformer
private static final String FIELDTYPE_EntityGolemBase_hookHandlers = "java/util/HashMap";
/**
* Adds a reference to a golems dataWatcher field to the stack.
* Adds a reference to a golems hookHandlers field to the stack.
*
* @param instructionList
* @param golemVar
@@ -297,6 +297,7 @@ public class ASMTransformer
if( method.name.equals( "onLeftClickEntity" ) )
{
this.transformMethod_ItemGolemBell_OnLeftClickEntity( method );
break; // Stop searching.
}
}
@@ -322,6 +323,7 @@ public class ASMTransformer
if( method.name.equals( "spawnCreature" ) )
{
this.transformMethod_ItemGolemPlacer_SpawnCreature( method );
break; // Stop searching.
}
}
@@ -340,26 +342,17 @@ public class ASMTransformer
ClassReader classReader = new ClassReader( classBytes );
classReader.accept( classNode, 0 );
boolean isObf = false;
MethodNode render = null;
// Transform methods
for( MethodNode method : classNode.methods )
{
if( method.name.equals( "func_76986_a" ) )
if( method.name.equals( "render" ) )
{
isObf = true;
}
// Render
else if( method.name.equals( "render" ) )
{
render = method;
// Render
this.transformMethod_RenderGolemBase_Render( method );
break; // Stop searching.
}
}
// Render
this.transformMethod_RenderGolemBase_Render( render, isObf );
// Create the writer
ClassWriter writer = new ClassWriter( ClassWriter.COMPUTE_MAXS );
classNode.accept( writer );
@@ -452,7 +445,7 @@ public class ASMTransformer
private void transformMethod_GolemBase_ReadEntityFromNBT( final MethodNode method )
{
// Locate the super call
AbstractInsnNode insertionPoint = this.findFirstOpCode( method.instructions, Opcodes.INVOKESTATIC );
AbstractInsnNode insertionPoint = this.findFirstOpCode( method.instructions, Opcodes.INVOKESPECIAL );
// Insert the hook
// GolemHooks.hook_ReadEntityFromNBT( this, this.hookHandlers, nbt);
@@ -599,7 +592,7 @@ public class ASMTransformer
}
private void transformMethod_RenderGolemBase_Render( final MethodNode method, final boolean isObf )
private void transformMethod_RenderGolemBase_Render( final MethodNode method )
{
// Find the return
AbstractInsnNode insertionPoint = this.findLastOpCode( method.instructions, Opcodes.RETURN );