Fixed entity interactions with force fields

Added ability for entities to pass through force field
Added attraction/repulsion visual effects
Fixed entity interaction scaling
Fixed client crash when connecting to a server next to a force field
This commit is contained in:
LemADEC 2016-07-10 19:43:20 +02:00
parent e067a3d8f3
commit f4644d45de
6 changed files with 222 additions and 116 deletions

View file

@ -23,5 +23,6 @@ public interface IForceFieldUpgradeEffector {
// Entity impact of this upgrade
// Return
int onEntityEffect(final float scaledValue, World world, final int x, final int y, final int z, Entity entity);
int onEntityEffect(final float scaledValue, World world, final int projectorX, final int projectorY, final int projectorZ,
final int blockX, final int blockY, final int blockZ, Entity entity);
}

View file

@ -231,10 +231,6 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
log_explosionX = explosionX;
log_explosionY = explosionY;
log_explosionZ = explosionZ;
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info("BlockForceField(" + tier + " at " + x + " " + y + " " + z + ")"
+ ".getExplosionResistance" + ((entity != null) ? " from " + entity : " at " + explosionX + " " + explosionY + " " + explosionZ));
}
}
// find explosion strength, defaults to no effect
@ -255,8 +251,8 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
case "class net.minecraft.entity.item.EntityTNTPrimed": strength = 5.0F; break;
case "class net.minecraft.entity.monster.EntityCreeper": strength = 3.0F; break; // *2 for powered ones
case "class appeng.entity.EntityTinyTNTPrimed": strength = 0.2F; break;
case "class ic2.core.block.EntityItnt": strength = 5.5F; break;
case "class ic2.core.block.EntityNuke": strength = 42.0F; break;
case "class ic2.core.block.EntityItnt": strength = 5.5F; break;
case "class ic2.core.block.EntityNuke": strength = 45.0F; break;
case "class ic2.core.block.EntityDynamite": strength = 1.0F; break;
case "class ic2.core.block.EntityStickyDynamite": strength = 1.0F; break;
default:
@ -270,14 +266,24 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
// apply damages to force field by consuming energy
Explosion explosion = new Explosion(world, entity, explosionX, explosionY, explosionZ, 4.0F);
Vector3 vDirection = new Vector3(x + 0.5D - explosionX, y + 0.5D - explosionY, z + 0.5D - explosionZ);
float magnitude = Math.max(1.0F, (float)vDirection.getMagnitude());
double magnitude = Math.max(1.0D, vDirection.getMagnitude());
if (magnitude != 0) {// normalize
vDirection.scale(1 / magnitude);
}
int damageLevel = Math.round(strength * 1000.0F / magnitude);
int damageLeft = applyDamage(world, x, y, z, DamageSource.setExplosionSource(explosion), 0, vDirection, damageLevel);
double damageLevel = strength / (magnitude * magnitude) * 1.0D;
double damageLeft = 0;
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
if (forceFieldSetup != null) {
damageLeft = forceFieldSetup.applyDamage(world, DamageSource.setExplosionSource(explosion), (int)damageLevel);
}
assert(damageLeft >= 0);
return 1.0F * super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info( "BlockForceField(" + tier + " at " + x + " " + y + " " + z + ")"
+ ".getExplosionResistance" + ((entity != null) ? " from " + entity : " at " + explosionX + " " + explosionY + " " + explosionZ)
+ " damageLevel " + damageLevel + " damageLeft " + damageLeft);
}
return super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
}
@Override

View file

