From 8f894a7129c4e34435acbd173ccecda40df798bc Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 21 Jun 2018 11:00:51 +0200 Subject: [PATCH 01/12] Fixed 332 world not updated during cross-dimensional transportation --- .../movement/TileEntityTransporterCore.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterCore.java b/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterCore.java index 0fb6d047..b82651fe 100644 --- a/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterCore.java +++ b/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterCore.java @@ -334,8 +334,19 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen } private void state_energizing() { + // load remote world + final WorldServer worldRemote = Commons.getOrCreateWorldServer(globalPositionRemote.dimensionId); + if (worldRemote == null) { + WarpDrive.logger.error(String.format("Unable to initialize dimension %d for %s", + globalPositionRemote.dimensionId, + this)); + isJammed = true; + reasonJammed = String.format("Unable to initialize dimension %d", globalPositionRemote.dimensionId); + return; + } + // get entities - final EntityValues entityValues = updateEntitiesToEnergize(); + final EntityValues entityValues = updateEntitiesToEnergize(worldRemote); // post event on first tick if (tickEnergizing == WarpDriveConfig.TRANSPORTER_ENERGIZING_CHARGING_TICKS) { @@ -360,9 +371,9 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen // transfer at final tick if ( vRemoteScanners == null || vRemoteScanners.isEmpty() ) { - energizeEntities(lockStrengthActual, movingEntitiesLocal, worldObj, globalPositionRemote.getVectorI()); + energizeEntities(lockStrengthActual, movingEntitiesLocal, worldRemote, globalPositionRemote.getVectorI()); } else { - energizeEntities(lockStrengthActual, movingEntitiesLocal, worldObj, vRemoteScanners); + energizeEntities(lockStrengthActual, movingEntitiesLocal, worldRemote, vRemoteScanners); } if ( vLocalScanners != null && !vLocalScanners.isEmpty() ) { @@ -814,7 +825,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen vRemoteScanners = focusValuesRemote.vScanners; // update entities in range - final EntityValues entityValues = updateEntitiesToEnergize(); + final EntityValues entityValues = updateEntitiesToEnergize(worldRemote); // compute energy cost from range energyCostForAcquiring = Math.max(0, WarpDriveConfig.TRANSPORTER_LOCKING_ENERGY_FACTORS[0] @@ -1138,7 +1149,7 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen } } - private EntityValues updateEntitiesToEnergize() { + private EntityValues updateEntitiesToEnergize(final WorldServer worldRemote) { final int countLocalScanners = vLocalScanners == null ? 0 : vLocalScanners.size(); final int countScanners = vRemoteScanners == null ? countLocalScanners : Math.min(countLocalScanners, vRemoteScanners.size()); @@ -1156,7 +1167,6 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen final EntityValues entityValuesLocal = updateEntitiesOnScanners(worldObj, vLocalScanners, countScanners, movingEntitiesLocal); // collect all candidates at remote location - final World worldRemote = Commons.getOrCreateWorldServer(globalPositionRemote.dimensionId); final EntityValues entityValuesRemote; if (vRemoteScanners != null) { entityValuesRemote = updateEntitiesOnScanners(worldRemote, vRemoteScanners, countScanners, movingEntitiesRemote); @@ -1285,7 +1295,8 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen } private static Entity getCandidateEntityOnScanner(final World world, final VectorI vScanner, final HashSet entitiesOnScanners) { - if (vScanner == null) { + if ( vScanner == null + || world == null ) { return null; } @@ -1343,6 +1354,10 @@ public class TileEntityTransporterCore extends TileEntityAbstractEnergy implemen } private static LinkedHashSet getCandidateEntitiesInArea(final World world, final GlobalPosition globalPosition) { + if (world == null) { + return new LinkedHashSet<>(0); + } + final AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox( globalPosition.x - WarpDriveConfig.TRANSPORTER_ENTITY_GRAB_RADIUS_BLOCKS, globalPosition.y - 1.0D, From 85176a583262b76c964cbfdbece2ea75d58742fb Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 21 Jun 2018 11:01:39 +0200 Subject: [PATCH 02/12] Fixed transporter beacon loosing enable state on chunk loading --- .../warpdrive/block/movement/TileEntityTransporterBeacon.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterBeacon.java b/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterBeacon.java index b3d0ac27..ad1373e0 100644 --- a/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterBeacon.java +++ b/src/main/java/cr0s/warpdrive/block/movement/TileEntityTransporterBeacon.java @@ -234,6 +234,7 @@ public class TileEntityTransporterBeacon extends TileEntityAbstractEnergy implem tagCompound.setLong("uuidLeast", uuidTransporterCore.getLeastSignificantBits()); } + tagCompound.setBoolean("isEnabled", isEnabled); tagCompound.setInteger("tickDeploying", tickDeploying); } @@ -248,6 +249,7 @@ public class TileEntityTransporterBeacon extends TileEntityAbstractEnergy implem nameTransporterCore = ""; } + isEnabled = !tagCompound.hasKey("isEnabled") || tagCompound.getBoolean("isEnabled"); tickDeploying = tagCompound.getInteger("tickDeploying"); } From 4eec3f7bce1194a8429bdf9abb45963ee9927c44 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 21 Jun 2018 11:11:50 +0200 Subject: [PATCH 03/12] Code cleanup --- src/main/java/cr0s/warpdrive/data/AcceleratorSetup.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/cr0s/warpdrive/data/AcceleratorSetup.java b/src/main/java/cr0s/warpdrive/data/AcceleratorSetup.java index 3fb08e07..a99ed60f 100644 --- a/src/main/java/cr0s/warpdrive/data/AcceleratorSetup.java +++ b/src/main/java/cr0s/warpdrive/data/AcceleratorSetup.java @@ -185,7 +185,9 @@ public class AcceleratorSetup extends GlobalPosition { break; } } - WarpDrive.logger.info("First void shell is " + firstVoidShell); + if (WarpDriveConfig.LOGGING_ACCELERATOR) { + WarpDrive.logger.info("First void shell is " + firstVoidShell); + } if (firstVoidShell == null) { WarpDrive.logger.warn("No void shell connection found"); return; From 3da0d4b1ca999d9e0cd65a3acf6817fcfebac83d Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 04:32:40 +0200 Subject: [PATCH 04/12] Fixed #319 xml file loading interrupted by missing optional mods --- src/main/java/cr0s/warpdrive/config/XmlFileManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/cr0s/warpdrive/config/XmlFileManager.java b/src/main/java/cr0s/warpdrive/config/XmlFileManager.java index 1616b3fb..4bec5ad2 100644 --- a/src/main/java/cr0s/warpdrive/config/XmlFileManager.java +++ b/src/main/java/cr0s/warpdrive/config/XmlFileManager.java @@ -35,7 +35,7 @@ public abstract class XmlFileManager { final String result = XmlPreprocessor.checkModRequirements(document.getDocumentElement()); if (!result.isEmpty()) { WarpDrive.logger.info("Skipping configuration file " + file.getName() + " due to " + result); - return; + continue; } XmlPreprocessor.doModReqSanitation(document); From 35457765326a87a6a91e165babafc85079ab38e9 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 13:16:34 +0200 Subject: [PATCH 05/12] Implemented PreJump, TargetCheck & JumpResult events Fixed #341 --- .../cr0s/warpdrive/api/EventWarpDrive.java | 99 +++++++++++++++---- .../block/movement/TileEntityShipCore.java | 41 ++++++-- .../warpdrive/config/ShipMovementCosts.java | 14 +-- .../warpdrive/config/WarpDriveConfig.java | 2 + .../cr0s/warpdrive/event/DeploySequencer.java | 4 +- .../cr0s/warpdrive/event/JumpSequencer.java | 88 +++++++++++++---- 6 files changed, 193 insertions(+), 55 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/api/EventWarpDrive.java b/src/main/java/cr0s/warpdrive/api/EventWarpDrive.java index 0f139fd7..56b811bc 100644 --- a/src/main/java/cr0s/warpdrive/api/EventWarpDrive.java +++ b/src/main/java/cr0s/warpdrive/api/EventWarpDrive.java @@ -1,5 +1,8 @@ package cr0s.warpdrive.api; +import cr0s.warpdrive.api.computer.IShipController; + +import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; import cpw.mods.fml.common.eventhandler.Cancelable; @@ -19,28 +22,32 @@ public abstract class EventWarpDrive extends Event { public final int yCurrent; public final int zCurrent; - // 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 int x, final int y, final int z, - final int mass, final String jumpType, final int distance) { + final IShipController shipController, final String movementType) { super(); this.worldCurrent = world; this.xCurrent = x; this.yCurrent = y; this.zCurrent = z; - 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; @@ -56,13 +63,18 @@ public abstract class EventWarpDrive extends Event { private int cooldown_seconds; public MovementCosts(final World world, final int x, final int y, final int z, - 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, x, y, z, mass, jumpType, distance); + super(world, x, y, z, shipController, movementType); + + this.mass = mass; + this.distance = distance; this.warmup_seconds_initial = warmup_seconds; this.warmup_seconds = warmup_seconds; @@ -117,6 +129,7 @@ public abstract class EventWarpDrive extends Event { } } + // event for canceling a jump by broad permissions, called prior to jump @TODO not implemented @Cancelable public static class PreJump extends Ship { @@ -124,8 +137,8 @@ public abstract class EventWarpDrive extends Event { private final StringBuilder reason; public PreJump(final World world, final int x, final int y, final int z, - final int mass, final String jumpType, final int distance) { - super(world, x, y, z, mass, jumpType, distance); + final IShipController shipController, final String movementType) { + super(world, x, y, z, shipController, movementType); this.reason = new StringBuilder(); } @@ -142,11 +155,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 int x, final int y, final int z, - final int mass, final String jumpType, final int distance) { - super(world, x, y, z, 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 int x, final int y, final int z, + final IShipController shipController, final String movementType, + final int moveX, final int moveY, final int moveZ, + final World worldTarget, final AxisAlignedBB aabbTarget) { + super(worldCurrent, x, y, z, 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 int x, final int y, final int z, + final IShipController shipController, final String jumpType, + final boolean isSuccessful, final String reason) { + super(world, x, y, z, shipController, jumpType); + + this.isSuccessful = isSuccessful; + this.reason = reason; } } } diff --git a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java index 7ced6480..af56e851 100644 --- a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java +++ b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java @@ -2,6 +2,7 @@ package cr0s.warpdrive.block.movement; import cr0s.warpdrive.Commons; import cr0s.warpdrive.WarpDrive; +import cr0s.warpdrive.api.EventWarpDrive.Ship.PreJump; import cr0s.warpdrive.api.IStarMapRegistryTileEntity; import cr0s.warpdrive.block.TileEntityAbstractEnergy; import cr0s.warpdrive.config.Dictionary; @@ -41,6 +42,7 @@ import net.minecraft.util.Vec3; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.ForgeDirection; public class TileEntityShipCore extends TileEntityAbstractEnergy implements IStarMapRegistryTileEntity { @@ -125,12 +127,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta return; } - TileEntityShipController tileEntityShipController = tileEntityShipControllerWeakReference == null ? null : tileEntityShipControllerWeakReference.get(); - if ( tileEntityShipController != null - && tileEntityShipController.isInvalid() ) { - tileEntityShipControllerWeakReference = null; - tileEntityShipController = null; - } + TileEntityShipController tileEntityShipController = getShipController(); // Always cooldown if (cooldownTime_ticks > 0) { @@ -410,6 +407,16 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta } } + public TileEntityShipController getShipController() { + TileEntityShipController tileEntityShipController = tileEntityShipControllerWeakReference == null ? null : tileEntityShipControllerWeakReference.get(); + if ( tileEntityShipController != null + && tileEntityShipController.isInvalid() ) { + tileEntityShipControllerWeakReference = null; + tileEntityShipController = null; + } + return tileEntityShipController; + } + public boolean isOffline() { if (tileEntityShipControllerWeakReference == null) { return false; @@ -783,7 +790,19 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta } // compute movement costs - shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared))); + shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, + tileEntityShipController, shipMovementType, + shipMass, (int) Math.ceil(Math.sqrt(distanceSquared))); + + // allow other mods to validate too + final PreJump preJump; + preJump = new PreJump(worldObj, xCoord, yCoord, zCoord, getShipController(), shipMovementType.getName()); + MinecraftForge.EVENT_BUS.post(preJump); + if (preJump.isCanceled()) { + reason.append(preJump.getReason()); + return false; + } + return true; } @@ -796,7 +815,9 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta } // compute movement costs - final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared))); + final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, + tileEntityShipController, shipMovementType, + shipMass, (int) Math.ceil(Math.sqrt(distanceSquared))); return shipMovementCosts.maximumDistance_blocks; } @@ -808,7 +829,9 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy implements ISta } // compute movement costs - final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, shipMass, shipMovementType, (int) Math.ceil(Math.sqrt(distanceSquared))); + final ShipMovementCosts shipMovementCosts = new ShipMovementCosts(worldObj, xCoord, yCoord, zCoord, + tileEntityShipController, shipMovementType, + shipMass, (int) Math.ceil(Math.sqrt(distanceSquared))); return shipMovementCosts.energyRequired; } diff --git a/src/main/java/cr0s/warpdrive/config/ShipMovementCosts.java b/src/main/java/cr0s/warpdrive/config/ShipMovementCosts.java index 1ac635b3..f4fbf8ff 100644 --- a/src/main/java/cr0s/warpdrive/config/ShipMovementCosts.java +++ b/src/main/java/cr0s/warpdrive/config/ShipMovementCosts.java @@ -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.world.World; @@ -18,8 +19,9 @@ public class ShipMovementCosts { public final int sickness_seconds; public final int cooldown_seconds; - public ShipMovementCosts(final World world, final int x, final int y, final int z, - final int mass, final EnumShipMovementType shipMovementType, final int distance) { + public ShipMovementCosts(final World world, final int x, final int y, final int z, + 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)); @@ -29,7 +31,7 @@ public class ShipMovementCosts { // post event allowing other mods to adjust it final MovementCosts movementCosts = new MovementCosts(world, x, y, z, - mass, shipMovementType.getName(), distance, + shipController, shipMovementType.getName(), mass, distance, maximumDistance_blocks, energyRequired, warmup_seconds, sickness_seconds, cooldown_seconds); MinecraftForge.EVENT_BUS.post(movementCosts); @@ -51,9 +53,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); } diff --git a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java index 35b53bd7..4c4d5ef6 100644 --- a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java +++ b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java @@ -140,6 +140,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; @@ -604,6 +605,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, diff --git a/src/main/java/cr0s/warpdrive/event/DeploySequencer.java b/src/main/java/cr0s/warpdrive/event/DeploySequencer.java index 1a65efbb..e6f4ec38 100644 --- a/src/main/java/cr0s/warpdrive/event/DeploySequencer.java +++ b/src/main/java/cr0s/warpdrive/event/DeploySequencer.java @@ -39,8 +39,8 @@ public class DeploySequencer extends JumpSequencer { } @Override - public void disable(final String reason) { - super.disable(reason); + public void disable(final boolean isSuccessful, final String reason) { + super.disable(isSuccessful, reason); callback.sequencer_finished(); } diff --git a/src/main/java/cr0s/warpdrive/event/JumpSequencer.java b/src/main/java/cr0s/warpdrive/event/JumpSequencer.java index e43e60bc..6a4bf758 100644 --- a/src/main/java/cr0s/warpdrive/event/JumpSequencer.java +++ b/src/main/java/cr0s/warpdrive/event/JumpSequencer.java @@ -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; @@ -49,17 +52,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; @@ -82,10 +93,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; @@ -161,7 +168,7 @@ public class JumpSequencer extends AbstractSequencer { register(); } - public void disable(final String reason) { + public void disable(final boolean isSuccessful, final String reason) { if (!isEnabled) { return; } @@ -176,6 +183,19 @@ public class JumpSequencer extends AbstractSequencer { } } + final JumpResult jumpResult; + if (!isSuccessful) { + jumpResult = new JumpResult(sourceWorld, ship.coreX, ship.coreY, ship.coreZ, + ship.shipCore.getShipController(), shipMovementType.getName(), false, reason); + } else { + final ChunkCoordinates coordTargetCore = transformation.apply(ship.coreX, ship.coreY, ship.coreZ); + final TileEntity tileEntity = targetWorld.getTileEntity(coordTargetCore.posX, coordTargetCore.posY, coordTargetCore.posZ); + final IShipController shipController = tileEntity instanceof TileEntityShipCore ? ((TileEntityShipCore) tileEntity).getShipController() : null; + jumpResult = new JumpResult(targetWorld, coordTargetCore.posX, coordTargetCore.posY, coordTargetCore.posZ, + shipController, shipMovementType.getName(), true, reason); + } + MinecraftForge.EVENT_BUS.post(jumpResult); + releaseChunks(); unregister(); } @@ -197,7 +217,7 @@ public class JumpSequencer extends AbstractSequencer { if (ship.minY < 0 || ship.maxY > 255) { final String msg = "Invalid Y coordinate(s), check ship dimensions..."; ship.messageToAllPlayersOnShip(msg); - disable(msg); + disable(false, msg); return true; } @@ -320,7 +340,7 @@ public class JumpSequencer extends AbstractSequencer { default: final String msg = "Invalid state, aborting jump..."; ship.messageToAllPlayersOnShip(msg); - disable(msg); + disable(false, msg); return true; } return true; @@ -443,7 +463,7 @@ public class JumpSequencer extends AbstractSequencer { if (!forceSourceChunks(reason)) { final String msg = reason.toString(); - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -462,7 +482,7 @@ public class JumpSequencer extends AbstractSequencer { if (!ship.save(reason)) { final String msg = reason.toString(); - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -482,7 +502,7 @@ public class JumpSequencer extends AbstractSequencer { if (!ship.checkBorders(reason)) { final String msg = reason.toString(); - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -560,7 +580,7 @@ public class JumpSequencer extends AbstractSequencer { if (!isTargetWorldFound) { LocalProfiler.stop(); ship.messageToAllPlayersOnShip(reason.toString()); - disable(reason.toString()); + disable(false, reason.toString()); return; } } @@ -574,7 +594,7 @@ public class JumpSequencer extends AbstractSequencer { final String msg = 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); ship.messageToAllPlayersOnShip(msg); - disable(msg); + disable(false, msg); return; } } @@ -675,7 +695,7 @@ public class JumpSequencer extends AbstractSequencer { } else { msg = firstAdjustmentReason + "\nNot enough space after adjustment, jump aborted!"; } - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -700,16 +720,17 @@ public class JumpSequencer extends AbstractSequencer { (int) axisAlignedBB.maxX, (int) axisAlignedBB.maxY, (int) axisAlignedBB.maxZ ); LocalProfiler.stop(); ship.messageToAllPlayersOnShip(message); - disable(message); + disable(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 String msg = checkMovementResult.reason + "\nJump aborted!"; - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -729,7 +750,7 @@ public class JumpSequencer extends AbstractSequencer { if (!forceTargetChunks(reason)) { final String msg = reason.toString(); - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -751,7 +772,7 @@ public class JumpSequencer extends AbstractSequencer { && shipMovementType != EnumShipMovementType.RESTORE ) { if (!ship.saveEntities(reason)) { final String msg = reason.toString(); - disable(msg); + disable(false, msg); ship.messageToAllPlayersOnShip(msg); LocalProfiler.stop(); return; @@ -1260,7 +1281,7 @@ public class JumpSequencer extends AbstractSequencer { doCollisionDamage(true); - disable("Jump done"); + disable(true,"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", @@ -1460,13 +1481,37 @@ public class JumpSequencer extends AbstractSequencer { } } - 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)); int x, y, z; ChunkCoordinates coordTarget; final ChunkCoordinates coordCoreAtTarget = transformation.apply(ship.coreX, ship.coreY, ship.coreZ); + + // post event allowing other mods to do their own checks + final ChunkCoordinates coordMinAtTarget = transformation.apply(ship.minX, ship.minY, ship.minZ); + final ChunkCoordinates coordMaxAtTarget = transformation.apply(ship.maxX, ship.maxY, ship.maxZ); + final AxisAlignedBB targetAABB = AxisAlignedBB.getBoundingBox( + coordMinAtTarget.posX, coordMinAtTarget.posY, coordMinAtTarget.posZ, + coordMaxAtTarget.posX, coordMaxAtTarget.posY, coordMaxAtTarget.posZ ); + final TargetCheck targetCheck = new TargetCheck(sourceWorld, ship.coreX, ship.coreY, ship.coreZ, + ship.shipCore.getShipController(), shipMovementType.getName(), + vMovement.x, vMovement.y, vMovement.z, + targetWorld, targetAABB); + MinecraftForge.EVENT_BUS.post(targetCheck); + if (targetCheck.isCanceled()) { + result.add(ship.coreX, ship.coreY, ship.coreZ, + coordCoreAtTarget.posX, + coordCoreAtTarget.posY, + coordCoreAtTarget.posZ, + false, + targetCheck.getReason() ); + return result; + } + + // scan target location Block blockSource; Block blockTarget; for (y = ship.minY; y <= ship.maxY; y++) { @@ -1509,6 +1554,7 @@ public class JumpSequencer extends AbstractSequencer { } if ( blockSource != Blocks.air + && WarpDriveConfig.G_ENABLE_PROTECTION_CHECKS && CommonProxy.isBlockPlaceCanceled(null, coordCoreAtTarget.posX, coordCoreAtTarget.posY, coordCoreAtTarget.posZ, targetWorld, coordTarget.posX, coordTarget.posY, coordTarget.posZ, blockSource, 0) ) { result.add(x, y, z, @@ -1553,7 +1599,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) { From c42a0b6e64be83385a6f9c92e06ed5c53c39f365 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 13:19:18 +0200 Subject: [PATCH 06/12] Removed provider name from debug command --- src/main/java/cr0s/warpdrive/command/CommandDebug.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/cr0s/warpdrive/command/CommandDebug.java b/src/main/java/cr0s/warpdrive/command/CommandDebug.java index 17ca554a..0c40529f 100644 --- a/src/main/java/cr0s/warpdrive/command/CommandDebug.java +++ b/src/main/java/cr0s/warpdrive/command/CommandDebug.java @@ -63,7 +63,7 @@ public class CommandDebug extends CommandBase WarpDrive.logger.info("/" + getCommandName() + " " + dim + " " + x + "," + y + "," + z + " " + block + ":" + metadata + " " + actions); final World worldObj = DimensionManager.getWorld(dim); final TileEntity te = worldObj.getTileEntity(x, y, z); - WarpDrive.logger.info("[" + getCommandName() + "] In dimension " + worldObj.getProviderName() + " - " + worldObj.getWorldInfo().getWorldName() + ", Current block is " + WarpDrive.logger.info("[" + getCommandName() + "] In dimension " + worldObj.getWorldInfo().getWorldName() + ", Current block is " + worldObj.getBlock(x, y, z) + ":" + worldObj.getBlockMetadata(x, y, z) + ", tile entity is " + ((te == null) ? "undefined" : "defined")); final String side = FMLCommonHandler.instance().getEffectiveSide().isClient() ? "Client" : "Server"; From 59872c2be0e80c369e665c6bd9ec0e85c1445e52 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 16:39:14 +0200 Subject: [PATCH 07/12] Code cleanup --- .../cr0s/warpdrive/api/IDamageReceiver.java | 6 ++-- .../cr0s/warpdrive/block/TileEntityLaser.java | 29 ++++++++++++------- .../cr0s/warpdrive/data/ForceFieldSetup.java | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/api/IDamageReceiver.java b/src/main/java/cr0s/warpdrive/api/IDamageReceiver.java index 29860215..123579a4 100644 --- a/src/main/java/cr0s/warpdrive/api/IDamageReceiver.java +++ b/src/main/java/cr0s/warpdrive/api/IDamageReceiver.java @@ -9,15 +9,15 @@ public interface IDamageReceiver { /** * Return the block hardness to use for damage resolution. - * Useful for blocks that are unbreakable to normal tools like forcefields. + * Useful for blocks that are unbreakable to normal tools like force fields. */ - float getBlockHardness(World world, final int x, final int y, final int z, + float getBlockHardness(final World world, final int x, final int y, final int z, final DamageSource damageSource, final int damageParameter, final Vector3 damageDirection, final int damageLevel); /** * Resolve damage applied to a certain level at specific coordinates. * Returns the remaining damage level or 0 if it was fully absorbed. */ - int applyDamage(World world, final int x, final int y, final int z, + int applyDamage(final World world, final int x, final int y, final int z, final DamageSource damageSource, final int damageParameter, final Vector3 damageDirection, final int damageLevel); } diff --git a/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java b/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java index 451198c2..95b35a51 100644 --- a/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java +++ b/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java @@ -137,11 +137,13 @@ 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)); } } } @@ -312,19 +314,20 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre if (WarpDrive.fieldBlockHardness != null) { // WarpDrive.fieldBlockHardness.setAccessible(true); try { - hardness = (float)WarpDrive.fieldBlockHardness.get(block); + hardness = (float) WarpDrive.fieldBlockHardness.get(block); } catch (final IllegalArgumentException | IllegalAccessException exception) { exception.printStackTrace(); WarpDrive.logger.error("Unable to access block hardness value of " + block); } } if (block instanceof IDamageReceiver) { - hardness = ((IDamageReceiver)block).getBlockHardness(worldObj, blockHit.blockX, blockHit.blockY, blockHit.blockZ, + hardness = ((IDamageReceiver) block).getBlockHardness(worldObj, blockHit.blockX, blockHit.blockY, blockHit.blockZ, WarpDrive.damageLaser, beamFrequency, vDirection, energy); } if (WarpDriveConfig.LOGGING_WEAPON) { - WarpDrive.logger.info("Block collision found at " + blockHit.blockX + " " + blockHit.blockY + " " + blockHit.blockZ - + " with block " + block + " of hardness " + hardness); + WarpDrive.logger.info(String.format("Block collision found at (%d %d %d) with block %s of hardness %.2f", + blockHit.blockX, blockHit.blockY, blockHit.blockZ, + block.getUnlocalizedName(), hardness)); } // check area protection @@ -363,10 +366,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); @@ -377,7 +386,7 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre break; } if (WarpDriveConfig.LOGGING_WEAPON) { - WarpDrive.logger.info("Beam energy down to " + energy); + WarpDrive.logger.info(String.format("Beam energy down to %d", energy)); } // apply chance of absorption @@ -403,8 +412,8 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre // apply custom damages if (block instanceof IDamageReceiver) { - energy = ((IDamageReceiver)block).applyDamage(worldObj, blockHit.blockX, blockHit.blockY, blockHit.blockZ, - WarpDrive.damageLaser, beamFrequency, vDirection, energy); + energy = ((IDamageReceiver) block).applyDamage(worldObj, blockHit.blockX, blockHit.blockY, blockHit.blockZ, + WarpDrive.damageLaser, beamFrequency, vDirection, energy); if (WarpDriveConfig.LOGGING_WEAPON) { WarpDrive.logger.info("IDamageReceiver damage applied, remaining energy is " + energy); } diff --git a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java index 9600f9c0..5fa29abe 100644 --- a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java +++ b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java @@ -335,7 +335,7 @@ public class ForceFieldSetup extends GlobalPosition { public double applyDamage(final World world, final DamageSource damageSource, final double damageLevel) { assert(damageSource != null); - final TileEntity tileEntity = world.getTileEntity(this.x, this.y, this.z); + final TileEntity tileEntity = world.getTileEntity(x, y, z); if (tileEntity instanceof TileEntityForceFieldProjector) { final double scaledDamage = damageLevel * entityEnergyCost / 2000.0D; ((TileEntityForceFieldProjector)tileEntity).onEnergyDamage(scaledDamage); From d50d4c4bf31c8b464aa09532e25416daae28e6d5 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 17:29:04 +0200 Subject: [PATCH 08/12] Fixed laser not passing through force fields with same beam frequency --- .../cr0s/warpdrive/block/TileEntityLaser.java | 210 +++++++++++++++++- 1 file changed, 208 insertions(+), 2 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java b/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java index 95b35a51..5c44d1d3 100644 --- a/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java +++ b/src/main/java/cr0s/warpdrive/block/TileEntityLaser.java @@ -5,11 +5,14 @@ import cr0s.warpdrive.WarpDrive; import cr0s.warpdrive.api.IBeamFrequency; import cr0s.warpdrive.api.IDamageReceiver; import cr0s.warpdrive.api.IVideoChannel; +import cr0s.warpdrive.block.forcefield.BlockForceField; +import cr0s.warpdrive.block.forcefield.TileEntityForceField; import cr0s.warpdrive.block.weapon.BlockLaserCamera; import cr0s.warpdrive.block.weapon.TileEntityLaserCamera; import cr0s.warpdrive.config.Dictionary; import cr0s.warpdrive.config.WarpDriveConfig; import cr0s.warpdrive.data.CelestialObjectManager; +import cr0s.warpdrive.data.ForceFieldSetup; import cr0s.warpdrive.data.Vector3; import cr0s.warpdrive.data.VectorI; import cr0s.warpdrive.network.PacketHandler; @@ -30,11 +33,14 @@ 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.AxisAlignedBB; import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; +import net.minecraft.world.World; import cpw.mods.fml.common.Optional; @@ -148,6 +154,204 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre } } + // loosely based on World.rayTraceBlocks/func_147447_a + // - 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 MovingObjectPosition rayTraceBlocks(final World world, final Vec3 vSource, final Vec3 vTarget, final int beamFrequency, + final boolean checkLiquids, final boolean checkAir, final boolean doReturnMissed) { + // validate parameters + if (Double.isNaN(vSource.xCoord) || Double.isNaN(vSource.yCoord) || Double.isNaN(vSource.zCoord)) { + return null; + } + + if (Double.isNaN(vTarget.xCoord) || Double.isNaN(vTarget.yCoord) || Double.isNaN(vTarget.zCoord)) { + return null; + } + + // check collision at source + final int xSource = MathHelper.floor_double(vSource.xCoord); + final int ySource = MathHelper.floor_double(vSource.yCoord); + final int zSource = MathHelper.floor_double(vSource.zCoord); + final Block blockSource = world.getBlock(xSource, ySource, zSource); + final int metadataSource = world.getBlockMetadata(xSource, ySource, zSource); + + if ( (checkAir || blockSource.getCollisionBoundingBoxFromPool(world, xSource, ySource, zSource) != null) + && blockSource.canCollideCheck(metadataSource, checkLiquids)) { + final MovingObjectPosition movingObjectPosition = blockSource.collisionRayTrace(world, xSource, ySource, zSource, vSource, vTarget); + + if (movingObjectPosition != null) { + return movingObjectPosition; + } + } + + // loop positions along trajectory + final int xTarget = MathHelper.floor_double(vTarget.xCoord); + final int yTarget = MathHelper.floor_double(vTarget.yCoord); + final int zTarget = MathHelper.floor_double(vTarget.zCoord); + + final Vec3 vCurrent = Vec3.createVectorHelper(vSource.xCoord, vSource.yCoord, vSource.zCoord); + int xCurrent = xSource; + int yCurrent = ySource; + int zCurrent = zSource; + MovingObjectPosition movingObjectPositionMissed = null; + + int countLoop = WarpDriveConfig.LASER_CANNON_RANGE_MAX * 2; + while (countLoop-- >= 0) { + // sanity check + if (Double.isNaN(vCurrent.xCoord) || Double.isNaN(vCurrent.yCoord) || Double.isNaN(vCurrent.zCoord)) { + WarpDrive.logger.error(String.format("Critical error while raytracing blocks from %s to %s in %s", + vSource, vTarget, world.provider.getDimensionName())); + return null; + } + + // check arrival + if (xCurrent == xTarget && yCurrent == yTarget && zCurrent == zTarget) { + return doReturnMissed ? movingObjectPositionMissed : 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.xCoord - vCurrent.xCoord; + final double yDeltaToTarget = vTarget.yCoord - vCurrent.yCoord; + final double zDeltaToTarget = vTarget.zCoord - vCurrent.zCoord; + + if (hasOffsetX) { + xDeltaNormalized = (xProposed - vCurrent.xCoord) / xDeltaToTarget; + } + + if (hasOffsetY) { + yDeltaNormalized = (yProposed - vCurrent.yCoord) / yDeltaToTarget; + } + + if (hasOffsetZ) { + zDeltaNormalized = (zProposed - vCurrent.zCoord) / zDeltaToTarget; + } + + // move along shortest axis + final EnumFacing facing; + if (xDeltaNormalized < yDeltaNormalized && xDeltaNormalized < zDeltaNormalized) { + if (xTarget > xCurrent) { + facing = EnumFacing.WEST; + } else { + facing = EnumFacing.EAST; + } + + vCurrent.xCoord = xProposed; + vCurrent.yCoord += yDeltaToTarget * xDeltaNormalized; + vCurrent.zCoord += zDeltaToTarget * xDeltaNormalized; + } else if (yDeltaNormalized < zDeltaNormalized) { + if (yTarget > yCurrent) { + facing = EnumFacing.UP; + } else { + facing = EnumFacing.DOWN; + } + + vCurrent.xCoord += xDeltaToTarget * yDeltaNormalized; + vCurrent.yCoord = yProposed; + vCurrent.zCoord += zDeltaToTarget * yDeltaNormalized; + } else { + if (zTarget > zCurrent) { + facing = EnumFacing.SOUTH; + } else { + facing = EnumFacing.NORTH; + } + + vCurrent.xCoord += xDeltaToTarget * zDeltaNormalized; + vCurrent.yCoord += yDeltaToTarget * zDeltaNormalized; + vCurrent.zCoord = zProposed; + } + + // round to block position + xCurrent = MathHelper.floor_double(vCurrent.xCoord); + if (facing == EnumFacing.EAST) { + xCurrent--; + } + + yCurrent = MathHelper.floor_double(vCurrent.yCoord); + if (facing == EnumFacing.DOWN) { + yCurrent--; + } + + zCurrent = MathHelper.floor_double(vCurrent.zCoord); + if (facing == EnumFacing.NORTH) { + zCurrent--; + } + + // get current block + final Block blockCurrent = world.getBlock(xCurrent, yCurrent, zCurrent); + final int metadataCurrent = world.getBlockMetadata(xCurrent, yCurrent, zCurrent); + + // allow passing through force fields with same beam frequency + if (blockCurrent instanceof BlockForceField) { + final TileEntity tileEntity = world.getTileEntity(xCurrent, yCurrent, zCurrent); + 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 (checkAir || blockCurrent.getCollisionBoundingBoxFromPool(world, xCurrent, yCurrent, zCurrent) != null) { + if (blockCurrent.canCollideCheck(metadataCurrent, checkLiquids)) { + final MovingObjectPosition movingObjectPosition = blockCurrent.collisionRayTrace(world, xCurrent, yCurrent, zCurrent, vCurrent, vTarget); + if (movingObjectPosition != null) { + return movingObjectPosition; + } + } else { + movingObjectPositionMissed = new MovingObjectPosition(xCurrent, yCurrent, zCurrent, facing.ordinal(), vCurrent, false); + } + } + } + + return doReturnMissed ? movingObjectPositionMissed : null; + } + private void emitBeam(final int beamEnergy) { int energy = beamEnergy; @@ -180,7 +384,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 MovingObjectPosition mopResult = worldObj.rayTraceBlocks(vSource.toVec3(), vReachPoint.toVec3()); + final MovingObjectPosition mopResult = rayTraceBlocks(worldObj, vSource.toVec3(), vReachPoint.toVec3(), beamFrequency, + false, true, false); scanResult_blockUnlocalizedName = null; scanResult_blockMetadata = 0; @@ -224,7 +429,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 MovingObjectPosition blockHit = worldObj.rayTraceBlocks(vSource.toVec3(), vReachPoint.toVec3()); + final MovingObjectPosition blockHit = rayTraceBlocks(worldObj, vSource.toVec3(), vReachPoint.toVec3(), beamFrequency, + false, true, false); double blockHitDistance = beamLengthBlocks + 0.1D; if (blockHit != null) { blockHitDistance = blockHit.hitVec.distanceTo(vSource.toVec3()); From 3d5e483b5afc592c211f58403472469ce3b55d0f Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 17:30:46 +0200 Subject: [PATCH 09/12] Increased force field damage from lasers by 4x, from explosion by 2x --- .../java/cr0s/warpdrive/data/ForceFieldSetup.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java index 5fa29abe..a963322b 100644 --- a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java +++ b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java @@ -337,8 +337,17 @@ public class ForceFieldSetup extends GlobalPosition { assert(damageSource != null); final TileEntity tileEntity = world.getTileEntity(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; From 7c2cb9c4e4f751f8f11f312b93dbc58f720bd787 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 17:31:56 +0200 Subject: [PATCH 10/12] Improved weapon logs to include force field damages --- .../block/forcefield/TileEntityForceFieldProjector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/cr0s/warpdrive/block/forcefield/TileEntityForceFieldProjector.java b/src/main/java/cr0s/warpdrive/block/forcefield/TileEntityForceFieldProjector.java index e3413bad..099aef8b 100644 --- a/src/main/java/cr0s/warpdrive/block/forcefield/TileEntityForceFieldProjector.java +++ b/src/main/java/cr0s/warpdrive/block/forcefield/TileEntityForceFieldProjector.java @@ -210,7 +210,7 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField } if (damagesEnergyCost > 0.0D) { - if (WarpDriveConfig.LOGGING_FORCEFIELD) { + if (WarpDriveConfig.LOGGING_WEAPON) { WarpDrive.logger.info(String.format("%s damages received, energy lost: %.6f", toString(), damagesEnergyCost)); } consumeEnergy(damagesEnergyCost, false); From 06cea1161b4b3a15fd31d9d2e20320041fb88a15 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 18:27:34 +0200 Subject: [PATCH 11/12] Added prototype for player homes --- .../warpdrive/data/ExtendedProperties.java | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/main/java/cr0s/warpdrive/data/ExtendedProperties.java diff --git a/src/main/java/cr0s/warpdrive/data/ExtendedProperties.java b/src/main/java/cr0s/warpdrive/data/ExtendedProperties.java new file mode 100644 index 00000000..54a811c4 --- /dev/null +++ b/src/main/java/cr0s/warpdrive/data/ExtendedProperties.java @@ -0,0 +1,195 @@ +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 net.minecraftforge.common.IExtendedEntityProperties; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ExtendedProperties implements IExtendedEntityProperties { + + 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 (ExtendedProperties) entityLivingBase.getExtendedProperties(IDENTIFIER); + } + + + // IExtendedEntityProperties overrides + + @Override + public void saveNBTData(final NBTTagCompound tagCompound) { + if (globalPositionHome != null) { + final NBTTagCompound nbtHome = new NBTTagCompound(); + globalPositionHome.writeToNBT(nbtHome); + tagCompound.setTag("home", nbtHome); + } + } + + @Override + public void loadNBTData(final NBTTagCompound tagCompound) { + if (tagCompound.hasKey("home")) { + final NBTTagCompound nbtHome = tagCompound.getCompoundTag("home"); + globalPositionHome = new GlobalPosition(nbtHome); + } + } + + @Override + public void init(final Entity entity, final World world) { + if ( world == null + || !(entity instanceof EntityLivingBase) + || entity.worldObj == 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.worldObj.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)"; + } + } +} From 90abf4fcde95537419275a2beb30fc8ec3fbb27b Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 1 Jul 2018 18:27:54 +0200 Subject: [PATCH 12/12] Version bump to 1.4.2 --- build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.properties b/build.properties index eb65b9ae..a656909c 100644 --- a/build.properties +++ b/build.properties @@ -1,4 +1,4 @@ # minecraft_version=1.7.10 forge_version=10.13.4.1492-1.7.10 -mod_version=1.4.1 +mod_version=1.4.2