From 9bd098bd4f2dbe46605a284d90dc5aaaf0be7a19 Mon Sep 17 00:00:00 2001 From: LemADEC <lemadec.fr@gmail.com> Date: Mon, 14 Aug 2017 16:12:25 +0200 Subject: [PATCH] Updated force field range to double it Improved force field memory usage Updated force field stabilisation to increase speed Added 64 blocks range cap with fusion and inversion upgrades --- build.gradle | 4 +- .../warpdrive/data/EnumForceFieldShape.java | 112 ++++++++++++++---- .../warpdrive/data/EnumForceFieldUpgrade.java | 4 +- .../cr0s/warpdrive/data/ForceFieldSetup.java | 37 +++--- 4 files changed, 111 insertions(+), 46 deletions(-) diff --git a/build.gradle b/build.gradle index 61e7ec24..0b554fe9 100644 --- a/build.gradle +++ b/build.gradle @@ -119,9 +119,9 @@ idea { } runClient { - jvmArgs "-Xmx1024m", "-Xms1024m", "-ea" + jvmArgs "-Xmx2048m", "-Xms1024m", "-ea" } runServer { - jvmArgs "-Xmx1024m", "-Xms1024m", "-ea" + jvmArgs "-Xmx2048m", "-Xms1024m", "-ea" } \ No newline at end of file diff --git a/src/main/java/cr0s/warpdrive/data/EnumForceFieldShape.java b/src/main/java/cr0s/warpdrive/data/EnumForceFieldShape.java index 4284bc98..bf1d4518 100644 --- a/src/main/java/cr0s/warpdrive/data/EnumForceFieldShape.java +++ b/src/main/java/cr0s/warpdrive/data/EnumForceFieldShape.java @@ -1,6 +1,7 @@ package cr0s.warpdrive.data; +import cr0s.warpdrive.WarpDrive; import cr0s.warpdrive.api.IForceFieldShape; import java.util.HashMap; @@ -39,13 +40,51 @@ public enum EnumForceFieldShape implements IForceFieldShape { @Override public Map<VectorI, Boolean> getVertexes(ForceFieldSetup forceFieldSetup) { - VectorI vScale = forceFieldSetup.vMax.clone().translateBack(forceFieldSetup.vMin); - Map<VectorI, Boolean> mapVertexes = new HashMap<>(vScale.x * vScale.y * vScale.z); + final VectorI vScale = forceFieldSetup.vMax.clone().translateBack(forceFieldSetup.vMin); + final boolean isFusionOrInverted = forceFieldSetup.hasFusion || forceFieldSetup.isInverted; + final int sizeEstimation; + if (!isFusionOrInverted) {// surface only + // plane surface is r^2 + // sphere surface is 4*PI*r^2 + // cylinder surface is 2*PI*r^2 + 2*PI*r*h = 2*PI*r^2 * 1.5 + // cube surface is 4*6*r^2 + final int maxRadius = 1 + (int) Math.ceil(Math.max(vScale.x, Math.max(vScale.y, vScale.z)) / 2.0F); + switch(this) { + case SPHERE: + sizeEstimation = (int) Math.ceil(4 * Math.PI * maxRadius * maxRadius); + break; + + case CYLINDER_H: + case CYLINDER_V: + case TUBE: + sizeEstimation = (int) Math.ceil(4 * Math.PI * maxRadius * maxRadius * 1.5F); + break; + + case CUBE: + case TUNNEL: + sizeEstimation = 4 * 6 * maxRadius * maxRadius; + break; + + case PLANE: + sizeEstimation = maxRadius * maxRadius; + break; + + default: + assert(false); + sizeEstimation = 8; + break; + } + } else { + sizeEstimation = vScale.x * vScale.y * vScale.z; + } + final Map<VectorI, Boolean> mapVertexes = new HashMap<>(sizeEstimation); + float radius; float halfThickness = forceFieldSetup.thickness / 2.0F; float radiusInterior2; float radiusPerimeter2; VectorI vCenter; + boolean isPerimeter; switch(this) { case SPHERE: radius = forceFieldSetup.vMax.y; @@ -53,13 +92,16 @@ public enum EnumForceFieldShape implements IForceFieldShape { radiusPerimeter2 = (radius + halfThickness) * (radius + halfThickness); vCenter = new VectorI(0, 0, 0); for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) { - int y2 = (y - vCenter.y) * (y - vCenter.y); + final int y2 = (y - vCenter.y) * (y - vCenter.y); for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) { - int x2 = (x - vCenter.x) * (x - vCenter.x); + final int x2 = (x - vCenter.x) * (x - vCenter.x); for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { - int z2 = (z - vCenter.z) * (z - vCenter.z); + final int z2 = (z - vCenter.z) * (z - vCenter.z); if (x2 + y2 + z2 <= radiusPerimeter2) { - mapVertexes.put(new VectorI(x, y, z), x2 + y2 + z2 >= radiusInterior2); + isPerimeter = x2 + y2 + z2 >= radiusInterior2; + if (isPerimeter || isFusionOrInverted) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -76,9 +118,11 @@ public enum EnumForceFieldShape implements IForceFieldShape { for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { int z2 = (z - vCenter.z) * (z - vCenter.z); if (y2 + z2 <= radiusPerimeter2) { - boolean isPerimeter = y2 + z2 >= radiusInterior2; - for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) { - mapVertexes.put(new VectorI(x, y, z), isPerimeter); + isPerimeter = y2 + z2 >= radiusInterior2; + if (isPerimeter || isFusionOrInverted) { + for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -95,9 +139,11 @@ public enum EnumForceFieldShape implements IForceFieldShape { for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) { int y2 = (y - vCenter.y) * (y - vCenter.y); if (x2 + y2 <= radiusPerimeter2) { - boolean isPerimeter = x2 + y2 >= radiusInterior2; - for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { - mapVertexes.put(new VectorI(x, y, z), isPerimeter); + isPerimeter = x2 + y2 >= radiusInterior2; + if (isPerimeter || isFusionOrInverted) { + for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -114,9 +160,11 @@ public enum EnumForceFieldShape implements IForceFieldShape { for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { int z2 = (z - vCenter.z) * (z - vCenter.z); if (x2 + z2 <= radiusPerimeter2) { - boolean isPerimeter = x2 + z2 >= radiusInterior2; - for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) { - mapVertexes.put(new VectorI(x, y, z), isPerimeter); + isPerimeter = x2 + z2 >= radiusInterior2; + if (isPerimeter || isFusionOrInverted) { + for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -133,7 +181,10 @@ public enum EnumForceFieldShape implements IForceFieldShape { for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { boolean zFace = Math.abs(z - forceFieldSetup.vMin.z) <= halfThickness || Math.abs(z - forceFieldSetup.vMax.z) <= halfThickness; - mapVertexes.put(new VectorI(x, y, z), xFace || yFace || zFace); + isPerimeter = xFace || yFace || zFace; + if (isPerimeter || isFusionOrInverted) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -141,11 +192,13 @@ public enum EnumForceFieldShape implements IForceFieldShape { case PLANE: for (int y = forceFieldSetup.vMin.y; y <= forceFieldSetup.vMax.y; y++) { - boolean yFace = Math.abs(y - forceFieldSetup.vMin.y) <= halfThickness - || Math.abs(y - forceFieldSetup.vMax.y) <= halfThickness; - for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) { - for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { - mapVertexes.put(new VectorI(x, y, z), yFace); + isPerimeter = Math.abs(y - forceFieldSetup.vMin.y) <= halfThickness + || Math.abs(y - forceFieldSetup.vMax.y) <= halfThickness; + if (isPerimeter || isFusionOrInverted) { + for (int x = forceFieldSetup.vMin.x; x <= forceFieldSetup.vMax.x; x++) { + for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -157,10 +210,12 @@ public enum EnumForceFieldShape implements IForceFieldShape { boolean xFace = Math.abs(x - forceFieldSetup.vMin.x) <= halfThickness || Math.abs(x - forceFieldSetup.vMax.x) <= halfThickness; for (int z = forceFieldSetup.vMin.z; z <= forceFieldSetup.vMax.z; z++) { - boolean isPerimeter = xFace - || Math.abs(z - forceFieldSetup.vMin.z) <= halfThickness - || Math.abs(z - forceFieldSetup.vMax.z) <= halfThickness; - mapVertexes.put(new VectorI(x, y, z), isPerimeter); + isPerimeter = xFace + || Math.abs(z - forceFieldSetup.vMin.z) <= halfThickness + || Math.abs(z - forceFieldSetup.vMax.z) <= halfThickness; + if (isPerimeter || isFusionOrInverted) { + mapVertexes.put(new VectorI(x, y, z), isPerimeter); + } } } } @@ -171,6 +226,13 @@ public enum EnumForceFieldShape implements IForceFieldShape { } + if (mapVertexes.size() > sizeEstimation) { + WarpDrive.logger.warn(String.format("Underestimated memory location lag %d > %d for shape %s with size %s, isFusionOrInverted %s. Please report this to the mod author", + mapVertexes.size(), sizeEstimation, + unlocalizedName, + vScale, + isFusionOrInverted)); + } return mapVertexes; } } diff --git a/src/main/java/cr0s/warpdrive/data/EnumForceFieldUpgrade.java b/src/main/java/cr0s/warpdrive/data/EnumForceFieldUpgrade.java index 8b994a41..4c0b56e0 100644 --- a/src/main/java/cr0s/warpdrive/data/EnumForceFieldUpgrade.java +++ b/src/main/java/cr0s/warpdrive/data/EnumForceFieldUpgrade.java @@ -39,13 +39,13 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr INVERSION ("inversion" , 1, 0, 1.0F, 1.0F, 1.250F, 1.250F, 0.000F, 0.000F, 1500.0F, 0.150F, 0.150F, 20.0F, "value is boolean"), ITEM_PORT ("item_port" , 0, 1, 1.0F, 10.0F, 0.000F, 0.000F, 0.950F, 0.900F, 50.0F, 0.120F, 0.500F, 2.0F, "value is boolean"), PUMPING ("pumping" , 0, 1, 1000.0F, 50000.0F, 0.800F, 1.000F, 0.400F, 1.000F, 800.0F, 0.150F, 4.500F, 0.0F, "value is viscosity"), - RANGE ("range" , 4, 1, 8.0F, 56.0F, 1.150F, 0.800F, 1.150F, 0.800F, 10.0F, 0.300F, 0.750F, 12.0F, "value is bonus blocks"), + RANGE ("range" , 4, 1, 8.0F, 128.0F, 1.150F, 0.450F, 1.150F, 0.450F, 10.0F, 0.300F, 0.750F, 12.0F, "value is bonus blocks"), REPULSION ("repulsion" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 5.0F, "value is acceleration"), ROTATION ("rotation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"), SHOCK ("shock" , 3, 1, 1.0F, 10.0F, 0.800F, 0.800F, 0.800F, 0.800F, 300.0F, 0.600F, 4.000F, 30.0F, "value is damage points"), SILENCER ("silencer" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.120F, 0.620F, 0.0F, "value is boolean"), SPEED ("speed" , 4, 1, 1.0F, 20.0F, 1.250F, 6.000F, 1.200F, 5.000F, 200.0F, 0.135F, 1.250F, 15.0F, "value is not used (just a counter)"), - STABILIZATION("stabilization", 0, 1, 1.0F, 6.0F, 0.250F, 0.550F, 0.025F, 0.150F, 400.0F, 0.050F, 73.600F, 0.0F, "value is boolean"), + STABILIZATION("stabilization", 0, 1, 1.0F, 9.0F, 0.250F, 0.850F, 0.025F, 0.450F, 400.0F, 0.050F, 73.600F, 0.0F, "value is boolean"), THICKNESS ("thickness" , 5, 1, 0.2F, 1.0F, 0.800F, 1.600F, 0.900F, 1.500F, 100.0F, 0.400F, 2.200F, 5.0F, "value is bonus ratio"), TRANSLATION ("translation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"), ; diff --git a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java index 84451fef..b7ca0dab 100644 --- a/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java +++ b/src/main/java/cr0s/warpdrive/data/ForceFieldSetup.java @@ -256,23 +256,6 @@ public class ForceFieldSetup extends GlobalPosition { scanSpeed = Math.min(FORCEFIELD_MAX_SCAN_SPEED_BLOCKS_PER_SECOND, scanSpeed); placeSpeed = Math.min(FORCEFIELD_MAX_PLACE_SPEED_BLOCKS_PER_SECOND, placeSpeed); - // range is maximum distance - double range = getScaledUpgrade(EnumForceFieldUpgrade.RANGE); - if (range == 0.0D) { - range = 8.0D; - v3Min = new Vector3(-1.0D, -1.0D, -1.0D); - v3Max = new Vector3( 1.0D, 1.0D, 1.0D); - } - vMin.x = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.x)) * range); - vMin.y = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.y)) * range); - vMin.z = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.z)) * range); - vMax.x = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.x)) * range); - vMax.y = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.y)) * range); - vMax.z = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.z)) * range); - vTranslation.x += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.x)) * range); - vTranslation.y += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.y)) * range); - vTranslation.z += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.z)) * range); - // acceleration is a compound of attraction and repulsion accelerationLevel = getScaledUpgrade(EnumForceFieldUpgrade.ATTRACTION) - getScaledUpgrade(EnumForceFieldUpgrade.REPULSION); @@ -289,6 +272,26 @@ public class ForceFieldSetup extends GlobalPosition { breaking_maxHardness = getScaledUpgrade(EnumForceFieldUpgrade.BREAKING); pumping_maxViscosity = getScaledUpgrade(EnumForceFieldUpgrade.PUMPING); thickness = 1.0F + getScaledUpgrade(EnumForceFieldUpgrade.THICKNESS); + + // range is maximum distance + double range = getScaledUpgrade(EnumForceFieldUpgrade.RANGE); + if (range == 0.0D) { + range = 8.0D; + v3Min = new Vector3(-1.0D, -1.0D, -1.0D); + v3Max = new Vector3( 1.0D, 1.0D, 1.0D); + } + if (hasFusion || isInverted) { + range = Math.min(64.0D, range); + } + vMin.x = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.x)) * range); + vMin.y = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.y)) * range); + vMin.z = (int) Math.round(Math.min(0.0D, Math.max(-1.0D, v3Min.z)) * range); + vMax.x = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.x)) * range); + vMax.y = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.y)) * range); + vMax.z = (int) Math.round(Math.min(1.0D, Math.max( 0.0D, v3Max.z)) * range); + vTranslation.x += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.x)) * range); + vTranslation.y += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.y)) * range); + vTranslation.z += (int) Math.round(Math.min(1.0D, Math.max(-1.0D, v3Translation.z)) * range); } public double getEntityEnergyCost(final int countEntityInteractions) {