Skip to content

Instantly share code, notes, and snippets.

@hohserg1
Created June 5, 2022 22:33
Show Gist options
  • Save hohserg1/8ebd7de5e1e158636e81bbcaf7b8bccd to your computer and use it in GitHub Desktop.
Save hohserg1/8ebd7de5e1e158636e81bbcaf7b8bccd to your computer and use it in GitHub Desktop.
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