Updated force field interaction with explosions on 1.12.2
This commit is contained in:
parent
9653bcfe10
commit
d6b8a68489
2 changed files with 113 additions and 36 deletions
|
@ -619,6 +619,16 @@ public class Commons {
|
||||||
return name.equals("Server thread") || name.equals("Client thread");
|
return name.equals("Server thread") || name.equals("Client thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isClientThread() {
|
||||||
|
final String name = Thread.currentThread().getName();
|
||||||
|
return name.equals("Client thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isServerThread() {
|
||||||
|
final String name = Thread.currentThread().getName();
|
||||||
|
return name.equals("Server thread");
|
||||||
|
}
|
||||||
|
|
||||||
// loosely inspired by crunchify
|
// loosely inspired by crunchify
|
||||||
public static void dumpAllThreads() {
|
public static void dumpAllThreads() {
|
||||||
final StringBuilder stringBuilder = new StringBuilder();
|
final StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
|
@ -16,6 +16,7 @@ import cr0s.warpdrive.data.VectorI;
|
||||||
import cr0s.warpdrive.event.ModelBakeEventHandler;
|
import cr0s.warpdrive.event.ModelBakeEventHandler;
|
||||||
import cr0s.warpdrive.render.BakedModelCamouflage;
|
import cr0s.warpdrive.render.BakedModelCamouflage;
|
||||||
|
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||||
import net.minecraft.creativetab.CreativeTabs;
|
import net.minecraft.creativetab.CreativeTabs;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
|
@ -47,6 +49,7 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.DamageSource;
|
import net.minecraft.util.DamageSource;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.Explosion;
|
import net.minecraft.world.Explosion;
|
||||||
import net.minecraft.world.IBlockAccess;
|
import net.minecraft.world.IBlockAccess;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -350,43 +353,71 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @TODO MC1.10 explosion effect redesign
|
// explosion handling, preferably without ASM
|
||||||
private double log_explosionX;
|
private int previous_exploderId = -1;
|
||||||
private double log_explosionY = -1.0D;
|
private long previous_tickWorld = -1L;
|
||||||
private double log_explosionZ;
|
private int previous_idDimension = Integer.MAX_VALUE;
|
||||||
|
private Vec3d previous_vExplosion = new Vec3d(0.0D, -1.0D, 0.0D);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public float getExplosionResistance(final Entity exploder) {
|
public float getExplosionResistance(@Nullable final Entity exploder) {
|
||||||
|
final int exploderId = exploder == null ? -1 : exploder.getEntityId();
|
||||||
|
if ( exploderId != previous_exploderId
|
||||||
|
&& Commons.isServerThread() ) {
|
||||||
|
new RuntimeException(String.format("Invalid call to deprecated getExplosionResistance(%s)", exploder)).printStackTrace();
|
||||||
|
WarpDrive.logger.error(String.format("Invalid call to getExplosionResistance from %s",
|
||||||
|
exploder));
|
||||||
|
return Float.MAX_VALUE;
|
||||||
|
}
|
||||||
return super.getExplosionResistance(exploder);
|
return super.getExplosionResistance(exploder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getExplosionResistance(Entity entity, World world, BlockPos blockPos, double explosionX, double explosionY, double explosionZ) {
|
public float getExplosionResistance(final World world, final BlockPos blockPos, @Nullable final Entity exploder, final Explosion explosion) {
|
||||||
boolean enableFirstHit = (log_explosionX != explosionX || log_explosionY != explosionY || log_explosionZ != explosionZ);
|
previous_exploderId = exploder == null ? -1 : exploder.getEntityId();
|
||||||
if (enableFirstHit) {
|
final long tickWorld = world.getTotalWorldTime();
|
||||||
log_explosionX = explosionX;
|
final Vec3d vExplosion = explosion.getPosition();
|
||||||
log_explosionY = explosionY;
|
final boolean isFirstHit = Math.abs(tickWorld - previous_tickWorld) > 100L
|
||||||
log_explosionZ = explosionZ;
|
|| previous_idDimension != world.provider.getDimension()
|
||||||
|
|| Math.abs(previous_vExplosion.x - vExplosion.x) > 5.0D
|
||||||
|
|| Math.abs(previous_vExplosion.y - vExplosion.y) > 5.0D
|
||||||
|
|| Math.abs(previous_vExplosion.z - vExplosion.z) > 5.0D;
|
||||||
|
if (isFirstHit) {
|
||||||
|
previous_tickWorld = tickWorld;
|
||||||
|
previous_idDimension = world.provider.getDimension();
|
||||||
|
previous_vExplosion = new Vec3d(vExplosion.x, vExplosion.y, vExplosion.z);
|
||||||
|
if (!Commons.isSafeThread()) {
|
||||||
|
WarpDrive.logger.error(String.format("Bad multithreading detected %s from exploder %s explosion %s",
|
||||||
|
Commons.format(world, blockPos), exploder, explosion ));
|
||||||
|
new ConcurrentModificationException().printStackTrace();
|
||||||
|
}
|
||||||
|
WarpDrive.logger.error(String.format("Explosion check %s from exploder %s explosion %s",
|
||||||
|
Commons.format(world, blockPos), exploder, explosion ));
|
||||||
}
|
}
|
||||||
|
|
||||||
// find explosion strength, defaults to no effect
|
// find explosion strength, defaults to no effect
|
||||||
double strength = 0.0D;
|
double strength = 0.0D;
|
||||||
if ( entity == null
|
if ( exploder == null
|
||||||
&& explosionX == Math.rint(explosionX)
|
&& vExplosion.x == Math.rint(vExplosion.x)
|
||||||
&& explosionY == Math.rint(explosionY)
|
&& vExplosion.y == Math.rint(vExplosion.y)
|
||||||
&& explosionZ == Math.rint(explosionZ) ) {
|
&& vExplosion.z == Math.rint(vExplosion.z) ) {
|
||||||
|
final BlockPos blockPosExplosion = new BlockPos((int) vExplosion.x, (int) vExplosion.y, (int) vExplosion.z);
|
||||||
// IC2 Reactor blowing up => block is already air
|
// IC2 Reactor blowing up => block is already air
|
||||||
final IBlockState blockState = world.getBlockState(new BlockPos((int)explosionX, (int)explosionY, (int)explosionZ));
|
final IBlockState blockState = world.getBlockState(blockPosExplosion);
|
||||||
final TileEntity tileEntity = world.getTileEntity(new BlockPos((int)explosionX, (int)explosionY, (int)explosionZ));
|
final TileEntity tileEntity = world.getTileEntity(blockPosExplosion);
|
||||||
if (enableFirstHit && WarpDriveConfig.LOGGING_FORCE_FIELD) {
|
if (isFirstHit && !WarpDriveConfig.LOGGING_FORCE_FIELD) {
|
||||||
WarpDrive.logger.info(String.format("Block at location is %s %s with tileEntity %s",
|
WarpDrive.logger.info(String.format("Force field %s: explosion from %s %s with tileEntity %s",
|
||||||
blockState.getBlock(), blockState.getBlock().getTranslationKey(), tileEntity));
|
Commons.format(world, blockPos),
|
||||||
|
blockState.getBlock(), blockState.getBlock().getRegistryName(), tileEntity ));
|
||||||
}
|
}
|
||||||
// explosion with no entity and block removed, hence we can't compute the energy impact => boosting explosion resistance
|
// explosion with no entity and block removed, hence we can't compute the energy impact => boosting explosion resistance
|
||||||
return 2.0F * super.getExplosionResistance(entity, world, blockPos, explosionX, explosionY, explosionZ);
|
return 2.0F * super.getExplosionResistance(world, blockPos, exploder, explosion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity != null) {
|
if (exploder != null) {
|
||||||
switch (entity.getClass().toString()) {
|
final String nameExploder = exploder.getClass().toString();
|
||||||
|
switch (nameExploder) {
|
||||||
// Vanilla explosive
|
// Vanilla explosive
|
||||||
case "class net.minecraft.entity.item.EntityEnderCrystal": strength = 6.0D; break;
|
case "class net.minecraft.entity.item.EntityEnderCrystal": strength = 6.0D; break;
|
||||||
case "class net.minecraft.entity.item.EntityMinecartTNT": strength = 4.0D; break;
|
case "class net.minecraft.entity.item.EntityMinecartTNT": strength = 4.0D; break;
|
||||||
|
@ -431,45 +462,70 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
||||||
case "class tconstruct.mechworks.entity.item.ExplosivePrimed": strength = 5.0D; break;
|
case "class tconstruct.mechworks.entity.item.ExplosivePrimed": strength = 5.0D; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (enableFirstHit) {
|
if (isFirstHit) {
|
||||||
WarpDrive.logger.error(String.format("Unknown explosion source %s %s", entity.getClass().toString(), entity));
|
WarpDrive.logger.error(String.format("Unknown exploder instance %s %s %s",
|
||||||
|
EntityList.getKey(exploder), nameExploder, exploder ));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strength == 0.0D) {// (no exploder or not a valid one, let's check the explosion itself)
|
||||||
|
final String nameExplosion = explosion.getClass().toString();
|
||||||
|
switch (nameExplosion) {
|
||||||
|
// Vanilla explosive
|
||||||
|
case "class icbm.classic.content.explosive.blast.threaded.BlastNuclear": strength = 15.0D; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (isFirstHit) {
|
||||||
|
WarpDrive.logger.error(String.format("Unknown explosion instance %s %s %s",
|
||||||
|
vExplosion, nameExplosion, explosion ));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply damages to force field by consuming energy
|
// apply damages to force field by consuming energy
|
||||||
final Explosion explosion = new Explosion(world, entity, explosionX, explosionY, explosionZ, 4.0F);
|
final Vector3 vDirection = new Vector3(blockPos.getX() + 0.5D - vExplosion.x,
|
||||||
final Vector3 vDirection = new Vector3(x + 0.5D - explosionX, y + 0.5D - explosionY, z + 0.5D - explosionZ);
|
blockPos.getY() + 0.5D - vExplosion.y,
|
||||||
|
blockPos.getZ() + 0.5D - vExplosion.z );
|
||||||
final double magnitude = Math.max(1.0D, vDirection.getMagnitude());
|
final double magnitude = Math.max(1.0D, vDirection.getMagnitude());
|
||||||
if (magnitude != 0) {// normalize
|
if (magnitude != 0) {// normalize
|
||||||
vDirection.scale(1 / magnitude);
|
vDirection.scale(1 / magnitude);
|
||||||
}
|
}
|
||||||
final double damageLevel = strength / (magnitude * magnitude) * 1.0D;
|
final double damageLevel = strength / (magnitude * magnitude) * 1.0D;
|
||||||
double damageLeft = 0;
|
double damageLeft = 0;
|
||||||
final ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, blockPos);
|
final ForceFieldSetup forceFieldSetup = Commons.isSafeThread() ? getForceFieldSetup(world, blockPos) : null;
|
||||||
if (forceFieldSetup != null) {
|
if (forceFieldSetup != null) {
|
||||||
damageLeft = forceFieldSetup.applyDamage(world, DamageSource.setExplosionSource(explosion), damageLevel);
|
damageLeft = forceFieldSetup.applyDamage(world, DamageSource.causeExplosionDamage(explosion), damageLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert damageLeft >= 0;
|
assert damageLeft >= 0;
|
||||||
if (enableFirstHit && WarpDriveConfig.LOGGING_FORCE_FIELD) {
|
if (isFirstHit && !WarpDriveConfig.LOGGING_FORCE_FIELD) {
|
||||||
WarpDrive.logger.info(String.format("BlockForceField(%d %s) involved in explosion %s damageLevel %d damageLeft %d",
|
WarpDrive.logger.info(String.format("Force field %s %s involved in explosion %s strength %.3f magnitude %.3f damageLevel %.3f damageLeft %.3f",
|
||||||
tier, Commons.format(world, blockPos),
|
enumTier, Commons.format(world, blockPos),
|
||||||
((entity != null) ? " from " + entity : " at " + explosionX + " " + explosionY + " " + explosionZ),
|
((exploder != null) ? String.format("from %s", exploder) : String.format("from %s at %s", explosion, vExplosion)),
|
||||||
damageLevel, damageLeft));
|
strength, magnitude, damageLevel, damageLeft));
|
||||||
}
|
}
|
||||||
return super.getExplosionResistance(entity, world, blockPos, explosionX, explosionY, explosionZ);
|
return super.getExplosionResistance(world, blockPos, exploder, explosion);
|
||||||
}
|
}
|
||||||
/**/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canDropFromExplosion(final Explosion explosion) {
|
public boolean canDropFromExplosion(final Explosion explosion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEntityDestroy(final IBlockState state, final IBlockAccess world, final BlockPos pos, final Entity entity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockExploded(final World world, @Nonnull final BlockPos blockPos, @Nonnull final Explosion explosion) {
|
public void onBlockExploded(final World world, @Nonnull final BlockPos blockPos, @Nonnull final Explosion explosion) {
|
||||||
|
// weapon mods should be intercepted earlier, so we'll spam the console for now...
|
||||||
|
WarpDrive.logger.warn(String.format("Force field %s %s has exploded in explosion %s at %s, please report to mod author",
|
||||||
|
enumTier, Commons.format(world, blockPos),
|
||||||
|
explosion, explosion.getPosition() ));
|
||||||
downgrade(world, blockPos);
|
downgrade(world, blockPos);
|
||||||
super.onBlockExploded(world, blockPos, explosion);
|
super.onBlockExploded(world, blockPos, explosion);
|
||||||
}
|
}
|
||||||
|
@ -505,4 +561,15 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
||||||
|
|
||||||
return damageLevel;
|
return damageLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public float getBlockHardness(final IBlockState blockState, final World worldIn, final BlockPos pos) {
|
||||||
|
final String name = Thread.currentThread().getName();
|
||||||
|
// hide unbreakable status from ICBM explosion handler (as of ICBM-classic-1.12.2-3.3.0b63, Nuclear skip unbreakable blocks)
|
||||||
|
if (name.startsWith("ICBM")) {
|
||||||
|
return WarpDriveConfig.HULL_HARDNESS[enumTier.getIndex()];
|
||||||
|
}
|
||||||
|
return super.getBlockHardness(blockState, worldIn, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue