diff options
author | NotAPenguin <michiel.vandeginste@gmail.com> | 2024-09-02 23:17:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-02 23:17:17 +0200 |
commit | 1b820de08a05070909a267e17f033fcf58ac8710 (patch) | |
tree | 02831a025986a06b20f87e5bcc69d1e0c639a342 /src/main/java/tectech/mechanics | |
parent | afd3fd92b6a6ab9ab0d0dc3214e6bc8ff7a86c9b (diff) | |
download | GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.gz GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.bz2 GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.zip |
The Great Renaming (#3014)
* move kekztech to a single root dir
* move detrav to a single root dir
* move gtnh-lanthanides to a single root dir
* move tectech and delete some gross reflection in gt++
* remove more reflection inside gt5u
* delete more reflection in gt++
* fix imports
* move bartworks and bwcrossmod
* fix proxies
* move galactigreg and ggfab
* move gtneioreplugin
* try to fix gt++ bee loader
* apply the rename rules to BW
* apply rename rules to bwcrossmod
* apply rename rules to detrav scanner mod
* apply rename rules to galacticgreg
* apply rename rules to ggfab
* apply rename rules to goodgenerator
* apply rename rules to gtnh-lanthanides
* apply rename rules to gt++
* apply rename rules to kekztech
* apply rename rules to kubatech
* apply rename rules to tectech
* apply rename rules to gt
apply the rename rules to gt
* fix tt import
* fix mui hopefully
* fix coremod except intergalactic
* rename assline recipe class
* fix a class name i stumbled on
* rename StructureUtility to GTStructureUtility to prevent conflict with structurelib
* temporary rename of GTTooltipDataCache to old name
* fix gt client/server proxy names
Diffstat (limited to 'src/main/java/tectech/mechanics')
16 files changed, 1250 insertions, 0 deletions
diff --git a/src/main/java/tectech/mechanics/dataTransport/DataPacket.java b/src/main/java/tectech/mechanics/dataTransport/DataPacket.java new file mode 100644 index 0000000000..96af1f1afb --- /dev/null +++ b/src/main/java/tectech/mechanics/dataTransport/DataPacket.java @@ -0,0 +1,104 @@ +package tectech.mechanics.dataTransport; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import net.minecraft.nbt.NBTTagCompound; + +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +/** + * Created by Tec on 05.04.2017. + */ +public abstract class DataPacket<T> { + + private static final byte MAX_HISTORY = 64; + private final Set<Vec3Impl> trace = new LinkedHashSet<>(); + + protected T content; + + protected DataPacket(T content) { + this.content = content; + } + + protected DataPacket(NBTTagCompound nbt) { + content = contentFromNBT(nbt.getCompoundTag("qContent")); + for (int i = 0; i < nbt.getByte("qHistory"); i++) { + trace.add(new Vec3Impl(nbt.getInteger("qX" + i), nbt.getInteger("qY" + i), nbt.getInteger("qZ" + i))); + } + } + + public final NBTTagCompound toNbt() { + NBTTagCompound nbt = new NBTTagCompound(); + NBTTagCompound contentTag = contentToNBT(); + if (contentTag != null) { + nbt.setTag("qContent", contentTag); + } + nbt.setByte("qHistory", (byte) trace.size()); + int i = 0; + for (Vec3Impl v : trace) { + nbt.setInteger("qX" + i, v.get0()); + nbt.setInteger("qY" + i, v.get1()); + nbt.setInteger("qZ" + i, v.get2()); + i++; + } + return nbt; + } + + protected abstract NBTTagCompound contentToNBT(); + + protected abstract T contentFromNBT(NBTTagCompound nbt); + + protected abstract T unifyContentWith(T content); + + public final boolean contains(Vec3Impl v) { + return trace.contains(v); + } + + public final boolean check() { + return trace.size() <= MAX_HISTORY; + } + + public abstract boolean extraCheck(); + + protected final DataPacket<T> unifyTrace(Vec3Impl... positions) { + Collections.addAll(trace, positions); + return (check() && extraCheck()) ? this : null; + } + + protected final DataPacket<T> unifyTrace(DataPacket<T> p) { + if (p == null) return this; + trace.addAll(p.trace); + return (check() && extraCheck()) ? this : null; + } + + protected final DataPacket<T> unifyWith(DataPacket<T> p) { + if (p == null) return this; + trace.addAll(p.trace); + if (check() && extraCheck()) { + content = unifyContentWith(p.content); + return this; + } + return null; + } + + public final T contentIfNotInTrace(Vec3Impl pos) { + if (trace.contains(pos)) { + return null; + } + return getContent(); + } + + public T getContent() { + return content; + } + + public String getContentString() { + return content.toString(); + } + + public final int getTraceSize() { + return trace.size(); + } +} diff --git a/src/main/java/tectech/mechanics/dataTransport/InventoryDataPacket.java b/src/main/java/tectech/mechanics/dataTransport/InventoryDataPacket.java new file mode 100644 index 0000000000..b779a2c897 --- /dev/null +++ b/src/main/java/tectech/mechanics/dataTransport/InventoryDataPacket.java @@ -0,0 +1,62 @@ +package tectech.mechanics.dataTransport; + +import java.util.ArrayList; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import tectech.recipe.TTRecipeAdder; + +public class InventoryDataPacket extends DataPacket<ItemStack[]> { + + public InventoryDataPacket(ItemStack[] content) { + super(content); + } + + public InventoryDataPacket(NBTTagCompound compound) { + super(compound); + } + + @Override + protected ItemStack[] contentFromNBT(NBTTagCompound nbt) { + int count = nbt.getInteger("count"); + if (count > 0) { + ArrayList<ItemStack> stacks = new ArrayList<>(); + for (int i = 0; i < count; i++) { + ItemStack stack = ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Integer.toString(i))); + if (stack != null) { + stacks.add(stack); + } + } + return stacks.size() > 0 ? stacks.toArray(TTRecipeAdder.nullItem) : null; + } + return null; + } + + @Override + protected NBTTagCompound contentToNBT() { + NBTTagCompound compound = new NBTTagCompound(); + if (content != null && content.length > 0) { + compound.setInteger("count", content.length); + for (int i = 0; i < content.length; i++) { + compound.setTag(Integer.toString(i), content[i].writeToNBT(new NBTTagCompound())); + } + } + return compound; + } + + @Override + public boolean extraCheck() { + return true; + } + + @Override + protected ItemStack[] unifyContentWith(ItemStack[] content) { + throw new NoSuchMethodError("Unavailable to unify item stack data packet"); + } + + @Override + public String getContentString() { + return "Stack Count: " + (content == null ? 0 : content.length); + } +} diff --git a/src/main/java/tectech/mechanics/dataTransport/QuantumDataPacket.java b/src/main/java/tectech/mechanics/dataTransport/QuantumDataPacket.java new file mode 100644 index 0000000000..974831df07 --- /dev/null +++ b/src/main/java/tectech/mechanics/dataTransport/QuantumDataPacket.java @@ -0,0 +1,50 @@ +package tectech.mechanics.dataTransport; + +import net.minecraft.nbt.NBTTagCompound; + +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +public class QuantumDataPacket extends DataPacket<Long> { + + public QuantumDataPacket(Long content) { + super(content); + } + + public QuantumDataPacket(NBTTagCompound compound) { + super(compound); + } + + @Override + protected Long contentFromNBT(NBTTagCompound nbt) { + return nbt.getLong("computation"); + } + + @Override + protected NBTTagCompound contentToNBT() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setLong("computation", content); + return compound; + } + + @Override + public boolean extraCheck() { + return true; + } + + @Override + protected Long unifyContentWith(Long content) { + return this.content + content; + } + + public QuantumDataPacket unifyTraceWith(Vec3Impl... positions) { + return (QuantumDataPacket) super.unifyTrace(positions); + } + + public QuantumDataPacket unifyTraceWith(QuantumDataPacket p) { + return (QuantumDataPacket) super.unifyTrace(p); + } + + public QuantumDataPacket unifyPacketWith(QuantumDataPacket p) { + return (QuantumDataPacket) super.unifyWith(p); + } +} diff --git a/src/main/java/tectech/mechanics/enderStorage/EnderFluidContainer.java b/src/main/java/tectech/mechanics/enderStorage/EnderFluidContainer.java new file mode 100644 index 0000000000..f77a5a1b51 --- /dev/null +++ b/src/main/java/tectech/mechanics/enderStorage/EnderFluidContainer.java @@ -0,0 +1,134 @@ +package tectech.mechanics.enderStorage; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; + +import tectech.TecTech; + +public class EnderFluidContainer implements IFluidHandler, Serializable { + + private static final long serialVersionUID = 2L; + private static final int SERIALIZE_TYPE_WITH_NBT = 0; + private static final int SERIALIZE_TYPE_WITHOUT_NBT = 1; + private static final int SERIALIZE_TYPE_NULL = 2; + + private static final int CAPACITY = 64000; + private transient FluidStack fluidStack; + + public EnderFluidContainer() {} + + private FluidStack getFluidStack() { + return fluidStack; + } + + private void setFluidStack(FluidStack fluidStack) { + this.fluidStack = fluidStack; + } + + @Override + public int fill(ForgeDirection side, FluidStack fluidStackIn, boolean doFill) { + int filledFluid = 0; + FluidStack fluidStackStored = getFluidStack(); + if (fluidStackIn != null) { + if (fluidStackStored == null) { + fluidStackStored = fluidStackIn.copy(); + fluidStackStored.amount = 0; + } + if (fluidStackStored.amount < CAPACITY && fluidStackIn.isFluidEqual(fluidStackStored)) { + filledFluid = Math.min(CAPACITY - fluidStackStored.amount, fluidStackIn.amount); + if (doFill) { + fluidStackStored.amount += filledFluid; + setFluidStack(fluidStackStored); + } + } + } + return filledFluid; + } + + @Override + public FluidStack drain(ForgeDirection side, FluidStack fluidStack, boolean doDrain) { + FluidStack fluidStackOutput = null; + if (fluidStack != null && fluidStack.isFluidEqual(getFluidStack())) { + fluidStackOutput = drain(side, fluidStack.amount, doDrain); + } + return fluidStackOutput; + } + + @Override + public FluidStack drain(ForgeDirection side, int amount, boolean doDrain) { + FluidStack fluidStackOutput = null; + FluidStack fluidStackStored = getFluidStack(); + if (fluidStackStored != null && fluidStackStored.amount > 0) { + int drainedFluid = Math.min(fluidStackStored.amount, amount); + fluidStackOutput = fluidStackStored.copy(); + fluidStackOutput.amount = drainedFluid; + if (doDrain) { + fluidStackStored.amount -= drainedFluid; + if (fluidStackStored.amount == 0) { + fluidStackStored = null; + } + setFluidStack(fluidStackStored); + } + } + return fluidStackOutput; + } + + @Override + public boolean canFill(ForgeDirection forgeDirection, Fluid fluid) { + return true; + } + + @Override + public boolean canDrain(ForgeDirection forgeDirection, Fluid fluid) { + return true; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection forgeDirection) { + return new FluidTankInfo[] { new FluidTankInfo(getFluidStack(), CAPACITY) }; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + if (fluidStack != null) { + out.writeByte(fluidStack.tag != null ? SERIALIZE_TYPE_WITH_NBT : SERIALIZE_TYPE_WITHOUT_NBT); + if (fluidStack.tag != null) CompressedStreamTools.write(fluidStack.tag, out); + out.writeUTF( + fluidStack.getFluid() + .getName()); + out.writeInt(fluidStack.amount); + } else { + out.writeByte(SERIALIZE_TYPE_NULL); + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + byte type = in.readByte(); + NBTTagCompound tag = null; + switch (type) { + case SERIALIZE_TYPE_WITH_NBT: + tag = CompressedStreamTools.read(new DataInputStream(in)); + case SERIALIZE_TYPE_WITHOUT_NBT: + fluidStack = FluidRegistry.getFluidStack(in.readUTF(), in.readInt()); + break; + case SERIALIZE_TYPE_NULL: + fluidStack = null; + break; + default: + TecTech.LOGGER.error("Something very wrong... got a fluid container with state " + type); + fluidStack = null; + } + if (fluidStack != null) fluidStack.tag = tag; + } +} diff --git a/src/main/java/tectech/mechanics/enderStorage/EnderLinkTag.java b/src/main/java/tectech/mechanics/enderStorage/EnderLinkTag.java new file mode 100644 index 0000000000..516b7fd637 --- /dev/null +++ b/src/main/java/tectech/mechanics/enderStorage/EnderLinkTag.java @@ -0,0 +1,39 @@ +package tectech.mechanics.enderStorage; + +import java.io.Serializable; +import java.util.UUID; + +import com.google.common.base.Objects; + +public class EnderLinkTag implements Serializable { + + private static final long serialVersionUID = 6884008436570077863L; + private final String frequency; + private final UUID player; + + public EnderLinkTag(String frequency, UUID player) { + this.frequency = frequency; + this.player = player; + } + + public String getFrequency() { + return frequency; + } + + public UUID getUUID() { + return player; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EnderLinkTag that = (EnderLinkTag) o; + return Objects.equal(frequency, that.frequency) && Objects.equal(player, that.player); + } + + @Override + public int hashCode() { + return Objects.hashCode(frequency, player); + } +} diff --git a/src/main/java/tectech/mechanics/enderStorage/EnderLinkTank.java b/src/main/java/tectech/mechanics/enderStorage/EnderLinkTank.java new file mode 100644 index 0000000000..1b14c1371a --- /dev/null +++ b/src/main/java/tectech/mechanics/enderStorage/EnderLinkTank.java @@ -0,0 +1,47 @@ +package tectech.mechanics.enderStorage; + +import java.io.Serializable; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.fluids.IFluidHandler; + +import com.google.common.base.Objects; + +public class EnderLinkTank implements Serializable { + + private static final long serialVersionUID = 1030297456736434221L; + private final int X; + private final int Y; + private final int Z; + private final int D; + + public EnderLinkTank(IFluidHandler fluidHandler) { + TileEntity tile = (TileEntity) fluidHandler; + X = tile.xCoord; + Y = tile.yCoord; + Z = tile.zCoord; + D = tile.getWorldObj().provider.dimensionId; + } + + public IFluidHandler getFluidHandler() { + IFluidHandler fluidHandler = null; + TileEntity tile = DimensionManager.getWorld(D) + .getTileEntity(X, Y, Z); + if (tile instanceof IFluidHandler) fluidHandler = (IFluidHandler) tile; + return fluidHandler; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EnderLinkTank that = (EnderLinkTank) o; + return X == that.X && Y == that.Y && Z == that.Z && D == that.D; + } + + @Override + public int hashCode() { + return Objects.hashCode(X, Y, Z, D); + } +} diff --git a/src/main/java/tectech/mechanics/enderStorage/EnderWorldSavedData.java b/src/main/java/tectech/mechanics/enderStorage/EnderWorldSavedData.java new file mode 100644 index 0000000000..d6182794b7 --- /dev/null +++ b/src/main/java/tectech/mechanics/enderStorage/EnderWorldSavedData.java @@ -0,0 +1,144 @@ +package tectech.mechanics.enderStorage; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.WorldSavedData; +import net.minecraft.world.storage.MapStorage; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fluids.IFluidHandler; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import tectech.Reference; + +public class EnderWorldSavedData extends WorldSavedData { + + private static EnderWorldSavedData INSTANCE; + + private static final String DATA_NAME = Reference.MODID + "_EnderWorldSavedData"; + private static final String ENDER_LIQUID_TAG_LINK = DATA_NAME + "_EnderLiquidTagLink"; + private static final String ENDER_LIQUID_TANK_LINK = DATA_NAME + "_EnderLiquidTankLink"; + private static final EnderLinkTag DEFAULT_LINK_TAG = new EnderLinkTag("", null); + + private Map<EnderLinkTag, EnderFluidContainer> EnderLiquidTagLink = new HashMap<>(); + private Map<EnderLinkTank, EnderLinkTag> EnderLiquidTankLink = new HashMap<>(); + + public EnderWorldSavedData() { + super(DATA_NAME); + } + + public EnderWorldSavedData(String s) { + super(s); + } + + @SuppressWarnings("unchecked") + @Override + public void readFromNBT(NBTTagCompound nbtTagCompound) { + try { + byte[] ba = nbtTagCompound.getByteArray(ENDER_LIQUID_TAG_LINK); + InputStream is = new ByteArrayInputStream(ba); + ObjectInputStream ois = new ObjectInputStream(is); + Object data = ois.readObject(); + EnderLiquidTagLink = (Map<EnderLinkTag, EnderFluidContainer>) data; + } catch (IOException | ClassNotFoundException ignored) { + System.out.println("ENDER_LIQUID_TAG_LINK LOAD FAILED"); + System.out.println(ignored); + } + + try { + byte[] ba = nbtTagCompound.getByteArray(ENDER_LIQUID_TANK_LINK); + InputStream is = new ByteArrayInputStream(ba); + ObjectInputStream ois = new ObjectInputStream(is); + Object data = ois.readObject(); + EnderLiquidTankLink = (Map<EnderLinkTank, EnderLinkTag>) data; + } catch (IOException | ClassNotFoundException ignored) { + System.out.println("ENDER_LIQUID_TANK_LINK LOAD FAILED"); + System.out.println(ignored); + } + } + + @Override + public void writeToNBT(NBTTagCompound nbtTagCompound) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(EnderLiquidTagLink); + oos.flush(); + byte[] data = bos.toByteArray(); + nbtTagCompound.setByteArray(ENDER_LIQUID_TAG_LINK, data); + } catch (IOException ignored) { + System.out.println("ENDER_LIQUID_TAG_LINK SAVE FAILED"); + System.out.println(ignored); + } + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(EnderLiquidTankLink); + oos.flush(); + byte[] data = bos.toByteArray(); + nbtTagCompound.setByteArray(ENDER_LIQUID_TANK_LINK, data); + } catch (IOException ignored) { + System.out.println("ENDER_LIQUID_TANK_LINK SAVE FAILED"); + System.out.println(ignored); + } + } + + private static void loadInstance() { + if (INSTANCE == null) { + MapStorage storage = DimensionManager.getWorld(0).mapStorage; + INSTANCE = (EnderWorldSavedData) storage.loadData(EnderWorldSavedData.class, DATA_NAME); + if (INSTANCE == null) { + INSTANCE = new EnderWorldSavedData(); + storage.setData(DATA_NAME, INSTANCE); + } + } + INSTANCE.markDirty(); + } + + private static Map<EnderLinkTag, EnderFluidContainer> getEnderLiquidLink() { + loadInstance(); + return INSTANCE.EnderLiquidTagLink; + } + + private static Map<EnderLinkTank, EnderLinkTag> getEnderLiquidTankLink() { + loadInstance(); + return INSTANCE.EnderLiquidTankLink; + } + + public static EnderFluidContainer getEnderFluidContainer(EnderLinkTag tag) { + if (!getEnderLiquidLink().containsKey(tag)) { + getEnderLiquidLink().put(tag, new EnderFluidContainer()); + } + return getEnderLiquidLink().get(tag); + } + + public static EnderLinkTag getEnderLinkTag(IFluidHandler handler) { + EnderLinkTank tank = new EnderLinkTank(handler); + if (!getEnderLiquidTankLink().containsKey(tank)) { + getEnderLiquidTankLink().put(tank, DEFAULT_LINK_TAG); + } + return getEnderLiquidTankLink().get(tank); + } + + public static void bindEnderLinkTag(IFluidHandler handler, EnderLinkTag tag) { + EnderLinkTank tank = new EnderLinkTank(handler); + getEnderLiquidTankLink().remove(tank); + getEnderLiquidTankLink().put(tank, tag); + } + + @SubscribeEvent + public void onWorldUnload(WorldEvent.Unload event) { + if (event.world.provider.dimensionId == 0) { + INSTANCE = null; + } + } +} diff --git a/src/main/java/tectech/mechanics/pipe/IActivePipe.java b/src/main/java/tectech/mechanics/pipe/IActivePipe.java new file mode 100644 index 0000000000..e6f981d627 --- /dev/null +++ b/src/main/java/tectech/mechanics/pipe/IActivePipe.java @@ -0,0 +1,12 @@ +package tectech.mechanics.pipe; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; + +public interface IActivePipe extends IMetaTileEntity { + + void setActive(boolean active); + + boolean getActive(); + + void markUsed(); +} diff --git a/src/main/java/tectech/mechanics/pipe/IConnectsToDataPipe.java b/src/main/java/tectech/mechanics/pipe/IConnectsToDataPipe.java new file mode 100644 index 0000000000..b186840a42 --- /dev/null +++ b/src/main/java/tectech/mechanics/pipe/IConnectsToDataPipe.java @@ -0,0 +1,17 @@ +package tectech.mechanics.pipe; + +import net.minecraftforge.common.util.ForgeDirection; + +/** + * Created by Tec on 26.02.2017. + */ +public interface IConnectsToDataPipe { + + boolean canConnectData(ForgeDirection side); + + IConnectsToDataPipe getNext(IConnectsToDataPipe source); + + boolean isDataInputFacing(ForgeDirection side); + + byte getColorization(); +} diff --git a/src/main/java/tectech/mechanics/pipe/IConnectsToEnergyTunnel.java b/src/main/java/tectech/mechanics/pipe/IConnectsToEnergyTunnel.java new file mode 100644 index 0000000000..b2381b2b69 --- /dev/null +++ b/src/main/java/tectech/mechanics/pipe/IConnectsToEnergyTunnel.java @@ -0,0 +1,11 @@ +package tectech.mechanics.pipe; + +import net.minecraftforge.common.util.ForgeDirection; + +/** + * Created by Tec on 26.02.2017. + */ +public interface IConnectsToEnergyTunnel { + + boolean canConnect(ForgeDirection side); +} diff --git a/src/main/java/tectech/mechanics/pipe/PipeActivityMessage.java b/src/main/java/tectech/mechanics/pipe/PipeActivityMessage.java new file mode 100644 index 0000000000..d6b3717eb5 --- /dev/null +++ b/src/main/java/tectech/mechanics/pipe/PipeActivityMessage.java @@ -0,0 +1,136 @@ +package tectech.mechanics.pipe; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import eu.usrv.yamcore.network.client.AbstractClientMessageHandler; +import eu.usrv.yamcore.network.server.AbstractServerMessageHandler; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import io.netty.buffer.ByteBuf; + +public class PipeActivityMessage implements IMessage { + + int mPosX; + int mPosY; + int mPosZ; + int mPosD; + int mActive; + + public PipeActivityMessage() {} + + private PipeActivityMessage(IActivePipe metaTile) { + IGregTechTileEntity base = metaTile.getBaseMetaTileEntity(); + mPosX = base.getXCoord(); + mPosY = base.getYCoord(); + mPosZ = base.getZCoord(); + mPosD = base.getWorld().provider.dimensionId; + mActive = metaTile.getActive() ? 1 : 0; + } + + private PipeActivityMessage(World world, int x, int y, int z, boolean active) { + mPosX = x; + mPosY = y; + mPosZ = z; + mPosD = world.provider.dimensionId; + mActive = active ? 1 : 0; + } + + @Override + public void fromBytes(ByteBuf pBuffer) { + NBTTagCompound tTag = ByteBufUtils.readTag(pBuffer); + mPosX = tTag.getInteger("posx"); + mPosY = tTag.getInteger("posy"); + mPosZ = tTag.getInteger("posz"); + mPosD = tTag.getInteger("posd"); + mActive = tTag.getInteger("active"); + } + + @Override + public void toBytes(ByteBuf pBuffer) { + NBTTagCompound tFXTag = new NBTTagCompound(); + tFXTag.setInteger("posx", mPosX); + tFXTag.setInteger("posy", mPosY); + tFXTag.setInteger("posz", mPosZ); + tFXTag.setInteger("posd", mPosD); + tFXTag.setInteger("active", mActive); + + ByteBufUtils.writeTag(pBuffer, tFXTag); + } + + public static class PipeActivityQuery extends PipeActivityMessage { + + public PipeActivityQuery() {} + + public PipeActivityQuery(IActivePipe metaTile) { + super(metaTile); + } + + public PipeActivityQuery(World world, int x, int y, int z, boolean active) { + super(world, x, y, z, active); + } + } + + public static class PipeActivityData extends PipeActivityMessage { + + public PipeActivityData() {} + + private PipeActivityData(PipeActivityQuery query) { + mPosX = query.mPosX; + mPosY = query.mPosY; + mPosZ = query.mPosZ; + mPosD = query.mPosD; + mActive = query.mActive; + } + + public PipeActivityData(IActivePipe metaTile) { + super(metaTile); + } + + public PipeActivityData(World world, int x, int y, int z, boolean active) { + super(world, x, y, z, active); + } + } + + public static class ClientHandler extends AbstractClientMessageHandler<PipeActivityData> { + + @Override + public IMessage handleClientMessage(EntityPlayer pPlayer, PipeActivityData pMessage, MessageContext pCtx) { + if (pPlayer.worldObj.provider.dimensionId == pMessage.mPosD) { + TileEntity te = pPlayer.worldObj.getTileEntity(pMessage.mPosX, pMessage.mPosY, pMessage.mPosZ); + if (te instanceof IGregTechTileEntity) { + IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity(); + if (meta instanceof IActivePipe) { + ((IActivePipe) meta).setActive(pMessage.mActive == 1); + } + } + } + return null; + } + } + + public static class ServerHandler extends AbstractServerMessageHandler<PipeActivityQuery> { + + @Override + public IMessage handleServerMessage(EntityPlayer pPlayer, PipeActivityQuery pMessage, MessageContext pCtx) { + World world = DimensionManager.getWorld(pMessage.mPosD); + if (world != null) { + TileEntity te = world.getTileEntity(pMessage.mPosX, pMessage.mPosY, pMessage.mPosZ); + if (te instanceof IGregTechTileEntity) { + IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity(); + if (meta instanceof IActivePipe) { + pMessage.mActive = ((IActivePipe) meta).getActive() ? 1 : 0; + return new PipeActivityData(pMessage); + } + } + } + return null; + } + } +} diff --git a/src/main/java/tectech/mechanics/spark/RendererMessage.java b/src/main/java/tectech/mechanics/spark/RendererMessage.java new file mode 100644 index 0000000000..6c52e43b0d --- /dev/null +++ b/src/main/java/tectech/mechanics/spark/RendererMessage.java @@ -0,0 +1,148 @@ +package tectech.mechanics.spark; + +import static gregtech.api.enums.Mods.Thaumcraft; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import eu.usrv.yamcore.network.client.AbstractClientMessageHandler; +import io.netty.buffer.ByteBuf; +import thaumcraft.client.fx.bolt.FXLightningBolt; + +// TODO Re-work how sparks are distributed +public class RendererMessage implements IMessage { + + HashSet<ThaumSpark> sparkList; + + public RendererMessage() {} + + @SuppressWarnings("unchecked") + @Override + public void fromBytes(ByteBuf pBuffer) { + if (FMLCommonHandler.instance() + .getSide() + .isServer()) return; + try { + // I'd love to know why I need to offset by one byte for this to work + byte[] boop = pBuffer.array(); + boop = Arrays.copyOfRange(boop, 1, boop.length); + InputStream is = new ByteArrayInputStream(boop); + ObjectInputStream ois = new ValidatingObjectInputStream(is); + Object data = ois.readObject(); + sparkList = (HashSet<ThaumSpark>) data; + } catch (IOException | ClassNotFoundException ignored) {} + } + + @Override + public void toBytes(ByteBuf pBuffer) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(sparkList); + oos.flush(); + InputStream is = new ByteArrayInputStream(baos.toByteArray()); + pBuffer.writeBytes(is, baos.toByteArray().length); + } catch (IOException ignore) {} + } + + public static class RendererData extends RendererMessage { + + public RendererData() {} + + public RendererData(HashSet<ThaumSpark> eSparkList) { + sparkList = eSparkList; + } + } + + public static class ClientHandler extends AbstractClientMessageHandler<RendererData> { + + @Override + public IMessage handleClientMessage(EntityPlayer pPlayer, RendererData pMessage, MessageContext pCtx) { + // disgusting + Random localRand = Minecraft.getMinecraft().theWorld.rand; + int[] zapsToUse = new int[4]; + for (int i = 0; i < 3; i++) { + zapsToUse[i] = localRand.nextInt(pMessage.sparkList.size()); + } + int i = 0; + for (ThaumSpark sp : pMessage.sparkList) { + for (int j : zapsToUse) { + if (i == j) { + thaumLightning(sp.x, sp.y, sp.z, sp.xR, sp.yR, sp.zR, sp.wID); + } + } + i++; + } + pMessage.sparkList.clear(); + return null; + } + } + + @SideOnly(Side.CLIENT) + private static void thaumLightning(int tX, int tY, int tZ, int tXN, int tYN, int tZN, int wID) { + // This is enough to check for thaum, since it only ever matters for client side effects (Tested not to crash) + if (Thaumcraft.isModLoaded()) { + World world = Minecraft.getMinecraft().theWorld; + if (world.provider.dimensionId == wID) { + FXLightningBolt bolt = new FXLightningBolt( + world, + tX + 0.5F, + tY + 0.5F, + tZ + 0.5F, + tX + tXN + 0.5F, + tY + tYN + 0.5F, + tZ + tZN + 0.5F, + world.rand.nextLong(), + 6, + 0.5F, + 8); + bolt.defaultFractal(); + bolt.setType(2); + bolt.setWidth(0.125F); + bolt.finalizeBolt(); + } + } + } + + private static class ValidatingObjectInputStream extends ObjectInputStream { + + private static final Logger logger = LogManager.getLogger(); + private static final Marker securityMarker = MarkerManager.getMarker("SuspiciousPackets"); + + private ValidatingObjectInputStream(InputStream in) throws IOException { + super(in); + } + + @Override + protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + String name = desc.getName(); + if (!name.equals("java.util.HashSet") && !name.equals("tectech.mechanics.spark.ThaumSpark")) { + logger.warn(securityMarker, "Received packet containing disallowed class: " + name); + throw new RuntimeException(); + } + return super.resolveClass(desc); + } + } +} diff --git a/src/main/java/tectech/mechanics/spark/ThaumSpark.java b/src/main/java/tectech/mechanics/spark/ThaumSpark.java new file mode 100644 index 0000000000..12c04f2cfe --- /dev/null +++ b/src/main/java/tectech/mechanics/spark/ThaumSpark.java @@ -0,0 +1,57 @@ +package tectech.mechanics.spark; + +import java.io.Serializable; +import java.util.Objects; + +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +public class ThaumSpark implements Serializable { + + // This works regardless of if TC is loaded + private static final long serialVersionUID = -7037856938316679566L; + public int x, y, z, wID; + public byte xR, yR, zR; + + public ThaumSpark(int x, int y, int z, byte xR, byte yR, byte zR, int wID) { + this.x = x; + this.y = y; + this.z = z; + + this.xR = xR; + this.yR = yR; + this.zR = zR; + + this.wID = wID; + } + + public ThaumSpark(Vec3Impl origin, Vec3Impl target, int wID) { + this.x = origin.get0(); + this.y = origin.get1(); + this.z = origin.get2(); + + Vec3Impl offset = target.sub(origin); + this.xR = (byte) offset.get0(); + this.yR = (byte) offset.get1(); + this.zR = (byte) offset.get2(); + + this.wID = wID; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ThaumSpark that = (ThaumSpark) o; + return x == that.x && y == that.y + && z == that.z + && wID == that.wID + && xR == that.xR + && yR == that.yR + && zR == that.zR; + } + + @Override + public int hashCode() { + return Objects.hash(x, y, z, wID, xR, yR, zR); + } +} diff --git a/src/main/java/tectech/mechanics/tesla/ITeslaConnectable.java b/src/main/java/tectech/mechanics/tesla/ITeslaConnectable.java new file mode 100644 index 0000000000..27fa829bad --- /dev/null +++ b/src/main/java/tectech/mechanics/tesla/ITeslaConnectable.java @@ -0,0 +1,184 @@ +package tectech.mechanics.tesla; + +import static java.lang.Math.sqrt; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Multimap; + +import tectech.mechanics.spark.ThaumSpark; + +public interface ITeslaConnectable extends ITeslaConnectableSimple { + + // Map with all Teslas in the same dimension and the distance to them //TODO Range + Multimap<Integer, ITeslaConnectableSimple> getTeslaNodeMap(); + + // ThaumCraft lighting coordinate pairs, so we can send them in bursts and save on lag + HashSet<ThaumSpark> getSparkList(); + + // -128 to -1 disables capability + // 0 means any source or target + // 1 to 127 must match on source and target or source/target must be 0 + byte getTeslaTransmissionCapability(); + + // Transmission Range is typically 16+ in blocks + int getTeslaTransmissionRange(); + + boolean isOverdriveEnabled(); + + int getTeslaEnergyLossPerBlock(); + + float getTeslaOverdriveLossCoefficient(); + + long getTeslaOutputVoltage(); + + long getTeslaOutputCurrent(); + + boolean teslaDrainEnergy(long teslaVoltageDrained); + + class TeslaUtil { + + private static final HashSet<ITeslaConnectableSimple> teslaSimpleNodeSet = new HashSet<>(); // Targets for power + // transmission + private static final HashSet<ITeslaConnectable> teslaNodeSet = new HashSet<>(); // Sources of power transmission + private static final List<ITeslaConnectableSimple> scheduledRemove = new ArrayList<>(); + + public static void teslaSimpleNodeSetAdd(ITeslaConnectableSimple target) { + if (!teslaSimpleNodeSet.contains(target)) { + teslaSimpleNodeSet.add(target); + teslaNodeSet.forEach(origin -> addTargetToTeslaOrigin(target, origin)); + } + } + + public static void teslaSimpleNodeSetRemove(ITeslaConnectableSimple target) { + teslaSimpleNodeSet.remove(target); + if (target instanceof ITeslaConnectable) teslaNodeSet.remove(target); + teslaNodeSet.forEach(origin -> removeTargetFromTeslaOrigin(target, origin)); + } + + public static void teslaSimpleNodeSetRemoveScheduled(ITeslaConnectableSimple target) { + scheduledRemove.add(target); + } + + public static void housekeep() { + for (ITeslaConnectableSimple e : scheduledRemove) { + teslaSimpleNodeSet.remove(e); + } + scheduledRemove.clear(); + } + + private static void addTargetToTeslaOrigin(ITeslaConnectableSimple target, ITeslaConnectable origin) { + if (origin.equals(target) || !origin.getTeslaDimension() + .equals(target.getTeslaDimension())) { + // Skip if looking at myself and skip if not in the same dimension + // TODO, INTERDIM? + return; + } else if (origin.getTeslaTransmissionCapability() != 0 && origin.getTeslaReceptionCapability() != 0 + && origin.getTeslaTransmissionCapability() != origin.getTeslaReceptionCapability()) { + // Skip if incompatible + return; + } + // Range calc + int distance = (int) sqrt( + origin.getTeslaPosition() + .distanceSq(target.getTeslaPosition())); + if (distance > origin.getTeslaTransmissionRange() * target.getTeslaReceptionCoefficient()) { + // Skip if the range is too vast + return; + } + origin.getTeslaNodeMap() + .put(distance, target); + } + + private static void removeTargetFromTeslaOrigin(ITeslaConnectableSimple target, ITeslaConnectable origin) { + // Range calc TODO Remove duplicate? + int distance = (int) sqrt( + origin.getTeslaPosition() + .distanceSq(target.getTeslaPosition())); + origin.getTeslaNodeMap() + .remove(distance, target); + } + + public static void generateTeslaNodeMap(ITeslaConnectable origin) { + origin.getTeslaNodeMap() + .clear(); + for (ITeslaConnectableSimple target : teslaSimpleNodeSet) { + // Sanity checks + if (target == null) { + // The Tesla Covers do not remove themselves from the list and this is the code that does + teslaSimpleNodeSet.remove(null); + continue; + } + addTargetToTeslaOrigin(target, origin); + } + teslaNodeSet.add(origin); + } + + public static long powerTeslaNodeMap(ITeslaConnectable origin) { + long remainingAmperes = origin.getTeslaOutputCurrent(); + boolean canSendPower = !origin.isTeslaReadyToReceive() && remainingAmperes > 0; + + if (canSendPower) { + for (Map.Entry<Integer, ITeslaConnectableSimple> Rx : origin.getTeslaNodeMap() + .entries()) { + // Do we still have power left to send kind of check + if (origin.getTeslaStoredEnergy() + < (origin.isOverdriveEnabled() ? origin.getTeslaOutputVoltage() * 2 + : origin.getTeslaOutputVoltage())) + break; + // Explicit words for the important fields + ITeslaConnectableSimple target = Rx.getValue(); + int distance = Rx.getKey(); + // Can our target receive energy? + if (!target.isTeslaReadyToReceive()) continue; + + // Calculate the voltage output + long outputVoltageInjectable; + long outputVoltageConsumption; + if (origin.isOverdriveEnabled()) { + outputVoltageInjectable = origin.getTeslaOutputVoltage(); + outputVoltageConsumption = origin.getTeslaOutputVoltage() + + ((long) distance * origin.getTeslaEnergyLossPerBlock()) + + (long) Math + .round(origin.getTeslaOutputVoltage() * origin.getTeslaOverdriveLossCoefficient()); + } else { + outputVoltageInjectable = origin.getTeslaOutputVoltage() + - ((long) distance * origin.getTeslaEnergyLossPerBlock()); + outputVoltageConsumption = origin.getTeslaOutputVoltage(); + } + + // Break out of the loop if the cost is too high + // Since the next target will have an even higher cost, just quit now. + if (origin.getTeslaStoredEnergy() < outputVoltageConsumption) break; + + // Now shove in as many packets as will fit~ + while (canSendPower) { + if (target.teslaInjectEnergy(outputVoltageInjectable)) { + origin.teslaDrainEnergy(outputVoltageConsumption); + origin.getSparkList() + .add( + new ThaumSpark( + origin.getTeslaPosition(), + target.getTeslaPosition(), + origin.getTeslaDimension())); + remainingAmperes--; + // Update the can send power flag each time we send power + canSendPower = (origin.getTeslaStoredEnergy() < outputVoltageConsumption + || remainingAmperes > 0); + } else { + // Breaks out when I can't send anymore power + break; + } + } + + // Break out if we can't send power anymore + if (!canSendPower) break; + } + } + return origin.getTeslaOutputCurrent() - remainingAmperes; + } + } +} diff --git a/src/main/java/tectech/mechanics/tesla/ITeslaConnectableSimple.java b/src/main/java/tectech/mechanics/tesla/ITeslaConnectableSimple.java new file mode 100644 index 0000000000..8cbbd75ca0 --- /dev/null +++ b/src/main/java/tectech/mechanics/tesla/ITeslaConnectableSimple.java @@ -0,0 +1,24 @@ +package tectech.mechanics.tesla; + +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +public interface ITeslaConnectableSimple { + + // -128 to -1 disables capability + // 0 means any source or target + // 1 to 127 must match on source and target or source/target must be 0 + byte getTeslaReceptionCapability(); + + // Reception Coefficient is a range extension, typical is 1 + float getTeslaReceptionCoefficient(); + + boolean isTeslaReadyToReceive(); + + long getTeslaStoredEnergy(); + + boolean teslaInjectEnergy(long teslaVoltageInjected); + + Vec3Impl getTeslaPosition(); + + Integer getTeslaDimension(); +} diff --git a/src/main/java/tectech/mechanics/tesla/TeslaCoverConnection.java b/src/main/java/tectech/mechanics/tesla/TeslaCoverConnection.java new file mode 100644 index 0000000000..0ab421361f --- /dev/null +++ b/src/main/java/tectech/mechanics/tesla/TeslaCoverConnection.java @@ -0,0 +1,81 @@ +package tectech.mechanics.tesla; + +import static tectech.mechanics.tesla.ITeslaConnectable.TeslaUtil.teslaSimpleNodeSetRemoveScheduled; + +import net.minecraftforge.common.util.ForgeDirection; + +import com.google.common.base.Objects; +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; + +public class TeslaCoverConnection implements ITeslaConnectableSimple { + + private final IGregTechTileEntity IGT; + private final Vec3Impl pos; + private final byte teslaReceptionCapability; + + public TeslaCoverConnection(IGregTechTileEntity IGT, byte teslaReceptionCapability) { + this.IGT = IGT; + this.pos = new Vec3Impl(IGT.getXCoord(), IGT.getYCoord(), IGT.getZCoord()); + + this.teslaReceptionCapability = teslaReceptionCapability; + } + + @Override + public byte getTeslaReceptionCapability() { + return teslaReceptionCapability; + } + + @Override + public float getTeslaReceptionCoefficient() { + return 1; + } + + @Override + public boolean isTeslaReadyToReceive() { + return true; + } + + @Override + public long getTeslaStoredEnergy() { + return IGT.getStoredEU(); + } + + @Override + public Vec3Impl getTeslaPosition() { + return pos; + } + + @Override + public Integer getTeslaDimension() { + return IGT.getWorld().provider.dimensionId; + } + + @Override + public boolean teslaInjectEnergy(long teslaVoltageInjected) { + // Same as in the microwave transmitters, this does not account for amp limits + boolean output = false; + + if (!IGT.isDead()) { + output = IGT.injectEnergyUnits(ForgeDirection.UP, teslaVoltageInjected, 1L) > 0L; + } else { + teslaSimpleNodeSetRemoveScheduled(this); + } + + return output; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TeslaCoverConnection that = (TeslaCoverConnection) o; + return Objects.equal(IGT, that.IGT); + } + + @Override + public int hashCode() { + return Objects.hashCode(IGT); + } +} |