IndustrialWires/src/main/java/malte0811/industrialwires/blocks/TileEntityIWMultiblock.java
2018-11-17 12:23:31 +01:00

176 lines
5.5 KiB
Java

/*
* This file is part of Industrial Wires.
* Copyright (C) 2016-2018 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/>.
*/
package malte0811.industrialwires.blocks;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IDirectionalTile;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IGeneralMultiblock;
import malte0811.industrialwires.util.MiscUtils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.function.BiConsumer;
public abstract class TileEntityIWMultiblock extends TileEntityIWBase implements IGeneralMultiblock,
IDirectionalTile {
protected final static String OFFSET = "offset";
protected final static String FORMED = "formed";
protected final static String MIRRORED = "mirrored";
protected final static String FACING = "facing";
//HFR
protected Vec3i size;
public Vec3i offset = new Vec3i(0, 1, 0);
public boolean formed;
public boolean mirrored;
public long onlyLocalDissassembly;
public EnumFacing facing = EnumFacing.NORTH;
@Nonnull
protected abstract BlockPos getOrigin();
public abstract IBlockState getOriginalBlock();
public ItemStack getOriginalItem() {
IBlockState state = getOriginalBlock();
return new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state));
}
public BiConsumer<World, BlockPos> getOriginalBlockPlacer() {
return (w, p)->w.setBlockState(p, getOriginalBlock());
}
@Nullable
public <T extends TileEntityIWMultiblock> T master(T here) {
if (!isLogicDummy()) {
return here;
}
TileEntity m = world.getTileEntity(pos.subtract(offset));
if (m!=null&&m.getClass().equals(this.getClass())) {
return (T) m;
}
return null;
}
@Override
public boolean isLogicDummy() {
return offset.getX()!=0||offset.getY()!=0||offset.getZ()!=0;
}
@Nonnull
public <T extends TileEntityIWMultiblock> T masterOr(T here, @Nonnull T def) {
T master = master(here);
return master!=null?master:def;
}
public void disassemble() {
if (formed && !world.isRemote) {
BlockPos startPos = getOrigin();
BlockPos masterPos = getPos().subtract(offset);
long time = world.getTotalWorldTime();
Vec3i size = getSize();
for (int up = 0; up < size.getX(); up++) {
for (int forward = 0; forward < size.getY(); forward++) {
for (int right = 0; right < size.getZ(); right++) {
BlockPos pos = MiscUtils.offset(startPos, facing, mirrored, right, forward, up);
TileEntity te = world.getTileEntity(pos);
if (te instanceof TileEntityIWMultiblock) {
TileEntityIWMultiblock part = (TileEntityIWMultiblock) te;
Vec3i diff = pos.subtract(masterPos);
if (part.offset.equals(diff) && time != part.onlyLocalDissassembly) {
part.formed = false;
if (!pos.equals(this.pos)) {
part.getOriginalBlockPlacer().accept(world, pos);
} else if (part.getOriginalBlock()!=null) {
ItemStack drop = getOriginalItem();
world.spawnEntity(new EntityItem(world, pos.getX()+.5,pos.getY()+.5,pos.getZ()+.5, drop));
}
}
}
}
}
}
}
}
@Override
public void writeNBT(NBTTagCompound out, boolean updatePacket) {
out.setInteger(FACING, facing.getHorizontalIndex());
out.setIntArray(OFFSET, new int[]{offset.getX(), offset.getY(), offset.getZ()});
out.setBoolean(MIRRORED, mirrored);
out.setBoolean(FORMED, formed);
}
@Override
public void readNBT(NBTTagCompound in, boolean updatePacket) {
formed = in.getBoolean(FORMED);
mirrored = in.getBoolean(MIRRORED);
int[] offset = in.getIntArray(OFFSET);
this.offset = new Vec3i(offset[0], offset[1], offset[2]);
facing = EnumFacing.byHorizontalIndex(in.getInteger(FACING));
}
public Vec3i getSize() {
return size;
}
public int getRight() {
return dot(offset, facing.rotateY().getDirectionVec())*(mirrored?-1:1);
}
public int getForward() {
return dot(offset, facing.getDirectionVec());
}
protected int dot(Vec3i a, Vec3i b) {
return a.getX()*b.getX()+a.getY()*b.getY()+a.getZ()*b.getZ();
}
@Nonnull
@Override
public EnumFacing getFacing() {
return facing;
}
@Override
public void setFacing(@Nonnull EnumFacing facing) {
this.facing = facing;
}
@Override
public int getFacingLimitation() {
return 2;
}
@Override
public boolean mirrorFacingOnPlacement(@Nonnull EntityLivingBase placer) {
return false;
}
@Override
public boolean canHammerRotate(@Nonnull EnumFacing side, float hitX, float hitY, float hitZ, @Nonnull EntityLivingBase entity) {
return false;
}
@Override
public boolean canRotate(@Nonnull EnumFacing axis) {
return false;
}
}