Created
June 5, 2022 22:33
-
-
Save hohserg1/8ebd7de5e1e158636e81bbcaf7b8bccd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package hohserg.ie.exercises; | |
import blusunrize.immersiveengineering.api.TargetingInfo; | |
import blusunrize.immersiveengineering.api.energy.wires.IImmersiveConnectable; | |
import blusunrize.immersiveengineering.api.energy.wires.ImmersiveNetHandler; | |
import blusunrize.immersiveengineering.api.energy.wires.WireType; | |
import blusunrize.immersiveengineering.api.energy.wires.redstone.IRedstoneConnector; | |
import blusunrize.immersiveengineering.api.energy.wires.redstone.RedstoneWireNetwork; | |
import blusunrize.immersiveengineering.common.IEContent; | |
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces; | |
import blusunrize.immersiveengineering.common.items.ItemWireCoil; | |
import net.minecraft.block.Block; | |
import net.minecraft.block.material.Material; | |
import net.minecraft.block.properties.PropertyEnum; | |
import net.minecraft.block.state.BlockStateContainer; | |
import net.minecraft.block.state.IBlockState; | |
import net.minecraft.client.Minecraft; | |
import net.minecraft.creativetab.CreativeTabs; | |
import net.minecraft.entity.EntityLivingBase; | |
import net.minecraft.entity.player.EntityPlayer; | |
import net.minecraft.item.ItemStack; | |
import net.minecraft.nbt.NBTTagCompound; | |
import net.minecraft.network.NetworkManager; | |
import net.minecraft.network.play.server.SPacketUpdateTileEntity; | |
import net.minecraft.server.management.PlayerChunkMapEntry; | |
import net.minecraft.tileentity.TileEntity; | |
import net.minecraft.util.BlockRenderLayer; | |
import net.minecraft.util.EnumFacing; | |
import net.minecraft.util.EnumHand; | |
import net.minecraft.util.ITickable; | |
import net.minecraft.util.math.AxisAlignedBB; | |
import net.minecraft.util.math.BlockPos; | |
import net.minecraft.util.math.Vec3d; | |
import net.minecraft.util.math.Vec3i; | |
import net.minecraft.world.IBlockAccess; | |
import net.minecraft.world.World; | |
import net.minecraft.world.WorldServer; | |
import net.minecraftforge.fml.relauncher.Side; | |
import net.minecraftforge.fml.relauncher.SideOnly; | |
import javax.annotation.Nullable; | |
import static hohserg.ie.exercises.BlockTimer.TileTimer.State.countdown; | |
import static hohserg.ie.exercises.BlockTimer.TileTimer.State.pulse; | |
import static hohserg.ie.exercises.utils.MathUtils.clamp; | |
public class BlockTimer extends Block { | |
public static final PropertyEnum<EnumFacing> OUT = PropertyEnum.create("out", EnumFacing.class); | |
public BlockTimer() { | |
super(Material.IRON); | |
setRegistryName("timer"); | |
setUnlocalizedName("tfcs/timer"); | |
setCreativeTab(CreativeTabs.REDSTONE); | |
setLightOpacity(20); | |
} | |
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { | |
worldIn.setBlockState(pos, state.withProperty(OUT, EnumFacing.getDirectionFromEntityLiving(pos, placer).getOpposite()), 2); | |
} | |
@SideOnly(Side.CLIENT) | |
@Override | |
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { | |
if (worldIn.isRemote && !isRedWire(playerIn.getHeldItemMainhand()) && !isRedWire(playerIn.getHeldItemOffhand())) | |
Minecraft.getMinecraft().displayGuiScreen(new GuiTimer(pos)); | |
return true; | |
} | |
private static boolean isRedWire(ItemStack heldItem) { | |
return heldItem.getItem() == IEContent.itemWireCoil && | |
((ItemWireCoil) IEContent.itemWireCoil).getWireType(heldItem) == WireType.REDSTONE; | |
} | |
@Override | |
protected BlockStateContainer createBlockState() { | |
return new BlockStateContainer(this, OUT); | |
} | |
@Override | |
public int getMetaFromState(IBlockState state) { | |
return state.getValue(OUT).ordinal(); | |
} | |
@Override | |
public IBlockState getStateFromMeta(int meta) { | |
return getDefaultState().withProperty(OUT, EnumFacing.values()[meta]); | |
} | |
@Override | |
public boolean isFullBlock(IBlockState state) { | |
return false; | |
} | |
@Override | |
public boolean isOpaqueCube(IBlockState state) { | |
return false; | |
} | |
@Override | |
public boolean isTranslucent(IBlockState state) { | |
return true; | |
} | |
@Override | |
@SideOnly(Side.CLIENT) | |
public BlockRenderLayer getBlockLayer() { | |
return BlockRenderLayer.TRANSLUCENT; | |
} | |
@Override | |
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { | |
EnumFacing out = state.getValue(OUT); | |
double pixel = 1d / 16; | |
switch (out) { | |
case DOWN: | |
return new AxisAlignedBB(4 * pixel, 0.0D, 4 * pixel, 1.0D, 12 * pixel, 12 * pixel); | |
case UP: | |
return new AxisAlignedBB(4 * pixel, 0.0D, 4 * pixel, 1.0D, 12 * pixel, 12 * pixel); | |
case NORTH: | |
return new AxisAlignedBB(4 * pixel, 4 * pixel, 0.0D, 12 * pixel, 12 * pixel, 1.0D); | |
case SOUTH: | |
return new AxisAlignedBB(4 * pixel, 4 * pixel, 0.0D, 12 * pixel, 12 * pixel, 1.0D); | |
case WEST: | |
return new AxisAlignedBB(0.0D, 4 * pixel, 4 * pixel, 1.0D, 12 * pixel, 12 * pixel); | |
case EAST: | |
return new AxisAlignedBB(0.0D, 4 * pixel, 4 * pixel, 1.0D, 12 * pixel, 12 * pixel); | |
default: | |
return new AxisAlignedBB(0, 0, 0, 1, 1, 1); | |
} | |
} | |
public boolean canProvidePower(IBlockState state) { | |
return true; | |
} | |
public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { | |
if (blockState.getValue(OUT) == side.getOpposite()) { | |
TileEntity tileEntity = blockAccess.getTileEntity(pos); | |
if (tileEntity instanceof TileTimer) | |
if (((TileTimer) tileEntity).state == pulse) | |
return 15; | |
} | |
return 0; | |
} | |
@Override | |
public boolean hasTileEntity(IBlockState state) { | |
return true; | |
} | |
@Nullable | |
@Override | |
public TileEntity createTileEntity(World world, IBlockState state) { | |
return new TileTimer(); | |
} | |
public static class TileTimer extends TileEntity implements ITickable, IEBlockInterfaces.IRedstoneOutput, IRedstoneConnector { | |
private RedstoneWireNetwork network; | |
@Override | |
public void setNetwork(RedstoneWireNetwork redstoneWireNetwork) { | |
network = redstoneWireNetwork; | |
} | |
@Override | |
public RedstoneWireNetwork getNetwork() { | |
return network; | |
} | |
@Override | |
public void onChange() { | |
if (!this.isInvalid()) { | |
this.markDirty(); | |
IBlockState stateHere = this.world.getBlockState(this.pos); | |
this.world.notifyBlockUpdate(pos, stateHere, stateHere, 3); | |
this.world.notifyNeighborsOfStateChange(pos, BlockInit.timer, true); | |
} | |
} | |
@Override | |
public World getConnectorWorld() { | |
return world; | |
} | |
@Override | |
public void updateInput(byte[] signals) { | |
signals[0] = (byte) Math.max(state == pulse ? 15 : 0, signals[0]); | |
} | |
@Override | |
public boolean canConnect() { | |
return true; | |
} | |
@Override | |
public boolean canConnectCable(WireType cableType, TargetingInfo target, Vec3i offset) { | |
return cableType == WireType.REDSTONE; | |
} | |
@Override | |
public boolean isEnergyOutput() { | |
return false; | |
} | |
@Override | |
public int outputEnergy(int i, boolean b, int i1) { | |
return 0; | |
} | |
@Override | |
public BlockPos getConnectionMaster(@Nullable WireType wireType, TargetingInfo targetingInfo) { | |
return pos; | |
} | |
@Override | |
public WireType getCableLimiter(TargetingInfo targetingInfo) { | |
return WireType.REDSTONE; | |
} | |
@Override | |
public boolean allowEnergyToPass(ImmersiveNetHandler.Connection connection) { | |
return false; | |
} | |
@Override | |
public void removeCable(@Nullable ImmersiveNetHandler.Connection connection) { | |
} | |
public boolean moveConnectionTo(ImmersiveNetHandler.Connection c, BlockPos newEnd) { | |
return true; | |
} | |
@Override | |
public Vec3d getConnectionOffset(ImmersiveNetHandler.Connection connection) { | |
EnumFacing side = getDirection().getOpposite(); | |
double conRadius = connection.cableType.getRenderDiameter() / 2.0D; | |
return new Vec3d(0.5D - conRadius * (double) side.getFrontOffsetX(), 0.5D - conRadius * (double) side.getFrontOffsetY(), 0.5D - conRadius * (double) side.getFrontOffsetZ()); | |
} | |
private EnumFacing getDirection() { | |
return world.getBlockState(pos).getValue(OUT); | |
} | |
@Override | |
public int getStrongRSOutput(IBlockState iBlockState, EnumFacing enumFacing) { | |
return BlockInit.timer.getWeakPower(iBlockState, world, pos, enumFacing); | |
} | |
@Override | |
public boolean canConnectRedstone(IBlockState iBlockState, EnumFacing enumFacing) { | |
return true; | |
} | |
public void connectCable(WireType cableType, TargetingInfo target, IImmersiveConnectable other) { | |
RedstoneWireNetwork.updateConnectors(pos, world, network); | |
network.removeFromNetwork(null); | |
} | |
public enum State { | |
countdown, pulse | |
} | |
State state = countdown; | |
int ticks = 0; | |
public int getMaxTicks() { | |
return maxTicks; | |
} | |
public void setTicks(int maxTicks, int pulseTicks) { | |
this.maxTicks = clamp(10, maxTicks, 20 * 60 * 10); | |
this.pulseTicks = clamp(1, pulseTicks, this.maxTicks - 1); | |
ticks = 0; | |
state = countdown; | |
sendUpdates(); | |
} | |
public int getPulseTicks() { | |
return pulseTicks; | |
} | |
private int maxTicks = 20 * 5; | |
private int pulseTicks = 2; | |
@Override | |
public void update() { | |
if (isRunning()) { | |
ticks++; | |
if (state == countdown) { | |
if (ticks >= maxTicks - pulseTicks) { | |
state = pulse; | |
world.notifyNeighborsOfStateChange(pos, BlockInit.timer, true); | |
if (network != null) | |
network.updateValues(); | |
} | |
} else if (state == pulse) { | |
if (ticks >= maxTicks) { | |
ticks = 0; | |
state = countdown; | |
world.notifyNeighborsOfStateChange(pos, BlockInit.timer, true); | |
if (network != null) | |
network.updateValues(); | |
} | |
} | |
} else | |
ticks = 0; | |
} | |
public boolean isRunning() { | |
EnumFacing facing = getDirection().getOpposite(); | |
int vanillaPowered = world.isBlockIndirectlyGettingPowered(pos.offset(facing)); | |
int immersivePowered = network == null ? 0 : network.getPowerOutput(1); | |
return vanillaPowered == 0 && immersivePowered == 0; | |
} | |
@Override | |
public NBTTagCompound writeToNBT(NBTTagCompound compound) { | |
NBTTagCompound r = super.writeToNBT(compound); | |
r.setInteger("ticks", ticks); | |
r.setInteger("maxTicks", maxTicks); | |
r.setInteger("pulseTicks", pulseTicks); | |
return r; | |
} | |
@Override | |
public void readFromNBT(NBTTagCompound compound) { | |
super.readFromNBT(compound); | |
ticks = compound.getInteger("ticks"); | |
maxTicks = compound.getInteger("maxTicks"); | |
pulseTicks = compound.getInteger("pulseTicks"); | |
state = ticks >= maxTicks - pulseTicks ? pulse : countdown; | |
} | |
@Override | |
public NBTTagCompound getUpdateTag() { | |
return writeToNBT(new NBTTagCompound()); | |
} | |
@Nullable | |
@Override | |
public SPacketUpdateTileEntity getUpdatePacket() { | |
return new SPacketUpdateTileEntity(pos, 3, getUpdateTag()); | |
} | |
@Override | |
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { | |
readFromNBT(pkt.getNbtCompound()); | |
} | |
public void sendUpdates() { | |
if (world instanceof WorldServer) { | |
PlayerChunkMapEntry chunk = ((WorldServer) world).getPlayerChunkMap().getEntry(pos.getX() >> 4, pos.getZ() >> 4); | |
if (chunk != null) | |
chunk.sendPacket(getUpdatePacket()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment