leftAnimations.update();
rightAnimations.update();
//Get Mecha Type
MechaType type = this.getMechaType();
DriveableData data = getDriveableData();
if (type == null)
{
FlansMod.log("Mecha type null. Not ticking mecha");
return;
}
prevLegsYaw = legAxes.getYaw();
//Autorepair. Like a Boss.
if(toggleTimer == 0 && autoRepair())
{
for(EnumDriveablePart part: EnumDriveablePart.values())
{
DriveablePart thisPart = data.parts.get(part);
boolean hasCreativePlayer = seats != null && seats[0] != null && seats[0].riddenByEntity instanceof EntityPlayer && ((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode;
if(thisPart != null && thisPart.health < thisPart.maxHealth && (hasCreativePlayer || data.fuelInTank >= 10F))
{
thisPart.health += 1;
if(!hasCreativePlayer)
data.fuelInTank -= 10F;
}
}
toggleTimer = 20;
}
if(diamondDetect() != null && diamondTimer == 0 && worldObj.isRemote && seats[0] != null && seats[0].riddenByEntity instanceof EntityPlayer && FlansMod.proxy.isThePlayer((EntityPlayer)seats[0].riddenByEntity))
{
float sqDistance = 901;
for(float i = -30; i <= 30; i++)
{
for(float j = -30; j <= 30; j++)
{
for(float k = -30; k <= 30; k++)
{
int x = MathHelper.floor_double(i + posX);
int y = MathHelper.floor_double(j + posY);
int z = MathHelper.floor_double(k + posZ);
if(i * i + j * j + k * k < sqDistance && worldObj.getBlock(x, y, z) == (Blocks.diamond_ore))
{
sqDistance = i * i + j * j + k * k;
}
}
}
}
if(sqDistance < 901)
{
PacketPlaySound.sendSoundPacket(posX, posY, posZ, FlansMod.soundRange, dimension, diamondDetect().detectSound, false);
diamondTimer = 1 + 2 * MathHelper.floor_float(MathHelper.sqrt_float(sqDistance));
}
}
if(diamondTimer > 0) --diamondTimer;
//TODO better implement this
if(isPartIntact(EnumDriveablePart.hips))
{
setSize(type.width, type.height);
yOffset = type.yOffset;
}
else
{
setSize(type.width, type.height - type.chassisHeight);
yOffset = type.yOffset - type.chassisHeight;
}
//Work out of this is client side and the player is driving
boolean thePlayerIsDrivingThis = worldObj.isRemote && seats[0] != null && seats[0].riddenByEntity instanceof EntityPlayer && FlansMod.proxy.isThePlayer((EntityPlayer)seats[0].riddenByEntity);
boolean driverIsLiving = seats[0] != null && seats[0].riddenByEntity instanceof EntityLivingBase;
//Despawning
ticksSinceUsed++;
if(!worldObj.isRemote && seats[0].riddenByEntity != null)
ticksSinceUsed = 0;
if(!worldObj.isRemote && TeamsManager.mechaLove > 0 && ticksSinceUsed > TeamsManager.mechaLove * 20)
{
setDead();
}
//Timer, for general use (only current use is for Auto Repair)
if(toggleTimer > 0)
toggleTimer--;
//Player is not driving this. Update its position from server update packets
if(worldObj.isRemote && !thePlayerIsDrivingThis)
{
//The driveable is currently moving towards its server position. Continue doing so.
if (serverPositionTransitionTicker > 0)
{
double x = posX + (serverPosX - posX) / serverPositionTransitionTicker;
double y = posY + (serverPosY - posY) / serverPositionTransitionTicker;
double z = posZ + (serverPosZ - posZ) / serverPositionTransitionTicker;
double dYaw = MathHelper.wrapAngleTo180_double(serverYaw - axes.getYaw());
double dPitch = MathHelper.wrapAngleTo180_double(serverPitch - axes.getPitch());
double dRoll = MathHelper.wrapAngleTo180_double(serverRoll - axes.getRoll());
rotationYaw = (float)(axes.getYaw() + dYaw / serverPositionTransitionTicker);
rotationPitch = (float)(axes.getPitch() + dPitch / serverPositionTransitionTicker);
float rotationRoll = (float)(axes.getRoll() + dRoll / serverPositionTransitionTicker);
--serverPositionTransitionTicker;
setPosition(x, y, z);
setRotation(rotationYaw, rotationPitch, rotationRoll);
//return;
}
//If the driveable is at its server position and does not have the next update, it should just simulate itself as a server side driveable would, so continue
}
//Movement
if(seats[0] != null)
{
if(seats[0].riddenByEntity instanceof EntityLivingBase && !(seats[0].riddenByEntity instanceof EntityPlayer))
axes.setAngles(((EntityLivingBase)seats[0].riddenByEntity).renderYawOffset + 90F, 0F, 0F);
else
{
//Function to limit Head Movement Left/Right
if(type.limitHeadTurn)
{
float axesLegs = legAxes.getYaw();
float axesBody = axes.getYaw();
double dYaw = axesBody - axesLegs;
if(dYaw > 180)
axesBody -= 360F;
if(dYaw < -180)
axesBody += 360F;
if(axesLegs + type.limitHeadTurnValue < axesBody)
axes.setAngles(axesLegs + type.limitHeadTurnValue, 0F, 0F);
if(axesLegs - type.limitHeadTurnValue > axesBody)
axes.setAngles(axesLegs - type.limitHeadTurnValue, 0F, 0F);
}
float yaw = seats[0].looking.getYaw() - seats[0].prevLooking.getYaw();
axes.rotateGlobalYaw(yaw);
seats[0].looking.rotateGlobalYaw(-yaw);
}
}
moveX = 0;
moveZ = 0;
float jetPack = jetPackPower();
if(!onGround && thePlayerIsDrivingThis && Minecraft.getMinecraft().currentScreen instanceof GuiDriveableController && FlansMod.proxy.isKeyDown(4) && shouldFly() && (((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode || data.fuelInTank >= (10F*jetPack)))
{
motionY *= 0.95;
motionY += (0.07*jetPack);
fallDistance = 0;
if(!((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode)
data.fuelInTank -= (10F*jetPack);
if(rocketTimer <= 0 && rocketPack().soundEffect != null)
{
PacketPlaySound.sendSoundPacket(posX, posY, posZ, FlansMod.soundRange, dimension, rocketPack().soundEffect, false);
rocketTimer = rocketPack().soundTime;
}
}
else if(isInWater() && shouldFloat())
{
motionY *= 0.89;
motionY += 0.1;
}
if(rocketTimer != 0) rocketTimer --;
Vector3f actualMotion = new Vector3f(0F, motionY - (16F / 400F), 0F);
if(driverIsLiving)
{
EntityLivingBase entity = (EntityLivingBase)seats[0].riddenByEntity;
boolean driverIsCreative = entity instanceof EntityPlayer && ((EntityPlayer)entity).capabilities.isCreativeMode;
if(thePlayerIsDrivingThis && Minecraft.getMinecraft().currentScreen instanceof GuiDriveableController)
{
if(FlansMod.proxy.isKeyDown(0)) moveX = 1;
if(FlansMod.proxy.isKeyDown(1)) moveX = -1;
if(FlansMod.proxy.isKeyDown(2)) moveZ = -1;
if(FlansMod.proxy.isKeyDown(3)) moveZ = 1;
}
else if(seats[0].riddenByEntity instanceof EntityLiving && !(seats[0].riddenByEntity instanceof EntityPlayer))
{
moveZ = 1;
/*
EntityLiving ent = (EntityLiving)seats[0].riddenByEntity;
//System.out.println(ent.moveForward);
Vec3 target = Vec3.createVectorHelper(0D, 0D, 0D);
if(ent.getNavigator().getPath() != null)
target = ent.getNavigator().getPath().getPosition(ent);
moveX = (float) target.xCoord;
moveZ = (float) target.zCoord;
*/
}
Vector3f intent = new Vector3f(moveX, 0, moveZ);
if(Math.abs(intent.lengthSquared()) > 0.1)
{
intent.normalise();
++legSwing;
intent = axes.findLocalVectorGlobally(intent);
Vector3f intentOnLegAxes = legAxes.findGlobalVectorLocally(intent);
float intentAngle = (float)Math.atan2(intent.z, intent.x) * 180F / 3.14159265F;
float angleBetween = intentAngle - legAxes.getYaw();
if(angleBetween > 180F) angleBetween -= 360F;
if(angleBetween < -180F) angleBetween += 360F;
float signBetween = Math.signum(angleBetween);
angleBetween = Math.abs(angleBetween);
if(angleBetween > 0.1)
{
legAxes.rotateGlobalYaw(Math.min(angleBetween, type.rotateSpeed)*signBetween);
}
Vector3f motion = legAxes.getXAxis();
motion.scale((type.moveSpeed * data.engine.engineSpeed * speedMultiplier())*(4.3F/20F)*(intent.lengthSquared()));
boolean canThrustCreatively = seats != null && seats[0] != null && seats[0].riddenByEntity instanceof EntityPlayer && ((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode;
if((canThrustCreatively || data.fuelInTank > data.engine.fuelConsumption) && isPartIntact(EnumDriveablePart.hips))
{
if(onGround || jumpDelay != 0)
{
//Move!
Vector3f.add(actualMotion, motion, actualMotion);
}
else if(!onGround && shouldFly())
{
Vector3f flyMotion = new Vector3f(intent.x, 0F, intent.z);
Vector3f.add(actualMotion, flyMotion, actualMotion);
}
//If we can't thrust creatively, we must thrust using fuel. Nom.
if(!canThrustCreatively)
data.fuelInTank -= data.engine.fuelConsumption;
}
}
//Block breaking
if(!worldObj.isRemote)
{
//Use left and right items on the server side
if(leftMouseHeld)
useItem(true);
if(rightMouseHeld)
useItem(false);
//Check the left block being mined
if(breakingBlock != null)
{
//Get block and material
Block blockHit = worldObj.getBlock(breakingBlock.x, breakingBlock.y, breakingBlock.z);
int metadata = worldObj.getBlockMetadata(breakingBlock.x, breakingBlock.y, breakingBlock.z);
Material material = blockHit.getMaterial();
//Get the itemstacks in each hand
ItemStack leftStack = inventory.getStackInSlot(EnumMechaSlotType.leftTool);
ItemStack rightStack = inventory.getStackInSlot(EnumMechaSlotType.rightTool);
//Work out if we are actually breaking blocks
boolean leftStackIsTool = leftStack != null && leftStack.getItem() instanceof ItemMechaAddon;
boolean rightStackIsTool = rightStack != null && rightStack.getItem() instanceof ItemMechaAddon;
boolean breakingBlocks = (leftMouseHeld && leftStackIsTool) || (rightMouseHeld && rightStackIsTool);
//If we are not breaking blocks, reset everything
if(blockHit == null || !breakingBlocks)
{
//if(worldObj.isRemote)
// Minecraft.getMinecraft().renderGlobal.destroyBlockPartially(getEntityId(), breakingBlock.x, breakingBlock.y, breakingBlock.z, -1);
breakingBlock = null;
}
else
{
//Get the block hardness
float blockHardness = blockHit.getBlockHardness(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z);
//Calculate the mine speed
float mineSpeed = 1F;
boolean atLeastOneEffectiveTool = false;
if(leftStackIsTool)
{
MechaItemType leftType = ((ItemMechaAddon)leftStack.getItem()).type;
if(leftType.function.effectiveAgainst(material) && leftType.toolHardness > blockHardness)
{
mineSpeed *= leftType.speed;
atLeastOneEffectiveTool = true;
}
}
if(rightStackIsTool)
{
MechaItemType rightType = ((ItemMechaAddon)rightStack.getItem()).type;
if(rightType.function.effectiveAgainst(material) && rightType.toolHardness > blockHardness)
{
mineSpeed *= rightType.speed;
atLeastOneEffectiveTool = true;
}
}
//If this block is immortal, do not break it
if(blockHardness < -0.01F)
mineSpeed = 0F;
//If this block's hardness is zero-ish, then the tool's power is OVER 9000!!!!
else if(Math.abs(blockHardness) < 0.01F)
mineSpeed = 9001F;
else
{
mineSpeed /= blockHit.getBlockHardness(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z);
}
//Add block digging overlay
//if(worldObj.isRemote)
// Minecraft.getMinecraft().renderGlobal.destroyBlockPartially(getEntityId(), breakingBlock.x, breakingBlock.y, breakingBlock.z, (int)(breakingProgress * 10));
breakingProgress += 0.1F * mineSpeed;
if(breakingProgress >= 1F)
{
boolean cancelled = false;
if(entity instanceof EntityPlayerMP)
{
BlockEvent.BreakEvent event = ForgeHooks.onBlockBreakEvent(worldObj, ((EntityPlayerMP)entity).capabilities.isCreativeMode ? GameType.CREATIVE : ((EntityPlayerMP)entity).capabilities.allowEdit ? GameType.SURVIVAL : GameType.ADVENTURE, (EntityPlayerMP)entity, breakingBlock.x, breakingBlock.y, breakingBlock.z);
cancelled = event.isCanceled();
}
if(!cancelled)
{
//blockHit.dropBlockAsItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z, worldObj.getBlockMetadata(breakingBlock.x, breakingBlock.y, breakingBlock.z), 1);
//FlansMod.proxy.playBlockBreakSound(breakingBlock.x, breakingBlock.y, breakingBlock.z, worldObj.getBlockId(breakingBlock.x, breakingBlock.y, breakingBlock.z));
//worldObj.setBlockToAir(breakingBlock.x, breakingBlock.y, breakingBlock.z);
boolean vacuumItems = vacuumItems();
if(vacuumItems)
{
for(ItemStack stack : blockHit.getDrops(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z, metadata, 0))
{
//Check for iron regarding refining
if(refineIron() && (stack.getItem() == Blocks.iron_ore.getItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z)) && (((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode || data.fuelInTank >= 5F))
{
stack = (new ItemStack(Items.iron_ingot, 1, 0));
if (!((EntityPlayer)seats[0].riddenByEntity).capabilities.isCreativeMode)
data.fuelInTank -= 5F;
}
//Check for waste to be compacted
if(wasteCompact() && ((stack.getItem() == Blocks.cobblestone.getItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z)) || (stack.getItem() == Blocks.sand.getItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z)) || (stack.getItem() == Blocks.dirt.getItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z))))
{
stack.stackSize = 0;
}
//Check for item multipliers
if(stack.getItem() == Items.diamond)
{
float multiplier = diamondMultiplier();
stack.stackSize *= MathHelper.floor_float(multiplier) + (rand.nextFloat() < tailFloat(multiplier) ? 1 : 0);
}
if(stack.getItem() == Items.redstone)
{
float multiplier = redstoneMultiplier();
stack.stackSize *= MathHelper.floor_float(multiplier) + (rand.nextFloat() < tailFloat(multiplier) ? 1 : 0);
}
if(stack.getItem() == Items.coal)
{
float multiplier = coalMultiplier();
stack.stackSize *= MathHelper.floor_float(multiplier) + (rand.nextFloat() < tailFloat(multiplier) ? 1 : 0);
}
if(stack.getItem() == Items.emerald)
{
float multiplier = emeraldMultiplier();
stack.stackSize *= MathHelper.floor_float(multiplier) + (rand.nextFloat() < tailFloat(multiplier) ? 1 : 0);
}
if(stack.getItem() == Blocks.iron_ore.getItem(worldObj, breakingBlock.x, breakingBlock.y, breakingBlock.z) || stack.getItem() == Items.iron_ingot)
{
float multiplier = ironMultiplier();
stack.stackSize *= MathHelper.floor_float(multiplier) + (rand.nextFloat() < tailFloat(multiplier) ? 1 : 0);
}
//Check for auto coal consumption
if(autoCoal() && (stack.getItem() == Items.coal) && (data.fuelInTank + 250F < type.fuelTankSize))
{
data.fuelInTank = Math.min(data.fuelInTank + 1000F, type.fuelTankSize);
couldNotFindFuel = false;
stack.stackSize = 0;
}
//Add the itemstack to mecha inventory
if(!InventoryHelper.addItemStackToInventory(driveableData, stack, driverIsCreative) && !worldObj.isRemote && worldObj.getGameRules().getGameRuleBooleanValue("doTileDrops"))
{
worldObj.spawnEntityInWorld(new EntityItem(worldObj, breakingBlock.x + 0.5F, breakingBlock.y + 0.5F, breakingBlock.z + 0.5F, stack));
}
}
}
//Destroy block
worldObj.func_147480_a(breakingBlock.x, breakingBlock.y, breakingBlock.z, atLeastOneEffectiveTool && !vacuumItems);
}
}
}
}
}
}
motionY = actualMotion.y;
moveEntity(actualMotion.x, actualMotion.y, actualMotion.z);
//FlansMod.log("" + fallDistance);
setPosition(posX, posY, posZ);
//Fuel Handling
if(!couldNotFindFuel)
{
ItemStack fuelStack = foundFuel == -1 ? null : driveableData.getStackInSlot(foundFuel);
//If the fuel item has stack size <= 0, delete it
if(fuelStack != null && fuelStack.stackSize <= 0)
{
driveableData.setInventorySlotContents(foundFuel, null);
fuelStack = null;
}
//Find the next fuelling slot
if(fuelStack == null || !(fuelStack.getItem() instanceof ItemPart && ((ItemPart)fuelStack.getItem()).type.category == 9))
{
foundFuel = -1;
couldNotFindFuel = true;
for(int i = driveableData.getCargoInventoryStart(); i < driveableData.getCargoInventoryStart() + type.numCargoSlots; i++)
{
ItemStack tempStack = driveableData.getStackInSlot(i);
if(tempStack != null && tempStack.getItem() instanceof ItemPart && ((ItemPart)tempStack.getItem()).type.category == 9)
{
foundFuel = i;
fuelStack = tempStack;
couldNotFindFuel = false;
break;
}
}
}
//Work out if we are fuelling (from a Flan's Mod fuel item)
fuelling = foundFuel != -1 && fuelStack != null && data.fuelInTank < type.fuelTankSize && fuelStack.stackSize > 0 && fuelStack.getItem() instanceof ItemPart && ((ItemPart)fuelStack.getItem()).type.category == 9;
//If we are fuelling
if(fuelling)
{
int damage = fuelStack.getItemDamage();
//Consume 10 points of fuel (1 damage)
fuelStack.setItemDamage(damage + 1);
//Put 10 points of fuel
data.fuelInTank += 10;
//If we have finished this fuel item
if(damage >= fuelStack.getMaxDamage())
{
//Reset the damage to 0
fuelStack.setItemDamage(0);
//Consume one item
fuelStack.stackSize--;
//If we consumed the last one, destroy the stack
if(fuelStack.stackSize <= 0)
data.fuel = null;
}
}
//Check inventory slots for buildcraft buckets and if found, take fuel from them
if(FlansMod.hooks.BuildCraftLoaded && !fuelling)
{
for(int i = data.getCargoInventoryStart(); i < data.numCargo + type.numCargoSlots; i++)
{
ItemStack stack = data.getStackInSlot(i);
if(stack != null && stack.isItemEqual(FlansMod.hooks.BuildCraftOilBucket) && data.fuelInTank + 5000 <= type.fuelTankSize)
{
data.fuelInTank += 5000;
data.setInventorySlotContents(i, new ItemStack(Items.bucket));
couldNotFindFuel = false;
}
else if(stack != null && stack.isItemEqual(FlansMod.hooks.BuildCraftFuelBucket) && data.fuelInTank + 10000 <= type.fuelTankSize)
{
data.fuelInTank += 10000;
data.setInventorySlotContents(i, new ItemStack(Items.bucket));
couldNotFindFuel = false;
}
}
}
}