diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 1abc9e52f0..a3dafdd022 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -212,6 +212,7 @@ editor.errorload = Error loading file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0} editor.errorname = Map has no name defined. editor.update = Update +editor.randomize = Randomize editor.apply = Apply editor.generate = Generate editor.resize = Resize diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index a6dbfdab31..c6518854a9 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -13,7 +13,6 @@ import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.ScreenRecorder; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pools; @@ -131,10 +130,6 @@ public class Renderer implements ApplicationListener{ draw(); } - - if(!ui.chatfrag.chatOpen()){ - ScreenRecorder.record(); //this only does something if CoreGifRecorder is on the class path, which it usually isn't - } } void updateShake(float scale){ diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index c0bf7e8d41..cb6577a630 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -52,7 +52,7 @@ public class MapEditor{ tiles = createTiles(map.width, map.height); tags.putAll(map.tags); MapIO.readTiles(map, tiles); - checkTiles(); + checkLinkedTiles(); renderer.resize(width(), height()); loading = false; } @@ -61,12 +61,12 @@ public class MapEditor{ reset(); this.tiles = tiles; - checkTiles(); + checkLinkedTiles(); renderer.resize(width(), height()); } //adds missing blockparts - void checkTiles(){ + public void checkLinkedTiles(){ //clear block parts first for(int x = 0; x < width(); x ++){ for(int y = 0; y < height(); y++){ diff --git a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java index 1c4303bc6d..9780c99361 100644 --- a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java @@ -1,32 +1,49 @@ package io.anuke.mindustry.editor; +import io.anuke.arc.Core; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.graphics.Pixmap.Format; import io.anuke.arc.graphics.Texture; -import io.anuke.arc.scene.Element; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.editor.generation.FilterOption; -import io.anuke.mindustry.editor.generation.GenerateFilter; +import io.anuke.arc.util.Scaling; +import io.anuke.arc.util.async.AsyncExecutor; +import io.anuke.arc.util.async.AsyncResult; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.*; import io.anuke.mindustry.editor.generation.GenerateFilter.GenerateInput; -import io.anuke.mindustry.editor.generation.NoiseFilter; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.mindustry.world.DummyTile; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; +import static io.anuke.mindustry.Vars.mobile; + +@SuppressWarnings("unchecked") public class MapGenerateDialog extends FloatingDialog{ private final MapEditor editor; private Pixmap pixmap; private Texture texture; private GenerateInput input = new GenerateInput(); private Array filters = new Array<>(); + private int scaling = mobile ? 3 : 1; + private Supplier[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new}; + private Table filterTable; + + private AsyncExecutor executor = new AsyncExecutor(1); + private AsyncResult result; + private boolean generating; + private DummyTile returnTile = new DummyTile(); + + private DummyTile[][] buffer1, buffer2; public MapGenerateDialog(MapEditor editor){ - super("editor.generate"); + super("$editor.generate"); this.editor = editor; shown(this::setup); @@ -35,9 +52,17 @@ public class MapGenerateDialog extends FloatingDialog{ apply(); hide(); }).size(180f, 64f); + buttons.addButton("$editor.randomize", () -> { + for(GenerateFilter filter : filters){ + filter.randomize(); + } + update(); + }).size(180f, 64f); } void setup(){ + filters.clear(); + if(pixmap != null){ pixmap.dispose(); texture.dispose(); @@ -45,123 +70,246 @@ public class MapGenerateDialog extends FloatingDialog{ texture = null; } - pixmap = new Pixmap(editor.width(), editor.height(), Format.RGBA8888); + pixmap = new Pixmap(editor.width() / scaling, editor.height() / scaling, Format.RGBA8888); texture = new Texture(pixmap); cont.clear(); cont.table("flat", t -> { t.margin(8f); - t.add(new BorderImage(texture)).size(500f).padRight(6); + t.add(new BorderImage(texture)).grow().padRight(6).top().get().setScaling(Scaling.fit); t.table(right -> { - Table[] fs = {null}; - Runnable rebuild = () -> { - Table p = fs[0]; - p.clearChildren(); - - for(GenerateFilter filter : filters){ - p.table("button", f -> { - f.left(); - for(FilterOption option : filter.options){ - option.build(f); - f.row(); - } - for(Element e : f.getChildren()){ - e.changed(this::update); - } - }).pad(3).width(280f); - p.row(); - } - }; - - right.pane(p -> { - p.top(); - fs[0] = p; - }).fill().width(300f).growY().get().setScrollingDisabled(true, false); + right.pane(p -> filterTable = p).grow().get().setScrollingDisabled(true, false); right.row(); - right.addButton("$add", () -> { - filters.add(new NoiseFilter()); - rebuild.run(); - }).fillX().height(50f); + right.addButton("$add", this::showAdd).fillX().height(50f); }).grow(); - - t.row(); - t.addButton("$editor.update", () -> { - input.randomize(); - update(); - }).size(300f, 66f).colspan(2).pad(6); - }); + }).grow(); update(); + + buffer1 = create(); + buffer2 = create(); + } + + DummyTile[][] create(){ + DummyTile[][] out = new DummyTile[editor.width() / scaling][editor.height() / scaling]; + + for(int x = 0; x < out.length; x++){ + for(int y = 0; y < out[0].length; y++){ + out[x][y] = new DummyTile(); + } + } + return out; + } + + void rebuildFilters(){ + filterTable.clearChildren(); + filterTable.top(); + + for(GenerateFilter filter : filters){ + filterTable.table(t -> { + t.add(filter.name()).padTop(5).color(Pal.accent).growX().left(); + + t.row(); + + t.table(b -> { + b.left(); + b.defaults().size(50f); + b.addImageButton("icon-refresh", 14*2, () -> { + filter.randomize(); + update(); + }); + + b.addImageButton("icon-arrow-up", 10*2, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.max(0, idx - 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-arrow-down", 10*2, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.min(filters.size-1, idx + 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-trash", 14*2, () -> { + filters.remove(filter); + rebuildFilters(); + update(); + }); + }).growX(); + }).fillX(); + filterTable.row(); + filterTable.table("underline", f -> { + f.left(); + for(FilterOption option : filter.options){ + option.changed = this::update; + + f.table(t -> { + t.left(); + option.build(t); + }).growX().left(); + f.row(); + } + }).pad(3).padTop(0).width(280f); + filterTable.row(); + } + } + + void showAdd(){ + FloatingDialog selection = new FloatingDialog(""); + selection.setFillParent(false); + selection.cont.defaults().size(210f, 60f); + for(Supplier gen : filterTypes){ + GenerateFilter filter = gen.get(); + selection.cont.addButton(filter.name(), () -> { + filters.add(filter); + rebuildFilters(); + update(); + selection.hide(); + }); + selection.cont.row(); + } + + selection.addCloseButton(); + selection.show(); + } + + DummyTile dset(Tile tile){ + returnTile.set(tile); + return returnTile; } void apply(){ - Tile[][] writeTiles = new Tile[editor.width()][editor.height()]; + if(result != null){ + result.get(); + } + + //writeback buffer + DummyTile[][] writeTiles = new DummyTile[editor.width()][editor.height()]; for(int x = 0; x < editor.width(); x++){ for(int y = 0; y < editor.height(); y++){ - writeTiles[x][y] = new DummyTile(x, y); + writeTiles[x][y] = new DummyTile(); } } for(GenerateFilter filter : filters){ + input.setFilter(filter, (x, y) -> dset(editor.tile(x, y))); + //write to buffer for(int x = 0; x < editor.width(); x++){ for(int y = 0; y < editor.height(); y++){ Tile tile = editor.tile(x, y); - Tile write = writeTiles[x][y]; input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); filter.apply(input); - write.setRotation(tile.getRotation()); - write.setOre(input.ore); - write.setFloor((Floor)input.floor); - write.setBlock(input.block); - write.setTeam(tile.getTeam()); + writeTiles[x][y].set(input.floor, input.block, input.ore, tile.getTeam(), tile.getRotation()); } } editor.load(() -> { + //read from buffer back into tiles for(int x = 0; x < editor.width(); x++){ for(int y = 0; y < editor.height(); y++){ Tile tile = editor.tile(x, y); - Tile write = writeTiles[x][y]; + DummyTile write = writeTiles[x][y]; - tile.setRotation(write.getRotation()); - tile.setOre(write.ore()); - tile.setFloor(write.floor()); - tile.setBlock(write.block()); - tile.setTeam(write.getTeam()); + tile.setRotation((byte)write.rotation); + tile.setFloor((Floor)write.floor); + tile.setBlock(write.block); + tile.setTeam(write.team); + tile.setOre(write.ore); } } }); } + //reset undo stack as generation... messes things up + editor.load(editor::checkLinkedTiles); editor.renderer().updateAll(); editor.clearOp(); } void update(){ - boolean modified = false; - for(GenerateFilter filter : filters){ - modified = true; - for(int x = 0; x < editor.width(); x++){ - for(int y = 0; y < editor.height(); y++){ - Tile tile = editor.tile(x, y); - input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); - filter.apply(input); - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(input.floor, input.block, input.ore, Team.none)); - } - } + if(generating){ + return; } - if(!modified){ - for(int x = 0; x < editor.width(); x++){ - for(int y = 0; y < editor.height(); y++){ - Tile tile = editor.tile(x, y); - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none)); + Array copy = new Array<>(filters); + + result = executor.submit(() -> { + generating = true; + + if(!filters.isEmpty()){ + //write to buffer1 for reading + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + buffer1[px][py].set(editor.tile(px * scaling, py * scaling)); + } } } + + for(GenerateFilter filter : copy){ + input.setFilter(filter, (x, y) -> buffer1[x][y]); + //read from buffer1 and write to buffer2 + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + int x = px*scaling, y = py*scaling; + DummyTile tile = buffer1[px][py]; + input.begin(editor, x, y, tile.floor, tile.block, tile.ore); + filter.apply(input); + buffer2[px][py].set(input.floor, input.block, input.ore, tile.team, tile.rotation); + } + } + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + buffer1[px][py].set(buffer2[px][py]); + } + } + } + + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + int color; + //get result from buffer1 if there's filters left, otherwise get from editor directly + if(filters.isEmpty()){ + Tile tile = editor.tile(px * scaling, py * scaling); + color = MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none); + }else{ + DummyTile tile = buffer1[px][py]; + color = MapIO.colorFor(tile.floor, tile.block, tile.ore, Team.none); + } + pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color); + } + } + + Core.app.post(() -> { + texture.draw(pixmap, 0, 0); + generating = false; + }); + return null; + }); + } + + public static class DummyTile{ + public Block block = Blocks.air, ore = Blocks.air, floor = Blocks.air; + public Team team = Team.none; + public int rotation; + + void set(Block floor, Block wall, Block ore, Team team, int rotation){ + this.floor = floor; + this.block = wall; + this.ore = ore; + this.team = team; + this.rotation = rotation; + } + + void set(DummyTile other){ + set(other.floor, other.block, other.ore, other.team, other.rotation); + } + + void set(Tile other){ + set(other.floor(), other.block(), other.ore(), other.getTeam(), other.getRotation()); } - texture.draw(pixmap, 0, 0); } } diff --git a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java index c029eec7d7..042d08ed01 100644 --- a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java @@ -1,24 +1,25 @@ package io.anuke.mindustry.editor.generation; +import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile; import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; public class DistortFilter extends GenerateFilter{ float scl = 40, mag = 5; { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 1000f), - new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 10f) + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) ); } @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); + DummyTile 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); - in.floor = tile.floor(); - if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); - in.ore = tile.ore(); + in.floor = tile.floor; + if(!tile.block.synthetic() && !in.block.synthetic()) in.block = tile.block; + if(!((Floor)in.floor).isLiquid) in.ore = tile.ore; } } diff --git a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java index 81754438a4..50e6a69cc9 100644 --- a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java +++ b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.editor.generation; import io.anuke.arc.Core; import io.anuke.arc.function.*; import io.anuke.arc.scene.style.TextureRegionDrawable; +import io.anuke.arc.scene.ui.Slider; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.Vars; import io.anuke.mindustry.ui.dialogs.FloatingDialog; @@ -16,6 +17,7 @@ public abstract class FilterOption{ public static final Predicate wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full)); public abstract void build(Table table); + public Runnable changed = () -> {}; static class SliderOption extends FilterOption{ final String name; @@ -35,7 +37,9 @@ public abstract class FilterOption{ public void build(Table table){ table.add(name); table.row(); - table.addSlider(min, max, (max-min)/100f, setter).get().setValue(getter.get()); + Slider slider = table.addSlider(min, max, (max-min)/200f, setter).growX().get(); + slider.setValue(getter.get()); + slider.changed(changed); } } @@ -54,7 +58,6 @@ public abstract class FilterOption{ @Override public void build(Table table){ - table.add(name + ": "); table.addButton(b -> { b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()).setRegion(supplier.get().icon(Icon.small))).size(8*3); }, () -> { @@ -65,14 +68,17 @@ public abstract class FilterOption{ if(!filter.test(block)) continue; dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> { - consumer.accept(block); - dialog.hide(); + consumer.accept(block); + dialog.hide(); + changed.run(); }); if(++i % 10 == 0) dialog.cont.row(); } dialog.show(); - }); + }).pad(4).margin(12f); + + table.add(name); } } } diff --git a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java index fd3e107b6b..d889907b0c 100644 --- a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java @@ -1,14 +1,18 @@ package io.anuke.mindustry.editor.generation; +import io.anuke.arc.Core; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Pack; +import io.anuke.arc.util.noise.RidgedPerlin; import io.anuke.arc.util.noise.Simplex; import io.anuke.mindustry.editor.MapEditor; +import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; public abstract class GenerateFilter{ protected float o = (float)(Math.random()*10000000.0); + protected long seed; protected GenerateInput in; public FilterOption[] options; @@ -23,10 +27,26 @@ public abstract class GenerateFilter{ return (float)in.noise.octaveNoise2D(octaves, persistence, 1f/scl, x + o, y + o)*mag; } + protected float rnoise(float x, float y, float scl, float mag){ + return in.pnoise.getValue((int)(x + o), (int)(y + o), 1f/scl)*mag; + } + + public void randomize(){ + seed = Mathf.random(99999999); + } + + protected float chance(){ + return Mathf.randomSeed(Pack.longInt(in.x, in.y + (int)o)); + } + public void options(FilterOption... options){ this.options = options; } + public String name(){ + return Core.bundle.get("filter." + getClass().getSimpleName().toLowerCase().replace("filter", ""), getClass().getSimpleName().replace("Filter", "")); + } + public final void apply(GenerateInput in){ this.in = in; apply(); @@ -42,6 +62,8 @@ public abstract class GenerateFilter{ public Block floor, block, ore; Simplex noise = new Simplex(); + RidgedPerlin pnoise = new RidgedPerlin(0, 1); + TileProvider buffer; public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){ this.editor = editor; @@ -52,12 +74,18 @@ public abstract class GenerateFilter{ this.y = y; } - public void randomize(){ - noise.setSeed(Mathf.random(99999999)); + public void setFilter(GenerateFilter filter, TileProvider buffer){ + this.buffer = buffer; + noise.setSeed(filter.seed); + pnoise.setSeed((int)(filter.seed + 1)); } - Tile tile(double x, double y){ - return editor.tile((int)Mathf.clamp(x, 0, editor.width() - 1), (int)Mathf.clamp(y, 0, editor.height() - 1)); + DummyTile tile(float x, float y){ + return buffer.get(Mathf.clamp((int)x, 0, editor.width() - 1), Mathf.clamp((int)y, 0, editor.height() - 1)); + } + + public interface TileProvider{ + DummyTile get(int x, int y); } } } diff --git a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java index da9ace148f..580c6331a2 100644 --- a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java +++ b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java @@ -14,9 +14,9 @@ public class NoiseFilter extends GenerateFilter{ { options( - new SliderOption("scale", () -> scl, f -> scl = f, 1f, 100f), + 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, 20f), + 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, floorsOnly), new BlockOption("wall", () -> block, b -> block = b, wallsOnly) diff --git a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java new file mode 100644 index 0000000000..2920ee7ad3 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java @@ -0,0 +1,36 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; + +public class RiverNoiseFilter extends GenerateFilter{ + float scl = 40, threshold = 0f, threshold2 = 0.1f; + Block floor = Blocks.water, floor2 = Blocks.deepwater; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) + ); + } + + @Override + public void apply(){ + float noise = rnoise(in.x, in.y, scl, 1f); + + if(noise >= threshold){ + in.floor = floor; + + if(noise >= threshold2){ + in.floor = floor2; + } + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java new file mode 100644 index 0000000000..af6b09822e --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java @@ -0,0 +1,30 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class ScatterFilter extends GenerateFilter{ + float chance = 0.1f; + Block floor = Blocks.ice, block = Blocks.icerocks; + + { + options( + new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("block", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + + if(in.srcfloor == floor && in.srcblock == Blocks.air && chance() <= chance){ + in.block = block; + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java new file mode 100644 index 0000000000..7400e97f64 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java @@ -0,0 +1,41 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class TerrainFilter extends GenerateFilter{ + float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, circleScl = 2.1f; + Block floor = Blocks.stone, block = Blocks.rocks; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + 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, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + float noise = noise(in.x, in.y, scl, 1f, octaves, falloff) + Mathf.dst((float) in.x / in.editor.width(), (float) in.y / in.editor.height(), 0.5f, 0.5f) * circleScl; + + in.floor = floor; + in.ore = Blocks.air; + + if(noise >= threshold){ + in.block = block; + }else{ + in.block = Blocks.air; + } + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/DummyTile.java b/core/src/io/anuke/mindustry/world/DummyTile.java deleted file mode 100644 index 147bc96de9..0000000000 --- a/core/src/io/anuke/mindustry/world/DummyTile.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.anuke.mindustry.world; - -import io.anuke.mindustry.game.Team; - -public class DummyTile extends Tile{ - - public DummyTile(int x, int y){ - super(x, y); - } - - @Override - public Team getTeam(){ - return Team.all[getTeamID()]; - } - - @Override - protected void changed(){ - //nothing matters - } - - @Override - protected void preChanged(){ - //it really doesn't - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java index 19b9c92631..3b14abe2d3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -144,6 +144,7 @@ public class PowerGraph{ public void update(){ if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){ + powerBalance.addValue(0f); return; }