use of micdoodle8.mods.galacticraft.api.vector.BlockVec3 in project Galacticraft by micdoodle8.
the class SpinManager method refresh.
/**
* This will check all blocks which are in contact with each other to find
* the shape of the spacestation. It also finds the centre of mass (to
* rotate around) and the moment of inertia (how easy/hard this is to
* rotate).
* <p/>
* If placingThruster is true, it will return false if the thruster (at
* baseBlock) is not in contact with the "existing" spacestation - so the
* player cannot place thrusters on outlying disconnected blocks and expect
* them to have an effect.
* <p/>
* Note: this check will briefly load, server-side, all chunks which have
* spacestation blocks in them or 1 block adjacent to those.
*
* @param baseBlock
* @return
*/
public boolean refresh(BlockPos baseBlock, boolean placingThruster) {
if (this.oneSSBlock == null || this.worldProvider.worldObj.getBlockState(this.oneSSBlock).getBlock().isAir(this.worldProvider.worldObj, this.oneSSBlock)) {
if (baseBlock != null) {
this.oneSSBlock = baseBlock;
} else {
this.oneSSBlock = new BlockPos(0, 64, 0);
}
}
// Find contiguous blocks using an algorithm like the oxygen sealer one
List<BlockVec3> currentLayer = new LinkedList<BlockVec3>();
List<BlockVec3> nextLayer = new LinkedList<BlockVec3>();
final List<BlockPos> foundThrusters = new LinkedList<BlockPos>();
this.checked.clear();
currentLayer.add(new BlockVec3(this.oneSSBlock));
this.checked.add(new BlockVec3(this.oneSSBlock));
Block bStart = this.worldProvider.worldObj.getBlockState(this.oneSSBlock).getBlock();
if (bStart instanceof BlockSpinThruster) {
foundThrusters.add(this.oneSSBlock);
}
// Mass of a thruster
float thismass = 0.1F;
float thismassCentreX = 0.1F * this.oneSSBlock.getX();
float thismassCentreY = 0.1F * this.oneSSBlock.getY();
float thismassCentreZ = 0.1F * this.oneSSBlock.getZ();
float thismoment = 0F;
int thisssBoundsMaxX = this.oneSSBlock.getX();
int thisssBoundsMinX = this.oneSSBlock.getX();
int thisssBoundsMaxY = this.oneSSBlock.getY();
int thisssBoundsMinY = this.oneSSBlock.getY();
int thisssBoundsMaxZ = this.oneSSBlock.getZ();
int thisssBoundsMinZ = this.oneSSBlock.getZ();
while (currentLayer.size() > 0) {
int bits;
for (BlockVec3 vec : currentLayer) {
bits = vec.sideDoneBits;
if (vec.x < thisssBoundsMinX) {
thisssBoundsMinX = vec.x;
}
if (vec.y < thisssBoundsMinY) {
thisssBoundsMinY = vec.y;
}
if (vec.z < thisssBoundsMinZ) {
thisssBoundsMinZ = vec.z;
}
if (vec.x > thisssBoundsMaxX) {
thisssBoundsMaxX = vec.x;
}
if (vec.y > thisssBoundsMaxY) {
thisssBoundsMaxY = vec.y;
}
if (vec.z > thisssBoundsMaxZ) {
thisssBoundsMaxZ = vec.z;
}
for (int side = 0; side < 6; side++) {
if ((bits & (1 << side)) == 1) {
continue;
}
BlockVec3 sideVec = vec.newVecSide(side);
if (sideVec != null && !this.checked.contains(sideVec)) {
this.checked.add(sideVec);
Block b = sideVec.getBlockID(this.worldProvider.worldObj);
if (b != null && !b.isAir(this.worldProvider.worldObj, sideVec.toBlockPos()) && !(b instanceof BlockDynamicLiquid)) {
nextLayer.add(sideVec);
if (bStart.isAir(this.worldProvider.worldObj, this.oneSSBlock)) {
this.oneSSBlock = sideVec.toBlockPos();
bStart = b;
}
float m = 1.0F;
// Liquids have a mass of 1, stone, metal blocks etc will be heavier
if (!(b instanceof BlockLiquid)) {
// For most blocks, hardness gives a good idea of mass
m = b.getBlockHardness(this.worldProvider.worldObj, sideVec.toBlockPos());
if (m < 0.1F) {
m = 0.1F;
} else if (m > 30F) {
m = 30F;
}
// Wood items have a high hardness compared with their presumed mass
if (b.getMaterial() == Material.wood) {
m /= 4;
}
// TODO: higher mass for future Galacticraft hi-density item like neutronium
// Maybe also check for things in other mods by name: lead, uranium blocks?
}
thismassCentreX += m * sideVec.x;
thismassCentreY += m * sideVec.y;
thismassCentreZ += m * sideVec.z;
thismass += m;
thismoment += m * (sideVec.x * sideVec.x + sideVec.z * sideVec.z);
if (b instanceof BlockSpinThruster && !RedstoneUtil.isBlockReceivingRedstone(this.worldProvider.worldObj, sideVec.toBlockPos())) {
foundThrusters.add(sideVec.toBlockPos());
}
}
}
}
}
currentLayer = nextLayer;
nextLayer = new LinkedList<BlockVec3>();
}
if (placingThruster && !this.checked.contains(new BlockVec3(baseBlock))) {
if (foundThrusters.size() > 0) {
// The thruster was not placed on the existing contiguous space station: it must be.
if (ConfigManagerCore.enableDebug) {
GCLog.info("Thruster placed on wrong part of space station: base at " + this.oneSSBlock + " - baseBlock was " + baseBlock + " - found " + foundThrusters.size());
}
return false;
}
// (This first check prevents an infinite loop)
if (!this.oneSSBlock.equals(baseBlock)) {
this.oneSSBlock = baseBlock;
if (this.worldProvider.worldObj.getBlockState(this.oneSSBlock).getBlock().getMaterial() != Material.air) {
return this.refresh(baseBlock, true);
}
}
return false;
}
// Update thruster lists based on what was found
this.thrustersPlus.clear();
this.thrustersMinus.clear();
for (BlockPos thruster : foundThrusters) {
IBlockState state = this.worldProvider.worldObj.getBlockState(thruster);
int facing = state.getBlock().getMetaFromState(state) & 8;
if (facing == 0) {
this.thrustersPlus.add(thruster);
} else {
this.thrustersMinus.add(thruster);
}
}
// Calculate centre of mass
float mass = thismass;
this.massCentreX = thismassCentreX / thismass + 0.5F;
float massCentreY = thismassCentreY / thismass + 0.5F;
this.massCentreZ = thismassCentreZ / thismass + 0.5F;
// System.out.println("(X,Z) = "+this.massCentreX+","+this.massCentreZ);
this.setSpinCentre(this.massCentreX, this.massCentreZ);
// The boundary is at the outer edges of the blocks
this.ssBoundsMaxX = thisssBoundsMaxX + 1;
this.ssBoundsMinX = thisssBoundsMinX;
this.ssBoundsMaxY = thisssBoundsMaxY + 1;
this.ssBoundsMinY = thisssBoundsMinY;
this.ssBoundsMaxZ = thisssBoundsMaxZ + 1;
this.ssBoundsMinZ = thisssBoundsMinZ;
// Calculate momentOfInertia
thismoment -= this.massCentreX * this.massCentreX * mass;
thismoment -= this.massCentreZ * this.massCentreZ * mass;
this.momentOfInertia = thismoment;
// TODO
// TODO defy gravity
// TODO break blocks which are outside SS (not in checked)
// TODO prevent spin if there is a huge number of blocks outside SS
GCLog.debug("MoI = " + this.momentOfInertia + " CoMx = " + this.massCentreX + " CoMz = " + this.massCentreZ);
// Send packets to clients in this dimension
List<Object> objList = new ArrayList<Object>();
objList.add(Double.valueOf(this.spinCentreX));
objList.add(Double.valueOf(this.spinCentreZ));
GalacticraftCore.packetPipeline.sendToDimension(new PacketSimple(PacketSimple.EnumSimplePacket.C_UPDATE_STATION_DATA, GCCoreUtil.getDimensionID(this.worldProvider), objList), GCCoreUtil.getDimensionID(this.worldProvider));
objList = new ArrayList<Object>();
objList.add(Integer.valueOf(this.ssBoundsMinX));
objList.add(Integer.valueOf(this.ssBoundsMaxX));
objList.add(Integer.valueOf(this.ssBoundsMinY));
objList.add(Integer.valueOf(this.ssBoundsMaxY));
objList.add(Integer.valueOf(this.ssBoundsMinZ));
objList.add(Integer.valueOf(this.ssBoundsMaxZ));
GalacticraftCore.packetPipeline.sendToDimension(new PacketSimple(PacketSimple.EnumSimplePacket.C_UPDATE_STATION_BOX, GCCoreUtil.getDimensionID(this.worldProvider), objList), GCCoreUtil.getDimensionID(this.worldProvider));
this.updateSpinSpeed();
return true;
}
use of micdoodle8.mods.galacticraft.api.vector.BlockVec3 in project Galacticraft by micdoodle8.
the class TickHandlerServer method onServerTick.
@SubscribeEvent
public void onServerTick(ServerTickEvent event) {
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
// Prevent issues when clients switch to LAN servers
if (server == null) {
return;
}
if (event.phase == Phase.START) {
if (timerHoustonCommand > 0) {
if (--timerHoustonCommand == 0) {
CommandGCHouston.reset();
}
}
for (ScheduledDimensionChange change : TickHandlerServer.scheduledDimensionChanges) {
try {
GCPlayerStats stats = GCPlayerStats.get(change.getPlayer());
final WorldProvider provider = WorldUtil.getProviderForNameServer(change.getDimensionName());
if (provider != null) {
final Integer dim = GCCoreUtil.getDimensionID(provider);
GCLog.info("Found matching world (" + dim.toString() + ") for name: " + change.getDimensionName());
if (change.getPlayer().worldObj instanceof WorldServer) {
final WorldServer world = (WorldServer) change.getPlayer().worldObj;
WorldUtil.transferEntityToDimension(change.getPlayer(), dim, world);
}
} else {
GCLog.severe("World not found when attempting to transfer entity to dimension: " + change.getDimensionName());
}
stats.setTeleportCooldown(10);
GalacticraftCore.packetPipeline.sendTo(new PacketSimple(EnumSimplePacket.C_CLOSE_GUI, GCCoreUtil.getDimensionID(change.getPlayer().worldObj), new Object[] {}), change.getPlayer());
} catch (Exception e) {
GCLog.severe("Error occurred when attempting to transfer entity to dimension: " + change.getDimensionName());
e.printStackTrace();
}
}
TickHandlerServer.scheduledDimensionChanges.clear();
if (MapUtil.calculatingMap.get()) {
MapUtil.BiomeMapNextTick_MultiThreaded();
} else if (!MapUtil.doneOverworldTexture) {
MapUtil.makeOverworldTexture();
}
if (TickHandlerServer.spaceRaceData == null) {
World world = server.worldServerForDimension(0);
TickHandlerServer.spaceRaceData = (WorldDataSpaceRaces) world.getMapStorage().loadData(WorldDataSpaceRaces.class, WorldDataSpaceRaces.saveDataID);
if (TickHandlerServer.spaceRaceData == null) {
TickHandlerServer.spaceRaceData = new WorldDataSpaceRaces(WorldDataSpaceRaces.saveDataID);
world.getMapStorage().setData(WorldDataSpaceRaces.saveDataID, TickHandlerServer.spaceRaceData);
}
}
SpaceRaceManager.tick();
TileEntityOxygenSealer.onServerTick();
if (TickHandlerServer.tickCount % 33 == 0) {
WorldServer[] worlds = server.worldServers;
for (int i = worlds.length - 1; i >= 0; i--) {
WorldServer world = worlds[i];
TileEntityPainter.onServerTick(world);
}
}
if (TickHandlerServer.tickCount % 100 == 0) {
WorldServer[] worlds = server.worldServers;
for (int i = 0; i < worlds.length; i++) {
WorldServer world = worlds[i];
ChunkProviderServer chunkProviderServer = world.theChunkProviderServer;
Map<Long, List<Footprint>> footprintMap = TickHandlerServer.serverFootprintMap.get(GCCoreUtil.getDimensionID(world));
if (footprintMap != null) {
boolean mapChanged = false;
if (chunkProviderServer != null) {
Iterator iterator = chunkProviderServer.loadedChunks.iterator();
while (iterator.hasNext()) {
Chunk chunk = (Chunk) iterator.next();
long chunkKey = ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition);
List<Footprint> footprints = footprintMap.get(chunkKey);
if (footprints != null) {
List<Footprint> toRemove = new ArrayList<Footprint>();
for (int j = 0; j < footprints.size(); j++) {
footprints.get(j).age += 100;
if (footprints.get(j).age >= Footprint.MAX_AGE) {
toRemove.add(footprints.get(j));
}
}
if (!toRemove.isEmpty()) {
footprints.removeAll(toRemove);
}
footprintMap.put(chunkKey, footprints);
mapChanged = true;
GalacticraftCore.packetPipeline.sendToDimension(new PacketSimple(EnumSimplePacket.C_UPDATE_FOOTPRINT_LIST, GCCoreUtil.getDimensionID(worlds[i]), new Object[] { chunkKey, footprints.toArray(new Footprint[footprints.size()]) }), GCCoreUtil.getDimensionID(worlds[i]));
}
}
}
if (mapChanged) {
TickHandlerServer.serverFootprintMap.put(GCCoreUtil.getDimensionID(world), footprintMap);
}
}
}
}
if (!footprintBlockChanges.isEmpty()) {
for (BlockVec3Dim targetPoint : footprintBlockChanges) {
WorldServer[] worlds = server.worldServers;
for (int i = 0; i < worlds.length; i++) {
WorldServer world = worlds[i];
if (GCCoreUtil.getDimensionID(world) == targetPoint.dim) {
long chunkKey = ChunkCoordIntPair.chunkXZ2Int((int) targetPoint.x >> 4, (int) targetPoint.z >> 4);
GalacticraftCore.packetPipeline.sendToAllAround(new PacketSimple(EnumSimplePacket.C_FOOTPRINTS_REMOVED, GCCoreUtil.getDimensionID(world), new Object[] { chunkKey, new BlockVec3(targetPoint.x, targetPoint.y, targetPoint.z) }), new NetworkRegistry.TargetPoint(targetPoint.dim, targetPoint.x, targetPoint.y, targetPoint.z, 50));
// Map<Long, List<Footprint>> footprintMap = TickHandlerServer.serverFootprintMap.get(world.provider.dimensionId);
//
// if (footprintMap != null && !footprintMap.isEmpty())
// {
// List<Footprint> footprints = footprintMap.get(chunkKey);
// if (footprints != null)
// GalacticraftCore.packetPipeline.sendToAllAround(new PacketSimple(EnumSimplePacket.C_UPDATE_FOOTPRINT_LIST, new Object[] { chunkKey, footprints.toArray(new Footprint[footprints.size()]) }), new NetworkRegistry.TargetPoint(targetPoint.dim, targetPoint.x, targetPoint.y, targetPoint.z, 50));
// }
}
}
}
footprintBlockChanges.clear();
}
if (tickCount % 20 == 0) {
if (!playersRequestingMapData.isEmpty()) {
File baseFolder = new File(DimensionManager.getCurrentSaveRootDirectory(), "galacticraft/overworldMap");
if (!baseFolder.exists() && !baseFolder.mkdirs()) {
GCLog.severe("Base folder(s) could not be created: " + baseFolder.getAbsolutePath());
} else {
ArrayList<EntityPlayerMP> copy = new ArrayList<EntityPlayerMP>(playersRequestingMapData);
BufferedImage reusable = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
for (EntityPlayerMP playerMP : copy) {
GCPlayerStats stats = GCPlayerStats.get(playerMP);
MapUtil.makeVanillaMap(playerMP.dimension, (int) Math.floor(stats.getCoordsTeleportedFromZ()) >> 4, (int) Math.floor(stats.getCoordsTeleportedFromZ()) >> 4, baseFolder, reusable);
}
playersRequestingMapData.removeAll(copy);
}
}
}
TickHandlerServer.tickCount++;
EnergyNetwork.tickCount++;
} else if (event.phase == Phase.END) {
for (FluidNetwork network : new ArrayList<>(fluidNetworks)) {
if (!network.pipes.isEmpty()) {
network.tickEnd();
} else {
fluidNetworks.remove(network);
}
}
int maxPasses = 10;
while (!TickHandlerServer.networkTicks.isEmpty()) {
LinkedList<EnergyNetwork> pass = new LinkedList<>();
pass.addAll(TickHandlerServer.networkTicks);
TickHandlerServer.networkTicks.clear();
for (EnergyNetwork grid : pass) {
grid.tickEnd();
}
if (--maxPasses <= 0) {
break;
}
}
maxPasses = 10;
while (!TickHandlerServer.oxygenTransmitterUpdates.isEmpty()) {
LinkedList<TileEntityFluidTransmitter> pass = new LinkedList<>();
pass.addAll(TickHandlerServer.oxygenTransmitterUpdates);
TickHandlerServer.oxygenTransmitterUpdates.clear();
for (TileEntityFluidTransmitter newTile : pass) {
if (!newTile.isInvalid()) {
newTile.refresh();
}
}
if (--maxPasses <= 0) {
break;
}
}
maxPasses = 10;
while (!TickHandlerServer.energyTransmitterUpdates.isEmpty()) {
LinkedList<TileBaseConductor> pass = new LinkedList<>();
pass.addAll(TickHandlerServer.energyTransmitterUpdates);
TickHandlerServer.energyTransmitterUpdates.clear();
for (TileBaseConductor newTile : pass) {
if (!newTile.isInvalid()) {
newTile.refresh();
}
}
if (--maxPasses <= 0) {
break;
}
}
}
}
use of micdoodle8.mods.galacticraft.api.vector.BlockVec3 in project Galacticraft by micdoodle8.
the class TickHandlerServer method onWorldTick.
@SubscribeEvent
public void onWorldTick(WorldTickEvent event) {
if (event.phase == Phase.START) {
final WorldServer world = (WorldServer) event.world;
CopyOnWriteArrayList<ScheduledBlockChange> changeList = TickHandlerServer.scheduledBlockChanges.get(GCCoreUtil.getDimensionID(world));
if (changeList != null && !changeList.isEmpty()) {
int blockCount = 0;
int blockCountMax = Math.max(this.MAX_BLOCKS_PER_TICK, changeList.size() / 4);
List<ScheduledBlockChange> newList = new ArrayList<ScheduledBlockChange>(Math.max(0, changeList.size() - blockCountMax));
for (ScheduledBlockChange change : changeList) {
if (++blockCount > blockCountMax) {
newList.add(change);
} else {
if (change != null) {
BlockPos changePosition = change.getChangePosition();
Block block = world.getBlockState(changePosition).getBlock();
// Only replace blocks of type BlockAir or fire - this is to prevent accidents where other mods have moved blocks
if (changePosition != null && (block instanceof BlockAir || block == Blocks.fire)) {
world.setBlockState(changePosition, change.getChangeID().getStateFromMeta(change.getChangeMeta()), change.getChangeUpdateFlag());
}
}
}
}
changeList.clear();
TickHandlerServer.scheduledBlockChanges.remove(GCCoreUtil.getDimensionID(world));
if (newList.size() > 0) {
TickHandlerServer.scheduledBlockChanges.put(GCCoreUtil.getDimensionID(world), new CopyOnWriteArrayList<ScheduledBlockChange>(newList));
}
}
CopyOnWriteArrayList<BlockVec3> torchList = TickHandlerServer.scheduledTorchUpdates.get(GCCoreUtil.getDimensionID(world));
if (torchList != null && !torchList.isEmpty()) {
for (BlockVec3 torch : torchList) {
if (torch != null) {
BlockPos pos = new BlockPos(torch.x, torch.y, torch.z);
Block b = world.getBlockState(pos).getBlock();
if (b instanceof BlockUnlitTorch) {
world.scheduleUpdate(pos, b, 2 + world.rand.nextInt(30));
}
}
}
torchList.clear();
TickHandlerServer.scheduledTorchUpdates.remove(GCCoreUtil.getDimensionID(world));
}
if (world.provider instanceof IOrbitDimension) {
try {
int dim = GCCoreUtil.getDimensionID(WorldUtil.getProviderForNameServer(((IOrbitDimension) world.provider).getPlanetToOrbit()));
int minY = ((IOrbitDimension) world.provider).getYCoordToTeleportToPlanet();
final Entity[] entityList = world.loadedEntityList.toArray(new Entity[world.loadedEntityList.size()]);
for (final Entity e : entityList) {
if (e.posY <= minY && e.worldObj == world) {
WorldUtil.transferEntityToDimension(e, dim, world, false, null);
}
}
} catch (Exception ex) {
}
}
int dimensionID = GCCoreUtil.getDimensionID(world);
if (worldsNeedingUpdate.contains(dimensionID)) {
worldsNeedingUpdate.remove(dimensionID);
for (Object obj : event.world.loadedTileEntityList) {
TileEntity tile = (TileEntity) obj;
if (tile instanceof TileEntityFluidTank) {
((TileEntityFluidTank) tile).updateClient = true;
}
}
}
} else if (event.phase == Phase.END) {
final WorldServer world = (WorldServer) event.world;
for (GalacticraftPacketHandler handler : packetHandlers) {
handler.tick(world);
}
int dimID = GCCoreUtil.getDimensionID(world);
Set<BlockPos> edgesList = TickHandlerServer.edgeChecks.get(dimID);
final HashSet<BlockPos> checkedThisTick = new HashSet<>();
if (edgesList != null && !edgesList.isEmpty()) {
List<BlockPos> edgesListCopy = new ArrayList<>();
edgesListCopy.addAll(edgesList);
for (BlockPos edgeBlock : edgesListCopy) {
if (edgeBlock != null && !checkedThisTick.contains(edgeBlock)) {
if (TickHandlerServer.scheduledForChange(dimID, edgeBlock)) {
continue;
}
ThreadFindSeal done = new ThreadFindSeal(world, edgeBlock, 0, new ArrayList<TileEntityOxygenSealer>());
checkedThisTick.addAll(done.checkedAll());
}
}
TickHandlerServer.edgeChecks.remove(GCCoreUtil.getDimensionID(world));
}
}
}
use of micdoodle8.mods.galacticraft.api.vector.BlockVec3 in project Galacticraft by micdoodle8.
the class TileEntityAluminumWireSwitch method refresh.
@Override
public void refresh() {
boolean newDisableConnections = this.disableConnections();
if (newDisableConnections && !this.disableConnections) {
this.disableConnections = newDisableConnections;
if (!this.worldObj.isRemote) {
this.disConnect();
}
} else if (!newDisableConnections && this.disableConnections) {
this.disableConnections = newDisableConnections;
if (!this.worldObj.isRemote) {
// Force a full network refresh of this and conductors either side
this.setNetwork(null);
}
}
if (!this.worldObj.isRemote) {
this.adjacentConnections = null;
if (!this.disableConnections) {
this.getNetwork().refresh();
BlockVec3 thisVec = new BlockVec3(this);
for (EnumFacing side : EnumFacing.VALUES) {
if (this.canConnect(side, NetworkType.POWER)) {
TileEntity tileEntity = thisVec.getTileEntityOnSide(this.worldObj, side);
if (tileEntity instanceof TileBaseConductor && ((TileBaseConductor) tileEntity).canConnect(side.getOpposite(), NetworkType.POWER)) {
IGridNetwork otherNet = ((INetworkProvider) tileEntity).getNetwork();
if (!this.getNetwork().equals(otherNet)) {
if (!otherNet.getTransmitters().isEmpty()) {
otherNet.merge(this.getNetwork());
}
}
}
}
}
}
}
}
use of micdoodle8.mods.galacticraft.api.vector.BlockVec3 in project Galacticraft by micdoodle8.
the class TileEntityArclamp method lightArea.
public void lightArea() {
if (this.usingBuckets.getAndSet(true) || this.usingLightList.getAndSet(true)) {
return;
}
// long time1 = System.nanoTime();
int index = 0;
Block air = Blocks.air;
Block breatheableAirID = GCBlocks.breatheableAir;
IBlockState brightAir = GCBlocks.brightAir.getDefaultState();
IBlockState brightBreatheableAir = GCBlocks.brightBreatheableAir.getDefaultState();
boolean dirty = false;
checkedClear();
HashSet<BlockVec3> airToRevert = new HashSet<>();
airToRevert.addAll(airToRestore);
LinkedList<BlockVec3> airNew = new LinkedList<>();
LinkedList<BlockVec3> currentLayer = new LinkedList<>();
LinkedList<BlockVec3> nextLayer = new LinkedList<>();
BlockVec3 thisvec = new BlockVec3(this);
currentLayer.add(thisvec);
World world = this.worldObj;
int sideskip1 = this.sideRear;
int sideskip2 = this.facingSide ^ 1;
int side, bits;
for (int i = 0; i < 6; i++) {
if (i != sideskip1 && i != sideskip2 && i != (sideskip1 ^ 1) && i != (sideskip2 ^ 1)) {
BlockVec3 onEitherSide = thisvec.newVecSide(i);
Block b = onEitherSide.getBlockIDsafe_noChunkLoad(world);
if (b != null && b.getLightOpacity() < 15) {
currentLayer.add(onEitherSide);
}
}
}
BlockVec3 inFront = new BlockVec3(this);
for (int i = 0; i < 4; i++) {
inFront = inFront.newVecSide(this.facingSide);
Block b = inFront.getBlockIDsafe_noChunkLoad(world);
if (b == null || b.getLightOpacity() == 15) {
break;
}
inFront = inFront.newVecSide(sideskip1 ^ 1);
b = inFront.getBlockIDsafe_noChunkLoad(world);
if (b != null && b.getLightOpacity() < 15) {
currentLayer.add(inFront);
} else {
break;
}
}
inFront = new BlockVec3(this).newVecSide(this.facingSide);
for (int count = 0; count < LIGHTRANGE; count++) {
for (BlockVec3 vec : currentLayer) {
// Shape the arc lamp lighted area to more of a cone in front of it
if (count > 1) {
int offset = 0;
switch(this.facingSide) {
case 0:
offset = inFront.y - vec.y;
break;
case 1:
offset = vec.y - inFront.y;
break;
case 2:
offset = inFront.z - vec.z;
break;
case 3:
offset = vec.z - inFront.z;
break;
case 4:
offset = inFront.x - vec.x;
break;
case 5:
offset = vec.x - inFront.x;
break;
}
int offset2 = 0;
switch(this.sideRear ^ 1) {
case 0:
offset2 = inFront.y - vec.y;
break;
case 1:
offset2 = vec.y - inFront.y;
break;
case 2:
offset2 = inFront.z - vec.z;
break;
case 3:
offset2 = vec.z - inFront.z;
break;
case 4:
offset2 = inFront.x - vec.x;
break;
case 5:
offset2 = vec.x - inFront.x;
break;
}
if (offset2 - 2 > offset)
offset = offset2 - 2;
if (Math.abs(vec.x - inFront.x) > offset + 2)
continue;
if (Math.abs(vec.y - inFront.y) > offset + 2)
continue;
if (Math.abs(vec.z - inFront.z) > offset + 2)
continue;
}
// Now process each layer outwards from the source, finding new blocks to light (similar to ThreadFindSeal)
// This is high performance code using our own custom HashSet (that's intBucket)
side = 0;
bits = vec.sideDoneBits;
boolean doShine = false;
do {
// and never go 'backwards'
if ((bits & (1 << side)) == 0) {
BlockVec3 sideVec = vec.newVecSide(side);
boolean toAdd = false;
if (!checkedContains(vec, side)) {
checkedAdd(sideVec);
toAdd = true;
}
Block b = sideVec.getBlockIDsafe_noChunkLoad(world);
if (b instanceof BlockAir) {
if (toAdd && side != sideskip1 && side != sideskip2) {
nextLayer.add(sideVec);
}
} else {
doShine = true;
// Glass blocks go through to the next layer as well
if (side != sideskip1 && side != sideskip2) {
if (toAdd && b != null && b.getLightOpacity(world, sideVec.toBlockPos()) == 0) {
nextLayer.add(sideVec);
}
}
}
}
side++;
} while (side < 6);
if (doShine) {
airNew.add(vec);
Block id = vec.getBlockIDsafe_noChunkLoad(world);
if (Blocks.air == id) {
this.brightenAir(world, vec, brightAir);
index = this.checkLightPartA(EnumSkyBlock.BLOCK, vec.toBlockPos(), index);
dirty = true;
} else if (id == breatheableAirID) {
this.brightenAir(world, vec, brightBreatheableAir);
index = this.checkLightPartA(EnumSkyBlock.BLOCK, vec.toBlockPos(), index);
dirty = true;
}
}
}
if (nextLayer.size() == 0) {
break;
}
currentLayer = nextLayer;
nextLayer = new LinkedList<BlockVec3>();
}
if (dirty) {
this.markDirty();
this.checkLightPartB(EnumSkyBlock.BLOCK, index);
}
// Look for any holdover bright blocks which are no longer lit (e.g. because the Arc Lamp became blocked in a tunnel)
airToRevert.removeAll(airNew);
index = 0;
dirty = false;
for (Object obj : airToRevert) {
BlockVec3 vec = (BlockVec3) obj;
this.setDarkerAir(vec);
index = this.checkLightPartA(EnumSkyBlock.BLOCK, vec.toBlockPos(), index);
this.airToRestore.remove(vec);
dirty = true;
}
if (dirty) {
this.markDirty();
this.checkLightPartB(EnumSkyBlock.BLOCK, index);
}
// long time3 = System.nanoTime();
// float total = (time3 - time1) / 1000000.0F;
// GCLog.info(" Total Time taken: " + String.format("%.2f", total) + "ms");
this.usingBuckets.set(false);
this.usingLightList.set(false);
}
Aggregations