Merge remote-tracking branch 'origin/MC1.7' into MC1.12

This commit is contained in:
Unknown 2018-07-01 23:56:31 +02:00
commit 63158a6aaf
14 changed files with 607 additions and 68 deletions

View file

@ -109,6 +109,7 @@ import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemArmor.ArmorMaterial;

View file

@ -1,5 +1,8 @@
package cr0s.warpdrive.api;
import cr0s.warpdrive.api.computer.IShipController;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
@ -17,26 +20,30 @@ public abstract class EventWarpDrive extends Event {
public final World worldCurrent;
public final BlockPos posCurrent;
// ship stats
public final int mass;
// ship access
public final IShipController shipController;
// movement description
public final String jumpType;
public final int distance;
// movement description, see EnumShipMovementType
public final String movementType;
public Ship(final World world, final BlockPos blockPos,
final int mass, final String jumpType, final int distance) {
final IShipController shipController, final String movementType) {
super();
this.worldCurrent = world;
this.posCurrent = blockPos;
this.mass = mass;
this.jumpType = jumpType;
this.distance = distance;
this.shipController = shipController;
this.movementType = movementType;
}
// event used to update movement costs for display or an actual jump
public static class MovementCosts extends Ship {
public final int mass;
public final int distance;
// original values for reference
public final int warmup_seconds_initial;
public final int energyRequired_initial;
@ -52,13 +59,18 @@ public abstract class EventWarpDrive extends Event {
private int cooldown_seconds;
public MovementCosts(final World world, final BlockPos blockPos,
final int mass, final String jumpType, final int distance,
final IShipController shipController, final String movementType,
final int mass,
final int distance,
final int maximumDistance_blocks,
final int energyRequired,
final int warmup_seconds,
final int sickness_seconds,
final int cooldown_seconds) {
super(world, blockPos, mass, jumpType, distance);
super(world, blockPos, shipController, movementType);
this.mass = mass;
this.distance = distance;
this.warmup_seconds_initial = warmup_seconds;
this.warmup_seconds = warmup_seconds;
@ -113,6 +125,7 @@ public abstract class EventWarpDrive extends Event {
}
}
// event for canceling a jump by broad permissions, called prior to jump
@Cancelable
public static class PreJump extends Ship {
@ -120,8 +133,8 @@ public abstract class EventWarpDrive extends Event {
private final StringBuilder reason;
public PreJump(final World world, final BlockPos blockPos,
final int mass, final String jumpType, final int distance) {
super(world, blockPos, mass, jumpType, distance);
final IShipController shipController, final String movementType) {
super(world, blockPos, shipController, movementType);
this.reason = new StringBuilder();
}
@ -138,11 +151,63 @@ public abstract class EventWarpDrive extends Event {
}
}
public static class PostJump extends Ship {
// event for checking collision at target location, called during jump until a valid location is found
@Cancelable
public static class TargetCheck extends Ship {
public PostJump(final World world, final BlockPos blockPos,
final int mass, final String jumpType, final int distance) {
super(world, blockPos, mass, jumpType, distance);
// movement vector
public final int moveX;
public final int moveY;
public final int moveZ;
// target position
public final World worldTarget;
public final AxisAlignedBB aabbTarget;
// cancellation message
private final StringBuilder reason;
public TargetCheck(final World worldCurrent, final BlockPos blockPos,
final IShipController shipController, final String movementType,
final int moveX, final int moveY, final int moveZ,
final World worldTarget, final AxisAlignedBB aabbTarget) {
super(worldCurrent, blockPos, shipController, movementType);
this.moveX = moveX;
this.moveY = moveY;
this.moveZ = moveZ;
this.worldTarget = worldTarget;
this.aabbTarget = aabbTarget;
this.reason = new StringBuilder();
}
public String getReason() {
return reason.toString();
}
public void appendReason(final String reasonAdded) {
if (reason.length() > 0) {
reason.append("\n");
}
reason.append(reasonAdded);
}
}
// event reporting when a jump is cancelled or successful
public static class JumpResult extends Ship {
public final boolean isSuccessful;
public final String reason;
public JumpResult(final World world, final BlockPos blockPos,
final IShipController shipController, final String jumpType,
final boolean isSuccessful, final String reason) {
super(world, blockPos, shipController, jumpType);
this.isSuccessful = isSuccessful;
this.reason = reason;
}
}
}

View file

@ -21,5 +21,5 @@ public interface IDamageReceiver {
* Returns the remaining damage level or 0 if it was fully absorbed.
*/
int applyDamage(final IBlockState blockState, final World world, final BlockPos blockPos,
final DamageSource damageSource, final int damageParameter, final Vector3 damageDirection, final int damageLevel);
final DamageSource damageSource, final int damageParameter, final Vector3 damageDirection, final int damageLevel);
}

View file

@ -4,9 +4,12 @@ import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBeamFrequency;
import cr0s.warpdrive.api.IDamageReceiver;
import cr0s.warpdrive.block.forcefield.BlockForceField;
import cr0s.warpdrive.block.forcefield.TileEntityForceField;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.CelestialObjectManager;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.SoundEvents;
import cr0s.warpdrive.data.Vector3;
import cr0s.warpdrive.network.PacketHandler;
@ -22,19 +25,25 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.MutableBlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Optional;
@ -112,15 +121,198 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
if (isEmitting) {
energyFromOtherBeams += amount;
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(this + " Added energy " + amount);
WarpDrive.logger.info(String.format("%s Added boosting energy %d for a total accumulation of %d",
this, amount, energyFromOtherBeams));
}
} else {
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(this + " Ignored energy " + amount);
WarpDrive.logger.warn(String.format("%s Ignored boosting energy %d",
this, amount));
}
}
}
// loosely based on World.rayTraceBlocks
// - replaced byte b0 with EnumFacing
// - inverted 2nd flag
// - added force field pass through based on beamFrequency
// - increased max range from 200 to laser limit
// - code cleanup
public static RayTraceResult rayTraceBlocks(final World world, final Vec3d vSource, final Vec3d vTarget, final int beamFrequency,
final boolean stopOnLiquid, final boolean checkBlockWithoutBoundingBox, final boolean returnLastUncollidableBlock) {
// validate parameters
if (Double.isNaN(vSource.x) || Double.isNaN(vSource.y) || Double.isNaN(vSource.z)) {
return null;
}
if (Double.isNaN(vTarget.x) || Double.isNaN(vTarget.y) || Double.isNaN(vTarget.z)) {
return null;
}
// check collision at source
final int xSource = MathHelper.floor(vSource.x);
final int ySource = MathHelper.floor(vSource.y);
final int zSource = MathHelper.floor(vSource.z);
final MutableBlockPos mutableBlockPos = new MutableBlockPos(xSource, ySource, zSource);
final IBlockState blockStateSource = world.getBlockState(mutableBlockPos);
if ( (checkBlockWithoutBoundingBox || blockStateSource.getCollisionBoundingBox(world, mutableBlockPos) != Block.NULL_AABB)
&& blockStateSource.getBlock().canCollideCheck(blockStateSource, stopOnLiquid)) {
final RayTraceResult rayTraceResult = blockStateSource.collisionRayTrace(world, mutableBlockPos, vSource, vTarget);
if (rayTraceResult != null) {
return rayTraceResult;
}
}
// loop positions along trajectory
final int xTarget = MathHelper.floor(vTarget.x);
final int yTarget = MathHelper.floor(vTarget.y);
final int zTarget = MathHelper.floor(vTarget.z);
final Vector3 v3Current = new Vector3(vSource.x, vSource.y, vSource.z);
int xCurrent = xSource;
int yCurrent = ySource;
int zCurrent = zSource;
RayTraceResult rayTraceResultMissed = null;
int countLoop = WarpDriveConfig.LASER_CANNON_RANGE_MAX * 2;
while (countLoop-- >= 0) {
// sanity check
if (Double.isNaN(v3Current.x) || Double.isNaN(v3Current.y) || Double.isNaN(v3Current.z)) {
WarpDrive.logger.error(String.format("Critical error while ray tracing blocks from %s to %s in %s",
vSource, vTarget, Commons.format(world)));
return null;
}
// check arrival
if (xCurrent == xTarget && yCurrent == yTarget && zCurrent == zTarget) {
return returnLastUncollidableBlock ? rayTraceResultMissed : null;
}
// propose 1 block step along each axis
boolean hasOffsetX = true;
boolean hasOffsetY = true;
boolean hasOffsetZ = true;
double xProposed = 999.0D;
double yProposed = 999.0D;
double zProposed = 999.0D;
if (xTarget > xCurrent) {
xProposed = xCurrent + 1.0D;
} else if (xTarget < xCurrent) {
xProposed = xCurrent + 0.0D;
} else {
hasOffsetX = false;
}
if (yTarget > yCurrent) {
yProposed = yCurrent + 1.0D;
} else if (yTarget < yCurrent) {
yProposed = yCurrent + 0.0D;
} else {
hasOffsetY = false;
}
if (zTarget > zCurrent) {
zProposed = zCurrent + 1.0D;
} else if (zTarget < zCurrent) {
zProposed = zCurrent + 0.0D;
} else {
hasOffsetZ = false;
}
// compute normalized movement
double xDeltaNormalized = 999.0D;
double yDeltaNormalized = 999.0D;
double zDeltaNormalized = 999.0D;
final double xDeltaToTarget = vTarget.x - v3Current.x;
final double yDeltaToTarget = vTarget.y - v3Current.y;
final double zDeltaToTarget = vTarget.z - v3Current.z;
if (hasOffsetX) {
xDeltaNormalized = (xProposed - v3Current.x) / xDeltaToTarget;
if (xDeltaNormalized == -0.0D) {
xDeltaNormalized = -1.0E-4D;
}
}
if (hasOffsetY) {
yDeltaNormalized = (yProposed - v3Current.y) / yDeltaToTarget;
if (yDeltaNormalized == -0.0D) {
yDeltaNormalized = -1.0E-4D;
}
}
if (hasOffsetZ) {
zDeltaNormalized = (zProposed - v3Current.z) / zDeltaToTarget;
if (zDeltaNormalized == -0.0D) {
zDeltaNormalized = -1.0E-4D;
}
}
// move along shortest axis
final EnumFacing enumFacing;
if (xDeltaNormalized < yDeltaNormalized && xDeltaNormalized < zDeltaNormalized) {
enumFacing = xTarget > xSource ? EnumFacing.WEST : EnumFacing.EAST;
v3Current.x = xProposed;
v3Current.y = v3Current.y + yDeltaToTarget * xDeltaNormalized;
v3Current.z = v3Current.z + zDeltaToTarget * xDeltaNormalized;
} else if (yDeltaNormalized < zDeltaNormalized) {
enumFacing = yTarget > ySource ? EnumFacing.DOWN : EnumFacing.UP;
v3Current.x = v3Current.x + xDeltaToTarget * yDeltaNormalized;
v3Current.y = yProposed;
v3Current.z = v3Current.z + zDeltaToTarget * yDeltaNormalized;
} else {
enumFacing = zTarget > zSource ? EnumFacing.NORTH : EnumFacing.SOUTH;
v3Current.x = v3Current.x + xDeltaToTarget * zDeltaNormalized;
v3Current.y = v3Current.y + yDeltaToTarget * zDeltaNormalized;
v3Current.z = zProposed;
}
// round to block position
xCurrent = MathHelper.floor(v3Current.x) - (enumFacing == EnumFacing.EAST ? 1 : 0);
yCurrent = MathHelper.floor(v3Current.y) - (enumFacing == EnumFacing.UP ? 1 : 0);
zCurrent = MathHelper.floor(v3Current.z) - (enumFacing == EnumFacing.SOUTH ? 1 : 0);
// get current block
final IBlockState blockStateCurrent = world.getBlockState(mutableBlockPos.setPos(xCurrent, yCurrent, zCurrent));
// allow passing through force fields with same beam frequency
if (blockStateCurrent.getBlock() instanceof BlockForceField) {
final TileEntity tileEntity = world.getTileEntity(mutableBlockPos);
if (tileEntity instanceof TileEntityForceField) {
final ForceFieldSetup forceFieldSetup = ((TileEntityForceField) tileEntity).getForceFieldSetup();
if (forceFieldSetup == null) {
// projector not loaded yet, consider it jammed by default
WarpDrive.logger.warn(String.format("Laser beam stopped by non-loaded force field projector at %s", tileEntity));
} else {
if (forceFieldSetup.beamFrequency == beamFrequency) {// pass-through force field
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(String.format("Laser beam passing through force field %s", tileEntity));
}
continue;
}
}
}
}
if ( checkBlockWithoutBoundingBox
|| blockStateCurrent.getMaterial() == Material.PORTAL
|| blockStateCurrent.getCollisionBoundingBox(world, mutableBlockPos) != null) {
if (blockStateCurrent.getBlock().canCollideCheck(blockStateCurrent, stopOnLiquid)) {
final RayTraceResult rayTraceResult = blockStateCurrent.collisionRayTrace(world, mutableBlockPos, v3Current.toVec3d(), vTarget);
if (rayTraceResult != null) {
return rayTraceResult;
}
} else {
rayTraceResultMissed = new RayTraceResult(RayTraceResult.Type.MISS, v3Current.toVec3d(), enumFacing, mutableBlockPos);
}
}
}
return returnLastUncollidableBlock ? rayTraceResultMissed : null;
}
private void emitBeam(final int beamEnergy) {
int energy = beamEnergy;
@ -153,7 +345,8 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
// This is a scanning beam, do not deal damage to block nor entity
if (beamFrequency == BEAM_FREQUENCY_SCANNING) {
final RayTraceResult mopResult = world.rayTraceBlocks(vSource.toVec3d(), vReachPoint.toVec3d());
final RayTraceResult mopResult = rayTraceBlocks(world, vSource.toVec3d(), vReachPoint.toVec3d(), beamFrequency,
false, true, false);
scanResult_blockUnlocalizedName = null;
scanResult_blockMetadata = 0;
@ -196,7 +389,8 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
double distanceTravelled = 0.0D; // distance traveled from beam sender to previous hit if there were any
for (int passedBlocks = 0; passedBlocks < beamLengthBlocks; passedBlocks++) {
// Get next block hit
final RayTraceResult blockHit = world.rayTraceBlocks(vSource.toVec3d(), vReachPoint.toVec3d());
final RayTraceResult blockHit = rayTraceBlocks(world, vSource.toVec3d(), vReachPoint.toVec3d(), beamFrequency,
false, true, false);
double blockHitDistance = beamLengthBlocks + 0.1D;
if (blockHit != null) {
blockHitDistance = blockHit.hitVec.distanceTo(vSource.toVec3d());
@ -300,7 +494,7 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(String.format("Block collision found %s with block %s of hardness %.2f",
Commons.format(world, blockHit.getBlockPos()),
blockState.getBlock(), hardness));
blockState.getBlock().getRegistryName(), hardness));
}
// check area protection
@ -341,10 +535,16 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
Math.round(hardness * WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_HARDNESS));
final double absorptionChance = Commons.clamp(0.0D, WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ABSORPTION_MAX,
hardness * WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ABSORPTION_PER_BLOCK_HARDNESS);
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(String.format("Block energy cost is %d with %.1f %% of absorption",
energyCost, absorptionChance * 100.0D));
}
// apply environmental absorption
energy *= getTransmittance(blockHitDistance - distanceTravelled);
do {
// Consume energy
energy *= getTransmittance(blockHitDistance - distanceTravelled);
energy -= energyCost;
distanceTravelled = blockHitDistance;
vHitPoint = new Vector3(blockHit.hitVec);
@ -381,8 +581,8 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
// apply custom damages
if (blockState.getBlock() instanceof IDamageReceiver) {
energy = ((IDamageReceiver)blockState.getBlock()).applyDamage(blockState, world, blockHit.getBlockPos(),
WarpDrive.damageLaser, beamFrequency, vDirection, energy);
energy = ((IDamageReceiver) blockState.getBlock()).applyDamage(blockState, world, blockHit.getBlockPos(),
WarpDrive.damageLaser, beamFrequency, vDirection, energy);
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(String.format("IDamageReceiver damage applied, remaining energy is %d", energy));
}

View file

@ -228,7 +228,7 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
}
if (damagesEnergyCost > 0.0D) {
if (WarpDriveConfig.LOGGING_FORCE_FIELD) {
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(String.format("%s damages received, energy lost: %.6f", toString(), damagesEnergyCost));
}
consumeEnergy(damagesEnergyCost, false);

View file

@ -3,6 +3,7 @@ package cr0s.warpdrive.block.movement;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.TileEntitySecurityStation;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.EventWarpDrive.Ship.PreJump;
import cr0s.warpdrive.api.IStarMapRegistryTileEntity;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.ShipMovementCosts;
@ -48,6 +49,7 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@ -719,7 +721,19 @@ public class TileEntityShipCore extends TileEntityAbstractShipController impleme
}
// compute movement costs
shipMovementCosts = new ShipMovementCosts(world, pos, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared)));
shipMovementCosts = new ShipMovementCosts(world, pos,
this, shipMovementType,
shipMass, (int) Math.ceil(Math.sqrt(distanceSquared)));
// allow other mods to validate too
final PreJump preJump;
preJump = new PreJump(world, pos, this, shipMovementType.getName());
MinecraftForge.EVENT_BUS.post(preJump);
if (preJump.isCanceled()) {
reason.append(preJump.getReason());
return false;
}
return true;
}
@ -732,7 +746,9 @@ public class TileEntityShipCore extends TileEntityAbstractShipController impleme
}
// compute movement costs
final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(world, pos, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared)));
final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(world, pos,
this, shipMovementType,
shipMass, (int) Math.ceil(Math.sqrt(distanceSquared)));
return shipMovementCosts.maximumDistance_blocks;
}
@ -744,7 +760,9 @@ public class TileEntityShipCore extends TileEntityAbstractShipController impleme
}
// compute movement costs
final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(world, pos, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared)));
final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(world, pos,
this, shipMovementType,
shipMass, (int) Math.ceil(Math.sqrt(distanceSquared)));
return shipMovementCosts.energyRequired;
}

