diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 29dad558e5..b64e8feca4 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -6,15 +6,15 @@ on: - 'v*' jobs: - buildJava14: + deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up JDK 14 + - name: Set up JDK 16 uses: actions/setup-java@v1 with: - java-version: 14 + java-version: 16 - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Add Arc release diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f769d87b6a..5888db4507 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -3,15 +3,15 @@ name: Pull Request Tests on: [pull_request, workflow_dispatch] jobs: - buildJava14: + testPR: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up JDK 14 + - name: Set up JDK 16 uses: actions/setup-java@v1 with: - java-version: 14 + java-version: 16 - name: Run unit tests and build JAR run: ./gradlew test desktop:dist - name: Upload desktop JAR for testing diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d300e57e24..1409aef4ff 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -3,7 +3,7 @@ name: Tests on: [push, workflow_dispatch] jobs: - buildJava14: + runPush: runs-on: ubuntu-latest steps: @@ -17,9 +17,9 @@ jobs: git tag ${BNUM} git config --global user.name "Build Uploader" git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM} - - name: Set up JDK 14 + - name: Set up JDK 16 uses: actions/setup-java@v1 with: - java-version: 14 + java-version: 16 - name: Run unit tests run: ./gradlew clean cleanTest test diff --git a/README.md b/README.md index b6b3e26597..575f421530 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md). Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). If you'd rather compile on your own, follow these instructions. -First, make sure you have [JDK 14](https://adoptopenjdk.net/archive.html?variant=openjdk14&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands: +First, make sure you have [JDK 16](https://adoptopenjdk.net/archive.html?variant=openjdk16&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands: ### Windows diff --git a/android/build.gradle b/android/build.gradle index 0196805db9..a4de97915b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,9 +7,7 @@ buildscript{ } dependencies{ - //IMPORTANT NOTICE: any version of the plugin after 3.4.1 will break builds - //it appears abstract methods don't get desugared properly (if at all) - classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.android.tools.build:gradle:7.1.0-alpha02' } } diff --git a/android/src/mindustry/android/AndroidRhinoContext.java b/android/src/mindustry/android/AndroidRhinoContext.java index 1b845d61cf..ab28532941 100644 --- a/android/src/mindustry/android/AndroidRhinoContext.java +++ b/android/src/mindustry/android/AndroidRhinoContext.java @@ -62,13 +62,6 @@ public class AndroidRhinoContext{ initApplicationClassLoader(createClassLoader(AndroidContextFactory.class.getClassLoader())); } - @Override - protected Context makeContext(){ - Context ctx = super.makeContext(); - ctx.setClassShutter(Scripts::allowClass); - return ctx; - } - /** * Create a ClassLoader which is able to deal with bytecode * @param parent the parent of the create classloader diff --git a/build.gradle b/build.gradle index 950d2cda44..f93082e0fa 100644 --- a/build.gradle +++ b/build.gradle @@ -196,12 +196,7 @@ allprojects{ tasks.withType(JavaCompile){ targetCompatibility = 8 - //TODO fix dynamically, this is a hack - if(System.getProperty("user.name") == "anuke"){ - sourceCompatibility = JavaVersion.VERSION_15 - }else{ - sourceCompatibility = JavaVersion.VERSION_14 - } + sourceCompatibility = JavaVersion.VERSION_16 options.encoding = "UTF-8" options.compilerArgs += ["-Xlint:deprecation"] dependsOn clearCache @@ -224,18 +219,13 @@ configure(project(":annotations")){ //compile with java 8 compatibility for everything except the annotation project configure(subprojects - project(":annotations")){ tasks.withType(JavaCompile){ - options.compilerArgs.addAll(['--release', '8', '--enable-preview']) - - doFirst{ - options.compilerArgs = options.compilerArgs.findAll{it != '--enable-preview' } - } + options.compilerArgs.addAll(['--release', '8']) } tasks.withType(Javadoc){ options{ addStringOption('Xdoclint:none', '-quiet') - addBooleanOption('-enable-preview', true) - addStringOption('-release', '14') + addStringOption('-release', '16') } } } @@ -302,9 +292,8 @@ project(":core"){ kapt{ javacOptions{ - option("-source", "14") + option("-source", "16") option("-target", "1.8") - option("--enable-preview") } } @@ -430,6 +419,8 @@ project(":tests"){ } test{ + //fork every test so mods don't interact with each other + forkEvery = 1 useJUnitPlatform() workingDir = new File("../core/assets") testLogging{ diff --git a/core/src/mindustry/ClientLauncher.java b/core/src/mindustry/ClientLauncher.java index 6042a38b19..71b04314a8 100644 --- a/core/src/mindustry/ClientLauncher.java +++ b/core/src/mindustry/ClientLauncher.java @@ -83,7 +83,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform Fonts.loadDefaultFont(); //load fallback atlas if max texture size is below 4096 - assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = (TextureAtlas)t; + assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = (TextureAtlas)t; assets.loadRun("maps", Map.class, () -> maps.loadPreviews()); Musics.load(); diff --git a/core/src/mindustry/ai/BaseAI.java b/core/src/mindustry/ai/BaseAI.java index bebbdc1e8c..6ca2a5a751 100644 --- a/core/src/mindustry/ai/BaseAI.java +++ b/core/src/mindustry/ai/BaseAI.java @@ -289,7 +289,7 @@ public class BaseAI{ } Tile o = world.tile(tile.x + p.x, tile.y + p.y); - if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor)){ + if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor || o.block() instanceof ShockMine)){ continue outer; } diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index bd283e80e9..16e1af2d52 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -16,7 +16,6 @@ import mindustry.world.blocks.defense.*; import mindustry.world.blocks.defense.turrets.*; import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.environment.*; -import mindustry.world.blocks.experimental.*; import mindustry.world.blocks.legacy.*; import mindustry.world.blocks.liquid.*; import mindustry.world.blocks.logic.*; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index e6bffdedd4..b5225e6b85 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -612,9 +612,9 @@ public class UnitTypes implements ContentList{ bullet = new LiquidBulletType(Liquids.slag){{ damage = 11; speed = 2.4f; - drag = 0.01f; + drag = 0.009f; shootEffect = Fx.shootSmall; - lifetime = 56f; + lifetime = 57f; collidesAir = false; }}; }}); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 93fa1e68a2..a416b5d2fd 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -323,13 +323,14 @@ public class Control implements ApplicationListener, Loadable{ if(slot != null && !clearSectors){ try{ + boolean hadNoCore = !sector.info.hasCore; reloader.begin(); slot.load(); slot.setAutosave(true); state.rules.sector = sector; //if there is no base, simulate a new game and place the right loadout at the spawn position - if(state.rules.defaultTeam.cores().isEmpty()){ + if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){ //no spawn set -> delete the sector save if(sector.info.spawnPosition == 0){ diff --git a/core/src/mindustry/core/Platform.java b/core/src/mindustry/core/Platform.java index a595668aa8..bbceee8a64 100644 --- a/core/src/mindustry/core/Platform.java +++ b/core/src/mindustry/core/Platform.java @@ -79,15 +79,6 @@ public interface Platform{ } default Context getScriptContext(){ - ContextFactory.getGlobalSetter().setContextFactoryGlobal(new ContextFactory(){ - @Override - protected Context makeContext(){ - Context ctx = super.makeContext(); - ctx.setClassShutter(Scripts::allowClass); - return ctx; - } - }); - Context c = Context.enter(); c.setOptimizationLevel(9); return c; diff --git a/core/src/mindustry/editor/MapGenerateDialog.java b/core/src/mindustry/editor/MapGenerateDialog.java index 71f4f60264..31af738182 100644 --- a/core/src/mindustry/editor/MapGenerateDialog.java +++ b/core/src/mindustry/editor/MapGenerateDialog.java @@ -164,7 +164,7 @@ public class MapGenerateDialog extends BaseDialog{ for(int x = 0; x < editor.width(); x++){ for(int y = 0; y < editor.height(); y++){ Tile tile = editor.tile(x, y); - input.apply(x, y, tile.block(), tile.floor(), tile.overlay()); + input.set(x, y, tile.block(), tile.floor(), tile.overlay()); filter.apply(input); writeTiles[x + y*world.width()] = PackTile.get(input.block.id, input.floor.id, input.overlay.id); } @@ -340,6 +340,7 @@ public class MapGenerateDialog extends BaseDialog{ if(filter.isPost() && applied) continue; p.button((icon == '\0' ? "" : icon + " ") + filter.name(), Styles.cleart, () -> { + filter.randomize(); filters.add(filter); rebuildFilters(); update(); @@ -419,7 +420,7 @@ public class MapGenerateDialog extends BaseDialog{ pixmap.each((px, py) -> { int x = px * scaling, y = py * scaling; long tile = buffer1[px + py * w]; - input.apply(x, y, content.block(PackTile.block(tile)), content.block(PackTile.floor(tile)), content.block(PackTile.overlay(tile))); + input.set(x, y, content.block(PackTile.block(tile)), content.block(PackTile.floor(tile)), content.block(PackTile.overlay(tile))); filter.apply(input); buffer2[px + py * w] = PackTile.get(input.block.id, input.floor.id, input.overlay.id); }); diff --git a/core/src/mindustry/editor/MapInfoDialog.java b/core/src/mindustry/editor/MapInfoDialog.java index a18828f1f0..da4bf5a4b3 100644 --- a/core/src/mindustry/editor/MapInfoDialog.java +++ b/core/src/mindustry/editor/MapInfoDialog.java @@ -3,6 +3,7 @@ package mindustry.editor; import arc.*; import arc.scene.ui.*; import arc.struct.*; +import arc.util.*; import mindustry.*; import mindustry.game.*; import mindustry.io.*; @@ -73,8 +74,12 @@ public class MapInfoDialog extends BaseDialog{ t.row(); t.add("@editor.generation").padRight(8).left(); t.button("@edit", () -> { - generate.show(Vars.maps.readFilters(editor.tags.get("genfilters", "")), - filters -> editor.tags.put("genfilters", JsonIO.write(filters))); + generate.show(maps.readFilters(editor.tags.get("genfilters", "")), + filters -> { + //reset seed to 0 so it is not written + filters.each(f -> f.seed = 0); + editor.tags.put("genfilters", JsonIO.write(filters)); + }); hide(); }).left().width(200f); diff --git a/core/src/mindustry/entities/effect/ParticleEffect.java b/core/src/mindustry/entities/effect/ParticleEffect.java index a6e5df24a8..2b8fd4e52d 100644 --- a/core/src/mindustry/entities/effect/ParticleEffect.java +++ b/core/src/mindustry/entities/effect/ParticleEffect.java @@ -59,12 +59,12 @@ public class ParticleEffect extends Effect{ Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> { Lines.lineAngle(ox + x, oy + y, Mathf.angle(x, y), len); - Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity); + Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity* Draw.getColor().a); }); }else{ Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> { Draw.rect(tex, ox + x, oy + y, rad, rad, e.rotation + offset + e.time * spin); - Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity); + Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity * Draw.getColor().a); }); } } diff --git a/core/src/mindustry/graphics/CacheLayer.java b/core/src/mindustry/graphics/CacheLayer.java index 31b8074196..a68b7f6e06 100644 --- a/core/src/mindustry/graphics/CacheLayer.java +++ b/core/src/mindustry/graphics/CacheLayer.java @@ -3,6 +3,7 @@ package mindustry.graphics; import arc.*; import arc.graphics.*; import arc.graphics.gl.*; +import arc.util.*; import static mindustry.Vars.*; @@ -53,7 +54,7 @@ public class CacheLayer{ } public static class ShaderLayer extends CacheLayer{ - public Shader shader; + public @Nullable Shader shader; public ShaderLayer(Shader shader){ //shader will be null on headless backend, but that's ok diff --git a/core/src/mindustry/graphics/MenuRenderer.java b/core/src/mindustry/graphics/MenuRenderer.java index 307b337028..3bb562bde1 100644 --- a/core/src/mindustry/graphics/MenuRenderer.java +++ b/core/src/mindustry/graphics/MenuRenderer.java @@ -44,9 +44,7 @@ public class MenuRenderer implements Disposable{ Seq ores = content.blocks().select(b -> b instanceof OreBlock && !(b instanceof WallOreBlock)); shadows = new FrameBuffer(width, height); int offset = Mathf.random(100000); - Simplex s1 = new Simplex(offset); - Simplex s2 = new Simplex(offset + 1); - Simplex s3 = new Simplex(offset + 2); + int s1 = offset, s2 = offset + 1, s3 = offset + 2; Block[] selected = Structs.select( new Block[]{Blocks.sand, Blocks.sandWall}, new Block[]{Blocks.shale, Blocks.shaleWall}, @@ -85,27 +83,27 @@ public class MenuRenderer implements Disposable{ Block ore = Blocks.air; Block wall = Blocks.air; - if(s1.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){ + if(Simplex.noise2d(s1, 3, 0.5, 1/20.0, x, y) > 0.5){ wall = walld; } - if(s3.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){ + if(Simplex.noise2d(s3, 3, 0.5, 1/20.0, x, y) > 0.5){ floor = floord2; if(wall != Blocks.air){ wall = walld2; } } - if(s2.octaveNoise2D(3, 0.3, 1/30.0, x, y) > tr1){ + if(Simplex.noise2d(s2, 3, 0.3, 1/30.0, x, y) > tr1){ ore = ore1; } - if(s2.octaveNoise2D(2, 0.2, 1/15.0, x, y+99999) > tr2){ + if(Simplex.noise2d(s2, 2, 0.2, 1/15.0, x, y+99999) > tr2){ ore = ore2; } if(doheat){ - double heat = s3.octaveNoise2D(4, 0.6, 1 / 50.0, x, y + 9999); + double heat = Simplex.noise2d(s3, 4, 0.6, 1 / 50.0, x, y + 9999); double base = 0.65; if(heat > base){ @@ -126,7 +124,7 @@ public class MenuRenderer implements Disposable{ if(tech){ int mx = x % secSize, my = y % secSize; int sclx = x / secSize, scly = y / secSize; - if(s1.octaveNoise2D(2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){ + if(Simplex.noise2d(s1, 2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){ floor = Blocks.darkPanel3; if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 1){ floor = Blocks.darkPanel4; @@ -140,7 +138,7 @@ public class MenuRenderer implements Disposable{ } if(tendrils){ - if(RidgedPerlin.noise2d(1 + offset, x, y, 1f / 17f) > 0f){ + if(Ridged.noise2d(1 + offset, x, y, 1f / 17f) > 0f){ floor = Mathf.chance(0.2) ? Blocks.sporeMoss : Blocks.moss; if(wall != Blocks.air){ diff --git a/core/src/mindustry/graphics/g3d/SunMesh.java b/core/src/mindustry/graphics/g3d/SunMesh.java index bef0761d5f..6b00aa3885 100644 --- a/core/src/mindustry/graphics/g3d/SunMesh.java +++ b/core/src/mindustry/graphics/g3d/SunMesh.java @@ -12,7 +12,6 @@ public class SunMesh extends HexMesh{ public SunMesh(Planet planet, int divisions, double octaves, double persistence, double scl, double pow, double mag, float colorScale, Color... colors){ super(planet, new HexMesher(){ - Simplex sim = new Simplex(); @Override public float getHeight(Vec3 position){ @@ -21,7 +20,7 @@ public class SunMesh extends HexMesh{ @Override public Color getColor(Vec3 position){ - double height = Math.pow(sim.octaveNoise3D(octaves, persistence, scl, position.x, position.y, position.z), pow) * mag; + double height = Math.pow(Simplex.noise3d(0, octaves, persistence, scl, position.x, position.y, position.z), pow) * mag; return Tmp.c1.set(colors[Mathf.clamp((int)(height * colors.length), 0, colors.length - 1)]).mul(colorScale); } }, divisions, Shaders.unlit); diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 43a90298bc..b5695d9773 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -28,9 +28,6 @@ import static mindustry.Vars.*; public class LExecutor{ public static final int maxInstructions = 1000; - //for noise operations - public static final Simplex noise = new Simplex(); - //special variables public static final int varCounter = 0, diff --git a/core/src/mindustry/logic/LogicOp.java b/core/src/mindustry/logic/LogicOp.java index 2de33558b9..9604279584 100644 --- a/core/src/mindustry/logic/LogicOp.java +++ b/core/src/mindustry/logic/LogicOp.java @@ -2,6 +2,7 @@ package mindustry.logic; import arc.math.*; import arc.util.*; +import arc.util.noise.*; public enum LogicOp{ add("+", (a, b) -> a + b), @@ -32,7 +33,7 @@ public enum LogicOp{ min("min", true, Math::min), angle("angle", true, (x, y) -> Angles.angle((float)x, (float)y)), len("len", true, (x, y) -> Mathf.dst((float)x, (float)y)), - noise("noise", true, LExecutor.noise::rawNoise2D), + noise("noise", true, (x, y) -> Simplex.raw2d(0, x, y)), abs("abs", a -> Math.abs(a)), log("log", Math::log), log10("log10", Math::log10), diff --git a/core/src/mindustry/maps/filters/BlendFilter.java b/core/src/mindustry/maps/filters/BlendFilter.java index d8d1ceda9e..7f0d319df9 100644 --- a/core/src/mindustry/maps/filters/BlendFilter.java +++ b/core/src/mindustry/maps/filters/BlendFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,12 +12,12 @@ public class BlendFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), - new BlockOption("block", () -> block, b -> block = b, anyOptional), - new BlockOption("floor", () -> floor, b -> floor = b, anyOptional), - new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional) - ); + return new FilterOption[]{ + new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), + new BlockOption("block", () -> block, b -> block = b, anyOptional), + new BlockOption("floor", () -> floor, b -> floor = b, anyOptional), + new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional) + }; } @Override @@ -32,7 +31,7 @@ public class BlendFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ if(in.floor == block || block == Blocks.air || in.floor == ignore || (!floor.isFloor() && (in.block == block || in.block == ignore))) return; int rad = (int)radius; diff --git a/core/src/mindustry/maps/filters/ClearFilter.java b/core/src/mindustry/maps/filters/ClearFilter.java index 59e1a5b53c..3b2684ef7e 100644 --- a/core/src/mindustry/maps/filters/ClearFilter.java +++ b/core/src/mindustry/maps/filters/ClearFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -12,7 +11,9 @@ public class ClearFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr(new BlockOption("block", () -> block, b -> block = b, b -> oresOnly.get(b) || wallsOnly.get(b))); + return new BlockOption[]{ + new BlockOption("block", () -> block, b -> block = b, b -> oresOnly.get(b) || wallsOnly.get(b)) + }; } @Override @@ -21,7 +22,7 @@ public class ClearFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ if(in.block == block){ in.block = Blocks.air; diff --git a/core/src/mindustry/maps/filters/CoreSpawnFilter.java b/core/src/mindustry/maps/filters/CoreSpawnFilter.java index 84447ea1f3..5e18726d45 100644 --- a/core/src/mindustry/maps/filters/CoreSpawnFilter.java +++ b/core/src/mindustry/maps/filters/CoreSpawnFilter.java @@ -1,7 +1,6 @@ package mindustry.maps.filters; import arc.struct.*; -import arc.util.*; import mindustry.gen.*; import mindustry.world.*; import mindustry.world.blocks.storage.*; @@ -14,10 +13,9 @@ public class CoreSpawnFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( //disabled until necessary // SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display() - ); + return new FilterOption[]{}; } @Override diff --git a/core/src/mindustry/maps/filters/DistortFilter.java b/core/src/mindustry/maps/filters/DistortFilter.java index 4ae9c5a1d2..8b6d80e8e1 100644 --- a/core/src/mindustry/maps/filters/DistortFilter.java +++ b/core/src/mindustry/maps/filters/DistortFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.gen.*; import mindustry.maps.filters.FilterOption.*; import mindustry.world.*; @@ -10,10 +9,10 @@ public class DistortFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 200f), - new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) - ); + return new SliderOption[]{ + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 200f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) + }; } @Override @@ -27,8 +26,8 @@ public class DistortFilter extends GenerateFilter{ } @Override - public void apply(){ - Tile tile = in.tile(in.x + noise(in.x, in.y, scl, mag) - mag / 2f, in.y + noise(in.x, in.y + o, scl, mag) - mag / 2f); + public void apply(GenerateInput in){ + Tile tile = in.tile(in.x + noise(in, scl, mag) - mag / 2f, in.y + noise(in, scl, mag) - mag / 2f); in.floor = tile.floor(); if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); diff --git a/core/src/mindustry/maps/filters/EnemySpawnFilter.java b/core/src/mindustry/maps/filters/EnemySpawnFilter.java index 682d82debf..7d2a5d8d1d 100644 --- a/core/src/mindustry/maps/filters/EnemySpawnFilter.java +++ b/core/src/mindustry/maps/filters/EnemySpawnFilter.java @@ -1,7 +1,6 @@ package mindustry.maps.filters; import arc.struct.*; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.maps.filters.FilterOption.*; @@ -13,9 +12,9 @@ public class EnemySpawnFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display() - ); + return new SliderOption[]{ + new SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display() + }; } @Override diff --git a/core/src/mindustry/maps/filters/GenerateFilter.java b/core/src/mindustry/maps/filters/GenerateFilter.java index b938914528..cdddad9099 100644 --- a/core/src/mindustry/maps/filters/GenerateFilter.java +++ b/core/src/mindustry/maps/filters/GenerateFilter.java @@ -12,12 +12,9 @@ import mindustry.gen.*; import mindustry.world.*; public abstract class GenerateFilter{ - protected transient float o = (float)(Math.random() * 10000000.0); - protected transient int seed; - protected transient GenerateInput in; + public int seed = 0; public void apply(Tiles tiles, GenerateInput in){ - this.in = in; if(isBuffered()){ //buffer of tiles used, each tile packed into a long struct @@ -26,8 +23,8 @@ public abstract class GenerateFilter{ for(int i = 0; i < tiles.width * tiles.height; i++){ Tile tile = tiles.geti(i); - in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); - apply(); + in.set(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); + apply(in); buffer[i] = PackTile.get(in.block.id, in.floor.id, in.overlay.id); } @@ -48,8 +45,8 @@ public abstract class GenerateFilter{ } }else{ for(Tile tile : tiles){ - in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); - apply(); + in.set(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); + apply(in); tile.setFloor(in.floor.asFloor()); tile.setOverlay(!in.floor.asFloor().hasSurface() && in.overlay.asFloor().needsSurface ? Blocks.air : in.overlay); @@ -61,16 +58,11 @@ public abstract class GenerateFilter{ } } - public final void apply(GenerateInput in){ - this.in = in; - apply(); - } - /** @return a new array of options for configuring this filter */ public abstract FilterOption[] options(); /** apply the actual filter on the input */ - protected void apply(){} + public void apply(GenerateInput in){} /** draw any additional guides */ public void draw(Image image){} @@ -93,7 +85,7 @@ public abstract class GenerateFilter{ /** set the seed to a random number */ public void randomize(){ - seed = Mathf.random(99999999); + seed = Mathf.random(999999999); } /** @return whether this filter needs a read/write buffer (e.g. not a 1:1 tile mapping). */ @@ -108,24 +100,26 @@ public abstract class GenerateFilter{ //utility generation functions - protected float noise(float x, float y, float scl, float mag){ - return (float)in.noise.octaveNoise2D(1f, 0f, 1f / scl, x + o, y + o) * mag; + //TODO would be nice if these functions used the seed and ditched "in" completely; simplex should be stateless + + protected float noise(GenerateInput in, float scl, float mag){ + return (float)Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag; } - protected float noise(float x, float y, float scl, float mag, float octaves, float persistence){ - return (float)in.noise.octaveNoise2D(octaves, persistence, 1f / scl, x + o, y + o) * mag; + protected float noise(GenerateInput in, float scl, float mag, float octaves, float persistence){ + return (float)Simplex.noise2d(seed, octaves, persistence, 1f / scl, in.x, in.y) * mag; } protected float rnoise(float x, float y, float scl, float mag){ - return RidgedPerlin.noise2d(seed + 1, (int)(x + o), (int)(y + o), 1f / scl) * mag; + return Ridged.noise2d(seed + 1, (int)(x), (int)(y), 1f / scl) * mag; } protected float rnoise(float x, float y, int octaves, float scl, float falloff, float mag){ - return RidgedPerlin.noise2d(seed + 1, (int)(x + o), (int)(y + o), octaves, falloff, 1f / scl) * mag; + return Ridged.noise2d(seed + 1, (int)(x), (int)(y), octaves, falloff, 1f / scl) * mag; } - protected float chance(){ - return Mathf.randomSeed(Pack.longInt(in.x, in.y + seed)); + protected float chance(int x, int y){ + return Mathf.randomSeed(Pack.longInt(x, y + seed)); } /** an input for generating at a certain coordinate. should only be instantiated once. */ @@ -137,10 +131,9 @@ public abstract class GenerateFilter{ /** output parameters */ public Block floor, block, overlay; - Simplex noise = new Simplex(); TileProvider buffer; - public void apply(int x, int y, Block block, Block floor, Block overlay){ + public void set(int x, int y, Block block, Block floor, Block overlay){ this.floor = floor; this.block = block; this.overlay = overlay; @@ -152,7 +145,6 @@ public abstract class GenerateFilter{ this.buffer = buffer; this.width = width; this.height = height; - noise.setSeed(filter.seed); } Tile tile(float x, float y){ diff --git a/core/src/mindustry/maps/filters/MedianFilter.java b/core/src/mindustry/maps/filters/MedianFilter.java index 001d79bba5..35d08f814d 100644 --- a/core/src/mindustry/maps/filters/MedianFilter.java +++ b/core/src/mindustry/maps/filters/MedianFilter.java @@ -2,7 +2,6 @@ package mindustry.maps.filters; import arc.math.*; import arc.struct.*; -import arc.util.*; import mindustry.gen.*; import mindustry.maps.filters.FilterOption.*; import mindustry.world.*; @@ -17,10 +16,10 @@ public class MedianFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), - new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f) - ); + return new SliderOption[]{ + new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), + new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f) + }; } @Override @@ -34,7 +33,7 @@ public class MedianFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ int rad = (int)radius; blocks.clear(); floors.clear(); diff --git a/core/src/mindustry/maps/filters/MirrorFilter.java b/core/src/mindustry/maps/filters/MirrorFilter.java index cdb324b0ef..d96c3a6b5f 100644 --- a/core/src/mindustry/maps/filters/MirrorFilter.java +++ b/core/src/mindustry/maps/filters/MirrorFilter.java @@ -12,17 +12,17 @@ import mindustry.maps.filters.FilterOption.*; import mindustry.world.*; public class MirrorFilter extends GenerateFilter{ - private final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2(); + private static final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2(); int angle = 45; boolean rotate = false; @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("angle", () -> angle, f -> angle = (int)f, 0, 360, 45), - new ToggleOption("rotate", () -> rotate, f -> rotate = f) - ); + return new FilterOption[]{ + new SliderOption("angle", () -> angle, f -> angle = (int)f, 0, 360, 45), + new ToggleOption("rotate", () -> rotate, f -> rotate = f) + }; } @Override @@ -31,7 +31,7 @@ public class MirrorFilter extends GenerateFilter{ } @Override - protected void apply(){ + public void apply(GenerateInput in){ v1.trnsExact(angle - 90, 1f); v2.set(v1).scl(-1f); @@ -41,7 +41,7 @@ public class MirrorFilter extends GenerateFilter{ v3.set(in.x, in.y); if(!left(v1, v2, v3)){ - mirror(v3, v1.x, v1.y, v2.x, v2.y); + mirror(in.width, in.height, v3, v1.x, v1.y, v2.x, v2.y); Tile tile = in.tile(v3.x, v3.y); in.floor = tile.floor(); if(!tile.block().synthetic()){ @@ -73,11 +73,11 @@ public class MirrorFilter extends GenerateFilter{ Draw.reset(); } - void mirror(Vec2 p, float x0, float y0, float x1, float y1){ + void mirror(int width, int height, Vec2 p, float x0, float y0, float x1, float y1){ //special case: uneven map mirrored at 45 degree angle (or someone might just want rotational symmetry) - if((in.width != in.height && angle % 90 != 0) || rotate){ - p.x = in.width - p.x - 1; - p.y = in.height - p.y - 1; + if((width != height && angle % 90 != 0) || rotate){ + p.x = width - p.x - 1; + p.y = height - p.y - 1; }else{ float dx = x1 - x0; float dy = y1 - y0; diff --git a/core/src/mindustry/maps/filters/NoiseFilter.java b/core/src/mindustry/maps/filters/NoiseFilter.java index acbf8162c6..b4aad342d2 100644 --- a/core/src/mindustry/maps/filters/NoiseFilter.java +++ b/core/src/mindustry/maps/filters/NoiseFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,15 +12,15 @@ public class NoiseFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("target", () -> target, b -> target = b, anyOptional), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), - new BlockOption("wall", () -> block, b -> block = b, wallsOptional) - ); + return new FilterOption[]{ + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("target", () -> target, b -> target = b, anyOptional), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), + new BlockOption("wall", () -> block, b -> block = b, wallsOptional) + }; } @Override @@ -30,8 +29,8 @@ public class NoiseFilter extends GenerateFilter{ } @Override - public void apply(){ - float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); + public void apply(GenerateInput in){ + float noise = noise(in, scl, 1f, octaves, falloff); if(noise > threshold && (target == Blocks.air || in.floor == target || in.block == target)){ if(floor != Blocks.air) in.floor = floor; diff --git a/core/src/mindustry/maps/filters/OreFilter.java b/core/src/mindustry/maps/filters/OreFilter.java index 5487ea0d59..e5fd5f1344 100644 --- a/core/src/mindustry/maps/filters/OreFilter.java +++ b/core/src/mindustry/maps/filters/OreFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,14 +12,14 @@ public class OreFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("ore", () -> ore, b -> ore = b, oresOnly), - new BlockOption("target", () -> target, b -> target = b, oresFloorsOptional) - ); + return new FilterOption[]{ + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("ore", () -> ore, b -> ore = b, oresOnly), + new BlockOption("target", () -> target, b -> target = b, oresFloorsOptional) + }; } @Override @@ -29,8 +28,8 @@ public class OreFilter extends GenerateFilter{ } @Override - public void apply(){ - float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); + public void apply(GenerateInput in){ + float noise = noise(in, scl, 1f, octaves, falloff); if(noise > threshold && in.overlay != Blocks.spawn && (target == Blocks.air || in.floor == target || in.overlay == target) && in.floor.asFloor().hasSurface()){ in.overlay = ore; diff --git a/core/src/mindustry/maps/filters/OreMedianFilter.java b/core/src/mindustry/maps/filters/OreMedianFilter.java index cba1d56936..9409604c23 100644 --- a/core/src/mindustry/maps/filters/OreMedianFilter.java +++ b/core/src/mindustry/maps/filters/OreMedianFilter.java @@ -2,7 +2,6 @@ package mindustry.maps.filters; import arc.math.*; import arc.struct.*; -import arc.util.*; import mindustry.*; import mindustry.content.*; import mindustry.gen.*; @@ -17,10 +16,10 @@ public class OreMedianFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f), - new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f) - ); + return new SliderOption[]{ + new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f), + new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f) + }; } @Override @@ -34,7 +33,7 @@ public class OreMedianFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ if(in.overlay == Blocks.spawn) return; int cx = (in.x / 2) * 2; diff --git a/core/src/mindustry/maps/filters/RiverNoiseFilter.java b/core/src/mindustry/maps/filters/RiverNoiseFilter.java index aeefe8422a..3fb6efab5e 100644 --- a/core/src/mindustry/maps/filters/RiverNoiseFilter.java +++ b/core/src/mindustry/maps/filters/RiverNoiseFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,16 +12,16 @@ public class RiverNoiseFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, -1f, 1f), - new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("block", () -> block, b -> block = b, wallsOnly), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), - new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) - ); + return new FilterOption[]{ + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, -1f, 1f), + new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("block", () -> block, b -> block = b, wallsOnly), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) + }; } @Override @@ -31,7 +30,7 @@ public class RiverNoiseFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ float noise = rnoise(in.x, in.y, (int)octaves, scl, falloff, 1f); if(noise >= threshold){ diff --git a/core/src/mindustry/maps/filters/ScatterFilter.java b/core/src/mindustry/maps/filters/ScatterFilter.java index b766183087..ca094891b4 100644 --- a/core/src/mindustry/maps/filters/ScatterFilter.java +++ b/core/src/mindustry/maps/filters/ScatterFilter.java @@ -1,6 +1,5 @@ package mindustry.maps.filters; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -13,12 +12,12 @@ public class ScatterFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f), - new BlockOption("flooronto", () -> flooronto, b -> flooronto = b, floorsOptional), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), - new BlockOption("block", () -> block, b -> block = b, wallsOresOptional) - ); + return new FilterOption[]{ + new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f), + new BlockOption("flooronto", () -> flooronto, b -> flooronto = b, floorsOptional), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), + new BlockOption("block", () -> block, b -> block = b, wallsOresOptional) + }; } @Override @@ -27,9 +26,9 @@ public class ScatterFilter extends GenerateFilter{ } @Override - public void apply(){ + public void apply(GenerateInput in){ - if(block != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && in.block == Blocks.air && chance() <= chance){ + if(block != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && in.block == Blocks.air && chance(in.x, in.y) <= chance){ if(!block.isOverlay()){ in.block = block; }else{ @@ -37,7 +36,7 @@ public class ScatterFilter extends GenerateFilter{ } } - if(floor != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && chance() <= chance){ + if(floor != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && chance(in.x, in.y) <= chance){ in.floor = floor; } } diff --git a/core/src/mindustry/maps/filters/SpawnPathFilter.java b/core/src/mindustry/maps/filters/SpawnPathFilter.java index ac49b13d31..09d453e513 100644 --- a/core/src/mindustry/maps/filters/SpawnPathFilter.java +++ b/core/src/mindustry/maps/filters/SpawnPathFilter.java @@ -19,9 +19,9 @@ public class SpawnPathFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("radius", () -> radius, f -> radius = (int)f, 1, 20).display() - ); + return new SliderOption[]{ + new SliderOption("radius", () -> radius, f -> radius = (int)f, 1, 20).display() + }; } @Override diff --git a/core/src/mindustry/maps/filters/TerrainFilter.java b/core/src/mindustry/maps/filters/TerrainFilter.java index f494d0c143..98fdc53d9d 100644 --- a/core/src/mindustry/maps/filters/TerrainFilter.java +++ b/core/src/mindustry/maps/filters/TerrainFilter.java @@ -1,7 +1,6 @@ package mindustry.maps.filters; import arc.math.*; -import arc.util.*; import mindustry.content.*; import mindustry.gen.*; import mindustry.world.*; @@ -14,16 +13,16 @@ public class TerrainFilter extends GenerateFilter{ @Override public FilterOption[] options(){ - return Structs.arr( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), - new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f), - new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), - new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f), - new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), - new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), - new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), - new BlockOption("wall", () -> block, b -> block = b, wallsOnly) - ); + return new FilterOption[]{ + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + }; } @Override @@ -32,8 +31,8 @@ public class TerrainFilter extends GenerateFilter{ } @Override - public void apply(){ - float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.width, (float)in.y / in.height, 0.5f, 0.5f) * circleScl; + public void apply(GenerateInput in){ + float noise = noise(in, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.width, (float)in.y / in.height, 0.5f, 0.5f) * circleScl; if(floor != Blocks.air){ in.floor = floor; diff --git a/core/src/mindustry/maps/generators/PlanetGenerator.java b/core/src/mindustry/maps/generators/PlanetGenerator.java index 521e5aa08e..4fe870d3dc 100644 --- a/core/src/mindustry/maps/generators/PlanetGenerator.java +++ b/core/src/mindustry/maps/generators/PlanetGenerator.java @@ -18,7 +18,6 @@ import static mindustry.Vars.*; public abstract class PlanetGenerator extends BasicGenerator implements HexMesher{ protected IntSeq ints = new IntSeq(); protected Sector sector; - protected Simplex noise = new Simplex(); /** Should generate sector bases for a planet. */ public void generateSector(Sector sector){ @@ -116,7 +115,7 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe @Override protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){ Vec3 v = sector.rect.project(x, y); - return (float)noise.octaveNoise3D(octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag; + return (float)Simplex.noise3d(0, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag; } /** @return the scaling factor for sector rects. */ diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java index fb68343b1a..f69537ef44 100644 --- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java @@ -18,6 +18,8 @@ import mindustry.world.*; import static mindustry.Vars.*; public class SerpuloPlanetGenerator extends PlanetGenerator{ + static final int seed = 0; + BaseGenerator basegen = new BaseGenerator(); float scl = 5f; float waterOffset = 0.07f; @@ -55,7 +57,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ float rawHeight(Vec3 position){ position = Tmp.v33.set(position).scl(scl); - return (Mathf.pow((float)noise.octaveNoise3D(7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset); + return (Mathf.pow((float)Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset); } @Override @@ -114,7 +116,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ tile.floor = getBlock(position); tile.block = tile.floor.asFloor().wall; - if(RidgedPerlin.noise3d(1, position.x, position.y, position.z, 2, 22) > 0.31){ + if(Ridged.noise3d(1, position.x, position.y, position.z, 2, 22) > 0.31){ tile.block = Blocks.air; } } @@ -125,12 +127,12 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ position = Tmp.v33.set(position).scl(scl); float rad = scl; float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad)); - float tnoise = (float)noise.octaveNoise3D(7, 0.56, 1f/3f, position.x, position.y + 999f, position.z); + float tnoise = (float)Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z); temp = Mathf.lerp(temp, tnoise, 0.5f); height *= 1.2f; height = Mathf.clamp(height); - float tar = (float)noise.octaveNoise3D(4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f; + float tar = (float)Simplex.noise3d(seed, 4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f; Block res = arr[Mathf.clamp((int)(temp * arr.length), 0, arr[0].length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)]; if(tar > 0.5f){ @@ -143,7 +145,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ @Override protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){ Vec3 v = sector.rect.project(x, y).scl(5f); - return (float)noise.octaveNoise3D(octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag; + return (float)Simplex.noise3d(seed, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag; } @Override @@ -250,15 +252,15 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ float scl = 1f; float addscl = 1.3f; - if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.25f*addscl){ + if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.25f*addscl){ ores.add(Blocks.oreCoal); } - if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x + 1, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.5f*addscl){ + if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x + 1, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.5f*addscl){ ores.add(Blocks.oreTitanium); } - if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x + 2, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.7f*addscl){ + if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x + 2, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.7f*addscl){ ores.add(Blocks.oreThorium); } diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index aa258a0666..de033c0e9a 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -1,6 +1,9 @@ package mindustry.mod; import arc.struct.*; +import mindustry.world.blocks.environment.*; +import mindustry.world.blocks.payloads.*; + /** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ @SuppressWarnings("deprecation") public class ClassMap{ @@ -171,20 +174,20 @@ public class ClassMap{ classes.put("OreBlock", mindustry.world.blocks.environment.OreBlock.class); classes.put("OverlayFloor", mindustry.world.blocks.environment.OverlayFloor.class); classes.put("Prop", mindustry.world.blocks.environment.Prop.class); - classes.put("SeaBush", mindustry.world.blocks.environment.SeaBush.class); - classes.put("Seaweed", mindustry.world.blocks.environment.Seaweed.class); + classes.put("Bush", Bush.class); + classes.put("WavingProp", WavingProp.class); classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class); classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class); - classes.put("StaticCoralWall", mindustry.world.blocks.environment.StaticCoralWall.class); + classes.put("StaticClusterWall", StaticClusterWall.class); classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class); classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class); classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class); classes.put("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class); classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.class); - classes.put("BlockLoader", mindustry.world.blocks.experimental.BlockLoader.class); - classes.put("BlockLoaderBuild", mindustry.world.blocks.experimental.BlockLoader.BlockLoaderBuild.class); - classes.put("BlockUnloader", mindustry.world.blocks.experimental.BlockUnloader.class); - classes.put("BlockUnloaderBuild", mindustry.world.blocks.experimental.BlockUnloader.BlockUnloaderBuild.class); + classes.put("BlockLoader", BlockLoader.class); + classes.put("BlockLoaderBuild", BlockLoader.BlockLoaderBuild.class); + classes.put("BlockUnloader", BlockUnloader.class); + classes.put("BlockUnloaderBuild", BlockUnloader.BlockUnloaderBuild.class); classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class); classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class); classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class); @@ -235,7 +238,7 @@ public class ClassMap{ classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class); classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class); classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class); - classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.PayloadVoid.BlockLoaderBuild.class); + classes.put("BlockLoaderBuild", PayloadVoid.PayloadVoidBuild.class); classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class); classes.put("Battery", mindustry.world.blocks.power.Battery.class); classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 6862b1a540..9c8c7f3b3a 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -752,8 +752,8 @@ public class ContentParser{ var out = ClassMap.classes.get(!base.isEmpty() && Character.isLowerCase(base.charAt(0)) ? Strings.capitalize(base) : base); if(out != null) return (Class)out; - //try to resolve it as a raw class name if it's allowed - if(base.indexOf('.') != -1 && Scripts.allowClass(base)){ + //try to resolve it as a raw class name + if(base.indexOf('.') != -1){ try{ return (Class)Class.forName(base); }catch(Exception ignored){ diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java index 4f70c0c814..1aa69b9ab7 100644 --- a/core/src/mindustry/mod/Scripts.java +++ b/core/src/mindustry/mod/Scripts.java @@ -22,22 +22,12 @@ import java.util.*; import java.util.regex.*; public class Scripts implements Disposable{ - private static final Seq blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", - "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", - ".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.", "mod.classmap"); - private static final Seq whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "jdk.proxy", "mindustry.gen.", - "mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent", "asyncexecutor"); - private final Context context; private final Scriptable scope; private boolean errored; LoadedMod currentMod = null; - public static boolean allowClass(String type){ - return !blacklist.contains(t -> type.toLowerCase(Locale.ROOT).contains(t)) || whitelist.contains(t -> type.toLowerCase(Locale.ROOT).contains(t)); - } - public Scripts(){ Time.mark(); diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 44ebebe8ae..ca5ff1fcf8 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -174,21 +174,12 @@ public class ModsDialog extends BaseDialog{ dialog.hide(); platform.showMultiFileChooser(file -> { - Runnable go = () -> { - try{ - mods.importMod(file); - setup(); - }catch(IOException e){ - ui.showException(e); - e.printStackTrace(); - } - }; - - //show unsafe jar file warning - if(file.extEquals("jar")){ - ui.showConfirm("@warning", "@mod.jarwarn", go); - }else{ - go.run(); + try{ + mods.importMod(file); + setup(); + }catch(IOException e){ + ui.showException(e); + Log.err(e); } }, "zip", "jar"); }).margin(12f); @@ -529,10 +520,7 @@ public class ModsDialog extends BaseDialog{ private void githubImportMod(String repo, boolean isJava){ if(isJava){ - ui.showConfirm("@warning", "@mod.jarwarn", () -> { - ui.loadfrag.show(); - githubImportJavaMod(repo); - }); + githubImportJavaMod(repo); }else{ ui.loadfrag.show(); Core.net.httpGet(ghApi + "/repos/" + repo, res -> { diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 5e31f6df00..4c2fc98b1c 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -92,6 +92,8 @@ public class ConstructBlock extends Block{ Fx.placeBlock.at(tile.drawx(), tile.drawy(), block.size); if(shouldPlay()) Sounds.place.at(tile, calcPitch(true)); + + Events.fire(new BlockBuildEndEvent(tile, builder, team, false, config)); } static boolean shouldPlay(){ @@ -123,8 +125,6 @@ public class ConstructBlock extends Block{ if(tile.build != null){ tile.build.placed(); } - - Events.fire(new BlockBuildEndEvent(tile, builder, team, false, config)); } @Override @@ -259,7 +259,9 @@ public class ConstructBlock extends Block{ if(progress >= 1f || state.rules.infiniteResources){ if(lastBuilder == null) lastBuilder = builder; - constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config); + if(!net.client()){ + constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config); + } } } diff --git a/core/src/mindustry/world/blocks/distribution/MassDriver.java b/core/src/mindustry/world/blocks/distribution/MassDriver.java index 94b993aa7f..045d61736f 100644 --- a/core/src/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/mindustry/world/blocks/distribution/MassDriver.java @@ -324,7 +324,7 @@ public class MassDriver extends Block{ } protected boolean shooterValid(Building other){ - return other instanceof MassDriverBuild entity && other.consValid() && entity.block == block && entity.link == pos() && within(other, range); + return other instanceof MassDriverBuild entity && other.isValid() && other.consValid() && entity.block == block && entity.link == pos() && within(other, range); } protected boolean linkValid(){ diff --git a/core/src/mindustry/world/blocks/experimental/BlockForge.java b/core/src/mindustry/world/blocks/experimental/BlockForge.java new file mode 100644 index 0000000000..29adc64d00 --- /dev/null +++ b/core/src/mindustry/world/blocks/experimental/BlockForge.java @@ -0,0 +1,14 @@ +package mindustry.world.blocks.experimental; + +@Deprecated +public class BlockForge extends mindustry.world.blocks.payloads.BlockForge{ + + public BlockForge(String name){ + super(name); + } + + @Deprecated + public class BlockForgeBuild extends mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild{ + + } +} diff --git a/core/src/mindustry/world/blocks/experimental/BlockLoader.java b/core/src/mindustry/world/blocks/experimental/BlockLoader.java index 41f2aa13f8..91a044d4f8 100644 --- a/core/src/mindustry/world/blocks/experimental/BlockLoader.java +++ b/core/src/mindustry/world/blocks/experimental/BlockLoader.java @@ -1,148 +1,14 @@ package mindustry.world.blocks.experimental; -import arc.*; -import arc.graphics.g2d.*; -import arc.util.*; -import mindustry.entities.units.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.type.*; -import mindustry.ui.*; -import mindustry.world.blocks.payloads.*; - -import static mindustry.Vars.*; - -public class BlockLoader extends PayloadBlock{ - public final int timerLoad = timers++; - - public float loadTime = 2f; - public int itemsLoaded = 5; - public float liquidsLoaded = 5f; - public int maxBlockSize = 2; +@Deprecated +public class BlockLoader extends mindustry.world.blocks.payloads.BlockLoader{ public BlockLoader(String name){ super(name); - - hasItems = true; - itemCapacity = 25; - //liquidCapacity = 25; - update = true; - outputsPayload = true; - size = 3; - rotate = true; } - @Override - public TextureRegion[] icons(){ - return new TextureRegion[]{region, inRegion, outRegion, topRegion}; - } + @Deprecated + public class BlockLoaderBuild extends mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild{ - @Override - public boolean outputsItems(){ - return false; - } - - @Override - public void setBars(){ - super.setBars(); - - bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); - } - - @Override - public void drawRequestRegion(BuildPlan req, Eachable list){ - Draw.rect(region, req.drawx(), req.drawy()); - Draw.rect(inRegion, req.drawx(), req.drawy(), req.rotation * 90); - Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); - Draw.rect(topRegion, req.drawx(), req.drawy()); - } - - public class BlockLoaderBuild extends PayloadBlockBuild{ - - @Override - public boolean acceptPayload(Building source, Payload payload){ - return super.acceptPayload(source, payload) && - (payload instanceof BuildPayload build) && - ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* || - ((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/); - } - - @Override - public boolean acceptItem(Building source, Item item){ - return items.total() < itemCapacity; - } - - @Override - public void draw(){ - Draw.rect(region, x, y); - - //draw input - boolean fallback = true; - for(int i = 0; i < 4; i++){ - if(blends(i) && i != rotation){ - Draw.rect(inRegion, x, y, (i * 90) - 180); - fallback = false; - } - } - if(fallback) Draw.rect(inRegion, x, y, rotation * 90); - - Draw.rect(outRegion, x, y, rotdeg()); - - Draw.z(Layer.blockOver); - drawPayload(); - - Draw.z(Layer.blockOver + 0.1f); - Draw.rect(topRegion, x, y); - } - - @Override - public void updateTile(){ - if(shouldExport()){ - moveOutPayload(); - }else if(moveInPayload()){ - - //load up items - if(payload.block().hasItems && items.any()){ - if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ - //load up items a set amount of times - for(int j = 0; j < itemsLoaded && items.any(); j++){ - - for(int i = 0; i < items.length(); i++){ - if(items.get(i) > 0){ - Item item = content.item(i); - if(payload.build.acceptItem(payload.build, item)){ - payload.build.handleItem(payload.build, item); - items.remove(item, 1); - break; - } - } - } - } - } - } - - //load up liquids (disabled) - /* - if(payload.block().hasLiquids && liquids.total() >= 0.001f){ - Liquid liq = liquids.current(); - float total = liquids.currentAmount(); - float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total); - if(payload.entity.acceptLiquid(payload.entity, liq, flow)){ - payload.entity.liquids.add(liq, flow); - liquids.remove(liq, flow); - } - }*/ - } - } - - public float fraction(){ - return payload == null ? 0f : payload.build.items.total() / (float)payload.build.block.itemCapacity; - } - - public boolean shouldExport(){ - return payload != null && - ((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || - (payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity)); - } } } diff --git a/core/src/mindustry/world/blocks/experimental/BlockUnloader.java b/core/src/mindustry/world/blocks/experimental/BlockUnloader.java index 53d4df1b66..1c655318e3 100644 --- a/core/src/mindustry/world/blocks/experimental/BlockUnloader.java +++ b/core/src/mindustry/world/blocks/experimental/BlockUnloader.java @@ -1,67 +1,14 @@ package mindustry.world.blocks.experimental; -import mindustry.gen.*; -import mindustry.type.*; - -import static mindustry.Vars.*; - -public class BlockUnloader extends BlockLoader{ +@Deprecated +public class BlockUnloader extends mindustry.world.blocks.payloads.BlockUnloader{ public BlockUnloader(String name){ super(name); } - @Override - public boolean outputsItems(){ - return true; - } + @Deprecated + public class BlockUnloaderBuild extends mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild{ - @Override - public boolean rotatedOutput(int x, int y){ - return false; - } - - public class BlockUnloaderBuild extends BlockLoaderBuild{ - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } - - @Override - public void updateTile(){ - if(shouldExport()){ - moveOutPayload(); - }else if(moveInPayload()){ - - //load up items - if(payload.block().hasItems && !full()){ - if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ - //load up items a set amount of times - for(int j = 0; j < itemsLoaded && !full(); j++){ - for(int i = 0; i < items.length(); i++){ - if(payload.build.items.get(i) > 0){ - Item item = content.item(i); - payload.build.items.remove(item, 1); - items.add(item, 1); - break; - } - } - } - } - } - } - - dump(); - } - - public boolean full(){ - return items.total() >= itemCapacity; - } - - @Override - public boolean shouldExport(){ - return payload != null && (payload.block().hasItems && payload.build.items.empty()); - } } } diff --git a/core/src/mindustry/world/blocks/payloads/BlockLoader.java b/core/src/mindustry/world/blocks/payloads/BlockLoader.java new file mode 100644 index 0000000000..001f93712a --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/BlockLoader.java @@ -0,0 +1,147 @@ +package mindustry.world.blocks.payloads; + +import arc.*; +import arc.graphics.g2d.*; +import arc.util.*; +import mindustry.entities.units.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; +import mindustry.ui.*; + +import static mindustry.Vars.*; + +public class BlockLoader extends PayloadBlock{ + public final int timerLoad = timers++; + + public float loadTime = 2f; + public int itemsLoaded = 5; + public float liquidsLoaded = 5f; + public int maxBlockSize = 2; + + public BlockLoader(String name){ + super(name); + + hasItems = true; + itemCapacity = 25; + //liquidCapacity = 25; + update = true; + outputsPayload = true; + size = 3; + rotate = true; + } + + @Override + public TextureRegion[] icons(){ + return new TextureRegion[]{region, inRegion, outRegion, topRegion}; + } + + @Override + public boolean outputsItems(){ + return false; + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); + } + + @Override + public void drawRequestRegion(BuildPlan req, Eachable list){ + Draw.rect(region, req.drawx(), req.drawy()); + Draw.rect(inRegion, req.drawx(), req.drawy(), req.rotation * 90); + Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); + Draw.rect(topRegion, req.drawx(), req.drawy()); + } + + public class BlockLoaderBuild extends PayloadBlockBuild{ + + @Override + public boolean acceptPayload(Building source, Payload payload){ + return super.acceptPayload(source, payload) && + (payload instanceof BuildPayload build) && + ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* || + ((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/); + } + + @Override + public boolean acceptItem(Building source, Item item){ + return items.total() < itemCapacity; + } + + @Override + public void draw(){ + Draw.rect(region, x, y); + + //draw input + boolean fallback = true; + for(int i = 0; i < 4; i++){ + if(blends(i) && i != rotation){ + Draw.rect(inRegion, x, y, (i * 90) - 180); + fallback = false; + } + } + if(fallback) Draw.rect(inRegion, x, y, rotation * 90); + + Draw.rect(outRegion, x, y, rotdeg()); + + Draw.z(Layer.blockOver); + drawPayload(); + + Draw.z(Layer.blockOver + 0.1f); + Draw.rect(topRegion, x, y); + } + + @Override + public void updateTile(){ + if(shouldExport()){ + moveOutPayload(); + }else if(moveInPayload()){ + + //load up items + if(payload.block().hasItems && items.any()){ + if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ + //load up items a set amount of times + for(int j = 0; j < itemsLoaded && items.any(); j++){ + + for(int i = 0; i < items.length(); i++){ + if(items.get(i) > 0){ + Item item = content.item(i); + if(payload.build.acceptItem(payload.build, item)){ + payload.build.handleItem(payload.build, item); + items.remove(item, 1); + break; + } + } + } + } + } + } + + //load up liquids (disabled) + /* + if(payload.block().hasLiquids && liquids.total() >= 0.001f){ + Liquid liq = liquids.current(); + float total = liquids.currentAmount(); + float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total); + if(payload.entity.acceptLiquid(payload.entity, liq, flow)){ + payload.entity.liquids.add(liq, flow); + liquids.remove(liq, flow); + } + }*/ + } + } + + public float fraction(){ + return payload == null ? 0f : payload.build.items.total() / (float)payload.build.block.itemCapacity; + } + + public boolean shouldExport(){ + return payload != null && + ((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || + (payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity)); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/BlockUnloader.java b/core/src/mindustry/world/blocks/payloads/BlockUnloader.java new file mode 100644 index 0000000000..8f4a644fce --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/BlockUnloader.java @@ -0,0 +1,67 @@ +package mindustry.world.blocks.payloads; + +import mindustry.gen.*; +import mindustry.type.*; + +import static mindustry.Vars.*; + +public class BlockUnloader extends BlockLoader{ + + public BlockUnloader(String name){ + super(name); + } + + @Override + public boolean outputsItems(){ + return true; + } + + @Override + public boolean rotatedOutput(int x, int y){ + return false; + } + + public class BlockUnloaderBuild extends BlockLoaderBuild{ + + @Override + public boolean acceptItem(Building source, Item item){ + return false; + } + + @Override + public void updateTile(){ + if(shouldExport()){ + moveOutPayload(); + }else if(moveInPayload()){ + + //load up items + if(payload.block().hasItems && !full()){ + if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ + //load up items a set amount of times + for(int j = 0; j < itemsLoaded && !full(); j++){ + for(int i = 0; i < items.length(); i++){ + if(payload.build.items.get(i) > 0){ + Item item = content.item(i); + payload.build.items.remove(item, 1); + items.add(item, 1); + break; + } + } + } + } + } + } + + dump(); + } + + public boolean full(){ + return items.total() >= itemCapacity; + } + + @Override + public boolean shouldExport(){ + return payload != null && (payload.block().hasItems && payload.build.items.empty()); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java index 3bf83976ec..0d1821c2f6 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java @@ -184,6 +184,7 @@ public class PayloadMassDriver extends PayloadBlock{ if(current != null && !( current instanceof PayloadDriverBuild entity && + current.isValid() && entity.consValid() && entity.block == block && entity.link == pos() && within(current, range) )){ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java index e1cb184f48..fa41218e3c 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java @@ -29,7 +29,7 @@ public class PayloadVoid extends PayloadBlock{ return new TextureRegion[]{region, topRegion}; } - public class BlockLoaderBuild extends PayloadBlockBuild{ + public class PayloadVoidBuild extends PayloadBlockBuild{ @Override public void draw(){ diff --git a/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java index 5295bf0703..1ef6010f2b 100644 --- a/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -61,6 +61,8 @@ public class ItemLiquidGenerator extends PowerGenerator{ @Override public void init(){ + emitLight = true; + lightRadius = 65f * size; if(!defaults){ setDefaults(); } diff --git a/desktop/build.gradle b/desktop/build.gradle index 4c8a14f86f..347ffeee07 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -48,7 +48,7 @@ task dist(type: Jar, dependsOn: configurations.runtimeClasspath){ } } -if(!project.ext.hasSprites()){ +if(!project.ext.hasSprites() && System.getenv("JITPACK") != "true"){ println "Scheduling sprite packing." run.dependsOn ":tools:pack" dist.dependsOn ":tools:pack" diff --git a/gradle.properties b/gradle.properties index 34b13c8f1d..15947e3eac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,5 @@ org.gradle.daemon=true -#--illegal-access=permit -org.gradle.jvmargs=-Xms256m -Xmx1024m +org.gradle.jvmargs=-Xms256m -Xmx1024m --illegal-access=permit # Don't recompute annotations if sources haven't been changed kapt.incremental.apt = true # Multithreaded @@ -9,4 +8,6 @@ kapt.use.worker.api=true kapt.include.compile.classpath=false # I don't need to use the kotlin stdlib yet, so remove it to prevent extra bloat & method count issues kotlin.stdlib.default.dependency=false -archash=3926b785320fea0cd9ca597f6bfa9071263a5464 +#needed for android compilation +android.useAndroidX=true +archash=07ced971f4c8b8b5a61aa3a84b29c90aa497cb48 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016..e708b1c023 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132ea..0f80bbf516 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfdc3..4f906e0c81 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -154,19 +156,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -175,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9618d8d960..107acd32c4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/jitpack.yml b/jitpack.yml index c06db14182..c418d56017 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,9 @@ +jdk: + - openjdk16 before_install: - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh - - source install-jdk.sh --feature 14 + - source install-jdk.sh --feature 16 - jshell --version +install: + - ./gradlew publishToMavenLocal + - sed -i 's/ --illegal-access=permit//' gradle.properties #remove extra flags after compilation \ No newline at end of file diff --git a/server/src/mindustry/server/ServerLauncher.java b/server/src/mindustry/server/ServerLauncher.java index 8c20047022..4d4d3d9aa1 100644 --- a/server/src/mindustry/server/ServerLauncher.java +++ b/server/src/mindustry/server/ServerLauncher.java @@ -2,7 +2,6 @@ package mindustry.server; import arc.*; import arc.backend.headless.*; -import arc.files.*; import arc.util.*; import mindustry.*; import mindustry.core.*; @@ -44,15 +43,6 @@ public class ServerLauncher implements ApplicationListener{ loadLocales = false; headless = true; - Fi plugins = Core.settings.getDataDirectory().child("plugins"); - if(plugins.isDirectory() && plugins.list().length > 0 && !plugins.sibling("mods").exists()){ - warn("[IMPORTANT NOTICE] &lrPlugins have been detected.&ly Automatically moving all contents of the plugin folder into the 'mods' folder. The original folder will not be removed; please do so manually."); - plugins.sibling("mods").mkdirs(); - for(Fi file : plugins.list()){ - file.copyTo(plugins.sibling("mods")); - } - } - Vars.loadSettings(); Vars.init(); content.createBaseContent(); diff --git a/servers_be.json b/servers_be.json index 6fcc7a4a4f..d22999dea0 100644 --- a/servers_be.json +++ b/servers_be.json @@ -13,8 +13,5 @@ }, { "address": "mindurka.tk:9999" - }, - { - "address": "mindustrypvp.ml:6000" } ] diff --git a/settings.gradle b/settings.gradle index ef9b57e54a..76eaa676a6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ -if(JavaVersion.current().ordinal() < JavaVersion.VERSION_14.ordinal()){ - throw new GradleException("!!! YOU MUST USE JAVA 14 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}") +if(JavaVersion.current().ordinal() < JavaVersion.VERSION_16.ordinal()){ + throw new Exception("!!! YOU MUST USE JAVA 16 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}") } include 'desktop', 'core', 'server', 'ios', 'annotations', 'tools', 'tests' diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 8bb1a1524e..2ea226ab7c 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -1,10 +1,12 @@ import arc.*; import arc.backend.headless.*; +import arc.files.*; import arc.func.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; import arc.util.*; +import arc.util.io.*; import arc.util.serialization.*; import arc.util.serialization.JsonValue.*; import mindustry.*; @@ -16,21 +18,36 @@ import mindustry.entities.units.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.io.*; +import mindustry.io.SaveIO.*; import mindustry.maps.*; +import mindustry.mod.*; +import mindustry.mod.Mods.*; import mindustry.net.Net; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.storage.*; import org.junit.jupiter.api.*; +import org.junit.jupiter.params.*; +import org.junit.jupiter.params.provider.*; + +import java.nio.*; import static mindustry.Vars.*; import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.DynamicTest.*; public class ApplicationTests{ static Map testMap; static boolean initialized; + //core/assets + static final Fi testDataFolder = new Fi("../../tests/build/test_data"); @BeforeAll - static void launchApplication(){ + public static void launchApplication(){ + launchApplication(true); + } + + public static void launchApplication(boolean clear){ //only gets called once if(initialized) return; initialized = true; @@ -43,6 +60,12 @@ public class ApplicationTests{ ApplicationCore core = new ApplicationCore(){ @Override public void setup(){ + //clear older data + if(clear){ + ApplicationTests.testDataFolder.deleteDirectory(); + } + + Core.settings.setDataDirectory(testDataFolder); headless = true; net = new Net(null); tree = new FileTree(); @@ -55,12 +78,26 @@ public class ApplicationTests{ } }; content.createBaseContent(); + mods.loadScripts(); + content.createModContent(); add(logic = new Logic()); add(netServer = new NetServer()); content.init(); + mods.eachClass(Mod::init); + + if(mods.hasContentErrors()){ + for(LoadedMod mod : mods.list()){ + if(mod.hasContentErrors()){ + for(Content cont : mod.erroredContent){ + throw new RuntimeException("error in file: " + cont.minfo.sourceFile.path(), cont.minfo.baseError); + } + } + } + } + } @Override @@ -96,6 +133,55 @@ public class ApplicationTests{ state.set(State.menu); } + @ParameterizedTest + @NullSource + @ValueSource(strings = { + "asd asd asd asd asdagagasasjakbgeah;jwrej 23424234", + "这个服务器可以用自己的语言说话" + }) + void writeStringTest(String string){ + ByteBuffer buffer = ByteBuffer.allocate(500); + TypeIO.writeString(buffer, string); + buffer.position(0); + assertEquals(TypeIO.readString(buffer), string); + } + + @Test + void writeRules(){ + ByteBuffer buffer = ByteBuffer.allocate(500); + + Rules rules = new Rules(); + rules.attackMode = true; + rules.buildSpeedMultiplier = 99f; + + TypeIO.writeRules(new Writes(new ByteBufferOutput(buffer)), rules); + buffer.position(0); + Rules res = TypeIO.readRules(new Reads(new ByteBufferInput(buffer))); + + assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier); + assertEquals(rules.attackMode, res.attackMode); + } + + @Test + void writeRules2(){ + Rules rules = new Rules(); + rules.attackMode = true; + rules.tags.put("blah", "bleh"); + rules.buildSpeedMultiplier = 99.1f; + + String str = JsonIO.write(rules); + Rules res = JsonIO.read(Rules.class, str); + + assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier); + assertEquals(rules.attackMode, res.attackMode); + assertEquals(rules.tags.get("blah"), res.tags.get("blah")); + + String str2 = JsonIO.write(new Rules(){{ + attackMode = true; + }}); + Log.info(str2); + } + @Test void serverListJson(){ String[] files = {"servers.json", "servers_be.json", "servers_v6.json"}; @@ -730,6 +816,83 @@ public class ApplicationTests{ } } + @TestFactory + DynamicTest[] testSectorValidity(){ + Seq out = new Seq<>(); + if(world == null) world = new World(); + + for(SectorPreset zone : content.sectors()){ + + out.add(dynamicTest(zone.name, () -> { + Time.setDeltaProvider(() -> 1f); + + logic.reset(); + try{ + world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate); + }catch(SaveException e){ + //fails randomly and I don't care about fixing it + e.printStackTrace(); + return; + } + zone.rules.get(state.rules); + ObjectSet resources = new ObjectSet<>(); + boolean hasSpawnPoint = false; + + for(Tile tile : world.tiles){ + if(tile.drop() != null){ + resources.add(tile.drop()); + } + if(tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam){ + hasSpawnPoint = true; + } + } + + Seq spawns = state.rules.spawns; + + int bossWave = 0; + if(state.rules.winWave > 0){ + bossWave = state.rules.winWave; + }else{ + outer: + for(int i = 1; i <= 1000; i++){ + for(SpawnGroup spawn : spawns){ + if(spawn.effect == StatusEffects.boss && spawn.getSpawned(i) > 0){ + bossWave = i; + break outer; + } + } + } + } + + if(state.rules.attackMode){ + bossWave = 100; + }else{ + assertNotEquals(0, bossWave, "Sector doesn't have a boss wave."); + } + + //TODO check for difficulty? + for(int i = 1; i <= bossWave; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getSpawned(i); + } + + assertNotEquals(0, total, "Sector " + zone + " has no spawned enemies at wave " + i); + //TODO this is flawed and needs to be changed later + //assertTrue(total < 75, "Sector spawns too many enemies at wave " + i + " (" + total + ")"); + } + + assertEquals(1, Team.sharded.cores().size, "Sector must have one core: " + zone); + assertTrue(Team.sharded.core().items.total() < 1000, "Sector must not have starting resources: " + zone); + + assertTrue(hasSpawnPoint, "Sector \"" + zone.name + "\" has no spawn points."); + assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.rules.waveTeam.data().hasCore()), "Sector \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns()); + })); + } + + return out.toArray(DynamicTest.class); + } + void initBuilding(){ createMap(); diff --git a/tests/src/test/java/GenericModTest.java b/tests/src/test/java/GenericModTest.java new file mode 100644 index 0000000000..f703d53873 --- /dev/null +++ b/tests/src/test/java/GenericModTest.java @@ -0,0 +1,35 @@ +import arc.*; +import arc.Net.*; +import arc.util.io.*; +import mindustry.*; +import org.junit.jupiter.api.*; + +import java.io.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class GenericModTest{ + + /** grabs a mod and puts it in the mod folder */ + static void grabMod(String url){ + //clear older mods + ApplicationTests.testDataFolder.deleteDirectory(); + Core.net = new Net(); + Core.net.setBlock(true); + Core.net.http(new HttpRequest().url(url).method(HttpMethod.GET), httpResponse -> { + try{ + ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream())); + }catch(IOException e){ + Assertions.fail(e); + } + }, Assertions::fail); + + ApplicationTests.launchApplication(false); + } + + static void checkExistence(String modName){ + assertNotEquals(Vars.mods, null); + assertNotEquals(Vars.mods.list().size, 0, "At least one mod must be loaded."); + assertEquals(Vars.mods.list().first().name, modName, modName + " must be loaded."); + } +} diff --git a/tests/src/test/java/IOTests.java b/tests/src/test/java/IOTests.java deleted file mode 100644 index d10774439a..0000000000 --- a/tests/src/test/java/IOTests.java +++ /dev/null @@ -1,63 +0,0 @@ -import arc.util.*; -import arc.util.io.*; -import mindustry.game.*; -import mindustry.io.*; -import org.junit.jupiter.api.*; -import org.junit.jupiter.params.*; -import org.junit.jupiter.params.provider.*; - -import java.nio.*; - -import static org.junit.jupiter.api.Assertions.*; - -public class IOTests{ - - @ParameterizedTest - @NullSource - @ValueSource(strings = { - "asd asd asd asd asdagagasasjakbgeah;jwrej 23424234", - "这个服务器可以用自己的语言说话" - }) - void writeStringTest(String string){ - ByteBuffer buffer = ByteBuffer.allocate(500); - TypeIO.writeString(buffer, string); - buffer.position(0); - assertEquals(TypeIO.readString(buffer), string); - } - - @Test - void writeRules(){ - ByteBuffer buffer = ByteBuffer.allocate(500); - - Rules rules = new Rules(); - rules.attackMode = true; - rules.buildSpeedMultiplier = 99f; - - TypeIO.writeRules(new Writes(new ByteBufferOutput(buffer)), rules); - buffer.position(0); - Rules res = TypeIO.readRules(new Reads(new ByteBufferInput(buffer))); - - assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier); - assertEquals(rules.attackMode, res.attackMode); - } - - @Test - void writeRules2(){ - Rules rules = new Rules(); - rules.attackMode = true; - rules.tags.put("blah", "bleh"); - rules.buildSpeedMultiplier = 99.1f; - - String str = JsonIO.write(rules); - Rules res = JsonIO.read(Rules.class, str); - - assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier); - assertEquals(rules.attackMode, res.attackMode); - assertEquals(rules.tags.get("blah"), res.tags.get("blah")); - - String str2 = JsonIO.write(new Rules(){{ - attackMode = true; - }}); - Log.info(str2); - } -} diff --git a/tests/src/test/java/ModTestBM.java b/tests/src/test/java/ModTestBM.java new file mode 100644 index 0000000000..a99969a188 --- /dev/null +++ b/tests/src/test/java/ModTestBM.java @@ -0,0 +1,39 @@ +import mindustry.*; +import mindustry.world.*; +import mindustry.world.meta.*; +import org.junit.jupiter.api.*; + +import static mindustry.Vars.*; +import static org.junit.jupiter.api.Assertions.*; + +//grabs a betamindy release and makes sure it initializes correctly +//this mod was chosen because: +//- it is one of the top java mods on the browser +//- it uses a variety of mindustry classes +//- it is popular enough to cause significant amounts of crashes when something breaks +//- I have some familiarity with its codebase +public class ModTestBM extends GenericModTest{ + + @Test + public void begin(){ + grabMod("https://github.com/sk7725/BetaMindy/releases/download/v0.955/BetaMindy.jar"); + + checkExistence("betamindy"); + + Block type = Vars.content.blocks().find(u -> u.name.equals("betamindy-piston")); + assertNotNull(type, "A mod block must be loaded."); + assertSame(type.buildVisibility, BuildVisibility.shown, "A mod block must be buildable."); + + world.loadMap(ApplicationTests.testMap); + Tile t = world.tile(3, 3); + + t.setBlock(type); + + //check for crash + t.build.update(); + + assertTrue(t.build.health > 0, "Block must be spawned and alive."); + assertSame(t.build.block, type, "Block must be spawned and alive."); + } + +} diff --git a/tests/src/test/java/ModTestExotic.java b/tests/src/test/java/ModTestExotic.java new file mode 100644 index 0000000000..c9e401f811 --- /dev/null +++ b/tests/src/test/java/ModTestExotic.java @@ -0,0 +1,40 @@ +import arc.util.*; +import mindustry.*; +import mindustry.gen.*; +import mindustry.type.*; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +//grabs a version-locked exotic-mod commit and makes sure its content is parsed correctly +//this mod was chosen because: +//- it is written solely in (h)json +//- it is probably the mod with the most json, and as such covers a lot of classes +//- it is popular enough in the mod browser +//- I am somewhat familiar with its files & the type of content it adds +public class ModTestExotic extends GenericModTest{ + + @Test + public void begin(){ + grabMod("https://github.com/BlueWolf3682/Exotic-Mod/archive/08c861398ac9c3d1292132f9a110e17e06294a90.zip"); + checkExistence("exotic-mod"); + + UnitType type = Vars.content.units().find(u -> u.name.equals("exotic-mod-luminance")); + assertNotNull(type, "A mod unit must be loaded."); + assertTrue(type.weapons.size > 0, "A mod unit must have a weapon."); + + Vars.world.loadMap(ApplicationTests.testMap); + + Unit unit = type.spawn(0, 0); + + //check for crash + unit.update(); + + assertTrue(unit.health > 0, "Unit must be spawned and alive."); + assertTrue(Groups.unit.size() > 0, "Unit must be spawned and alive."); + + //just an extra sanity check + Log.info("Modded units: @", Vars.content.units().select(u -> u.minfo.mod != null)); + } + +} diff --git a/tests/src/test/java/ModTestHAI.java b/tests/src/test/java/ModTestHAI.java new file mode 100644 index 0000000000..c33f9262c9 --- /dev/null +++ b/tests/src/test/java/ModTestHAI.java @@ -0,0 +1,39 @@ +import arc.util.*; +import mindustry.*; +import mindustry.gen.*; +import mindustry.type.*; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +//grabs a version-locked Heavy Armaments Industries commit and makes sure it initializes correctly +//this mod was chosen because: +//- it is one of the top JS mods, based on stars +//- it contains both JS and JSON, which can be used to test compatibility of the two +//- it can be used server-side (unlike FactoryDustry, which is a client-side texture pack that cannot be tested here) +public class ModTestHAI extends GenericModTest{ + + @Test + public void begin(){ + grabMod("https://github.com/Eschatologue/Heavy-Armaments-Industries/archive/d996e92dcf9a30a6acb7b3bfdfb6522dddc3804c.zip"); + checkExistence("heavy-armaments"); + + UnitType type = Vars.content.units().find(u -> u.name.equals("heavy-armaments-t3A_copter")); + assertNotNull(type, "A mod unit must be loaded."); + assertTrue(type.weapons.size > 0, "A mod unit must have a weapon."); + + Vars.world.loadMap(ApplicationTests.testMap); + + Unit unit = type.spawn(0, 0); + + //check for crash + unit.update(); + + assertTrue(unit.health > 0, "Unit must be spawned and alive."); + assertTrue(Groups.unit.size() > 0, "Unit must be spawned and alive."); + + //just an extra sanity check + Log.info("Modded units: @", Vars.content.units().select(u -> u.minfo.mod != null)); + } + +} diff --git a/tests/src/test/java/SectorTests.java b/tests/src/test/java/SectorTests.java deleted file mode 100644 index 8df675c04f..0000000000 --- a/tests/src/test/java/SectorTests.java +++ /dev/null @@ -1,105 +0,0 @@ -import arc.struct.*; -import arc.util.*; -import mindustry.content.*; -import mindustry.core.*; -import mindustry.core.GameState.*; -import mindustry.game.*; -import mindustry.io.SaveIO.*; -import mindustry.type.*; -import mindustry.world.*; -import mindustry.world.blocks.storage.*; -import org.junit.jupiter.api.*; - -import static mindustry.Vars.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; - -public class SectorTests{ - - @BeforeAll - static void launchApplication(){ - ApplicationTests.launchApplication(); - } - - @BeforeEach - void resetWorld(){ - Time.setDeltaProvider(() -> 1f); - logic.reset(); - state.set(State.menu); - } - - @TestFactory - DynamicTest[] testZoneValidity(){ - Seq out = new Seq<>(); - if(world == null) world = new World(); - - for(SectorPreset zone : content.sectors()){ - - out.add(dynamicTest(zone.name, () -> { - logic.reset(); - try{ - world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate); - }catch(SaveException e){ - //fails randomly and I don't care about fixing it - e.printStackTrace(); - return; - } - zone.rules.get(state.rules); - ObjectSet resources = new ObjectSet<>(); - boolean hasSpawnPoint = false; - - for(Tile tile : world.tiles){ - if(tile.drop() != null){ - resources.add(tile.drop()); - } - if(tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam){ - hasSpawnPoint = true; - } - } - - Seq spawns = state.rules.spawns; - - int bossWave = 0; - if(state.rules.winWave > 0){ - bossWave = state.rules.winWave; - }else{ - outer: - for(int i = 1; i <= 1000; i++){ - for(SpawnGroup spawn : spawns){ - if(spawn.effect == StatusEffects.boss && spawn.getSpawned(i) > 0){ - bossWave = i; - break outer; - } - } - } - } - - if(state.rules.attackMode){ - bossWave = 100; - }else{ - assertNotEquals(0, bossWave, "Sector doesn't have a boss wave."); - } - - //TODO check for difficulty? - for(int i = 1; i <= bossWave; i++){ - int total = 0; - for(SpawnGroup spawn : spawns){ - total += spawn.getSpawned(i); - } - - assertNotEquals(0, total, "Sector " + zone + " has no spawned enemies at wave " + i); - //TODO this is flawed and needs to be changed later - //assertTrue(total < 75, "Sector spawns too many enemies at wave " + i + " (" + total + ")"); - } - - assertEquals(1, Team.sharded.cores().size, "Sector must have one core: " + zone); - assertTrue(Team.sharded.core().items.total() < 1000, "Sector must not have starting resources: " + zone); - - assertTrue(hasSpawnPoint, "Sector \"" + zone.name + "\" has no spawn points."); - assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.rules.waveTeam.data().hasCore()), "Sector \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns()); - })); - } - - return out.toArray(DynamicTest.class); - } -} diff --git a/tests/src/test/java/power/DirectConsumerTests.java b/tests/src/test/java/power/DirectConsumerTests.java index 1b8aa04a8d..48110ee4e9 100644 --- a/tests/src/test/java/power/DirectConsumerTests.java +++ b/tests/src/test/java/power/DirectConsumerTests.java @@ -1,9 +1,18 @@ package power; +import mindustry.content.*; +import mindustry.type.*; +import mindustry.world.*; +import mindustry.world.blocks.power.PowerGenerator.*; +import mindustry.world.blocks.power.*; +import mindustry.world.blocks.production.*; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + /** Tests for direct power consumers. */ public class DirectConsumerTests extends PowerTestFixture{ - //TODO reimplement -/* + @Test void noPowerRequestedWithNoItems(){ testUnitFactory(0, 0, 0.08f, 0.08f, 1f); @@ -21,26 +30,26 @@ public class DirectConsumerTests extends PowerTestFixture{ } void testUnitFactory(int siliconAmount, int leadAmount, float producedPower, float requestedPower, float expectedSatisfaction){ - Tile consumerTile = createFakeTile(0, 0, new UnitFactory("fakefactory"){{ - entityType = UnitFactoryEntity::new; - unitType = UnitTypes.spirit; - produceTime = 60; + Tile ct = createFakeTile(0, 0, new GenericCrafter("fakefactory"){{ + hasPower = true; + hasItems = true; consumes.power(requestedPower); consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)); }}); - consumerTile.entity.items.add(Items.silicon, siliconAmount); - consumerTile.entity.items.add(Items.lead, leadAmount); + ct.block().init(); + ct.build.items.add(Items.silicon, siliconAmount); + ct.build.items.add(Items.lead, leadAmount); Tile producerTile = createFakeTile(2, 0, createFakeProducerBlock(producedPower)); - producerTile.ent().productionEfficiency = 1f; + ((GeneratorBuild)producerTile.build).productionEfficiency = 1f; PowerGraph graph = new PowerGraph(); - graph.add(producerTile.entity); - graph.add(consumerTile.entity); + graph.add(producerTile.build); + graph.add(ct.build); - consumerTile.entity.update(); + ct.build.update(); graph.update(); - assertEquals(expectedSatisfaction, consumerTile.entity.power.status); - }*/ + assertEquals(expectedSatisfaction, ct.build.power.status); + } } diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 71311cda10..2c58f974be 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -24,7 +24,6 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; * Any expected power amount (produced, consumed, buffered) should be affected by FakeThreadHandler.fakeDelta but status should not! */ public class ItemLiquidGeneratorTests extends PowerTestFixture{ - private ItemLiquidGenerator generator; private Tile tile; private ItemLiquidGeneratorBuild entity; diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 626986b5ce..b97890fed3 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -176,7 +176,7 @@ public class Generators{ for(int x = 0; x < dim; x++){ for(int y = 0; y < dim; y++){ float dst = Mathf.dst((float)x/dim, (float)y/dim, 0.5f, 0.5f) * 2f; - if(dst < 1.2f && RidgedPerlin.noise2d(1, x, y, 3, 1f / 40f) - dst*(1f-fract) > 0.16f){ + if(dst < 1.2f && Ridged.noise2d(1, x, y, 3, 1f / 40f) - dst*(1f-fract) > 0.16f){ image.setRaw(x, y, Color.whiteRgba); } } @@ -220,7 +220,7 @@ public class Generators{ TextureRegion[] regions = block.getGeneratedIcons(); - if(block.variants > 0){ + if(block.variants > 0 || block instanceof Floor){ for(TextureRegion region : block.variantRegions()){ GenRegion gen = (GenRegion)region; if(gen.path == null) continue; @@ -488,7 +488,7 @@ public class Generators{ image.each((x, y) -> { //add darker cracks on top - boolean rValue = Math.max(RidgedPerlin.noise2d(1, x, y, 3, 1f / (20f + image.width/8f)), 0) > 0.16f; + boolean rValue = Math.max(Ridged.noise2d(1, x, y, 3, 1f / (20f + image.width/8f)), 0) > 0.16f; //cut out random chunks with voronoi boolean vval = vn.noise(x, y, 1f / (14f + image.width/40f)) > 0.47; @@ -601,14 +601,11 @@ public class Generators{ /** Generates a scorch pixmap based on parameters. Thread safe, unless multiple scorch generators are running in parallel. */ public static class ScorchGenerator{ - private static final Simplex sim = new Simplex(); - public int size = 80, seed = 0, color = Color.whiteRgba; public double scale = 18, pow = 2, octaves = 4, pers = 0.4, add = 2, nscl = 4.5f; public Pixmap generate(){ Pixmap pix = new Pixmap(size, size); - sim.setSeed(seed); pix.each((x, y) -> { double dst = Mathf.dst(x, y, size/2, size/2) / (size / 2f); @@ -621,7 +618,7 @@ public class Generators{ } private double noise(float angle){ - return Math.pow(sim.octaveNoise2D(octaves, pers, 1 / scale, Angles.trnsx(angle, size/2f) + size/2f, Angles.trnsy(angle, size/2f) + size/2f), pow); + return Math.pow(Simplex.noise2d(seed, octaves, pers, 1 / scale, Angles.trnsx(angle, size/2f) + size/2f, Angles.trnsy(angle, size/2f) + size/2f), pow); } }