From c2ff5a69ef7bd12aa6be70e5f14d994e6479bf7e Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 22 Oct 2020 12:27:22 -0400 Subject: [PATCH] Buffered map-load filter support / Spawn path filter --- core/assets/bundles/bundle.properties | 1 + .../mindustry/editor/MapGenerateDialog.java | 13 ++-- .../mindustry/maps/filters/DistortFilter.java | 2 +- .../maps/filters/GenerateFilter.java | 55 +++++++++++++--- .../mindustry/maps/filters/MirrorFilter.java | 2 +- .../src/mindustry/maps/filters/OreFilter.java | 4 +- .../maps/filters/OreMedianFilter.java | 10 +-- .../mindustry/maps/filters/ScatterFilter.java | 2 +- .../maps/filters/SpawnPathFilter.java | 64 +++++++++++++++++++ .../mindustry/maps/filters/TerrainFilter.java | 3 +- .../maps/generators/BasicGenerator.java | 2 +- 11 files changed, 129 insertions(+), 29 deletions(-) create mode 100644 core/src/mindustry/maps/filters/SpawnPathFilter.java diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 9c4cb2f142..2b44d9ba40 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -421,6 +421,7 @@ filters.empty = [lightgray]No filters! Add one with the button below. filter.distort = Distort filter.noise = Noise filter.enemyspawn = Enemy Spawn Select +filter.spawnpath = Path To Spawn filter.corespawn = Core Select filter.median = Median filter.oremedian = Ore Median diff --git a/core/src/mindustry/editor/MapGenerateDialog.java b/core/src/mindustry/editor/MapGenerateDialog.java index c0292cbf74..8d0b4edd93 100644 --- a/core/src/mindustry/editor/MapGenerateDialog.java +++ b/core/src/mindustry/editor/MapGenerateDialog.java @@ -29,7 +29,8 @@ public class MapGenerateDialog extends BaseDialog{ private final Prov[] filterTypes = new Prov[]{ NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new, OreFilter::new, OreMedianFilter::new, MedianFilter::new, - BlendFilter::new, MirrorFilter::new, ClearFilter::new, CoreSpawnFilter::new, EnemySpawnFilter::new + BlendFilter::new, MirrorFilter::new, ClearFilter::new, CoreSpawnFilter::new, + EnemySpawnFilter::new, SpawnPathFilter::new }; private final MapEditor editor; private final boolean applied; @@ -121,9 +122,9 @@ 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.floor(), tile.block(), tile.overlay()); + input.apply(x, y, tile.block(), tile.floor(), tile.overlay()); filter.apply(input); - writeTiles[x][y].set(input.floor, input.block, input.ore, tile.team()); + writeTiles[x][y].set(input.floor, input.block, input.overlay, tile.team()); } } @@ -295,7 +296,7 @@ public class MapGenerateDialog extends BaseDialog{ for(Prov gen : filterTypes){ GenerateFilter filter = gen.get(); - if((!applied && filter.isBuffered()) || (filter.isPost() && applied)) continue; + if((filter.isPost() && applied)) continue; selection.cont.button(filter.name(), () -> { filters.add(filter); @@ -369,9 +370,9 @@ public class MapGenerateDialog extends BaseDialog{ pixmap.each((px, py) -> { int x = px * scaling, y = py * scaling; GenTile tile = buffer1[px][py]; - input.apply(x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore)); + input.apply(x, y, content.block(tile.block), content.block(tile.floor), content.block(tile.ore)); filter.apply(input); - buffer2[px][py].set(input.floor, input.block, input.ore, Team.get(tile.team)); + buffer2[px][py].set(input.floor, input.block, input.overlay, Team.get(tile.team)); }); pixmap.each((px, py) -> buffer1[px][py].set(buffer2[px][py])); diff --git a/core/src/mindustry/maps/filters/DistortFilter.java b/core/src/mindustry/maps/filters/DistortFilter.java index 32c8f18a14..daedca1765 100644 --- a/core/src/mindustry/maps/filters/DistortFilter.java +++ b/core/src/mindustry/maps/filters/DistortFilter.java @@ -26,6 +26,6 @@ public class DistortFilter extends GenerateFilter{ in.floor = tile.floor(); if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); - in.ore = tile.overlay(); + in.overlay = tile.overlay(); } } diff --git a/core/src/mindustry/maps/filters/GenerateFilter.java b/core/src/mindustry/maps/filters/GenerateFilter.java index c884d5296e..d69ce7305c 100644 --- a/core/src/mindustry/maps/filters/GenerateFilter.java +++ b/core/src/mindustry/maps/filters/GenerateFilter.java @@ -5,7 +5,10 @@ import arc.math.*; import arc.scene.ui.*; import arc.util.*; import arc.util.noise.*; +import mindustry.*; +import mindustry.annotations.Annotations.*; import mindustry.content.*; +import mindustry.gen.*; import mindustry.world.*; public abstract class GenerateFilter{ @@ -15,15 +18,42 @@ public abstract class GenerateFilter{ public void apply(Tiles tiles, GenerateInput in){ this.in = in; - for(Tile tile : tiles){ - in.apply(tile.x, tile.y, tile.floor(), tile.block(), tile.overlay()); - apply(); - tile.setFloor(in.floor.asFloor()); - tile.setOverlay(!in.floor.asFloor().hasSurface() ? Blocks.air : in.ore); + if(isBuffered()){ + //buffer of tiles used, each tile packed into a long struct + long[] buffer = new long[tiles.width * tiles.height]; - if(!tile.block().synthetic() && !in.block.synthetic()){ - tile.setBlock(in.block); + //save to buffer + for(int i = 0; i < tiles.width * tiles.height; i++){ + Tile tile = tiles.geti(i); + buffer[i] = TileBuffer.get(tile.blockID(), tile.floorID(), tile.overlayID()); + } + + for(int i = 0; i < tiles.width * tiles.height; i++){ + Tile tile = tiles.geti(i); + long b = buffer[i]; + + in.apply(tile.x, tile.y, Vars.content.block(TileBuffer.block(b)), Vars.content.block(TileBuffer.floor(b)), Vars.content.block(TileBuffer.overlay(b))); + apply(); + + tile.setFloor(in.floor.asFloor()); + tile.setOverlay(!in.floor.asFloor().hasSurface() ? Blocks.air : in.overlay); + + if(!tile.block().synthetic() && !in.block.synthetic()){ + tile.setBlock(in.block); + } + } + }else{ + for(Tile tile : tiles){ + in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay()); + apply(); + + tile.setFloor(in.floor.asFloor()); + tile.setOverlay(!in.floor.asFloor().hasSurface() ? Blocks.air : in.overlay); + + if(!tile.block().synthetic() && !in.block.synthetic()){ + tile.setBlock(in.block); + } } } } @@ -89,16 +119,16 @@ public abstract class GenerateFilter{ public int x, y, width, height; /** output parameters */ - public Block floor, block, ore; + public Block floor, block, overlay; Simplex noise = new Simplex(); RidgedPerlin pnoise = new RidgedPerlin(0, 1); TileProvider buffer; - public void apply(int x, int y, Block floor, Block block, Block ore){ + public void apply(int x, int y, Block block, Block floor, Block overlay){ this.floor = floor; this.block = block; - this.ore = ore; + this.overlay = overlay; this.x = x; this.y = y; } @@ -119,4 +149,9 @@ public abstract class GenerateFilter{ Tile get(int x, int y); } } + + @Struct + class TileBufferStruct{ + short block, floor, overlay; + } } diff --git a/core/src/mindustry/maps/filters/MirrorFilter.java b/core/src/mindustry/maps/filters/MirrorFilter.java index 8d2e22bdbe..3ebdb45a71 100644 --- a/core/src/mindustry/maps/filters/MirrorFilter.java +++ b/core/src/mindustry/maps/filters/MirrorFilter.java @@ -39,7 +39,7 @@ public class MirrorFilter extends GenerateFilter{ if(!tile.block().synthetic()){ in.block = tile.block(); } - in.ore = tile.overlay(); + in.overlay = tile.overlay(); } } diff --git a/core/src/mindustry/maps/filters/OreFilter.java b/core/src/mindustry/maps/filters/OreFilter.java index 491bbf0123..5f467511dc 100644 --- a/core/src/mindustry/maps/filters/OreFilter.java +++ b/core/src/mindustry/maps/filters/OreFilter.java @@ -26,8 +26,8 @@ public class OreFilter extends GenerateFilter{ public void apply(){ float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); - if(noise > threshold && in.ore != Blocks.spawn){ - in.ore = ore; + if(noise > threshold && in.overlay != Blocks.spawn){ + in.overlay = ore; } } } diff --git a/core/src/mindustry/maps/filters/OreMedianFilter.java b/core/src/mindustry/maps/filters/OreMedianFilter.java index c9fd8d91c6..27a10548af 100644 --- a/core/src/mindustry/maps/filters/OreMedianFilter.java +++ b/core/src/mindustry/maps/filters/OreMedianFilter.java @@ -29,14 +29,14 @@ public class OreMedianFilter extends GenerateFilter{ @Override public void apply(){ - if(in.ore == Blocks.spawn) return; + if(in.overlay == Blocks.spawn) return; int cx = (in.x / 2) * 2; int cy = (in.y / 2) * 2; - if(in.ore != Blocks.air){ - if(!(in.tile(cx + 1, cy).overlay() == in.ore && in.tile(cx, cy).overlay() == in.ore && in.tile(cx + 1, cy + 1).overlay() == in.ore && in.tile(cx, cy + 1).overlay() == in.ore && + if(in.overlay != Blocks.air){ + if(!(in.tile(cx + 1, cy).overlay() == in.overlay && in.tile(cx, cy).overlay() == in.overlay && in.tile(cx + 1, cy + 1).overlay() == in.overlay && in.tile(cx, cy + 1).overlay() == in.overlay && !in.tile(cx + 1, cy).block().isStatic() && !in.tile(cx, cy).block().isStatic() && !in.tile(cx + 1, cy + 1).block().isStatic() && !in.tile(cx, cy + 1).block().isStatic())){ - in.ore = Blocks.air; + in.overlay = Blocks.air; } } @@ -58,6 +58,6 @@ public class OreMedianFilter extends GenerateFilter{ int index = Math.min((int)(blocks.size * percentile), blocks.size - 1); int overlay = blocks.get(index); - in.ore = Vars.content.block(overlay); + in.overlay = Vars.content.block(overlay); } } diff --git a/core/src/mindustry/maps/filters/ScatterFilter.java b/core/src/mindustry/maps/filters/ScatterFilter.java index 4b90275b1f..67d2b0229e 100644 --- a/core/src/mindustry/maps/filters/ScatterFilter.java +++ b/core/src/mindustry/maps/filters/ScatterFilter.java @@ -27,7 +27,7 @@ public class ScatterFilter extends GenerateFilter{ if(!block.isOverlay()){ in.block = block; }else{ - in.ore = block; + in.overlay = block; } } diff --git a/core/src/mindustry/maps/filters/SpawnPathFilter.java b/core/src/mindustry/maps/filters/SpawnPathFilter.java new file mode 100644 index 0000000000..e5f7a3f223 --- /dev/null +++ b/core/src/mindustry/maps/filters/SpawnPathFilter.java @@ -0,0 +1,64 @@ +package mindustry.maps.filters; + +import arc.math.*; +import arc.struct.*; +import arc.util.*; +import mindustry.*; +import mindustry.ai.*; +import mindustry.content.*; +import mindustry.maps.filters.FilterOption.*; +import mindustry.world.*; +import mindustry.world.blocks.storage.*; + +import static mindustry.Vars.*; + +/** Selects X spawns from the spawn pool.*/ +public class SpawnPathFilter extends GenerateFilter{ + int radius = 3; + + @Override + public FilterOption[] options(){ + return Structs.arr( + new SliderOption("radius", () -> radius, f -> radius = (int)f, 1, 20).display() + ); + } + + @Override + public void apply(Tiles tiles, GenerateInput in){ + Tile core = null; + var spawns = new Seq(); + + for(Tile tile : tiles){ + if(tile.overlay() == Blocks.spawn){ + spawns.add(tile); + } + if(tile.block() instanceof CoreBlock && tile.team() != Vars.state.rules.waveTeam){ + core = tile; + } + } + + if(core != null && spawns.any()){ + for(var spawn : spawns){ + var path = Astar.pathfind(core.x, core.y, spawn.x, spawn.y, t -> t.solid() ? 20 : 1, Astar.manhattan, tile -> !tile.floor().isDeep()); + for(var tile : path){ + for(int x = -radius; x <= radius; x++){ + for(int y = -radius; y <= radius; y++){ + int wx = tile.x + x, wy = tile.y + y; + if(Structs.inBounds(wx, wy, world.width(), world.height()) && Mathf.within(x, y, radius)){ + Tile other = tiles.getn(wx, wy); + if(!other.synthetic()){ + other.setBlock(Blocks.air); + } + } + } + } + } + } + } + } + + @Override + public boolean isPost(){ + return true; + } +} diff --git a/core/src/mindustry/maps/filters/TerrainFilter.java b/core/src/mindustry/maps/filters/TerrainFilter.java index cc0ba82b54..4caea2041a 100644 --- a/core/src/mindustry/maps/filters/TerrainFilter.java +++ b/core/src/mindustry/maps/filters/TerrainFilter.java @@ -31,11 +31,10 @@ public class TerrainFilter extends GenerateFilter{ 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; in.floor = floor; - in.ore = Blocks.air; if(noise >= threshold){ in.block = block; - }else{ + }else if(!in.block.synthetic()){ in.block = Blocks.air; } } diff --git a/core/src/mindustry/maps/generators/BasicGenerator.java b/core/src/mindustry/maps/generators/BasicGenerator.java index e20350e6d3..1ef6d31297 100644 --- a/core/src/mindustry/maps/generators/BasicGenerator.java +++ b/core/src/mindustry/maps/generators/BasicGenerator.java @@ -248,7 +248,7 @@ public abstract class BasicGenerator implements WorldGenerator{ for(int x = -rad; x <= rad; x++){ for(int y = -rad; y <= rad; y++){ int wx = cx + x, wy = cy + y; - if(Structs.inBounds(wx, wy, width, height) && Mathf.dst(x, y, 0, 0) <= rad){ + if(Structs.inBounds(wx, wy, width, height) && Mathf.within(x, y, rad)){ Tile other = tiles.getn(wx, wy); other.setBlock(Blocks.air); }