@ -60,10 +60,12 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
private int setupTicks;
private int updateTicks;
private int soundTicks;
private final HashSet<UUID> setInteractedEntities = new HashSet<>();
protected boolean isPowered = true;
private ForceFieldSetup cache_forceFieldSetup;
private ForceFieldSetup legacy_forceFieldSetup;
private boolean legacy_isOn = true; // we assume it's on so we don't consume startup energy on chunk loading
private double consumptionLeftOver = 0.0D;
// carry over speed to next tick, useful for slow interactions
private float carryScanSpeed;
@ -106,7 +108,6 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
cooldownTicks = worldObj.rand.nextInt(PROJECTOR_COOLDOWN_TICKS);
setupTicks = worldObj.rand.nextInt(PROJECTOR_SETUP_TICKS);
updateTicks = worldObj.rand.nextInt(PROJECTOR_PROJECTION_UPDATE_TICKS);
getForceFieldSetup();
}
@Override
@ -136,10 +137,9 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
ForceFieldSetup forceFieldSetup = getForceFieldSetup();
int energyRequired;
if (!legacy_isOn) {
energyRequired = forceFieldSetup.startupEnergyCost;
energyRequired += Math.round(forceFieldSetup.placeEnergyCost * forceFieldSetup.placeSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
energyRequired = (int)Math.round(forceFieldSetup.startupEnergyCost + forceFieldSetup.placeEnergyCost * forceFieldSetup.placeSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
} else {
energyRequired = Math.round(forceFieldSetup.scanEnergyCost * forceFieldSetup.scanSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
energyRequired = (int)Math.round( forceFieldSetup.scanEnergyCost * forceFieldSetup.scanSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
}
if (energyRequired > getMaxEnergyStored()) {
WarpDrive.logger.error("Force field projector requires " + energyRequired + " to get started but can only store " + getMaxEnergyStored());
@ -151,10 +151,19 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
if (isOn) {
if (!legacy_isOn) {
consumeEnergy(forceFieldSetup.startupEnergyCost, false);
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(this + " starting up...");
}
legacy_isOn = true;
}
cooldownTicks = 0;
int countEntityInteractions = setInteractedEntities.size();
if (countEntityInteractions > 0) {
setInteractedEntities.clear();
consumeEnergy(forceFieldSetup.getEntityEnergyCost(countEntityInteractions), false);
}
updateTicks--;
if (updateTicks <= 0) {
updateTicks = PROJECTOR_PROJECTION_UPDATE_TICKS;
@ -174,7 +183,12 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
}
} else {
legacy_isOn = false;
if (legacy_isOn) {
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(this + " shutting down...");
}
legacy_isOn = false;
}
destroyForceField(false);
if (cooldownTicks > 0) {
cooldownTicks--;
@ -266,6 +280,10 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
return calculated_interiorField.contains(vector);
}
public boolean onEntityInteracted(final UUID uniqueID) {
return setInteractedEntities.add(uniqueID);
}
private void projectForceField() {
assert(!worldObj.isRemote && isCalculated());
@ -892,11 +910,14 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
// reset field in case of major changes
if (legacy_forceFieldSetup != null) {
int energyRequired = cache_forceFieldSetup.startupEnergyCost - legacy_forceFieldSetup.startupEnergyCost;
int energyRequired = (int)Math.max(0, Math.round(cache_forceFieldSetup.startupEnergyCost - legacy_forceFieldSetup.startupEnergyCost));
if ( legacy_forceFieldSetup.getCamouflageBlock() != cache_forceFieldSetup.getCamouflageBlock()
|| legacy_forceFieldSetup.getCamouflageMetadata() != cache_forceFieldSetup.getCamouflageMetadata()
|| legacy_forceFieldSetup.beamFrequency != cache_forceFieldSetup.beamFrequency
|| !consumeEnergy(energyRequired, false)) {
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(this + " rebooting with new rendering...");
}
destroyForceField(true);
} else if ( legacy_forceFieldSetup.isInverted != cache_forceFieldSetup.isInverted
@ -905,6 +926,9 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|| !legacy_forceFieldSetup.vMin.equals(cache_forceFieldSetup.vMin)
|| !legacy_forceFieldSetup.vMax.equals(cache_forceFieldSetup.vMax)
|| !legacy_forceFieldSetup.vTranslation.equals(cache_forceFieldSetup.vTranslation)) {
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info(this + " rebooting with new shape...");
}
destroyForceField(true);
isDirty.set(true);
}
@ -923,6 +947,15 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
return true;
}
public boolean consumeEnergy(final double amount_internal, boolean simulate) {
int intAmount = (int)Math.floor(amount_internal + consumptionLeftOver);
boolean bResult = super.consumeEnergy(intAmount, simulate);
if (!simulate) {
consumptionLeftOver = amount_internal + consumptionLeftOver - intAmount;
}
return bResult;
}
// OpenComputer callback methods
@Callback
@cpw.mods.fml.common.Optional.Method(modid = "OpenComputers")

View file

@ -20,26 +20,26 @@ import java.util.HashMap;
public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgradeEffector {
// Upgrade - Compatibility - ----- Value ----- -- Scan speed -- -- Place speed -- --------- Energy costs --------- comment
// name projector relay incr. cap minimum maximum minimum maximum startup scan place entity
NONE ("none" , 0, 0, 0.0F, 0.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.000F, 0.000F, 0.0F, ""),
ATTRACTION ("attraction" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 200.0F, "value is acceleration"),
BREAKING ("breaking" , 0, 1, 1.0F, 25.0F, 0.400F, 0.500F, 0.020F, 0.150F, 700.0F, 0.080F, 4.000F, 0.0F, "value is hardness level"),
CAMOUFLAGE ("camouflage" , 0, 1, 1.0F, 3.0F, 0.600F, 0.850F, 0.700F, 0.950F, 1000.0F, 3.000F, 7.000F, 0.0F, "value is boolean"),
COOLING ("cooling" , 3, 1, 30.0F, 300.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.060F, 1.500F, 1000.0F, "value is heat units"),
FUSION ("fusion" , 1, 1, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 1000.0F, 0.150F, 0.150F, 0.0F, "value is boolean"),
HEATING ("heating" , 3, 1, 100.0F, 10000.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.300F, 3.000F, 500.0F, "value is heat units"),
INVERSION ("inversion" , 1, 0, 1.0F, 1.0F, 1.250F, 1.250F, 0.000F, 0.000F, 1500.0F, 0.150F, 0.150F, 100.0F, "value is boolean"),
ITEM_PORT ("itemPort" , 0, 1, 1.0F, 10.0F, 0.000F, 0.000F, 0.950F, 0.900F, 50.0F, 0.120F, 0.500F, 800.0F, "value is boolean"),
PUMPING ("pumping" , 0, 1, 1000.0F, 50000.0F, 0.800F, 1.000F, 0.400F, 1.000F, 800.0F, 0.500F, 2.250F, 0.0F, "value is viscosity"),
RANGE ("range" , 4, 1, 8.0F, 56.0F, 1.150F, 0.800F, 1.150F, 0.800F, 10.0F, 0.300F, 0.750F, 400.0F, "value is bonus blocks"),
REPULSION ("repulsion" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 200.0F, "value is acceleration"),
ROTATION ("rotation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
SHOCK ("shock" , 3, 1, 1.0F, 10.0F, 0.800F, 0.800F, 0.800F, 0.800F, 300.0F, 0.600F, 4.000F, 3000.0F, "value is damage points"),
SILENCER ("silencer" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.120F, 0.620F, 0.0F, "value is boolean"),
SPEED ("speed" , 4, 1, 1.0F, 20.0F, 1.250F, 6.000F, 1.200F, 5.000F, 200.0F, 0.400F, 1.700F, 500.0F, "value is not used (just a counter)"),
STABILIZATION("stabilization", 0, 1, 1.0F, 6.0F, 0.450F, 0.550F, 0.050F, 0.150F, 400.0F, 1.520F, 4.300F, 0.0F, "value is boolean"),
THICKNESS ("thickness" , 5, 1, 0.2F, 1.0F, 0.800F, 1.600F, 0.000F, 0.000F, 100.0F, 0.700F, 2.400F, 100.0F, "value is bonus ratio"),
TRANSLATION ("translation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
// name projector relay incr. cap minimum maximum minimum maximum startup scan place entity
NONE ("none" , 0, 0, 0.0F, 0.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.000F, 0.000F, 0.0F, ""),
ATTRACTION ("attraction" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 8.0F, "value is acceleration"),
BREAKING ("breaking" , 0, 1, 1.0F, 25.0F, 0.400F, 0.500F, 0.020F, 0.150F, 700.0F, 0.080F, 4.000F, 0.0F, "value is hardness level"),
CAMOUFLAGE ("camouflage" , 0, 1, 1.0F, 3.0F, 0.600F, 0.850F, 0.700F, 0.950F, 1000.0F, 3.000F, 7.000F, 0.0F, "value is boolean"),
COOLING ("cooling" , 3, 1, 30.0F, 300.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.060F, 1.500F, 40.0F, "value is heat units"),
FUSION ("fusion" , 1, 1, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 1000.0F, 0.040F, 0.150F, 0.0F, "value is boolean"),
HEATING ("heating" , 3, 1, 100.0F, 10000.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.300F, 3.000F, 25.0F, "value is heat units"),
INVERSION ("inversion" , 1, 0, 1.0F, 1.0F, 1.250F, 1.250F, 0.000F, 0.000F, 1500.0F, 0.150F, 0.150F, 20.0F, "value is boolean"),
ITEM_PORT ("itemPort" , 0, 1, 1.0F, 10.0F, 0.000F, 0.000F, 0.950F, 0.900F, 50.0F, 0.120F, 0.500F, 2.0F, "value is boolean"),
PUMPING ("pumping" , 0, 1, 1000.0F, 50000.0F, 0.800F, 1.000F, 0.400F, 1.000F, 800.0F, 0.150F, 4.500F, 0.0F, "value is viscosity"),
RANGE ("range" , 4, 1, 8.0F, 56.0F, 1.150F, 0.800F, 1.150F, 0.800F, 10.0F, 0.300F, 0.750F, 12.0F, "value is bonus blocks"),
REPULSION ("repulsion" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 5.0F, "value is acceleration"),
ROTATION ("rotation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
SHOCK ("shock" , 3, 1, 1.0F, 10.0F, 0.800F, 0.800F, 0.800F, 0.800F, 300.0F, 0.600F, 4.000F, 30.0F, "value is damage points"),
SILENCER ("silencer" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.120F, 0.620F, 0.0F, "value is boolean"),
SPEED ("speed" , 4, 1, 1.0F, 20.0F, 1.250F, 6.000F, 1.200F, 5.000F, 200.0F, 0.135F, 1.250F, 15.0F, "value is not used (just a counter)"),
STABILIZATION("stabilization", 0, 1, 1.0F, 6.0F, 0.250F, 0.550F, 0.025F, 0.150F, 400.0F, 0.050F, 73.600F, 0.0F, "value is boolean"),
THICKNESS ("thickness" , 5, 1, 0.2F, 1.0F, 0.800F, 1.600F, 0.900F, 1.500F, 100.0F, 0.400F, 2.200F, 5.0F, "value is bonus ratio"),
TRANSLATION ("translation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
;
public final String unlocalizedName;
@ -147,15 +147,20 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
@Override
public int onEntityEffect(final float scaledValue, World world, final int x, final int y, final int z, Entity entity) {
public int onEntityEffect(final float scaledValue, World world, final int projectorX, final int projectorY, final int projectorZ,
final int blockX, final int blockY, final int blockZ, Entity entity) {
if (scaledValue == 0.0F) {
return 0;
}
// common particle effects properties
Vector3 origin = new Vector3(x + 0.5D, y + 0.5D, z + 0.5D);
Vector3 direction = new Vector3(entity).subtract(origin).normalize();
origin.translateFactor(direction, 0.6D);
Vector3 v3Projector = new Vector3(projectorX + 0.5D, projectorY + 0.5D, projectorZ + 0.5D);
double distanceCollision = v3Projector.distanceTo_square(new Vector3(blockX + 0.5D, blockY + 0.5D, blockZ + 0.5D));
double distanceEntity = v3Projector.distanceTo_square(entity);
Vector3 v3Entity = new Vector3(entity);
Vector3 v3Direction = new Vector3(entity).subtract(v3Projector).normalize();
v3Projector.translateFactor(v3Direction, 0.6D);
v3Entity.translateFactor(v3Direction, -0.6D);
// entity classification
int entityLevel = 0;
@ -164,50 +169,99 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
entityLevel = 0;
} else if (entity instanceof EntityPlayer) {
entityLevel = 4;
} else if (entity instanceof EntityMob
|| entity instanceof EntityGolem
|| entity instanceof EntityFireball
|| entity instanceof EntityTNTPrimed
|| entity instanceof EntityThrowable
|| entity instanceof EntityMinecart) {
} else if ( entity instanceof EntityMob
|| entity instanceof EntityGolem
|| entity instanceof EntityFireball
|| entity instanceof EntityTNTPrimed
|| entity instanceof EntityThrowable
|| entity instanceof EntityMinecart ) {
entityLevel = 3;
} else if (entity instanceof EntityLivingBase
|| entity instanceof EntityXPOrb
|| entity instanceof EntityBoat) {
} else if ( entity instanceof EntityLivingBase
|| entity instanceof EntityXPOrb
|| entity instanceof EntityBoat ) {
entityLevel = 2;
} else if (entity instanceof EntityItem
|| entity instanceof EntityArrow
|| entity instanceof EntityFallingBlock) {
} else if ( entity instanceof EntityItem
|| entity instanceof EntityArrow
|| entity instanceof EntityFallingBlock ) {
entityLevel = 1;
}
}
double maxSpeed = scaledValue / (entityLevel / 4.0F) * ForceFieldSetup.FORCEFIELD_ACCELERATION_FACTOR;
Vector3 motion = direction.clone().scale(maxSpeed); // new Vector3(entity.motionX, entity.motionY, entity.motionZ);
double speed = Math.abs(scaledValue) / (entityLevel / 4.0F) * ForceFieldSetup.FORCEFIELD_ACCELERATION_FACTOR;
Vector3 v3Motion = v3Direction.clone().scale(speed); // new Vector3(entity.motionX, entity.motionY, entity.motionZ);
/*
if (WarpDriveConfig.LOGGING_FORCEFIELD && WarpDrive.isDev) {
WarpDrive.logger.info(this + " scaledValue " + scaledValue + " entityLevel " + entityLevel + " speed " + speed
+ " entity " + v3Entity + " projector " + v3Projector + " direction " + v3Direction + " motion " + v3Motion + " entity " + entity);
}
/**/
// apply damages and particle effects
switch(this) {
case ATTRACTION:
if (scaledValue <= 0.1F || entityLevel > scaledValue) {
return 0;
}
// WarpDrive.logger.info("scaledValue " + scaledValue + " maxSpeed " + maxSpeed + " direction " + direction + " motion " + motion);
motion.invert();
v3Motion.invert();
entity.fallDistance = 0.0F;
entity.addVelocity(motion.x, motion.y, motion.z);
entity.addVelocity(v3Motion.x, v3Motion.y, v3Motion.z);
PacketHandler.sendBeamPacket(world, origin, origin.clone().translate(motion),
// pass through forcefield
if (distanceCollision <= distanceEntity) {
if (entity instanceof EntityLivingBase) {
((EntityLivingBase)entity).setPositionAndUpdate(
entity.posX - v3Direction.x * 2.0D,
entity.posY - v3Direction.y * 2.0D,
entity.posZ - v3Direction.z * 2.0D);
} else {
entity.setPosition(
entity.posX - v3Direction.x * 2.0D,
entity.posY - v3Direction.y * 2.0D,
entity.posZ - v3Direction.z * 2.0D);
}
v3Entity.translateFactor(v3Direction, 2.0D);
} else if (entity instanceof EntityPlayer) {
((EntityLivingBase)entity).setPositionAndUpdate(
entity.posX - v3Direction.x * 0.4D,
entity.posY - v3Direction.y * 0.4D,
entity.posZ - v3Direction.z * 0.4D);
}
// visual effect
PacketHandler.sendBeamPacket(world, v3Entity, v3Projector,
0.2F, 0.4F, 0.7F, 10, 0, 50);
return 10;
case REPULSION:
if (scaledValue <= 0.1F || entityLevel > scaledValue) {
if (scaledValue >= -0.1F || entityLevel > Math.abs(scaledValue)) {
return 0;
}
WarpDrive.logger.info("scaledValue " + scaledValue + " maxSpeed " + maxSpeed + " direction " + direction + " motion " + motion);
entity.fallDistance = 0.0F;
entity.addVelocity(motion.x, motion.y, motion.z);
entity.addVelocity(v3Motion.x, v3Motion.y, v3Motion.z);
PacketHandler.sendBeamPacket(world, origin, origin.clone().translate(motion),
// pass through forcefield
if (distanceCollision >= distanceEntity) {
if (entity instanceof EntityLivingBase) {
((EntityLivingBase)entity).setPositionAndUpdate(
entity.posX + v3Direction.x * 2.0D,
entity.posY + v3Direction.y * 2.0D,
entity.posZ + v3Direction.z * 2.0D);
} else {
entity.setPosition(
entity.posX + v3Direction.x * 2.0D,
entity.posY + v3Direction.y * 2.0D,
entity.posZ + v3Direction.z * 2.0D);
}
v3Entity.translateFactor(v3Direction, 2.0D);
} else if (entity instanceof EntityPlayer) {
((EntityLivingBase)entity).setPositionAndUpdate(
entity.posX + v3Direction.x * 0.4D,
entity.posY + v3Direction.y * 0.4D,
entity.posZ + v3Direction.z * 0.4D);
}
// visual effect
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
0.2F, 0.4F, 0.7F, 10, 0, 50);
return 10;
@ -217,8 +271,11 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
}
entity.attackEntityFrom(WarpDrive.damageCold, (300 - scaledValue) / 10);
direction.scale(0.20D);
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", origin, direction,
// visual effect
v3Direction.scale(0.20D);
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
0.25F, 0.38F, 0.75F, 10, 0, 50);
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", v3Entity, v3Direction,
0.20F + 0.10F * world.rand.nextFloat(), 0.25F + 0.25F * world.rand.nextFloat(), 0.60F + 0.30F * world.rand.nextFloat(),
0.0F, 0.0F, 0.0F, 32);
return 10;
@ -232,13 +289,16 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
}
entity.attackEntityFrom(WarpDrive.damageWarm, (scaledValue - 300) / 100);
direction.scale(0.20D);
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", origin, direction,
// visual effect
v3Direction.scale(0.20D);
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
0.95F, 0.52F, 0.38F, 10, 0, 50);
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", v3Entity, v3Direction,
0.90F + 0.10F * world.rand.nextFloat(), 0.35F + 0.25F * world.rand.nextFloat(), 0.30F + 0.15F * world.rand.nextFloat(),
0.0F, 0.0F, 0.0F, 32);
/*
direction.scale(0.10D);
PacketHandler.sendSpawnParticlePacket(world, "flame", origin, direction,
v3Direction.scale(0.10D);
PacketHandler.sendSpawnParticlePacket(world, "flame", v3Projector, v3Direction,
0.85F, 0.75F, 0.75F,
0.0F, 0.0F, 0.0F, 32);
/**/
@ -250,8 +310,11 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
}
entity.attackEntityFrom(WarpDrive.damageShock, Math.abs(scaledValue));
direction.scale(0.15D);
PacketHandler.sendSpawnParticlePacket(world, "fireworksSpark", origin, direction,
// visual effect
v3Direction.scale(0.15D);
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
0.35F, 0.57F, 0.87F, 10, 0, 50);
PacketHandler.sendSpawnParticlePacket(world, "fireworksSpark", v3Entity, v3Direction,
0.20F + 0.30F * world.rand.nextFloat(), 0.50F + 0.15F * world.rand.nextFloat(), 0.75F + 0.25F * world.rand.nextFloat(),
0.10F + 0.20F * world.rand.nextFloat(), 0.10F + 0.30F * world.rand.nextFloat(), 0.20F + 0.10F * world.rand.nextFloat(),
32);

View file

@ -2,12 +2,10 @@ package cr0s.warpdrive.data;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBeamFrequency;
import cr0s.warpdrive.block.forcefield.TileEntityForceFieldProjector;
import cr0s.warpdrive.block.forcefield.TileEntityForceFieldRelay;
import cr0s.warpdrive.config.WarpDriveConfig;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.*;
@ -22,7 +20,7 @@ public class ForceFieldRegistry {
public static Set<TileEntity> getTileEntities(final int beamFrequency, WorldServer worldSource, final int x, final int y, final int z) {
Set<GlobalPosition> setGlobalPositions = registry.get(beamFrequency);
if (setGlobalPositions == null) {
if (setGlobalPositions == null || worldSource == null) {
return new HashSet<>();
}
// find all relevant tiles by world and frequency, keep relays in range as starting point
@ -117,8 +115,7 @@ public class ForceFieldRegistry {
if (setGlobalPositions == null) {
setGlobalPositions = new HashSet<>(FORCE_FIELD_REGISTRY_DEFAULT_ENTRIES_PER_FREQUENCY);
}
for (Iterator<GlobalPosition> iterator = setGlobalPositions.iterator(); iterator.hasNext();) {
GlobalPosition globalPosition = iterator.next();
for (GlobalPosition globalPosition : setGlobalPositions) {
if (globalPosition.equals(tileEntity)) {
// already registered
return;

View file

@ -34,8 +34,10 @@ public class ForceFieldSetup extends GlobalPosition {
private static final float FORCEFIELD_MAX_PLACE_SPEED_BLOCKS_PER_SECOND = 4000;
private static final float FORCEFIELD_UPGRADE_BOOST_FACTOR_PER_PROJECTOR_TIER = 0.50F;
public static final float FORCEFIELD_UPGRADE_BOOST_FACTOR_PER_RELAY_TIER = 0.25F;
public static final double FORCEFIELD_ACCELERATION_FACTOR = 0.01D;
public static final double FORCEFIELD_ACCELERATION_FACTOR = 0.04D;
public static final int FORCEFIELD_RELAY_RANGE = 20;
private static final int FORCEFIELD_MAX_FACTOR_ENTITY_COST = 5;
private static final double FORCEFIELD_TAU_FACTOR_ENTITY_COST = - Math.log(ForceFieldSetup.FORCEFIELD_MAX_FACTOR_ENTITY_COST);
public final int beamFrequency;
public final byte tier;
@ -51,10 +53,10 @@ public class ForceFieldSetup extends GlobalPosition {
public float scanSpeed;
public float placeSpeed;
public int startupEnergyCost;
public int scanEnergyCost;
public int placeEnergyCost;
private int entityEnergyCost;
public double startupEnergyCost;
public double scanEnergyCost;
public double placeEnergyCost;
private double entityEnergyCost;
public float breaking_maxHardness;
public float temperatureLevel;
@ -82,14 +84,13 @@ public class ForceFieldSetup extends GlobalPosition {
this.beamFrequency = beamFrequency;
refresh();
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info("Force field projector energy costs:"
+ " startup " + startupEnergyCost
+ " / " + Math.round(startupEnergyCost + placeEnergyCost * placeSpeed * TileEntityForceFieldProjector.PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F)
+ " scan " + scanEnergyCost
+ " place " + placeEnergyCost
+ " entity " + entityEnergyCost
+ " speeds: scan " + scanSpeed
+ " place " + placeSpeed);
WarpDrive.logger.info(String.format("Force field projector energy costs: startup %.3f / %d scan %.3f place %.3f entity %.3f"
+ " speeds: scan %.3f place %.3f"
+ " sustain cost: scan %.3f place %.3f",
startupEnergyCost, Math.round(startupEnergyCost + placeEnergyCost * placeSpeed * TileEntityForceFieldProjector.PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F),
scanEnergyCost, placeEnergyCost, entityEnergyCost,
scanSpeed, placeSpeed,
(scanEnergyCost * scanSpeed), (placeEnergyCost * placeSpeed)));
}
}
@ -214,10 +215,10 @@ public class ForceFieldSetup extends GlobalPosition {
// set default coefficients, depending on projector
scanSpeed = FORCEFIELD_BASE_SCAN_SPEED_BLOCKS_PER_SECOND * (isDoubleSided ? 2.1F : 1.0F);
placeSpeed = FORCEFIELD_BASE_PLACE_SPEED_BLOCKS_PER_SECOND * (isDoubleSided ? 2.1F : 1.0F);
float startupEnergyCost = 60.0F + 20.0F * tier;
float scanEnergyCost = 1.0F + 1.0F * tier;
float placeEnergyCost = 3.0F + 3.0F * tier;
float entityEnergyCost = 2.0F;
startupEnergyCost = 60.0F + 20.0F * tier;
scanEnergyCost = 0.4F + 0.4F * tier;
placeEnergyCost = 3.0F + 3.0F * tier;
entityEnergyCost = 2.0F;
if (isDoubleSided) {
scanSpeed *= 2.1F;
placeSpeed *= 2.1F;
@ -246,17 +247,13 @@ public class ForceFieldSetup extends GlobalPosition {
startupEnergyCost += entry.getKey().getStartupEnergyCost(scaledValue);
scanEnergyCost += entry.getKey().getScanEnergyCost(scaledValue);
placeEnergyCost += entry.getKey().getPlaceEnergyCost(scaledValue);
entityEnergyCost += entry.getKey().getEntityEffectEnergyCost(scaledValue);
entityEnergyCost += entry.getKey().getEntityEffectEnergyCost(scaledValue);
}
}
// finalize coefficients
scanSpeed = Math.min(FORCEFIELD_MAX_SCAN_SPEED_BLOCKS_PER_SECOND, scanSpeed);
placeSpeed = Math.min(FORCEFIELD_MAX_PLACE_SPEED_BLOCKS_PER_SECOND, placeSpeed);
this.startupEnergyCost = Math.round(startupEnergyCost);
this.scanEnergyCost = Math.round(scanEnergyCost);
this.placeEnergyCost = Math.round(placeEnergyCost);
this.entityEnergyCost = Math.round(entityEnergyCost);
// range is maximum distance
double range = getScaledUpgrade(EnumForceFieldUpgrade.RANGE);
@ -293,25 +290,25 @@ public class ForceFieldSetup extends GlobalPosition {
thickness = 1.0F + getScaledUpgrade(EnumForceFieldUpgrade.THICKNESS);
}
@Override
public String toString() {
return String.format("%s @ DIM%d (%d %d %d) (%d %d %d) -> (%d %d %d)",
getClass().getSimpleName(), dimensionId,
x, y, z,
vMin.x, vMin.y, vMin.z,
vMax.x, vMax.y, vMax.z);
public double getEntityEnergyCost(final int countEntityInteractions) {
return entityEnergyCost * FORCEFIELD_MAX_FACTOR_ENTITY_COST * Math.exp(FORCEFIELD_TAU_FACTOR_ENTITY_COST / countEntityInteractions);
}
public int onEntityEffect(World world, final int x, final int y, final int z, Entity entity) {
public int onEntityEffect(World world, final int blockX, final int blockY, final int blockZ, Entity entity) {
int countdown = 0;
for (Map.Entry<IForceFieldUpgradeEffector, Float> entry : upgrades.entrySet()) {
Float value = entry.getValue();
if (entry.getKey() == EnumForceFieldUpgrade.COOLING || entry.getKey() == EnumForceFieldUpgrade.HEATING) {
value = temperatureLevel;
} else if (entry.getKey() == EnumForceFieldUpgrade.ATTRACTION || entry.getKey() == EnumForceFieldUpgrade.REPULSION) {
value = accelerationLevel;
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityForceFieldProjector) {
if (((TileEntityForceFieldProjector)tileEntity).onEntityInteracted(entity.getUniqueID())) {
for (Map.Entry<IForceFieldUpgradeEffector, Float> entry : upgrades.entrySet()) {
Float value = entry.getValue();
if (entry.getKey() == EnumForceFieldUpgrade.COOLING || entry.getKey() == EnumForceFieldUpgrade.HEATING) {
value = temperatureLevel;
} else if (entry.getKey() == EnumForceFieldUpgrade.ATTRACTION || entry.getKey() == EnumForceFieldUpgrade.REPULSION) {
value = accelerationLevel;
}
countdown += entry.getKey().onEntityEffect(value, world, x, y, z, blockX, blockY, blockZ, entity);
}
}
countdown += entry.getKey().onEntityEffect(value, world, x, y, z, entity);
}
return countdown;
}
@ -320,11 +317,20 @@ public class ForceFieldSetup extends GlobalPosition {
assert(damageSource != null);
TileEntity tileEntity = world.getTileEntity(this.x, this.y, this.z);
if (tileEntity instanceof TileEntityForceFieldProjector) {
float scaledDamage = damageLevel * entityEnergyCost / 20000.0F;
int energyCost = (int)Math.floor(scaledDamage) + (world.rand.nextFloat() <= scaledDamage - Math.floor(scaledDamage) ? 1 : 0);
((TileEntityForceFieldProjector)tileEntity).consumeEnergy(energyCost, false);
double scaledDamage = damageLevel * entityEnergyCost / 20000.0D;
WarpDrive.logger.info("Consuming " + scaledDamage);
((TileEntityForceFieldProjector)tileEntity).consumeEnergy(scaledDamage, false);
return 0;
}
return damageLevel;
}
@Override
public String toString() {
return String.format("%s @ DIM%d (%d %d %d) (%d %d %d) -> (%d %d %d)",
getClass().getSimpleName(), dimensionId,
x, y, z,
vMin.x, vMin.y, vMin.z,
vMax.x, vMax.y, vMax.z);
}
}