View file

@ -3,6 +3,7 @@ package cr0s.warpdrive.config;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.EventWarpDrive.Ship.MovementCosts;
import cr0s.warpdrive.api.computer.IShipController;
import cr0s.warpdrive.data.EnumShipMovementType;
import net.minecraft.util.math.BlockPos;
@ -20,7 +21,8 @@ public class ShipMovementCosts {
public final int cooldown_seconds;
public ShipMovementCosts(final World world, final BlockPos blockPos,
final int mass, final EnumShipMovementType shipMovementType, final int distance) {
final IShipController shipController, final EnumShipMovementType shipMovementType,
final int mass, final int distance) {
final Factors factorsForJumpParameters = WarpDriveConfig.SHIP_MOVEMENT_COSTS_FACTORS[shipMovementType.ordinal()];
final int maximumDistance_blocks = Commons.clamp(0, 30000000, evaluate(mass, distance, factorsForJumpParameters.maximumDistance));
final int energyRequired = Commons.clamp(0, Integer.MAX_VALUE, evaluate(mass, distance, factorsForJumpParameters.energyRequired));
@ -30,7 +32,7 @@ public class ShipMovementCosts {
// post event allowing other mods to adjust it
final MovementCosts movementCosts = new MovementCosts(world, blockPos,
mass, shipMovementType.getName(), distance,
shipController, shipMovementType.getName(), mass, distance,
maximumDistance_blocks, energyRequired, warmup_seconds, sickness_seconds, cooldown_seconds);
MinecraftForge.EVENT_BUS.post(movementCosts);
@ -52,9 +54,9 @@ public class ShipMovementCosts {
return Integer.MAX_VALUE;
}
final double value = factors[0]
+ factors[1] * mass
+ factors[2] * distance
+ factors[3] * Math.log(Math.max(1.0D, mass)) * (factors[4] != 0.0D ? Math.exp(distance / factors[4]) : 1.0D);
+ factors[1] * mass
+ factors[2] * distance
+ factors[3] * Math.log(Math.max(1.0D, mass)) * (factors[4] != 0.0D ? Math.exp(distance / factors[4]) : 1.0D);
return (int) Math.ceil(value);
}

View file

@ -142,6 +142,7 @@ public class WarpDriveConfig {
public static int G_LUA_SCRIPTS = LUA_SCRIPTS_ALL;
public static String G_SCHEMALOCATION = "warpDrive_schematics";
public static int G_BLOCKS_PER_TICK = 3500;
public static boolean G_ENABLE_PROTECTION_CHECKS = true;
// Client
public static float CLIENT_LOCATION_SCALE = 1.0F;
@ -613,6 +614,7 @@ public class WarpDriveConfig {
G_BLOCKS_PER_TICK = Commons.clamp(100, 100000,
config.get("general", "blocks_per_tick", G_BLOCKS_PER_TICK,
"Number of blocks to move per ticks, too high will cause lag spikes on ship jumping or deployment, too low may break the ship wirings").getInt());
G_ENABLE_PROTECTION_CHECKS = config.get("general", "enable_protection_checks", G_ENABLE_PROTECTION_CHECKS, "Enable area protection checks from other mods or plugins, disable if you use the event system exclusively").getBoolean(G_ENABLE_PROTECTION_CHECKS);
// Client
CLIENT_LOCATION_SCALE = Commons.clamp(0.25F, 4.0F, (float) config.get("client", "location_scale", CLIENT_LOCATION_SCALE,

View file

@ -37,7 +37,7 @@ public abstract class XmlFileManager {
final String result = XmlPreprocessor.checkModRequirements(document.getDocumentElement());
if (!result.isEmpty()) {
WarpDrive.logger.info(String.format("Skipping configuration file %s due to %s", file.getName(), result));
return;
continue;
}
XmlPreprocessor.doModReqSanitation(document);

View file

@ -186,7 +186,9 @@ public class AcceleratorSetup extends GlobalPosition {
break;
}
}
if (WarpDriveConfig.LOGGING_ACCELERATOR) {
WarpDrive.logger.info(String.format("First void shell is %s", firstVoidShell));
}
if (firstVoidShell == null) {
WarpDrive.logger.warn("No void shell connection found");
return;

View file

@ -0,0 +1,188 @@
package cr0s.warpdrive.data;
import cr0s.warpdrive.WarpDrive;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class ExtendedProperties {
public static final String IDENTIFIER = WarpDrive.MODID;
private EntityLivingBase entityLivingBase;
private GlobalPosition globalPositionHome;
private static final byte UPDATE_FLAG_ALL = 0x7F;
private static final byte UPDATE_FLAG_HOME = 0x01;
private byte updateFlags;
private static final int SYNC_DELAY_TICKS = 200; // 10 seconds
private int ticksToSync;
public ExtendedProperties() {
}
public static ExtendedProperties For(final EntityLivingBase entityLivingBase) {
return null; // (ExtendedProperties) entityLivingBase.getExtendedProperties(IDENTIFIER);
}
public void saveNBTData(final NBTTagCompound tagCompound) {
if (globalPositionHome != null) {
final NBTTagCompound nbtHome = new NBTTagCompound();
globalPositionHome.writeToNBT(nbtHome);
tagCompound.setTag("home", nbtHome);
}
}
public void loadNBTData(final NBTTagCompound tagCompound) {
if (tagCompound.hasKey("home")) {
final NBTTagCompound nbtHome = tagCompound.getCompoundTag("home");
globalPositionHome = new GlobalPosition(nbtHome);
}
}
public void init(final Entity entity, final World world) {
if ( world == null
|| !(entity instanceof EntityLivingBase)
|| entity.world == null ) {
WarpDrive.logger.error(String.format("Invalid parameters to ExtendedProperty.init(%s, %s)",
entity, world));
return;
}
entityLivingBase = (EntityLivingBase) entity;
globalPositionHome = null;
updateFlags = UPDATE_FLAG_ALL;
ticksToSync = world.rand.nextInt(SYNC_DELAY_TICKS);
}
// home
public void setHome(final int dimensionId, final int x, final int y, final int z) {
setHome(new GlobalPosition(dimensionId, x, y, z));
}
public void setHome(final GlobalPosition globalPosition) {
globalPositionHome = globalPosition;
setUpdateFlag(UPDATE_FLAG_HOME);
}
public GlobalPosition getHome() {
return globalPositionHome;
}
// synchronization
private void setUpdateFlag(final int flag) {
updateFlags |= flag;
}
public void requestFullSyncWithDelay(final int delay) {
setUpdateFlag(UPDATE_FLAG_ALL);
ticksToSync = delay;
}
public void requestFullSync() {
requestFullSyncWithDelay(0);
}
public byte[] getUpdateData() {
final byte updateFlags_save = updateFlags;
updateFlags = 0;
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
try {
dataOutputStream.writeInt(entityLivingBase.getEntityId());
dataOutputStream.writeByte(updateFlags_save);
if ((updateFlags_save & UPDATE_FLAG_HOME) != 0) {
dataOutputStream.writeBoolean(globalPositionHome != null);
if (globalPositionHome != null) {
dataOutputStream.writeInt(globalPositionHome.dimensionId);
dataOutputStream.writeInt(globalPositionHome.x);
dataOutputStream.writeInt(globalPositionHome.y);
dataOutputStream.writeInt(globalPositionHome.z);
}
}
return byteArrayOutputStream.toByteArray();
} catch (final IOException exception) {
exception.printStackTrace();
WarpDrive.logger.error(String.format("Exception while saving extended properties for entity %s",
entityLivingBase));
}
return null;
}
public boolean handleDataPacket(final byte[] data) {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
final DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
try {
final int entityId = dataInputStream.readInt();
if (entityId != entityLivingBase.getEntityId()) {
return false;
}
final int updateFlags_read = dataInputStream.readByte();
if ((updateFlags_read & UPDATE_FLAG_HOME) != 0) {
final boolean isHomeSet = dataInputStream.readBoolean();
if (isHomeSet) {
final int dimensionId = dataInputStream.readInt();
final int x = dataInputStream.readInt();
final int y = dataInputStream.readInt();
final int z = dataInputStream.readInt();
globalPositionHome = new GlobalPosition(dimensionId, x, y, z);
} else {
globalPositionHome = null;
}
}
return true;
} catch (final IOException exception) {
exception.printStackTrace();
WarpDrive.logger.error(String.format("Exception while reading extended properties for entity %s of %d bytes",
entityLivingBase, data.length));
return false;
}
}
public void handleSynchronization() {
if (entityLivingBase.world.isRemote) {
return;
}
ticksToSync--;
if (ticksToSync <= 0) {
ticksToSync = SYNC_DELAY_TICKS;
if (updateFlags != 0) {
final byte[] data = this.getUpdateData();
// @TODO PacketHandler.sendExtendedProperties(entity, data);
}
}
}
@Override
public String toString() {
try {
return hashCode() + " " + entityLivingBase;
} catch (final Exception exception) {
return hashCode() + " (error)";
}
}
}

View file

@ -322,8 +322,17 @@ public class ForceFieldSetup extends GlobalPosition {
assert damageSource != null;
final TileEntity tileEntity = world.getTileEntity(new BlockPos(x, y, z));
if (tileEntity instanceof TileEntityForceFieldProjector) {
final double scaledDamage = damageLevel * entityEnergyCost / 2000.0D;
((TileEntityForceFieldProjector)tileEntity).onEnergyDamage(scaledDamage);
final double scaledDamage;
if (damageSource.damageType.contains("explosion")) {
scaledDamage = damageLevel / 1000.0D + entityEnergyCost * 0.1D;
} else if (damageSource.damageType.contains("laser")) {
scaledDamage = damageLevel / 500.0D + entityEnergyCost * 5.0D;
} else {
WarpDrive.logger.warn(String.format("%s Unknown damage source %s '%s' %.1f",
this, damageSource, damageSource.getDamageType(), damageLevel));
scaledDamage = Commons.clamp(0, 10000, damageLevel);
}
((TileEntityForceFieldProjector) tileEntity).onEnergyDamage(scaledDamage);
return 0.0D;
}
return damageLevel;

View file

@ -42,8 +42,8 @@ public class DeploySequencer extends JumpSequencer {
}
@Override
public void disableAndMessage(final ITextComponent reason) {
super.disableAndMessage(reason);
public void disable(final boolean isSuccessful, final ITextComponent reason) {
super.disable(isSuccessful, reason);
callback.sequencer_finished();
}

View file

@ -4,8 +4,11 @@ import cr0s.warpdrive.CommonProxy;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.EventWarpDrive.Ship.JumpResult;
import cr0s.warpdrive.api.EventWarpDrive.Ship.TargetCheck;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.api.computer.IShipController;
import cr0s.warpdrive.block.movement.TileEntityShipCore;
import cr0s.warpdrive.data.CelestialObjectManager;
import cr0s.warpdrive.config.Dictionary;
@ -56,17 +59,25 @@ import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;
import net.minecraftforge.common.MinecraftForge;
public class JumpSequencer extends AbstractSequencer {
// Jump vector
protected Transformation transformation;
// movement parameters
private final EnumShipMovementType shipMovementType;
private int moveX, moveY, moveZ;
private final byte rotationSteps;
private final String nameTarget;
protected final int destX;
protected final int destY;
protected final int destZ;
// effect source
private Vector3 v3Source;
private int blocksPerTick = WarpDriveConfig.G_BLOCKS_PER_TICK;
private static final boolean enforceEntitiesPosition = false;
@ -89,10 +100,6 @@ public class JumpSequencer extends AbstractSequencer {
private boolean isPluginCheckDone = false;
private String firstAdjustmentReason = "";
protected final int destX;
protected final int destY;
protected final int destZ;
private long msCounter = 0;
private int ticks = 0;
@ -166,25 +173,41 @@ public class JumpSequencer extends AbstractSequencer {
register();
}
public void disableAndMessage(final ITextComponent textComponent) {
disable(textComponent);
public void disableAndMessage(final boolean isSuccessful, final ITextComponent textComponent) {
disable(isSuccessful, textComponent);
ship.messageToAllPlayersOnShip(textComponent);
}
public void disable(final ITextComponent textComponent) {
public void disable(final boolean isSuccessful, final ITextComponent textComponent) {
if (!isEnabled) {
return;
}
isEnabled = false;
final String formattedText = textComponent == null ? "" : textComponent.getFormattedText();
if (WarpDriveConfig.LOGGING_JUMP) {
if (textComponent == null || textComponent.getFormattedText().isEmpty()) {
WarpDrive.logger.info(this + " Killing jump sequencer...");
if (formattedText.isEmpty()) {
WarpDrive.logger.info(String.format("%s Killing jump sequencer...",
this));
} else {
WarpDrive.logger.info(this + " Killing jump sequencer... (" + textComponent.getFormattedText() + ")");
WarpDrive.logger.info(String.format("%s Killing jump sequencer... (%s)",
this, formattedText));
}
}
final JumpResult jumpResult;
if (!isSuccessful) {
jumpResult = new JumpResult(sourceWorld, ship.core,
ship.shipCore, shipMovementType.getName(), false, formattedText);
} else {
final BlockPos blockPosCoreTarget = transformation.apply(ship.core);
final TileEntity tileEntity = targetWorld.getTileEntity(blockPosCoreTarget);
final IShipController shipController = tileEntity instanceof TileEntityShipCore ? ((TileEntityShipCore) tileEntity) : null;
jumpResult = new JumpResult(targetWorld, blockPosCoreTarget,
shipController, shipMovementType.getName(), true, formattedText);
}
MinecraftForge.EVENT_BUS.post(jumpResult);
releaseChunks();
unregister();
}
@ -205,7 +228,7 @@ public class JumpSequencer extends AbstractSequencer {
if (ship.minY < 0 || ship.maxY > 255) {
final TextComponentBase msg = new TextComponentString("Invalid Y coordinate(s), check ship dimensions...");
disableAndMessage(msg);
disableAndMessage(false, msg);
return true;
}
@ -327,7 +350,7 @@ public class JumpSequencer extends AbstractSequencer {
default:
final TextComponentBase msg = new TextComponentString("Invalid state, aborting jump...");
disableAndMessage(msg);
disableAndMessage(false, msg);
return true;
}
return true;
@ -452,7 +475,7 @@ public class JumpSequencer extends AbstractSequencer {
if (!forceSourceChunks(reason)) {
final TextComponentBase msg = new TextComponentString(reason.toString());
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -470,7 +493,7 @@ public class JumpSequencer extends AbstractSequencer {
if (!ship.save(reason)) {
final ITextComponent msg = new TextComponentString(reason.toString());
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -489,7 +512,7 @@ public class JumpSequencer extends AbstractSequencer {
if (!ship.checkBorders(reason)) {
final ITextComponent msg = new TextComponentString(reason.toString());
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -565,7 +588,7 @@ public class JumpSequencer extends AbstractSequencer {
final boolean isTargetWorldFound = computeTargetWorld(celestialObjectSource, shipMovementType, reason);
if (!isTargetWorldFound) {
LocalProfiler.stop();
disableAndMessage(new TextComponentString(reason.toString()));
disableAndMessage(false, new TextComponentString(reason.toString()));
return;
}
}
@ -578,7 +601,7 @@ public class JumpSequencer extends AbstractSequencer {
LocalProfiler.stop();
final ITextComponent message = new TextComponentString(String.format("Ship is too big for a planet (max is %d blocks while ship is %d blocks)",
WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE, ship.actualMass));
disableAndMessage(message);
disableAndMessage(false, message);
return;
}
}
@ -680,7 +703,7 @@ public class JumpSequencer extends AbstractSequencer {
} else {
msg = new TextComponentString(firstAdjustmentReason + "\nNot enough space after adjustment, jump aborted!");
}
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -703,16 +726,17 @@ public class JumpSequencer extends AbstractSequencer {
(int) axisAlignedBB.minX, (int) axisAlignedBB.minY, (int) axisAlignedBB.minZ,
(int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ );
LocalProfiler.stop();
disableAndMessage(message);
disableAndMessage(false, message);
return;
}
}
}
if (!isPluginCheckDone) {
final CheckMovementResult checkMovementResult = checkCollisionAndProtection(transformation, true, "target");
final CheckMovementResult checkMovementResult = checkCollisionAndProtection(transformation, true,
"target", new VectorI(0, 0, 0));
if (checkMovementResult != null) {
final TextComponentBase msg = new TextComponentString(checkMovementResult.reason + "\nJump aborted!");
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -731,7 +755,7 @@ public class JumpSequencer extends AbstractSequencer {
if (!forceTargetChunks(reason)) {
final ITextComponent msg = new TextComponentString(reason.toString());
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -752,7 +776,7 @@ public class JumpSequencer extends AbstractSequencer {
&& shipMovementType != EnumShipMovementType.RESTORE ) {
if (!ship.saveEntities(reason)) {
final ITextComponent msg = new TextComponentString(reason.toString());
disableAndMessage(msg);
disableAndMessage(false, msg);
LocalProfiler.stop();
return;
}
@ -1117,7 +1141,8 @@ public class JumpSequencer extends AbstractSequencer {
final JumpBlock jumpBlock = ship.jumpBlocks[ship.jumpBlocks.length - actualIndexInShip - 1];
if (jumpBlock == null) {
if (WarpDriveConfig.LOGGING_JUMP) {
WarpDrive.logger.info(String.format("%s Moving ship externals: unexpected null found at ship[%d]", actualIndexInShip));
WarpDrive.logger.info(String.format("%s Moving ship externals: unexpected null found at ship[%d]",
this, actualIndexInShip));
}
actualIndexInShip++;
continue;
@ -1282,6 +1307,7 @@ public class JumpSequencer extends AbstractSequencer {
try {
// @TODO MC1.10 still leaking tile entities?
// targetWorld.loadedTileEntityList = removeDuplicates(targetWorld.loadedTileEntityList);
removeDuplicates(targetWorld.loadedTileEntityList);
} catch (final Exception exception) {
if (WarpDriveConfig.LOGGING_JUMP) {
WarpDrive.logger.info(String.format("TE Duplicates removing exception: %s", exception.getMessage()));
@ -1291,7 +1317,7 @@ public class JumpSequencer extends AbstractSequencer {
doCollisionDamage(true);
disable(new TextComponentString("Jump done"));
disable(true, new TextComponentString("Jump done"));
final int countAfter = targetWorld.loadedTileEntityList.size();
if (WarpDriveConfig.LOGGING_JUMP && countBefore != countAfter) {
WarpDrive.logger.info(String.format("Removing TE duplicates: tileEntities in target world after jump, cleanup %d -> %d",
@ -1489,12 +1515,14 @@ public class JumpSequencer extends AbstractSequencer {
isCollision = isCollision || pisCollision;
reason = preason;
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info(String.format("CheckMovementResult (%d %d %d) -> (%d %d %d) %s '%s'", sx, sy, sz, tx, ty, tz, isCollision, reason));
WarpDrive.logger.info(String.format("CheckMovementResult (%.1f %.1f %.1f) -> (%.1f %.1f %.1f) %s '%s'",
sx, sy, sz, tx, ty, tz, isCollision, reason));
}
}
}
private CheckMovementResult checkCollisionAndProtection(final ITransformation transformation, final boolean fullCollisionDetails, final String context) {
private CheckMovementResult checkCollisionAndProtection(final ITransformation transformation, final boolean fullCollisionDetails,
final String context, final VectorI vMovement) {
final CheckMovementResult result = new CheckMovementResult();
final VectorI offset = new VectorI((int) Math.signum(moveX), (int) Math.signum(moveY), (int) Math.signum(moveZ));
@ -1502,6 +1530,29 @@ public class JumpSequencer extends AbstractSequencer {
MutableBlockPos mutableBlockPosSource = new MutableBlockPos(0, 0, 0);
BlockPos blockPosTarget;
final BlockPos blockPosCoreAtTarget = transformation.apply(ship.core.getX(), ship.core.getY(), ship.core.getZ());
// post event allowing other mods to do their own checks
final BlockPos blockPosMinAtTarget = transformation.apply(ship.minX, ship.minY, ship.minZ);
final BlockPos blockPosMaxAtTarget = transformation.apply(ship.maxX, ship.maxY, ship.maxZ);
final AxisAlignedBB targetAABB = new AxisAlignedBB(
blockPosMinAtTarget.getX(), blockPosMinAtTarget.getY(), blockPosMinAtTarget.getZ(),
blockPosMaxAtTarget.getX(), blockPosMaxAtTarget.getY(), blockPosMaxAtTarget.getZ() );
final TargetCheck targetCheck = new TargetCheck(sourceWorld, ship.core,
ship.shipCore, shipMovementType.getName(),
vMovement.x, vMovement.y, vMovement.z,
targetWorld, targetAABB);
MinecraftForge.EVENT_BUS.post(targetCheck);
if (targetCheck.isCanceled()) {
result.add(ship.core.getX(), ship.core.getY(), ship.core.getZ(),
blockPosCoreAtTarget.getX(),
blockPosCoreAtTarget.getY(),
blockPosCoreAtTarget.getZ(),
false,
targetCheck.getReason() );
return result;
}
// scan target location
IBlockState blockStateSource;
IBlockState blockStateTarget;
for (y = ship.minY; y <= ship.maxY; y++) {
@ -1545,6 +1596,7 @@ public class JumpSequencer extends AbstractSequencer {
}
if ( blockStateSource.getBlock() != Blocks.AIR
&& WarpDriveConfig.G_ENABLE_PROTECTION_CHECKS
&& CommonProxy.isBlockPlaceCanceled(null, blockPosCoreAtTarget, targetWorld, blockPosTarget, blockStateSource)) {
result.add(x, y, z,
blockPosTarget.getX(),
@ -1588,7 +1640,7 @@ public class JumpSequencer extends AbstractSequencer {
}
final ITransformation testTransformation = new Transformation(ship, targetWorld, testMovement.x, testMovement.y, testMovement.z, rotationSteps);
return checkCollisionAndProtection(testTransformation, fullCollisionDetails, "ratio " + ratio + " testMovement " + testMovement);
return checkCollisionAndProtection(testTransformation, fullCollisionDetails, String.format("ratio %.3f movement %s", ratio, testMovement), testMovement);
}
private VectorI getMovementVector(final double ratio) {