mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
386 lines
11 KiB
Java
386 lines
11 KiB
Java
package com.hbm.blocks.machine;
|
|
|
|
import com.hbm.blocks.ModBlocks;
|
|
|
|
import java.util.Random;
|
|
|
|
import com.hbm.blocks.BlockEnums.LightType;
|
|
import com.hbm.blocks.ISpotlight;
|
|
import com.hbm.main.ResourceManager;
|
|
import com.hbm.world.gen.nbt.INBTBlockTransformable;
|
|
|
|
import cpw.mods.fml.client.registry.RenderingRegistry;
|
|
import cpw.mods.fml.relauncher.Side;
|
|
import cpw.mods.fml.relauncher.SideOnly;
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.block.BlockSlab;
|
|
import net.minecraft.block.material.MapColor;
|
|
import net.minecraft.block.material.Material;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.AxisAlignedBB;
|
|
import net.minecraft.world.IBlockAccess;
|
|
import net.minecraft.world.World;
|
|
import net.minecraftforge.client.model.obj.WavefrontObject;
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
|
|
|
public class Spotlight extends Block implements ISpotlight, INBTBlockTransformable {
|
|
|
|
public static final int META_YELLOW = 0;
|
|
public static final int META_GREEN = 1;
|
|
public static final int META_BLUE = 2;
|
|
|
|
public static boolean disableOnGeneration = true;
|
|
|
|
// I'd be extending the ReinforcedLamp class if it wasn't for the inverted behaviour of these specific lights
|
|
// I want these blocks to be eminently useful, so removing the need for redstone by default is desired,
|
|
// these act more like redstone torches, in that applying a signal turns them off
|
|
public boolean isOn;
|
|
|
|
public int beamLength;
|
|
public LightType type;
|
|
|
|
public Spotlight(Material mat, int beamLength, LightType type, boolean isOn) {
|
|
super(mat);
|
|
|
|
this.beamLength = beamLength;
|
|
this.type = type;
|
|
this.isOn = isOn;
|
|
|
|
this.setHardness(0.5F);
|
|
|
|
if(isOn) setLightLevel(1.0F);
|
|
}
|
|
|
|
public static int renderID = RenderingRegistry.getNextAvailableRenderId();
|
|
|
|
@Override
|
|
public int getRenderType() {
|
|
return renderID;
|
|
}
|
|
|
|
public WavefrontObject getModel() {
|
|
switch(type) {
|
|
case FLUORESCENT: return (WavefrontObject) ResourceManager.fluorescent_lamp;
|
|
case HALOGEN: return (WavefrontObject) ResourceManager.flood_lamp;
|
|
default: return (WavefrontObject) ResourceManager.cage_lamp;
|
|
}
|
|
}
|
|
|
|
public String getPartName(int connectionCount) {
|
|
switch(type) {
|
|
case HALOGEN: return "FloodLamp";
|
|
default: return "CageLamp";
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isOpaqueCube() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean renderAsNormalBlock() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
// Ah yes, I love methods named the literal opposite of what they do
|
|
public boolean getBlocksMovement(IBlockAccess world, int x, int y, int z) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public MapColor getMapColor(int meta) {
|
|
return MapColor.airColor;
|
|
}
|
|
|
|
@Override
|
|
public AxisAlignedBB getCollisionBoundingBoxFromPool(World p_149668_1_, int p_149668_2_, int p_149668_3_, int p_149668_4_) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) {
|
|
ForgeDirection dir = getDirection(world, x, y, z);
|
|
float[] bounds = swizzleBounds(dir);
|
|
float[] offset = new float[] { 0.5F - dir.offsetX * (0.5F - bounds[0]), 0.5F - dir.offsetY * (0.5F - bounds[1]), 0.5F - dir.offsetZ * (0.5F - bounds[2]) };
|
|
|
|
setBlockBounds(offset[0] - bounds[0], offset[1] - bounds[1], offset[2] - bounds[2], offset[0] + bounds[0], offset[1] + bounds[1], offset[2] + bounds[2]);
|
|
}
|
|
|
|
private float[] swizzleBounds(ForgeDirection dir) {
|
|
float[] bounds = getBounds();
|
|
switch(dir) {
|
|
case EAST:
|
|
case WEST: return new float[] { bounds[2], bounds[1], bounds[0] };
|
|
case UP:
|
|
case DOWN: return new float[] { bounds[1], bounds[2], bounds[0] };
|
|
default: return bounds;
|
|
}
|
|
}
|
|
|
|
// Returns an xyz (half-)size for a given object type
|
|
private float[] getBounds() {
|
|
switch(type) {
|
|
case FLUORESCENT: return new float[] { 0.5F, 0.5F, 0.1F };
|
|
case HALOGEN: return new float[] { 0.35F, 0.25F, 0.2F };
|
|
default: return new float[] { 0.25F, 0.2F, 0.15F };
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int onBlockPlaced(World world, int x, int y, int z, int side, float hx, float hy, float hz, int initData) {
|
|
return side << 1;
|
|
}
|
|
|
|
@Override
|
|
public void onBlockAdded(World world, int x, int y, int z) {
|
|
if(world.isRemote) return;
|
|
if(updatePower(world, x, y, z)) return;
|
|
updateBeam(world, x, y, z);
|
|
}
|
|
|
|
private boolean updatePower(World world, int x, int y, int z) {
|
|
if(isBroken(world.getBlockMetadata(x, y, z))) return false;
|
|
|
|
boolean isPowered = world.isBlockIndirectlyGettingPowered(x, y, z);
|
|
if(isOn && isPowered) {
|
|
world.scheduleBlockUpdate(x, y, z, this, 4);
|
|
return true;
|
|
} else if(!isOn && !isPowered) {
|
|
world.setBlock(x, y, z, getOn(), world.getBlockMetadata(x, y, z), 2);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void breakBlock(World world, int x, int y, int z, Block block, int metadata) {
|
|
ForgeDirection dir = getDirection(metadata);
|
|
super.breakBlock(world, x, y, z, block, metadata);
|
|
|
|
if(world.isRemote) return;
|
|
|
|
unpropagateBeam(world, x, y, z, dir);
|
|
}
|
|
|
|
@Override
|
|
public void updateTick(World world, int x, int y, int z, Random p_149674_5_) {
|
|
if (world.isRemote) return;
|
|
|
|
if (isOn && world.isBlockIndirectlyGettingPowered(x, y, z)) {
|
|
world.setBlock(x, y, z, getOff(), world.getBlockMetadata(x, y, z), 2);
|
|
}
|
|
}
|
|
|
|
// Repropagate the beam if we've become unblocked
|
|
@Override
|
|
public void onNeighborBlockChange(World world, int x, int y, int z, Block neighborBlock) {
|
|
if(world.isRemote) return;
|
|
if(neighborBlock instanceof SpotlightBeam) return;
|
|
if(neighborBlock == Blocks.air) return;
|
|
|
|
ForgeDirection dir = getDirection(world, x, y, z);
|
|
|
|
if(!canPlace(world, x, y, z, dir)) {
|
|
dropBlockAsItem(world, x, y, z, 0, 0);
|
|
world.setBlockToAir(x, y, z);
|
|
return;
|
|
}
|
|
|
|
if(updatePower(world, x, y, z)) return;
|
|
|
|
updateBeam(world, x, y, z);
|
|
}
|
|
|
|
@Override
|
|
public boolean canPlaceBlockOnSide(World world, int x, int y, int z, int side) {
|
|
if(!super.canPlaceBlockOnSide(world, x, y, z, side)) return false;
|
|
|
|
ForgeDirection dir = ForgeDirection.getOrientation(side);
|
|
|
|
return canPlace(world, x, y, z, dir);
|
|
}
|
|
|
|
// BlockSlab doesn't actually properly return isSideSolid,
|
|
// probably because MOJANK thought this would only ever be used for torches,
|
|
// which can't be placed on ceilings...
|
|
private boolean canPlace(World world, int x, int y, int z, ForgeDirection dir) {
|
|
x -= dir.offsetX;
|
|
y -= dir.offsetY;
|
|
z -= dir.offsetZ;
|
|
|
|
Block block = world.getBlock(x, y, z);
|
|
if(block instanceof BlockSlab) {
|
|
int meta = world.getBlockMetadata(x, y, z);
|
|
return dir == ((meta & 8) == 8 ? ForgeDirection.UP : ForgeDirection.DOWN) || block.func_149730_j();
|
|
}
|
|
|
|
return block.isSideSolid(world, x, y, z, dir);
|
|
}
|
|
|
|
private void updateBeam(World world, int x, int y, int z) {
|
|
if(!isOn) return;
|
|
|
|
ForgeDirection dir = getDirection(world, x, y, z);
|
|
propagateBeam(world, x, y, z, dir, beamLength, META_YELLOW);
|
|
}
|
|
|
|
public ForgeDirection getDirection(IBlockAccess world, int x, int y, int z) {
|
|
int metadata = world.getBlockMetadata(x, y, z);
|
|
return getDirection(metadata);
|
|
}
|
|
|
|
public ForgeDirection getDirection(int metadata) {
|
|
return ForgeDirection.getOrientation(metadata >> 1);
|
|
}
|
|
|
|
// Replace bulbs on broken lights with a click
|
|
@Override
|
|
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
|
|
int meta = world.getBlockMetadata(x, y, z);
|
|
if(!isBroken(meta)) return false;
|
|
|
|
repair(world, x, y, z);
|
|
return true;
|
|
}
|
|
|
|
private void repair(World world, int x, int y, int z) {
|
|
int meta = world.getBlockMetadata(x, y, z);
|
|
if(!isBroken(meta)) return;
|
|
|
|
world.setBlock(x, y, z, getOn(), meta - 1, 2);
|
|
|
|
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
|
|
int ox = x + dir.offsetX;
|
|
int oy = y + dir.offsetY;
|
|
int oz = z + dir.offsetZ;
|
|
Block block = world.getBlock(ox, oy, oz);
|
|
if(block == this) repair(world, ox, oy, oz);
|
|
}
|
|
}
|
|
|
|
public boolean isBroken(int metadata) {
|
|
return (metadata & 1) == 1;
|
|
}
|
|
|
|
@Override
|
|
public Item getItemDropped(int i, Random r, int j) {
|
|
return Item.getItemFromBlock(getOn());
|
|
}
|
|
|
|
@Override
|
|
@SideOnly(Side.CLIENT)
|
|
public Item getItem(World world, int x, int y, int z) {
|
|
return Item.getItemFromBlock(getOn());
|
|
}
|
|
|
|
@Override
|
|
protected ItemStack createStackedBlock(int e) {
|
|
return new ItemStack(getOn());
|
|
}
|
|
|
|
// Recursively add beam blocks, updating any that already exist with new incoming light directions
|
|
public static void propagateBeam(World world, int x, int y, int z, ForgeDirection dir, int distance, int meta) {
|
|
distance--;
|
|
if(distance <= 0)
|
|
return;
|
|
|
|
x += dir.offsetX;
|
|
y += dir.offsetY;
|
|
z += dir.offsetZ;
|
|
|
|
Block block = world.getBlock(x, y, z);
|
|
if(!block.isAir(world, x, y, z))
|
|
return;
|
|
|
|
if(!(block instanceof SpotlightBeam)) {
|
|
world.setBlock(x, y, z, ModBlocks.spotlight_beam, meta, 3);
|
|
}
|
|
|
|
// If we encounter an existing beam, add a new INCOMING direction to the
|
|
// metadata, and cancel propagation if something goes wrong
|
|
if (SpotlightBeam.setDirection(world, x, y, z, dir, true) == 0)
|
|
return;
|
|
|
|
propagateBeam(world, x, y, z, dir, distance, meta);
|
|
}
|
|
|
|
// Recursively delete beam blocks, if they aren't still illuminated from a different direction
|
|
public static void unpropagateBeam(World world, int x, int y, int z, ForgeDirection dir) {
|
|
x += dir.offsetX;
|
|
y += dir.offsetY;
|
|
z += dir.offsetZ;
|
|
|
|
Block block = world.getBlock(x, y, z);
|
|
if(!(block instanceof SpotlightBeam))
|
|
return;
|
|
|
|
// Remove the metadata associated with this direction
|
|
// If all directions are set to zero, delete the beam
|
|
if(SpotlightBeam.setDirection(world, x, y, z, dir, false) == 0) {
|
|
world.setBlockToAir(x, y, z);
|
|
}
|
|
|
|
unpropagateBeam(world, x, y, z, dir);
|
|
}
|
|
|
|
// Travels back through a beam to the source, and if found, repropagates the beam
|
|
public static void backPropagate(World world, int x, int y, int z, ForgeDirection dir, int meta) {
|
|
x -= dir.offsetX;
|
|
y -= dir.offsetY;
|
|
z -= dir.offsetZ;
|
|
|
|
Block block = world.getBlock(x, y, z);
|
|
if(block instanceof ISpotlight) {
|
|
ISpotlight spot = (ISpotlight) block;
|
|
propagateBeam(world, x, y, z, dir, spot.getBeamLength(), meta);
|
|
} else if(!(block instanceof SpotlightBeam)) {
|
|
return;
|
|
}
|
|
|
|
backPropagate(world, x, y, z, dir, meta);
|
|
}
|
|
|
|
protected Block getOff() {
|
|
if(this == ModBlocks.spotlight_incandescent) return ModBlocks.spotlight_incandescent_off;
|
|
if(this == ModBlocks.spotlight_fluoro) return ModBlocks.spotlight_fluoro_off;
|
|
if(this == ModBlocks.spotlight_halogen) return ModBlocks.spotlight_halogen_off;
|
|
|
|
return this;
|
|
}
|
|
|
|
protected Block getOn() {
|
|
if(this == ModBlocks.spotlight_incandescent_off) return ModBlocks.spotlight_incandescent;
|
|
if(this == ModBlocks.spotlight_fluoro_off) return ModBlocks.spotlight_fluoro;
|
|
if(this == ModBlocks.spotlight_halogen_off) return ModBlocks.spotlight_halogen;
|
|
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public int getBeamLength() {
|
|
return this.beamLength;
|
|
}
|
|
|
|
@Override
|
|
public int transformMeta(int meta, int coordBaseMode) {
|
|
// +1 to set as broken, won't turn on until broken and replaced
|
|
int disabled = disableOnGeneration ? 1 : 0;
|
|
return (INBTBlockTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + disabled;
|
|
}
|
|
|
|
@Override
|
|
public Block transformBlock(Block block) {
|
|
if(!disableOnGeneration) return block;
|
|
if(block == ModBlocks.spotlight_incandescent) return ModBlocks.spotlight_incandescent_off;
|
|
if(block == ModBlocks.spotlight_fluoro) return ModBlocks.spotlight_fluoro_off;
|
|
if(block == ModBlocks.spotlight_halogen) return ModBlocks.spotlight_halogen_off;
|
|
return block;
|
|
}
|
|
|
|
} |