Improved cloaking usability

- coil linking is visible before finishing the setup
- central prism is slightly larger
- LUA API gives explicit missing coils
Reduced lag induced from poorly written LUA scripts
Removed concurrent access to the world
Fixed an edge case where some areas wouldn't refresh after uncloaking
This commit is contained in:
LemADEC 2017-05-30 20:55:51 +02:00
parent 417c43489b
commit 3dbbf302a6
9 changed files with 288 additions and 217 deletions

View file

@ -9,6 +9,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.IIcon; import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
@ -16,6 +17,14 @@ import net.minecraftforge.common.util.ForgeDirection;
public class BlockCloakingCoil extends Block { public class BlockCloakingCoil extends Block {
// Metadata values
// 0 = not linked
// 1 = inner coil passive
// 2-7 = outer coil passive
// 8 = (not used)
// 9 = inner coil active
// 10-15 = outer coil active
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
private IIcon[] iconBuffer; private IIcon[] iconBuffer;
@ -27,53 +36,25 @@ public class BlockCloakingCoil extends Block {
setBlockName("warpdrive.detection.CloakingCoil"); setBlockName("warpdrive.detection.CloakingCoil");
} }
static final boolean oldTextures = true;
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@Override @Override
public void registerBlockIcons(IIconRegister iconRegister) { public void registerBlockIcons(IIconRegister iconRegister) {
iconBuffer = new IIcon[4]; iconBuffer = new IIcon[4];
if (oldTextures) { iconBuffer[0] = iconRegister.registerIcon("warpdrive:detection/cloaking_coil-channeling_inactive");
iconBuffer[0] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilSide"); iconBuffer[1] = iconRegister.registerIcon("warpdrive:detection/cloaking_coil-projecting_inactive");
iconBuffer[1] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilSideActive"); iconBuffer[2] = iconRegister.registerIcon("warpdrive:detection/cloaking_coil-channeling_active");
iconBuffer[2] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilTop"); iconBuffer[3] = iconRegister.registerIcon("warpdrive:detection/cloaking_coil-projecting_active");
} else {
iconBuffer[0] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilInPassive");
iconBuffer[1] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilOutPassive");
iconBuffer[2] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilInActive");
iconBuffer[3] = iconRegister.registerIcon("warpdrive:detection/cloakingCoilOutActive");
}
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@Override @Override
public IIcon getIcon(int side, int metadata) { public IIcon getIcon(final IBlockAccess blockAccess, final int x, final int y, final int z, final int side) {
// Metadata values final int metadata = blockAccess.getBlockMetadata(x, y, z);
// 0 = not linked
// 1 = inner coil passive
// 2-7 = outer coil passive
// 8 = (not used)
// 9 = inner coil active
// 10-15 = outer coil active
if (oldTextures) {
if (side == 0) {
return iconBuffer[2];
} else if (side == 1) {
return iconBuffer[2];
}
if (metadata < 8) {
return iconBuffer[0];
} else {
return iconBuffer[1];
}
} else {
// not linked or in inventory // not linked or in inventory
if (metadata == 0) { if (metadata == 0) {
if (side == 2) {
return iconBuffer[0];
} else {
return iconBuffer[1]; return iconBuffer[1];
} }
}
// inner coils // inner coils
if (metadata == 1) { if (metadata == 1) {
@ -83,29 +64,27 @@ public class BlockCloakingCoil extends Block {
} }
// outer coils // outer coils
int direction = (metadata & 7) - 2; final int direction = (metadata & 7) - 2;
int activeOffset = (metadata < 8) ? 0 : 2; final int activeOffset = (metadata < 8) ? 0 : 2;
if (ForgeDirection.OPPOSITES[direction] == side) { if (ForgeDirection.OPPOSITES[direction] == side) {
return iconBuffer[0 + activeOffset]; return iconBuffer[ activeOffset];
} else { } else {
return iconBuffer[1 + activeOffset]; return iconBuffer[1 + activeOffset];
} }
} }
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon(final int side, final int metadata) {
if (side == 3) {
return iconBuffer[0];
} else {
return iconBuffer[1];
}
} }
/**
* Returns the quantity of items to drop on block destruction.
*/
@Override @Override
public int quantityDropped(Random par1Random) { public int quantityDropped(final Random random) {
return 1; return 1;
} }
/**
* Returns the ID of the items to drop on destruction.
*/
@Override
public Item getItemDropped(int par1, Random par2Random, int par3) {
return Item.getItemFromBlock(this);
}
} }

View file

@ -97,14 +97,14 @@ public class BlockCloakingCore extends BlockAbstractContainer {
} }
@Override @Override
public void breakBlock(World par1World, int par2, int par3, int par4, Block par5, int par6) { public void breakBlock(final World world, final int x, final int y, final int z, final Block block, final int metadata) {
TileEntity te = par1World.getTileEntity(par2, par3, par4); final TileEntity tileEntity = world.getTileEntity(x, y, z);
if (te != null && te instanceof TileEntityCloakingCore) { if (tileEntity != null && tileEntity instanceof TileEntityCloakingCore) {
((TileEntityCloakingCore)te).isEnabled = false; ((TileEntityCloakingCore) tileEntity).isEnabled = false;
((TileEntityCloakingCore)te).disableCloakingField(); ((TileEntityCloakingCore) tileEntity).disableCloakingField();
} }
super.breakBlock(par1World, par2, par3, par4, par5, par6); super.breakBlock(world, x, y, z, block, metadata);
} }
} }

