2017-02-26 13:56:36 +01:00
|
|
|
/*
|
|
|
|
* This file is part of Industrial Wires.
|
|
|
|
* Copyright (C) 2016-2017 malte0811
|
|
|
|
*
|
|
|
|
* Industrial Wires is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Industrial Wires is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Industrial Wires. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2017-09-04 17:42:50 +02:00
|
|
|
package malte0811.industrialWires.blocks.hv;
|
2017-02-26 13:56:36 +01:00
|
|
|
|
2017-03-03 17:52:22 +01:00
|
|
|
import blusunrize.immersiveengineering.api.ApiUtils;
|
2018-01-28 21:29:55 +01:00
|
|
|
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces;
|
2017-04-02 17:16:42 +02:00
|
|
|
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IDirectionalTile;
|
2017-02-26 13:56:36 +01:00
|
|
|
import blusunrize.immersiveengineering.common.blocks.TileEntityIEBase;
|
2017-09-06 21:18:59 +02:00
|
|
|
import com.elytradev.mirage.lighting.IColoredLight;
|
|
|
|
import com.elytradev.mirage.lighting.Light;
|
2017-02-26 13:56:36 +01:00
|
|
|
import ic2.api.energy.event.EnergyTileLoadEvent;
|
|
|
|
import ic2.api.energy.event.EnergyTileUnloadEvent;
|
|
|
|
import ic2.api.energy.tile.IEnergyEmitter;
|
|
|
|
import ic2.api.energy.tile.IEnergySink;
|
|
|
|
import malte0811.industrialWires.IWConfig;
|
2017-09-04 17:42:50 +02:00
|
|
|
import malte0811.industrialWires.IWDamageSources;
|
2017-02-26 13:56:36 +01:00
|
|
|
import malte0811.industrialWires.IndustrialWires;
|
2017-09-04 17:42:50 +02:00
|
|
|
import malte0811.industrialWires.blocks.IBlockBoundsIW;
|
|
|
|
import malte0811.industrialWires.blocks.IHasDummyBlocksIW;
|
|
|
|
import malte0811.industrialWires.blocks.ISyncReceiver;
|
2017-02-26 13:56:36 +01:00
|
|
|
import malte0811.industrialWires.network.MessageTileSyncIW;
|
|
|
|
import malte0811.industrialWires.util.Beziers;
|
|
|
|
import malte0811.industrialWires.util.DualEnergyStorage;
|
2017-03-21 18:12:09 +01:00
|
|
|
import net.minecraft.block.Block;
|
2017-02-26 13:56:36 +01:00
|
|
|
import net.minecraft.block.state.IBlockState;
|
|
|
|
import net.minecraft.client.Minecraft;
|
2017-03-03 17:52:22 +01:00
|
|
|
import net.minecraft.entity.Entity;
|
2017-04-02 17:16:42 +02:00
|
|
|
import net.minecraft.entity.EntityLivingBase;
|
2017-03-03 17:52:22 +01:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
|
|
import net.minecraft.item.ItemStack;
|
2017-02-26 13:56:36 +01:00
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
import net.minecraft.nbt.NBTTagList;
|
|
|
|
import net.minecraft.tileentity.TileEntity;
|
2017-09-06 21:18:59 +02:00
|
|
|
import net.minecraft.util.EnumFacing;
|
|
|
|
import net.minecraft.util.EnumHand;
|
|
|
|
import net.minecraft.util.IStringSerializable;
|
|
|
|
import net.minecraft.util.ITickable;
|
2017-02-28 17:32:40 +01:00
|
|
|
import net.minecraft.util.math.AxisAlignedBB;
|
2017-02-26 13:56:36 +01:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.util.math.Vec3d;
|
2017-03-06 16:36:02 +01:00
|
|
|
import net.minecraft.world.World;
|
2017-02-26 13:56:36 +01:00
|
|
|
import net.minecraftforge.common.MinecraftForge;
|
|
|
|
import net.minecraftforge.common.capabilities.Capability;
|
|
|
|
import net.minecraftforge.energy.CapabilityEnergy;
|
|
|
|
import net.minecraftforge.energy.IEnergyStorage;
|
2017-08-23 22:30:24 +02:00
|
|
|
import net.minecraftforge.fml.common.Optional;
|
2017-09-06 21:18:59 +02:00
|
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
2017-02-26 13:56:36 +01:00
|
|
|
|
2017-05-10 17:56:05 +02:00
|
|
|
import javax.annotation.Nonnull;
|
2017-02-26 13:56:36 +01:00
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
2017-08-23 22:30:24 +02:00
|
|
|
import static malte0811.industrialWires.IndustrialWires.hasIC2;
|
2017-09-06 21:18:59 +02:00
|
|
|
import static malte0811.industrialWires.util.MiscUtils.interpolate;
|
|
|
|
|
|
|
|
@Optional.InterfaceList({
|
|
|
|
@Optional.Interface(modid = "ic2", iface = "ic2.api.energy.tile.IEnergySink"),
|
|
|
|
@Optional.Interface(modid = "mirage", iface = "com.elytradev.mirage.lighting.IColoredLight")
|
|
|
|
})
|
|
|
|
public class TileEntityJacobsLadder extends TileEntityIEBase implements ITickable, IHasDummyBlocksIW, ISyncReceiver,
|
2018-01-28 21:29:55 +01:00
|
|
|
IEnergySink, IBlockBoundsIW, IDirectionalTile, IColoredLight, IEBlockInterfaces.IPlayerInteraction {
|
2017-02-28 17:32:40 +01:00
|
|
|
public EnumFacing facing = EnumFacing.NORTH;
|
|
|
|
private DualEnergyStorage energy;
|
2017-02-26 13:56:36 +01:00
|
|
|
public LadderSize size;
|
|
|
|
|
|
|
|
public Vec3d[] controls;
|
|
|
|
//first and last move along the "rails", only the middle points move in bezier curves
|
2018-01-28 21:29:55 +01:00
|
|
|
private Vec3d[][] controlControls;
|
2017-02-26 13:56:36 +01:00
|
|
|
// movement of the controls in blocks/tick
|
|
|
|
public Vec3d[] controlMovement;
|
|
|
|
private double t = 0;
|
2018-01-28 21:29:55 +01:00
|
|
|
private int dummy = 0;
|
2017-02-26 13:56:36 +01:00
|
|
|
public int timeTillActive = -1;
|
|
|
|
private double tStep = 0;
|
|
|
|
private double consumtionEU;
|
|
|
|
private boolean addedToIC2Net = false;
|
|
|
|
private int soundPhase;
|
|
|
|
private Vec3d soundPos;
|
2017-03-03 17:52:22 +01:00
|
|
|
public double salt;
|
2017-02-26 13:56:36 +01:00
|
|
|
|
2018-01-28 21:29:55 +01:00
|
|
|
TileEntityJacobsLadder(LadderSize s) {
|
2017-02-26 13:56:36 +01:00
|
|
|
size = s;
|
|
|
|
initControl();
|
|
|
|
}
|
|
|
|
|
|
|
|
public TileEntityJacobsLadder() {
|
|
|
|
size = LadderSize.HUGE;
|
|
|
|
initControl();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initControl() {
|
|
|
|
controls = new Vec3d[size.arcPoints];
|
|
|
|
controlControls = new Vec3d[size.arcPoints - 2][size.movementPoints];
|
|
|
|
controlMovement = new Vec3d[size.arcPoints];
|
|
|
|
int sizeId = size.ordinal();
|
|
|
|
consumtionEU = IWConfig.HVStuff.jacobsUsageEU[sizeId];
|
2017-02-28 17:32:40 +01:00
|
|
|
energy = new DualEnergyStorage(20 * consumtionEU, 2 * consumtionEU);
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void update() {
|
2017-09-13 21:32:19 +02:00
|
|
|
ApiUtils.checkForNeedlessTicking(this);
|
2017-02-26 13:56:36 +01:00
|
|
|
if (isDummy()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-05-10 17:56:05 +02:00
|
|
|
if (!world.isRemote) {
|
2017-08-23 22:30:24 +02:00
|
|
|
if (hasIC2&&!addedToIC2Net) {
|
|
|
|
addToIC2Net();
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
if ((controlControls[0][0] == null || timeTillActive == -1 || t >= 1) && energy.getEnergyStoredEU() >= 2 * consumtionEU) {
|
2017-02-26 13:56:36 +01:00
|
|
|
for (int j = 0; j < size.movementPoints; j++) {
|
|
|
|
double y = j * (size.height + size.extraHeight) / (double) (size.movementPoints - 1) + size.innerPointOffset;
|
|
|
|
double width = widthFromHeight(y);
|
|
|
|
for (int i = 0; i < size.arcPoints - 2; i++) {
|
2017-05-10 17:56:05 +02:00
|
|
|
double z = size.zMax * 2 * (world.rand.nextDouble() - .5);
|
2017-02-28 17:32:40 +01:00
|
|
|
double xMin = width * i / (double) (size.arcPoints - 2) - width / 2 + size.bottomDistance / 2;
|
|
|
|
double xDiff = width / (double) (size.arcPoints - 2);
|
2017-05-10 17:56:05 +02:00
|
|
|
double x = world.rand.nextDouble() * xDiff + xMin;
|
2017-02-26 13:56:36 +01:00
|
|
|
controlControls[i][j] = new Vec3d(x, y, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t = 0;
|
|
|
|
timeTillActive = size.delay;
|
2017-05-10 17:56:05 +02:00
|
|
|
tStep = 1D / (int) (.875 * size.tickToTop + world.rand.nextInt(size.tickToTop / 4));
|
2017-02-26 13:56:36 +01:00
|
|
|
IndustrialWires.packetHandler.sendToAll(new MessageTileSyncIW(this, writeArcStarter()));
|
2017-02-28 17:32:40 +01:00
|
|
|
} else if (timeTillActive == 0 && t < 1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
double extracted = energy.extractEU(consumtionEU, false);
|
2017-02-28 17:32:40 +01:00
|
|
|
if (extracted >= consumtionEU) {
|
2017-02-26 13:56:36 +01:00
|
|
|
energy.extractEU(consumtionEU, true);
|
|
|
|
} else {
|
2017-02-28 17:32:40 +01:00
|
|
|
timeTillActive = -1 - size.delay;
|
2017-02-26 13:56:36 +01:00
|
|
|
NBTTagCompound nbt = new NBTTagCompound();
|
|
|
|
nbt.setBoolean("cancel", true);
|
|
|
|
IndustrialWires.packetHandler.sendToAll(new MessageTileSyncIW(this, nbt));
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
} else if (timeTillActive < -1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
//delay after energy was cut
|
|
|
|
timeTillActive++;
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
} else {
|
|
|
|
if (timeTillActive == 0 && t < 1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
for (int i = 0; i < size.arcPoints; i++) {
|
|
|
|
controls[i] = controls[i].add(controlMovement[i]);
|
|
|
|
}
|
|
|
|
for (int i = 1; i < size.arcPoints - 1; i++) {
|
|
|
|
controlMovement[i] = Beziers.getPoint(t, controlControls[i - 1]).subtract(controls[i]);
|
|
|
|
}
|
2017-03-03 17:52:22 +01:00
|
|
|
if (soundPhase < 0) {
|
2017-02-28 17:32:40 +01:00
|
|
|
IndustrialWires.proxy.playJacobsLadderSound(this, 0, soundPos);
|
|
|
|
soundPhase = 0;
|
|
|
|
}
|
|
|
|
if (t >= 7 * tStep && soundPhase == 0) {
|
2017-02-26 13:56:36 +01:00
|
|
|
IndustrialWires.proxy.playJacobsLadderSound(this, 1, soundPos);
|
|
|
|
soundPhase = 1;
|
2017-02-28 17:32:40 +01:00
|
|
|
} else if (t >= 1 - (4 * tStep) && soundPhase == 1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
IndustrialWires.proxy.playJacobsLadderSound(this, 2, soundPos);
|
|
|
|
soundPhase = 2;
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
} else if (t > 1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
timeTillActive = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (timeTillActive > 0) {
|
|
|
|
timeTillActive--;
|
2017-02-28 17:32:40 +01:00
|
|
|
} else if (timeTillActive == 0 && t < 1) {
|
2017-02-26 13:56:36 +01:00
|
|
|
t += tStep;
|
2017-03-03 17:52:22 +01:00
|
|
|
if (salt > 0) {
|
2017-05-11 16:39:20 +02:00
|
|
|
salt -= 1D / (20 * 20);//20 seconds per item of salt
|
2017-03-03 17:52:22 +01:00
|
|
|
} else if (salt < 0) {
|
|
|
|
salt = 0;
|
|
|
|
}
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
|
|
|
private void addToIC2Net() {
|
|
|
|
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this));
|
|
|
|
addedToIC2Net = true;
|
|
|
|
}
|
|
|
|
|
2017-02-28 17:32:40 +01:00
|
|
|
private void initArc(int delay) {
|
2017-03-03 17:52:22 +01:00
|
|
|
if (controlMovement == null) {
|
|
|
|
initControl();
|
|
|
|
}
|
2017-02-26 13:56:36 +01:00
|
|
|
controls[0] = new Vec3d(0, 0, 0);
|
|
|
|
controls[size.arcPoints - 1] = new Vec3d(size.bottomDistance, 0, 0);
|
2017-02-28 17:32:40 +01:00
|
|
|
controlMovement[0] = new Vec3d(-(size.topDistance - size.bottomDistance) / (2 * size.tickToTop), size.height / size.tickToTop, 0);
|
|
|
|
controlMovement[size.arcPoints - 1] = new Vec3d((size.topDistance - size.bottomDistance) / (2 * size.tickToTop), size.height / size.tickToTop, 0);
|
2017-02-26 13:56:36 +01:00
|
|
|
t = 0;
|
|
|
|
for (int i = 1; i < size.arcPoints - 1; i++) {
|
|
|
|
controls[i] = Beziers.getPoint(0, controlControls[i - 1]);
|
|
|
|
controlMovement[i] = Beziers.getPoint(tStep, controlControls[i - 1]).subtract(controls[i]);
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
double soundX = pos.getX() + .5;
|
|
|
|
double soundY = pos.getY() + .5 * size.dummyCount + size.heightOffset;
|
|
|
|
double soundZ = pos.getZ() + .5;
|
2017-02-26 13:56:36 +01:00
|
|
|
soundPos = new Vec3d(soundX, soundY, soundZ);
|
2017-02-28 17:32:40 +01:00
|
|
|
soundPhase = -1;
|
|
|
|
timeTillActive = delay;
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private double widthFromHeight(double h) {
|
|
|
|
return size.bottomDistance + h * (size.topDistance - size.bottomDistance) / size.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public void readCustomNBT(@Nonnull NBTTagCompound nbt, boolean descPacket) {
|
2017-02-26 13:56:36 +01:00
|
|
|
LadderSize oldSize = size;
|
|
|
|
size = LadderSize.values()[nbt.getInteger("size")];
|
|
|
|
if (size != oldSize) {
|
|
|
|
initControl();
|
|
|
|
}
|
|
|
|
dummy = nbt.getInteger("dummy");
|
2017-09-04 17:42:50 +02:00
|
|
|
energy.readFromNBT(nbt.getCompoundTag("energy"));
|
2017-02-28 17:32:40 +01:00
|
|
|
facing = EnumFacing.HORIZONTALS[nbt.getInteger("facing")];
|
2017-03-03 17:52:22 +01:00
|
|
|
salt = nbt.getDouble("salt");
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public void writeCustomNBT(@Nonnull NBTTagCompound nbt, boolean descPacket) {
|
2017-02-26 13:56:36 +01:00
|
|
|
nbt.setInteger("size", size.ordinal());
|
|
|
|
nbt.setInteger("dummy", dummy);
|
2017-02-28 17:32:40 +01:00
|
|
|
energy.writeToNbt(nbt, "energy");
|
|
|
|
nbt.setInteger("facing", facing.getHorizontalIndex());
|
2017-03-03 17:52:22 +01:00
|
|
|
nbt.setDouble("salt", salt);
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
private NBTTagCompound writeArcStarter() {
|
|
|
|
NBTTagCompound nbt = new NBTTagCompound();
|
|
|
|
NBTTagList ctrlCtrl = write2DVecArray(controlControls);
|
|
|
|
nbt.setTag("ctrlCtrl", ctrlCtrl);
|
|
|
|
nbt.setInteger("timeTillActive", timeTillActive);
|
|
|
|
nbt.setDouble("tStep", tStep);
|
2017-03-03 17:52:22 +01:00
|
|
|
nbt.setBoolean("start", true);
|
2017-02-26 13:56:36 +01:00
|
|
|
return nbt;
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
private void readArcStarter(NBTTagCompound nbt) {
|
|
|
|
controlControls = read2DVecArray(nbt.getTagList("ctrlCtrl", 9));
|
|
|
|
tStep = nbt.getDouble("tStep");
|
2017-03-03 17:52:22 +01:00
|
|
|
Minecraft.getMinecraft().addScheduledTask(() -> initArc(nbt.getInteger("timeTillActive")));
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
private Vec3d[][] read2DVecArray(NBTTagList nbt) {
|
|
|
|
Vec3d[][] ret = new Vec3d[nbt.tagCount()][];
|
2017-02-28 17:32:40 +01:00
|
|
|
for (int i = 0; i < ret.length; i++) {
|
|
|
|
ret[i] = readVecArray((NBTTagList) nbt.get(i));
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Vec3d[] readVecArray(NBTTagList nbt) {
|
|
|
|
Vec3d[] ret = new Vec3d[nbt.tagCount()];
|
2017-02-28 17:32:40 +01:00
|
|
|
for (int i = 0; i < ret.length; i++) {
|
2017-02-26 13:56:36 +01:00
|
|
|
NBTTagCompound vec = nbt.getCompoundTagAt(i);
|
|
|
|
ret[i] = new Vec3d(vec.getDouble("x"), vec.getDouble("y"), vec.getDouble("z"));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
private NBTTagList write2DVecArray(Vec3d[][] array) {
|
|
|
|
NBTTagList ret = new NBTTagList();
|
2017-02-28 17:32:40 +01:00
|
|
|
for (Vec3d[] subArray : array) {
|
2017-02-26 13:56:36 +01:00
|
|
|
ret.appendTag(writeVecArray(subArray));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
private NBTTagList writeVecArray(Vec3d[] array) {
|
|
|
|
NBTTagList ret = new NBTTagList();
|
2017-02-28 17:32:40 +01:00
|
|
|
for (Vec3d point : array) {
|
2017-02-26 13:56:36 +01:00
|
|
|
NBTTagCompound vec = new NBTTagCompound();
|
2017-06-25 18:34:10 +02:00
|
|
|
vec.setDouble("x", point.x);
|
|
|
|
vec.setDouble("y", point.y);
|
|
|
|
vec.setDouble("z", point.z);
|
2017-02-26 13:56:36 +01:00
|
|
|
ret.appendTag(vec);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
@Override
|
|
|
|
public boolean isDummy() {
|
|
|
|
return dummy != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-02-28 17:32:40 +01:00
|
|
|
public void placeDummies(IBlockState state) {
|
2017-02-26 13:56:36 +01:00
|
|
|
for (int i = 1; i <= size.dummyCount; i++) {
|
|
|
|
BlockPos pos2 = pos.offset(EnumFacing.UP, i);
|
2017-05-10 17:56:05 +02:00
|
|
|
world.setBlockState(pos2, state);
|
|
|
|
TileEntity te = world.getTileEntity(pos2);
|
2017-02-26 13:56:36 +01:00
|
|
|
if (te instanceof TileEntityJacobsLadder) {
|
|
|
|
((TileEntityJacobsLadder) te).size = size;
|
|
|
|
((TileEntityJacobsLadder) te).dummy = i;
|
2017-02-28 17:32:40 +01:00
|
|
|
((TileEntityJacobsLadder) te).facing = facing;
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-02-28 17:32:40 +01:00
|
|
|
public void breakDummies() {
|
2017-02-26 13:56:36 +01:00
|
|
|
for (int i = 0; i <= size.dummyCount; i++) {
|
2017-05-10 17:56:05 +02:00
|
|
|
if (i != dummy && world.getTileEntity(pos.offset(EnumFacing.UP, i - dummy)) instanceof TileEntityJacobsLadder) {
|
|
|
|
world.setBlockToAir(pos.offset(EnumFacing.UP, i - dummy));
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSync(NBTTagCompound nbt) {
|
2017-03-03 17:52:22 +01:00
|
|
|
if (nbt.hasKey("salt")) {
|
|
|
|
salt = nbt.getDouble("salt");
|
|
|
|
}
|
2017-02-26 13:56:36 +01:00
|
|
|
if (nbt.getBoolean("cancel")) {
|
|
|
|
timeTillActive = -1;
|
2017-02-28 17:32:40 +01:00
|
|
|
IndustrialWires.proxy.playJacobsLadderSound(this, -1, soundPos);
|
2017-03-03 17:52:22 +01:00
|
|
|
} else if (nbt.getBoolean("start")) {
|
2017-02-26 13:56:36 +01:00
|
|
|
readArcStarter(nbt);
|
|
|
|
}
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2018-01-28 21:29:55 +01:00
|
|
|
private boolean isActive() {
|
2017-03-06 16:36:02 +01:00
|
|
|
if (isDummy()) {
|
2017-05-10 17:56:05 +02:00
|
|
|
TileEntity master = world.getTileEntity(pos.down(dummy));
|
2017-05-11 16:39:20 +02:00
|
|
|
return master instanceof TileEntityJacobsLadder && ((TileEntityJacobsLadder) master).isActive();
|
2017-03-06 16:36:02 +01:00
|
|
|
}
|
2017-03-03 17:52:22 +01:00
|
|
|
return timeTillActive == 0 && t < 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onEntityTouch(Entity e) {
|
2017-05-10 17:56:05 +02:00
|
|
|
if (isDummy() && !world.isRemote) {
|
|
|
|
TileEntity master = world.getTileEntity(pos.down(dummy));
|
2017-03-03 17:52:22 +01:00
|
|
|
if (master instanceof TileEntityJacobsLadder && ((TileEntityJacobsLadder) master).isActive()) {
|
|
|
|
hurtEntity(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void hurtEntity(Entity e) {
|
2017-09-04 17:42:50 +02:00
|
|
|
e.attackEntityFrom(IWDamageSources.dmg_jacobs, IWConfig.HVStuff.jacobsBaseDmg * (size.ordinal() + 1));
|
2017-03-03 17:52:22 +01:00
|
|
|
}
|
|
|
|
|
2018-01-28 21:29:55 +01:00
|
|
|
@Override
|
|
|
|
public boolean interact(@Nonnull EnumFacing side, @Nonnull EntityPlayer player,@Nonnull EnumHand hand,
|
|
|
|
@Nonnull ItemStack heldItem, float hitX, float hitY, float hitZ) {
|
2017-05-10 17:56:05 +02:00
|
|
|
TileEntity masterTE = dummy == 0 ? this : world.getTileEntity(pos.down(dummy));
|
2017-03-03 17:52:22 +01:00
|
|
|
if (masterTE instanceof TileEntityJacobsLadder) {
|
|
|
|
TileEntityJacobsLadder master = (TileEntityJacobsLadder) masterTE;
|
|
|
|
if (master.isActive()) {
|
2017-05-10 17:56:05 +02:00
|
|
|
if (!world.isRemote) {
|
|
|
|
hurtEntity(player);
|
2017-03-03 17:52:22 +01:00
|
|
|
}
|
|
|
|
return true;
|
2017-05-10 17:56:05 +02:00
|
|
|
} else if (!heldItem.isEmpty() && ApiUtils.compareToOreName(heldItem, "itemSalt")) {
|
|
|
|
return master.salt(player, hand, heldItem);
|
2017-03-03 17:52:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean salt(EntityPlayer player, EnumHand hand, ItemStack held) {
|
|
|
|
if (salt < 3) {
|
2017-05-10 17:56:05 +02:00
|
|
|
if (!world.isRemote) {
|
2017-03-03 17:52:22 +01:00
|
|
|
salt++;
|
|
|
|
if (!player.isCreative()) {
|
2017-05-10 17:56:05 +02:00
|
|
|
held.shrink(1);
|
|
|
|
if (held.getCount() <= 0) {
|
|
|
|
player.setHeldItem(hand, ItemStack.EMPTY);
|
2017-03-03 17:52:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
NBTTagCompound update = new NBTTagCompound();
|
|
|
|
update.setDouble("salt", salt);
|
|
|
|
markDirty();
|
|
|
|
IndustrialWires.packetHandler.sendToAll(new MessageTileSyncIW(this, update));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-23 22:30:24 +02:00
|
|
|
public boolean rotate(World world, BlockPos pos) {
|
2017-03-06 16:36:02 +01:00
|
|
|
if (isActive()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-05-10 17:56:05 +02:00
|
|
|
if (!world.isRemote) {
|
2017-03-06 16:36:02 +01:00
|
|
|
EnumFacing targetDir = facing.rotateAround(EnumFacing.Axis.Y);
|
2017-05-11 16:39:20 +02:00
|
|
|
for (int i = -dummy; i < size.dummyCount - dummy + 1; i++) {
|
2017-03-06 16:36:02 +01:00
|
|
|
BlockPos currPos = pos.up(i);
|
|
|
|
TileEntity te = world.getTileEntity(currPos);
|
|
|
|
if (te instanceof TileEntityJacobsLadder) {
|
|
|
|
TileEntityJacobsLadder teJacobs = (TileEntityJacobsLadder) te;
|
|
|
|
teJacobs.facing = targetDir;
|
|
|
|
teJacobs.markDirty();
|
|
|
|
IBlockState state = world.getBlockState(currPos).getActualState(world, currPos);
|
2017-05-11 16:39:20 +02:00
|
|
|
world.notifyBlockUpdate(currPos, state, state, 3);
|
2017-03-06 16:36:02 +01:00
|
|
|
world.addBlockEvent(currPos, state.getBlock(), 255, 0);
|
2017-05-10 17:56:05 +02:00
|
|
|
world.notifyNeighborsOfStateChange(currPos, state.getBlock(), true);
|
2017-03-06 16:36:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
//ENERGY
|
|
|
|
@Override
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
2017-02-26 13:56:36 +01:00
|
|
|
public double getDemandedEnergy() {
|
|
|
|
return energy.getEURequested();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
2017-02-26 13:56:36 +01:00
|
|
|
public int getSinkTier() {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
2017-02-26 13:56:36 +01:00
|
|
|
public double injectEnergy(EnumFacing dir, double amount, double voltage) {
|
2017-02-28 17:32:40 +01:00
|
|
|
return amount - energy.insertEU(amount, true);
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
2017-02-26 13:56:36 +01:00
|
|
|
public boolean acceptsEnergyFrom(IEnergyEmitter iEnergyEmitter, EnumFacing enumFacing) {
|
2017-03-02 17:26:24 +01:00
|
|
|
return !isDummy() && enumFacing == facing;
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing from) {
|
2017-03-02 17:26:24 +01:00
|
|
|
return !isDummy() && from == facing && capability == CapabilityEnergy.ENERGY;
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
2018-02-08 22:08:21 +01:00
|
|
|
private EnergyCap energyCap = new EnergyCap();
|
2017-02-26 13:56:36 +01:00
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
2017-05-10 17:56:05 +02:00
|
|
|
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
|
2017-02-26 13:56:36 +01:00
|
|
|
if (hasCapability(capability, facing)) {
|
2017-02-28 17:32:40 +01:00
|
|
|
if (capability == CapabilityEnergy.ENERGY) {
|
2018-02-08 22:08:21 +01:00
|
|
|
return CapabilityEnergy.ENERGY.cast(energyCap);
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChunkUnload() {
|
2017-08-23 22:30:24 +02:00
|
|
|
if (hasIC2) {
|
|
|
|
removeFromIC2Net();
|
|
|
|
}
|
2017-02-26 13:56:36 +01:00
|
|
|
addedToIC2Net = false;
|
|
|
|
super.onChunkUnload();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void invalidate() {
|
2017-08-23 22:30:24 +02:00
|
|
|
if (hasIC2)
|
|
|
|
removeFromIC2Net();
|
|
|
|
if (world.isRemote) {
|
2017-02-28 17:32:40 +01:00
|
|
|
//stop sound
|
2017-02-26 13:56:36 +01:00
|
|
|
IndustrialWires.proxy.playJacobsLadderSound(this, -1, soundPos);
|
|
|
|
}
|
|
|
|
addedToIC2Net = false;
|
|
|
|
super.invalidate();
|
|
|
|
}
|
|
|
|
|
2017-08-23 22:30:24 +02:00
|
|
|
@Optional.Method(modid = "ic2")
|
|
|
|
private void removeFromIC2Net() {
|
|
|
|
if (!world.isRemote && addedToIC2Net) {
|
|
|
|
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-10 17:56:05 +02:00
|
|
|
@Nonnull
|
2017-02-28 17:32:40 +01:00
|
|
|
@Override
|
|
|
|
public AxisAlignedBB getRenderBoundingBox() {
|
|
|
|
return new AxisAlignedBB(pos, pos.add(1, 2, 1));
|
|
|
|
}
|
2017-02-26 13:56:36 +01:00
|
|
|
|
2017-03-21 18:12:09 +01:00
|
|
|
@Override
|
|
|
|
public AxisAlignedBB getBoundingBox() {
|
|
|
|
if (!isDummy()) {
|
|
|
|
//transformer
|
|
|
|
return Block.FULL_BLOCK_AABB;
|
|
|
|
} else {
|
|
|
|
Vec3d min;
|
|
|
|
Vec3d max;
|
|
|
|
double distX = (1 - size.topDistance) / 2;
|
|
|
|
double distZ = .5 - .0625 * (size.ordinal() + 1);
|
|
|
|
double h = Math.min(1, 1 + size.height - dummy);
|
|
|
|
if (facing.getAxis() == EnumFacing.Axis.Z) {
|
|
|
|
min = new Vec3d(distX, 0, distZ);
|
|
|
|
max = new Vec3d(1 - distX, h, 1 - distZ);
|
|
|
|
} else {
|
|
|
|
min = new Vec3d(distZ, 0, distX);
|
|
|
|
max = new Vec3d(1 - distZ, h, 1 - distX);
|
|
|
|
}
|
2017-06-25 18:34:10 +02:00
|
|
|
return new AxisAlignedBB(min.x, min.y, min.z, max.x, max.y, max.z);
|
2017-03-21 18:12:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-10 17:56:05 +02:00
|
|
|
@Nonnull
|
2017-04-02 17:16:42 +02:00
|
|
|
@Override
|
|
|
|
public EnumFacing getFacing() {
|
|
|
|
return facing;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public void setFacing(@Nonnull EnumFacing facing) {
|
2017-04-02 17:16:42 +02:00
|
|
|
this.facing = facing;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getFacingLimitation() {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public boolean mirrorFacingOnPlacement(@Nonnull EntityLivingBase placer) {
|
2017-04-02 17:16:42 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public boolean canHammerRotate(@Nonnull EnumFacing side, float hitX, float hitY, float hitZ, @Nonnull EntityLivingBase entity) {
|
2017-04-02 17:16:42 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-05-10 17:56:05 +02:00
|
|
|
public boolean canRotate(@Nonnull EnumFacing axis) {
|
2017-04-02 17:16:42 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-28 21:29:55 +01:00
|
|
|
private static final float[] saltColor = {1, 190 / 255F, 50 / 255F};
|
|
|
|
private static final float[] airColor = {1, .85F, 1};
|
2017-09-06 21:18:59 +02:00
|
|
|
|
2017-10-07 16:27:51 +02:00
|
|
|
private static final int factor = 20;
|
|
|
|
private static final double smallMin = Math.exp(-.5);
|
|
|
|
private static final double normalMin = Math.exp(-.25 * factor);
|
|
|
|
private static final double hugeMin = Math.exp(-.75 * factor);
|
2017-09-06 21:18:59 +02:00
|
|
|
public static float[] getColor(double t, double salt, LadderSize size) {
|
|
|
|
salt = Math.min(salt, 1);
|
|
|
|
double saltyness = 0;
|
|
|
|
double t2 = t - .5;
|
|
|
|
switch (size) {
|
|
|
|
case SMALL:
|
|
|
|
saltyness = salt * (1 - .9 * (Math.exp(-Math.abs(t2)) - smallMin));
|
|
|
|
break;
|
|
|
|
case NORMAL:
|
|
|
|
saltyness = salt * (1 - .9 * (Math.exp(-factor * t2 * t2) - normalMin));
|
|
|
|
break;
|
|
|
|
case HUGE:
|
|
|
|
saltyness = salt * (1 - .9 * (Math.exp(-Math.abs(factor * t2 * t2 * t2)) - hugeMin));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return interpolate(saltyness, saltColor, 1 - saltyness, airColor);
|
|
|
|
}
|
|
|
|
@Nullable
|
|
|
|
@Override
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
|
|
@Optional.Method(modid = "mirage")
|
|
|
|
public Light getColoredLight() {
|
|
|
|
if (timeTillActive == 0) {
|
|
|
|
float[] color = getColor(0, salt, size);
|
|
|
|
return Light.builder().pos(pos.getX()+.5,
|
|
|
|
Beziers.getPoint(.5, controls).y+pos.getY()+size.bottomDistance+1,
|
|
|
|
pos.getZ()+.5)
|
|
|
|
.color(color[0], color[1], color[2], 1)
|
|
|
|
.radius(size.soundVolume/3)
|
|
|
|
.build();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-03-21 18:12:09 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
public enum LadderSize implements IStringSerializable {
|
2017-02-28 17:32:40 +01:00
|
|
|
/*
|
|
|
|
all on a block (HV transformer)
|
|
|
|
small: height = .5 bottomDist = .15 topDist = .375
|
|
|
|
normal: height = .95 bottomDist = .2 topDist = .75
|
|
|
|
huge: height = 1.8 bottomDist = .25 topDist = 1
|
|
|
|
|
|
|
|
*/
|
|
|
|
SMALL(4, 4, .5, .375, .15, 20, .05, .2, .05, 1, 1, 5, 8, .03725, 1),
|
|
|
|
NORMAL(4, 4, .95, .75, .2, 25, .15, .3, .15, 1, 1, 5, 9, .075, 2),
|
|
|
|
HUGE(4, 5, 1.8, 1, .25, 30, .2, .5, .3, 1, 2, 5, 10, .125, 3);
|
2017-02-26 13:56:36 +01:00
|
|
|
public final int arcPoints;
|
|
|
|
public final int movementPoints;
|
|
|
|
// height of the electrodes
|
|
|
|
public final double height;
|
|
|
|
// distance between the electrodes at top and bottom
|
|
|
|
public final double topDistance;
|
|
|
|
public final double bottomDistance;
|
|
|
|
// ticks it takes for the arc to reach the top of the ladder on average
|
|
|
|
public final int tickToTop;
|
|
|
|
// maximum z offset for the inner bezier points
|
|
|
|
public final double zMax;
|
|
|
|
// additional height for inner bezier points, added to normal height and scaled
|
|
|
|
public final double extraHeight;
|
|
|
|
// fixed additional height for inner bezier points
|
|
|
|
public final double innerPointOffset;
|
|
|
|
// offset for rendering the arc, e.g. a value of 1 means the arc starts 1 block above the TE
|
|
|
|
public final double heightOffset;
|
|
|
|
// ticks between the end of one arc and the start of the next
|
|
|
|
public final int delay;
|
|
|
|
public final int renderPoints;
|
|
|
|
public final int dummyCount;
|
|
|
|
public final double renderDiameter;
|
2017-02-28 17:32:40 +01:00
|
|
|
public final float soundVolume;
|
2017-02-26 13:56:36 +01:00
|
|
|
|
2017-02-28 17:32:40 +01:00
|
|
|
LadderSize(int arcP, int movP, double height, double topD, double bottomD, int ttTop, double zMax, double extraH,
|
2017-03-03 17:52:22 +01:00
|
|
|
double iOff, double hOff, int dummies, int delay, int points, double renderDia, float volume) {
|
2017-02-26 13:56:36 +01:00
|
|
|
arcPoints = arcP;
|
|
|
|
movementPoints = movP;
|
2017-02-28 17:32:40 +01:00
|
|
|
this.height = height;
|
2017-02-26 13:56:36 +01:00
|
|
|
topDistance = topD;
|
|
|
|
bottomDistance = bottomD;
|
|
|
|
tickToTop = ttTop;
|
|
|
|
this.zMax = zMax;
|
|
|
|
extraHeight = extraH;
|
|
|
|
innerPointOffset = iOff;
|
|
|
|
heightOffset = hOff;
|
|
|
|
dummyCount = dummies;
|
|
|
|
this.delay = delay;
|
|
|
|
renderPoints = points;
|
|
|
|
renderDiameter = renderDia;
|
2017-02-28 17:32:40 +01:00
|
|
|
soundVolume = volume;
|
2017-02-26 13:56:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getName() {
|
|
|
|
return name().toLowerCase();
|
|
|
|
}
|
|
|
|
}
|
2017-02-28 17:32:40 +01:00
|
|
|
|
2017-02-26 13:56:36 +01:00
|
|
|
public class EnergyCap implements IEnergyStorage {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int receiveEnergy(int maxReceive, boolean simulate) {
|
|
|
|
return (int) energy.insertIF(maxReceive, !simulate);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int extractEnergy(int maxExtract, boolean simulate) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getEnergyStored() {
|
|
|
|
return (int) energy.getEnergyStoredIF();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getMaxEnergyStored() {
|
|
|
|
return (int) energy.getMaxStoredIF();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canExtract() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canReceive() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|