View file

@ -26,6 +26,9 @@ import net.minecraftforge.common.util.ForgeDirection;
public class TileEntityCloakingCore extends TileEntityAbstractEnergy { public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
private static final int CLOAKING_CORE_SOUND_UPDATE_TICKS = 40; private static final int CLOAKING_CORE_SOUND_UPDATE_TICKS = 40;
private static final int DISTANCE_INNER_COILS_BLOCKS = 2;
private static final int LASER_REFRESH_TICKS = 100;
private static final int LASER_DURATION_TICKS = 110;
public boolean isEnabled = false; public boolean isEnabled = false;
public byte tier = 1; // cloaking field tier, 1 or 2 public byte tier = 1; // cloaking field tier, 1 or 2
@ -36,18 +39,20 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
final float[] innerCoilColor_b = { 0.25f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.50f, 1.00f, 1.00f, 1.00f, 1.00f, 0.75f }; final float[] innerCoilColor_b = { 0.25f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.50f, 1.00f, 1.00f, 1.00f, 1.00f, 0.75f };
// Spatial cloaking field parameters // Spatial cloaking field parameters
private static final int innerCoilsDistance = 2; // Step length from core block to main coils private final boolean[] isValidInnerCoils = { false, false, false, false, false, false };
private final int[] outerCoilsDistance = {0, 0, 0, 0, 0, 0}; private final int[] distanceOuterCoils_blocks = { 0, 0, 0, 0, 0, 0 }; // 0 means invalid
public int minX = 0; private int minX = 0;
public int minY = 0; private int minY = 0;
public int minZ = 0; private int minZ = 0;
public int maxX = 0; private int maxX = 0;
public int maxY = 0; private int maxY = 0;
public int maxZ = 0; private int maxZ = 0;
public boolean isValid = false; private boolean isValid = false;
public boolean isCloaking = false; private String messageValidityIssues = "";
public int volume = 0; private boolean isCloaking = false;
private int volume = 0;
private int energyRequired = 0;
private int updateTicks = 0; private int updateTicks = 0;
private int laserDrawingTicks = 0; private int laserDrawingTicks = 0;
@ -80,6 +85,8 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
soundPlayed = false; soundPlayed = false;
} }
boolean isRefreshNeeded = false;
updateTicks--; updateTicks--;
if (updateTicks <= 0) { if (updateTicks <= 0) {
if (WarpDriveConfig.LOGGING_CLOAKING) { if (WarpDriveConfig.LOGGING_CLOAKING) {
@ -87,7 +94,8 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
} }
updateTicks = ((tier == 1) ? 20 : (tier == 2) ? 10 : 20) * WarpDriveConfig.CLOAKING_FIELD_REFRESH_INTERVAL_SECONDS; // resetting timer updateTicks = ((tier == 1) ? 20 : (tier == 2) ? 10 : 20) * WarpDriveConfig.CLOAKING_FIELD_REFRESH_INTERVAL_SECONDS; // resetting timer
isValid = validateAssembly(); isRefreshNeeded = validateAssembly();
isCloaking = WarpDrive.cloaks.isAreaExists(worldObj, xCoord, yCoord, zCoord); isCloaking = WarpDrive.cloaks.isAreaExists(worldObj, xCoord, yCoord, zCoord);
if (!isEnabled) {// disabled if (!isEnabled) {// disabled
if (isCloaking) {// disabled, cloaking => stop cloaking if (isCloaking) {// disabled, cloaking => stop cloaking
@ -95,14 +103,21 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
WarpDrive.logger.info(this + " Disabled, cloak field going down..."); WarpDrive.logger.info(this + " Disabled, cloak field going down...");
} }
disableCloakingField(); disableCloakingField();
} else {// disabled, no cloaking isRefreshNeeded = true;
} else {// disabled, not cloaking
// IDLE // IDLE
if (isRefreshNeeded) {
setCoilsState(false);
} }
}
} else {// isEnabled } else {// isEnabled
boolean hasEnoughPower = countBlocksAndConsumeEnergy(); updateVolumeAndEnergyRequired();
final boolean hasEnoughPower = energy_consume(energyRequired, false);
if (!isCloaking) {// enabled, not cloaking if (!isCloaking) {// enabled, not cloaking
if (hasEnoughPower && isValid) {// enabled, can cloak and able to if (hasEnoughPower && isValid) {// enabled, can cloak and able to
setCoilsState(true); setCoilsState(true);
isRefreshNeeded = true;
// Register cloak // Register cloak
WarpDrive.cloaks.updateCloakedArea(worldObj, WarpDrive.cloaks.updateCloakedArea(worldObj,
@ -122,16 +137,21 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
WarpDrive.logger.info("getCloakedArea1 returned null for " + worldObj + " " + xCoord + "," + yCoord + "," + zCoord); WarpDrive.logger.info("getCloakedArea1 returned null for " + worldObj + " " + xCoord + "," + yCoord + "," + zCoord);
} }
} }
} else {// enabled, not cloaking but not able to
} else {// enabled, not cloaking and not able to
// IDLE // IDLE
setCoilsState(false);
} }
} else {// enabled & cloaked
} else {// enabled & cloaking
if (!isValid) {// enabled, cloaking but invalid if (!isValid) {// enabled, cloaking but invalid
if (WarpDriveConfig.LOGGING_CLOAKING) { if (WarpDriveConfig.LOGGING_CLOAKING) {
WarpDrive.logger.info(this + " Coil(s) lost, cloak field is collapsing..."); WarpDrive.logger.info(this + " Coil(s) lost, cloak field is collapsing...");
} }
energy_consume(energy_getEnergyStored()); energy_consume(energy_getEnergyStored());
disableCloakingField(); disableCloakingField();
isRefreshNeeded = true;
} else {// enabled, cloaking and valid } else {// enabled, cloaking and valid
if (hasEnoughPower) {// enabled, cloaking and able to if (hasEnoughPower) {// enabled, cloaking and able to
// IDLE // IDLE
@ -145,19 +165,22 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
} }
} }
setCoilsState(true); setCoilsState(true);
} else {// loosing power } else {// loosing power
if (WarpDriveConfig.LOGGING_CLOAKING) { if (WarpDriveConfig.LOGGING_CLOAKING) {
WarpDrive.logger.info(this + " Low power, cloak field is collapsing..."); WarpDrive.logger.info(this + " Low power, cloak field is collapsing...");
} }
disableCloakingField(); disableCloakingField();
isRefreshNeeded = true;
} }
} }
} }
} }
} }
if (laserDrawingTicks++ > 100) { laserDrawingTicks--;
laserDrawingTicks = 0; if (isRefreshNeeded || laserDrawingTicks < 0) {
laserDrawingTicks = LASER_REFRESH_TICKS;
if (isEnabled && isValid) { if (isEnabled && isValid) {
drawLasers(); drawLasers();
@ -169,20 +192,29 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, (enabled) ? 1 : 0, 2); worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, (enabled) ? 1 : 0, 2);
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
setCoilState(innerCoilsDistance, direction, enabled); if (isValidInnerCoils[direction.ordinal()]) {
setCoilState(outerCoilsDistance[direction.ordinal()], direction, enabled); setCoilState(DISTANCE_INNER_COILS_BLOCKS, direction, enabled);
}
if (distanceOuterCoils_blocks[direction.ordinal()] > 0) {
setCoilState(distanceOuterCoils_blocks[direction.ordinal()], direction, enabled);
}
} }
} }
private void setCoilState(final int distance, final ForgeDirection direction, final boolean enabled) { private void setCoilState(final int distance, final ForgeDirection direction, final boolean enabled) {
int x = xCoord + distance * direction.offsetX; final int x = xCoord + distance * direction.offsetX;
int y = yCoord + distance * direction.offsetY; final int y = yCoord + distance * direction.offsetY;
int z = zCoord + distance * direction.offsetZ; final int z = zCoord + distance * direction.offsetZ;
if (worldObj.getBlock(x, y, z).isAssociatedBlock(WarpDrive.blockCloakingCoil)) { if (worldObj.getBlock(x, y, z).isAssociatedBlock(WarpDrive.blockCloakingCoil)) {
if (distance == innerCoilsDistance) { final int metadata_current = worldObj.getBlockMetadata(x, y, z);
worldObj.setBlockMetadataWithNotify(x, y, z, ((enabled) ? 9 : 1), 2); final int metadata_new;
if (distance == DISTANCE_INNER_COILS_BLOCKS) {
metadata_new = (enabled ? 9 : 1);
} else { } else {
worldObj.setBlockMetadataWithNotify(x, y, z, ((enabled) ? 10 : 2) + direction.ordinal(), 2); metadata_new = (enabled ? 10 : 2) + direction.ordinal();
}
if (metadata_current != metadata_new) {
worldObj.setBlockMetadataWithNotify(x, y, z, metadata_new, 2);
} }
} }
} }
@ -196,9 +228,9 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
g = 0.50f; g = 0.50f;
b = 0.50f; b = 0.50f;
} else if (tier == 1) { } else if (tier == 1) {
r = 0.25f; r = 0.00f;
g = 1.00f; g = 1.00f;
b = 0.00f; b = 0.25f;
} else if (tier == 2) { } else if (tier == 2) {
r = 0.00f; r = 0.00f;
g = 0.25f; g = 0.25f;
@ -207,24 +239,27 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
// Directions to check (all six directions: left, right, up, down, front, back) // Directions to check (all six directions: left, right, up, down, front, back)
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
if ( isValidInnerCoils[direction.ordinal()]
&& distanceOuterCoils_blocks[direction.ordinal()] > 0) {
PacketHandler.sendBeamPacketToPlayersInArea(worldObj, PacketHandler.sendBeamPacketToPlayersInArea(worldObj,
new Vector3( new Vector3(
xCoord + innerCoilsDistance * direction.offsetX, xCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * direction.offsetX,
yCoord + innerCoilsDistance * direction.offsetY, yCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * direction.offsetY,
zCoord + innerCoilsDistance * direction.offsetZ).translate(0.5), zCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * direction.offsetZ),
new Vector3( new Vector3(
xCoord + outerCoilsDistance[direction.ordinal()] * direction.offsetX, xCoord + 0.5D + distanceOuterCoils_blocks[direction.ordinal()] * direction.offsetX,
yCoord + outerCoilsDistance[direction.ordinal()] * direction.offsetY, yCoord + 0.5D + distanceOuterCoils_blocks[direction.ordinal()] * direction.offsetY,
zCoord + outerCoilsDistance[direction.ordinal()] * direction.offsetZ).translate(0.5), zCoord + 0.5D + distanceOuterCoils_blocks[direction.ordinal()] * direction.offsetZ),
r, g, b, 110, 0, r, g, b, LASER_DURATION_TICKS, 0,
AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ)); AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ));
} }
}
// draw connecting coils // draw connecting coils
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
ForgeDirection start = ForgeDirection.VALID_DIRECTIONS[i]; final ForgeDirection start = ForgeDirection.VALID_DIRECTIONS[i];
for (int j = i + 1; j < 6; j++) { for (int j = i + 1; j < 6; j++) {
ForgeDirection stop = ForgeDirection.VALID_DIRECTIONS[j]; final ForgeDirection stop = ForgeDirection.VALID_DIRECTIONS[j];
// skip mirrored coils (removing the inner lines) // skip mirrored coils (removing the inner lines)
if (start.getOpposite() == stop) { if (start.getOpposite() == stop) {
continue; continue;
@ -237,9 +272,15 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
b = innerCoilColor_b[mapIndex]; b = innerCoilColor_b[mapIndex];
PacketHandler.sendBeamPacketToPlayersInArea(worldObj, PacketHandler.sendBeamPacketToPlayersInArea(worldObj,
new Vector3(xCoord + innerCoilsDistance * start.offsetX, yCoord + innerCoilsDistance * start.offsetY, zCoord + innerCoilsDistance * start.offsetZ).translate(0.5), new Vector3(
new Vector3(xCoord + innerCoilsDistance * stop .offsetX, yCoord + innerCoilsDistance * stop .offsetY, zCoord + innerCoilsDistance * stop .offsetZ).translate(0.5), xCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * start.offsetX + 0.2D * stop .offsetX,
r, g, b, 110, 0, yCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * start.offsetY + 0.2D * stop .offsetY,
zCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * start.offsetZ + 0.2D * stop .offsetZ),
new Vector3(
xCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * stop .offsetX + 0.2D * start.offsetX,
yCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * stop .offsetY + 0.2D * start.offsetY,
zCoord + 0.5D + (DISTANCE_INNER_COILS_BLOCKS + 0.3D) * stop .offsetZ + 0.2D * start.offsetZ),
r, g, b, LASER_DURATION_TICKS, 0,
AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ)); AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ));
} }
} }
@ -257,35 +298,41 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
} }
} }
public boolean countBlocksAndConsumeEnergy() { public void updateVolumeAndEnergyRequired() {
int x, y, z, energyToConsume; int x, y, z;
volume = 0; int energyRequired_new;
int volume_new = 0;
if (tier == 1) {// tier1 = gaz and air blocks don't count if (tier == 1) {// tier1 = gaz and air blocks don't count
for (y = minY; y <= maxY; y++) { for (y = minY; y <= maxY; y++) {
for (x = minX; x <= maxX; x++) { for (x = minX; x <= maxX; x++) {
for(z = minZ; z <= maxZ; z++) { for(z = minZ; z <= maxZ; z++) {
if (!worldObj.isAirBlock(x, y, z)) { if (!worldObj.isAirBlock(x, y, z)) {
volume++; volume_new++;
} }
} }
} }
} }
energyToConsume = volume * WarpDriveConfig.CLOAKING_TIER1_ENERGY_PER_BLOCK; energyRequired_new = volume_new * WarpDriveConfig.CLOAKING_TIER1_ENERGY_PER_BLOCK;
} else {// tier2 = everything counts } else {// tier2 = everything counts
for (y = minY; y <= maxY; y++) { for (y = minY; y <= maxY; y++) {
for (x = minX; x <= maxX; x++) { for (x = minX; x <= maxX; x++) {
for(z = minZ; z <= maxZ; z++) { for(z = minZ; z <= maxZ; z++) {
if (!worldObj.getBlock(x, y, z) .isAssociatedBlock(Blocks.air)) { if (worldObj.getBlock(x, y, z) != Blocks.air) {
volume++; volume_new++;
} }
} }
} }
} }
energyToConsume = volume * WarpDriveConfig.CLOAKING_TIER2_ENERGY_PER_BLOCK; energyRequired_new = volume_new * WarpDriveConfig.CLOAKING_TIER2_ENERGY_PER_BLOCK;
} }
// WarpDrive.logger.info(this + " Consuming " + energyToConsume + " EU for " + blocksCount + " blocks"); volume = volume_new;
return energy_consume(energyToConsume, false); energyRequired = energyRequired_new;
if (WarpDriveConfig.LOGGING_ENERGY) {
WarpDrive.logger.info(String.format("%s Requiring %d EU for %d blocks",
this, energyRequired, volume));
}
} }
@Override @Override
@ -304,64 +351,100 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
public boolean validateAssembly() { public boolean validateAssembly() {
final int maxOuterCoilDistance = WarpDriveConfig.CLOAKING_MAX_FIELD_RADIUS - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS; final int maxOuterCoilDistance = WarpDriveConfig.CLOAKING_MAX_FIELD_RADIUS - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS;
boolean isRefreshNeeded = false;
int countIntegrity = 1; // 1 for the core + 1 per coil
final StringBuilder messageInnerCoils = new StringBuilder();
final StringBuilder messageOuterCoils = new StringBuilder();
// Directions to check (all six directions: left, right, up, down, front, back) // Directions to check (all six directions: left, right, up, down, front, back)
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
// check validity of inner coil // check validity of inner coil
int x = xCoord + innerCoilsDistance * direction.offsetX; int x = xCoord + DISTANCE_INNER_COILS_BLOCKS * direction.offsetX;
int y = yCoord + innerCoilsDistance * direction.offsetY; int y = yCoord + DISTANCE_INNER_COILS_BLOCKS * direction.offsetY;
int z = zCoord + innerCoilsDistance * direction.offsetZ; int z = zCoord + DISTANCE_INNER_COILS_BLOCKS * direction.offsetZ;
if (worldObj.getBlock(x, y, z).isAssociatedBlock(WarpDrive.blockCloakingCoil)) { final boolean isInnerValid = (worldObj.getBlock(x, y, z) == WarpDrive.blockCloakingCoil);
worldObj.setBlockMetadataWithNotify(x, y, z, 1, 2);
// whenever a change is detected, force a laser redraw
if (isInnerValid != isValidInnerCoils[direction.ordinal()]) {
isRefreshNeeded = true;
isValidInnerCoils[direction.ordinal()] = isInnerValid;
}
// update validity results
if (isValidInnerCoils[direction.ordinal()]) {
countIntegrity++;
} else { } else {
return false; if (messageInnerCoils.length() != 0) {
messageInnerCoils.append(", ");
}
messageInnerCoils.append(direction.name());
} }
// find closest outer coil // find closest outer coil
int newCoilDistance = 0; int newCoilDistance = 0;
for (int distance = 3; distance < maxOuterCoilDistance; distance++) { for (int distance = DISTANCE_INNER_COILS_BLOCKS + 1; distance < maxOuterCoilDistance; distance++) {
x += direction.offsetX; x += direction.offsetX;
y += direction.offsetY; y += direction.offsetY;
z += direction.offsetZ; z += direction.offsetZ;
if (worldObj.getBlock(x, y, z).isAssociatedBlock(WarpDrive.blockCloakingCoil)) { if (worldObj.getBlock(x, y, z) == WarpDrive.blockCloakingCoil) {
worldObj.setBlockMetadataWithNotify(x, y, z, 2 + direction.ordinal(), 2);
newCoilDistance = distance; newCoilDistance = distance;
break; break;
} }
} }
// disable previous outer coil, in case a different one was found // whenever a change is detected, disable previous outer coil if it was valid and force a laser redraw
int oldCoilDistance = outerCoilsDistance[direction.ordinal()]; final int oldCoilDistance = distanceOuterCoils_blocks[direction.ordinal()];
if ( newCoilDistance != oldCoilDistance && oldCoilDistance > 0) { if (newCoilDistance != oldCoilDistance) {
int oldX = xCoord + oldCoilDistance * direction.offsetX; if (oldCoilDistance > 0) {
int oldY = yCoord + oldCoilDistance * direction.offsetY; final int oldX = xCoord + oldCoilDistance * direction.offsetX;
int oldZ = zCoord + oldCoilDistance * direction.offsetZ; final int oldY = yCoord + oldCoilDistance * direction.offsetY;
if (worldObj.getBlock(oldX, oldY, oldZ).isAssociatedBlock(WarpDrive.blockCloakingCoil)) { final int oldZ = zCoord + oldCoilDistance * direction.offsetZ;
if (worldObj.getBlock(oldX, oldY, oldZ) == WarpDrive.blockCloakingCoil) {
worldObj.setBlockMetadataWithNotify(oldX, oldY, oldZ, 0, 2); worldObj.setBlockMetadataWithNotify(oldX, oldY, oldZ, 0, 2);
} }
} }
isRefreshNeeded = true;
distanceOuterCoils_blocks[direction.ordinal()] = Math.max(0, newCoilDistance);
}
// check validity and save new coil position // update validity results
if (newCoilDistance <= 0) { if (newCoilDistance > 0) {
outerCoilsDistance[direction.ordinal()] = 0; countIntegrity++;
if (WarpDriveConfig.LOGGING_CLOAKING) { } else {
WarpDrive.logger.info("Invalid outer coil assembly at " + direction); if (messageOuterCoils.length() != 0) {
messageOuterCoils.append(", ");
} }
return false; messageOuterCoils.append(direction.name());
} }
outerCoilsDistance[direction.ordinal()] = newCoilDistance; }
// build status message
final float integrity = countIntegrity / 13.0F;
if (messageInnerCoils.length() > 0 && messageOuterCoils.length() > 0) {
messageValidityIssues = StatCollector.translateToLocalFormatted("warpdrive.cloakingCore.missingInnerAndOuter",
Math.round(100.0F * integrity), messageInnerCoils, messageOuterCoils);
} else if (messageInnerCoils.length() > 0) {
messageValidityIssues = StatCollector.translateToLocalFormatted("warpdrive.cloakingCore.missingInner",
Math.round(100.0F * integrity), messageInnerCoils);
} else if (messageOuterCoils.length() > 0) {
messageValidityIssues = StatCollector.translateToLocalFormatted("warpdrive.cloakingCore.missingOuter",
Math.round(100.0F * integrity), messageOuterCoils);
} else {
messageValidityIssues = StatCollector.translateToLocalFormatted("warpdrive.cloakingCore.valid");
} }
// Update cloaking field parameters defined by coils // Update cloaking field parameters defined by coils
minX = xCoord - outerCoilsDistance[4] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS; isValid = countIntegrity >= 13;
maxX = xCoord + outerCoilsDistance[5] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS; minX = xCoord - distanceOuterCoils_blocks[4] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS;
minY = Math.max( 0, yCoord - outerCoilsDistance[0] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS); maxX = xCoord + distanceOuterCoils_blocks[5] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS;
maxY = Math.min(255, yCoord + outerCoilsDistance[1] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS); minY = Math.max( 0, yCoord - distanceOuterCoils_blocks[0] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS);
minZ = zCoord - outerCoilsDistance[2] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS; maxY = Math.min(255, yCoord + distanceOuterCoils_blocks[1] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS);
maxZ = zCoord + outerCoilsDistance[3] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS; minZ = zCoord - distanceOuterCoils_blocks[2] - WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS;
return true; maxZ = zCoord + distanceOuterCoils_blocks[3] + WarpDriveConfig.CLOAKING_COIL_CAPTURE_BLOCKS;
return isRefreshNeeded;
} }
@Override @Override
@ -372,7 +455,7 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
final String unlocalizedStatus; final String unlocalizedStatus;
if (!isValid) { if (!isValid) {
unlocalizedStatus = "warpdrive.cloakingCore.invalidAssembly"; unlocalizedStatus = messageValidityIssues;
} else if (!isEnabled) { } else if (!isEnabled) {
unlocalizedStatus = "warpdrive.cloakingCore.disabled"; unlocalizedStatus = "warpdrive.cloakingCore.disabled";
} else if (!isCloaking) { } else if (!isCloaking) {
@ -386,12 +469,16 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
volume); volume);
} }
// OpenComputer callback methods // Common OC/CC methods
@Callback public Object[] tier(Object[] arguments) {
@Optional.Method(modid = "OpenComputers") if (arguments.length == 1) {
public Object[] tier(Context context, Arguments arguments) { int tier_new;
if (arguments.count() == 1) { try {
if (arguments.checkInteger(0) == 2) { tier_new = Commons.toInt(arguments[0]);
} catch(Exception exception) {
return new Integer[] { (int) tier };
}
if (tier_new == 2) {
tier = 2; tier = 2;
} else { } else {
tier = 1; tier = 1;
@ -401,49 +488,52 @@ public class TileEntityCloakingCore extends TileEntityAbstractEnergy {
return new Integer[] { (int) tier }; return new Integer[] { (int) tier };
} }
public Object[] isAssemblyValid() {
return new Object[] { isValid, Commons.removeFormatting(messageValidityIssues) };
}
public Object[] enable(Object[] arguments) {
if (arguments.length == 1) {
isEnabled = Commons.toBool(arguments[0]);
markDirty();
}
return new Object[] { isEnabled };
}
// OpenComputer callback methods
@Callback
@Optional.Method(modid = "OpenComputers")
public Object[] tier(Context context, Arguments arguments) {
return tier(argumentsOCtoCC(arguments));
}
@Callback @Callback
@Optional.Method(modid = "OpenComputers") @Optional.Method(modid = "OpenComputers")
public Object[] isAssemblyValid(Context context, Arguments arguments) { public Object[] isAssemblyValid(Context context, Arguments arguments) {
return new Object[] { validateAssembly() }; return isAssemblyValid();
} }
@Callback @Callback
@Optional.Method(modid = "OpenComputers") @Optional.Method(modid = "OpenComputers")
public Object[] enable(Context context, Arguments arguments) { public Object[] enable(Context context, Arguments arguments) {
if (arguments.count() == 1) { return enable(argumentsOCtoCC(arguments));
isEnabled = arguments.checkBoolean(0);
markDirty();
}
return new Object[] { isEnabled };
} }
// ComputerCraft IPeripheral methods implementation // ComputerCraft IPeripheral methods implementation
@Override @Override
@Optional.Method(modid = "ComputerCraft") @Optional.Method(modid = "ComputerCraft")
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) { public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) {
String methodName = getMethodName(method); final String methodName = getMethodName(method);
switch (methodName) { switch (methodName) {
case "tier": case "tier":
if (arguments.length == 1) { return tier(arguments);
if (Commons.toInt(arguments[0]) == 2) {
tier = 2;
} else {
tier = 1;
}
markDirty();
}
return new Integer[] { (int) tier };
case "isAssemblyValid": case "isAssemblyValid":
return new Object[] { validateAssembly() }; return isAssemblyValid();
case "enable": case "enable":
if (arguments.length == 1) { return enable(arguments);
isEnabled = Commons.toBool(arguments[0]);
markDirty();
}
return new Object[] { isEnabled };
} }
return super.callMethod(computer, context, method, arguments); return super.callMethod(computer, context, method, arguments);

View file

@ -135,14 +135,11 @@ public class CloakedArea {
if (Math.abs(dX) < RADIUS && Math.abs(dY) < RADIUS && Math.abs(dZ) < RADIUS) { if (Math.abs(dX) < RADIUS && Math.abs(dY) < RADIUS && Math.abs(dZ) < RADIUS) {
if (decloak) { if (decloak) {
PacketHandler.sendCloakPacket(entityPlayerMP, this, true);
revealChunksToPlayer(entityPlayerMP); revealChunksToPlayer(entityPlayerMP);
revealEntitiesToPlayer(entityPlayerMP); revealEntitiesToPlayer(entityPlayerMP);
} } else if (!isEntityWithinArea(entityPlayerMP)) {
if (!isEntityWithinArea(entityPlayerMP) && !decloak) {
PacketHandler.sendCloakPacket(entityPlayerMP, this, false); PacketHandler.sendCloakPacket(entityPlayerMP, this, false);
} else if (decloak) {
PacketHandler.sendCloakPacket(entityPlayerMP, this, true);
} }
} }
} }

View file

@ -21,14 +21,15 @@ if cloakingCore == nil then
else else
cloakingCore.tier(1) cloakingCore.tier(1)
cloakingCore.enable(true) cloakingCore.enable(true)
if cloakingCore.isAssemblyValid() then local isValid, message = cloakingCore.isAssemblyValid()
if isValid then
term.setBackgroundColor(colors.lime) term.setBackgroundColor(colors.lime)
term.setTextColor(colors.blue) term.setTextColor(colors.blue)
term.write("Tier 1 cloaking is enabled") term.write("Tier 1 cloaking is enabled")
else else
term.setBackgroundColor(colors.red) term.setBackgroundColor(colors.red)
term.setTextColor(colors.white) term.setTextColor(colors.white)
term.write("Invalid cloaking assembly!") print(message)
term.setBackgroundColor(colors.black) term.setBackgroundColor(colors.black)
term.setTextColor(colors.white) term.setTextColor(colors.white)
print() print()

View file

@ -21,14 +21,15 @@ if cloakingCore == nil then
else else
cloakingCore.tier(2) cloakingCore.tier(2)
cloakingCore.enable(true) cloakingCore.enable(true)
if cloakingCore.isAssemblyValid() then local isValid, message = cloakingCore.isAssemblyValid()
if isValid then
term.setBackgroundColor(colors.lime) term.setBackgroundColor(colors.lime)
term.setTextColor(colors.red) term.setTextColor(colors.red)
term.write("Tier 2 cloaking is enabled") term.write("Tier 2 cloaking is enabled")
else else
term.setBackgroundColor(colors.red) term.setBackgroundColor(colors.red)
term.setTextColor(colors.white) term.setTextColor(colors.white)
term.write("Invalid cloaking assembly!") print(message)
term.setBackgroundColor(colors.black) term.setBackgroundColor(colors.black)
term.setTextColor(colors.white) term.setTextColor(colors.white)
print() print()

View file

@ -4,13 +4,14 @@ local term = require("term")
if not component.isAvailable("warpdriveCloakingCore") then if not component.isAvailable("warpdriveCloakingCore") then
print("No cloaking core detected") print("No cloaking core detected")
else else
local cloakingcore = component.warpdriveCloakingCore local cloakingCore = component.warpdriveCloakingCore
cloakingcore.tier(1) cloakingCore.tier(1)
cloakingcore.enable(true) cloakingCore.enable(true)
if cloakingcore.isAssemblyValid() then local isValid, message = cloakingCore.isAssemblyValid()
if isValid then
print("Tier 1 cloaking is enabled") print("Tier 1 cloaking is enabled")
else else
print("Invalid cloaking assembly") print(message)
print() print()
print("In each of the 6 directions, you need to place exactly 2 Cloaking coils, for a total of 12 coils.") print("In each of the 6 directions, you need to place exactly 2 Cloaking coils, for a total of 12 coils.")
print("The 6 inner coils shall be exactly one block away from the core.") print("The 6 inner coils shall be exactly one block away from the core.")

View file

@ -4,13 +4,14 @@ local term = require("term")
if not component.isAvailable("warpdriveCloakingCore") then if not component.isAvailable("warpdriveCloakingCore") then
print("No cloaking core detected") print("No cloaking core detected")
else else
local cloakingcore = component.warpdriveCloakingCore local cloakingCore = component.warpdriveCloakingCore
cloakingcore.tier(2) cloakingCore.tier(2)
cloakingcore.enable(true) cloakingCore.enable(true)
if cloakingcore.isAssemblyValid() then local isValid, message = cloakingCore.isAssemblyValid()
if isValid then
print("Tier 2 cloaking is enabled") print("Tier 2 cloaking is enabled")
else else
print("Invalid cloaking assembly") print(message)
print() print()
print("In each of the 6 directions, you need to place exactly 2 Cloaking coils, for a total of 12 coils.") print("In each of the 6 directions, you need to place exactly 2 Cloaking coils, for a total of 12 coils.")
print("The 6 inner coils shall be exactly one block away from the core.") print("The 6 inner coils shall be exactly one block away from the core.")

View file

@ -3,13 +3,14 @@ local component = require("component")
if not component.isAvailable("warpdriveCloakingCore") then if not component.isAvailable("warpdriveCloakingCore") then
print("No cloaking core detected") print("No cloaking core detected")
else else
local cloakingcore = component.warpdriveCloakingCore local cloakingCore = component.warpdriveCloakingCore
cloakingcore.tier(2) cloakingCore.tier(2)
cloakingcore.enable(true) cloakingCore.enable(true)
if cloakingcore.isAssemblyValid() then local isValid, message = cloakingCore.isAssemblyValid()
if isValid then
print("Cloaking is disabled") print("Cloaking is disabled")
else else
print("Invalid assembly") print(message)
print() print()
print("In each of the 6 directions, you need to place exactly 2 Cloaking device coils, for a total of 12 coils.") print("In each of the 6 directions, you need to place exactly 2 Cloaking device coils, for a total of 12 coils.")
print("The 6 inner coils shall be exactly one block away from the core.") print("The 6 inner coils shall be exactly one block away from the core.")