Unfinished generation tool

This commit is contained in:
Anuken
2019-03-15 00:13:54 -04:00
parent 43bcf0cf3b
commit 7d1a8f5404
28 changed files with 575 additions and 156 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

View File

@@ -211,6 +211,8 @@ editor.elevation = Elevation
editor.errorload = Error loading file:\n[accent]{0} editor.errorload = Error loading file:\n[accent]{0}
editor.errorsave = Error saving file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0}
editor.errorname = Map has no name defined. editor.errorname = Map has no name defined.
editor.update = Update
editor.apply = Apply
editor.generate = Generate editor.generate = Generate
editor.resize = Resize editor.resize = Resize
editor.loadmap = Load Map editor.loadmap = Load Map

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 238 KiB

View File

@@ -1083,7 +1083,7 @@ public class Blocks implements ContentList{
inaccuracy = 18f; inaccuracy = 18f;
shootCone = 35f; shootCone = 35f;
health = 220; health = 220*size*size;
}}; }};
hail = new ArtilleryTurret("hail"){{ hail = new ArtilleryTurret("hail"){{
@@ -1301,7 +1301,7 @@ public class Blocks implements ContentList{
powerUsed = 0.5f; powerUsed = 0.5f;
consumes.powerBuffered(1200f); consumes.powerBuffered(1200f);
range = 160f; range = 160f;
reload = 200f; reload = 170f;
firingMoveFract = 0.1f; firingMoveFract = 0.1f;
shootDuration = 220f; shootDuration = 220f;

View File

@@ -35,12 +35,12 @@ public class EditorTile extends Tile{
} }
Block previous = floor(); Block previous = floor();
Block ore = oreBlock(); Block ore = ore();
if(previous == type && ore == Blocks.air) return; if(previous == type && ore == Blocks.air) return;
super.setFloor(type); super.setFloor(type);
//ore may get nullified so make sure to save editrs //ore may get nullified so make sure to save editrs
if(oreBlock() != ore){ if(ore() != ore){
op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, oreBlock().id)); op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, ore().id));
} }
if(previous != type){ if(previous != type){
op(TileOp.get(x, y, (byte)OpType.floor.ordinal(), previous.id, type.id)); op(TileOp.get(x, y, (byte)OpType.floor.ordinal(), previous.id, type.id));

View File

@@ -101,7 +101,7 @@ public enum EditorTool{
boolean synth = editor.drawBlock.synthetic(); boolean synth = editor.drawBlock.synthetic();
Block draw = editor.drawBlock; Block draw = editor.drawBlock;
dest = draw instanceof OreBlock ? tile.oreBlock() : isfloor ? floor : block; dest = draw instanceof OreBlock ? tile.ore() : isfloor ? floor : block;
if(dest == draw || block == Blocks.part || block.isMultiblock()){ if(dest == draw || block == Blocks.part || block.isMultiblock()){
return; return;
@@ -190,7 +190,7 @@ public enum EditorTool{
boolean eq(int px, int py){ boolean eq(int px, int py){
Tile tile = data.tile(px, py); Tile tile = data.tile(px, py);
return (data.drawBlock instanceof OreBlock ? tile.oreBlock() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid); return (data.drawBlock instanceof OreBlock ? tile.ore() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid);
} }
}, },
zoom; zoom;

View File

@@ -224,6 +224,9 @@ public class MapEditor{
if(drawBlock.synthetic()){ if(drawBlock.synthetic()){
tile.setTeam(drawTeam); tile.setTeam(drawTeam);
} }
if(drawBlock.rotate){
tile.setRotation((byte)rotation);
}
} }
} }
} }

View File

@@ -37,6 +37,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
private MapInfoDialog infoDialog; private MapInfoDialog infoDialog;
private MapLoadDialog loadDialog; private MapLoadDialog loadDialog;
private MapResizeDialog resizeDialog; private MapResizeDialog resizeDialog;
private MapGenerateDialog generateDialog;
private ScrollPane pane; private ScrollPane pane;
private FloatingDialog menu; private FloatingDialog menu;
private boolean saved = false; private boolean saved = false;
@@ -50,8 +51,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor = new MapEditor(); editor = new MapEditor();
view = new MapView(editor); view = new MapView(editor);
infoDialog = new MapInfoDialog(editor); infoDialog = new MapInfoDialog(editor);
generateDialog = new MapGenerateDialog(editor);
menu = new FloatingDialog("$menu"); menu = new FloatingDialog("$menu");
menu.addCloseButton(); menu.addCloseButton();
@@ -62,15 +63,20 @@ public class MapEditorDialog extends Dialog implements Disposable{
menu.cont.table(t -> { menu.cont.table(t -> {
t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5); t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5);
t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2); t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save);
t.row();
t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> { t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> {
infoDialog.show(); infoDialog.show();
menu.hide(); menu.hide();
}); });
t.row();
t.addImageTextButton("$editor.generate", "icon-editor", isize, () -> {
generateDialog.show();
menu.hide();
});
t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> { t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> {
resizeDialog.show(); resizeDialog.show();
menu.hide(); menu.hide();

View File

@@ -0,0 +1,167 @@
package io.anuke.mindustry.editor;
import io.anuke.arc.collection.Array;
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.mindustry.editor.generation.GenerateFilter.GenerateInput;
import io.anuke.mindustry.editor.generation.NoiseFilter;
import io.anuke.mindustry.game.Team;
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.Tile;
import io.anuke.mindustry.world.blocks.Floor;
public class MapGenerateDialog extends FloatingDialog{
private final MapEditor editor;
private Pixmap pixmap;
private Texture texture;
private GenerateInput input = new GenerateInput();
private Array<GenerateFilter> filters = new Array<>();
public MapGenerateDialog(MapEditor editor){
super("editor.generate");
this.editor = editor;
shown(this::setup);
addCloseButton();
buttons.addButton("$editor.apply", () -> {
apply();
hide();
}).size(180f, 64f);
}
void setup(){
if(pixmap != null){
pixmap.dispose();
texture.dispose();
pixmap = null;
texture = null;
}
pixmap = new Pixmap(editor.width(), editor.height(), 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.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.row();
right.addButton("$add", () -> {
filters.add(new NoiseFilter());
rebuild.run();
}).fillX().height(50f);
}).grow();
t.row();
t.addButton("$editor.update", () -> {
input.randomize();
update();
}).size(300f, 66f).colspan(2).pad(6);
});
update();
}
void apply(){
Tile[][] writeTiles = new Tile[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);
}
}
for(GenerateFilter filter : filters){
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());
}
}
editor.load(() -> {
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];
tile.setRotation(write.getRotation());
tile.setOre(write.ore());
tile.setFloor(write.floor());
tile.setBlock(write.block());
tile.setTeam(write.getTeam());
}
}
});
}
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(!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));
}
}
}
texture.draw(pixmap, 0, 0);
}
}

View File

@@ -139,8 +139,8 @@ public class MapRenderer implements Disposable{
region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon();
offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl;
offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl;
}else if(wall == Blocks.air && tile.oreBlock() != null){ }else if(wall == Blocks.air && tile.ore() != null){
region = tile.oreBlock().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.oreBlock().editorVariantRegions().length-1)];; region = tile.ore().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.ore().editorVariantRegions().length-1)];;
}else{ }else{
region = Core.atlas.find("clear-editor"); region = Core.atlas.find("clear-editor");
} }

View File

@@ -200,7 +200,7 @@ public class WaveInfoDialog extends FloatingDialog{
preview.clear(); preview.clear();
preview.top(); preview.top();
Array<SpawnGroup> groups = (this.groups == null ? DefaultWaves.getDefaultSpawns() : this.groups); Array<SpawnGroup> groups = (this.groups == null ? DefaultWaves.get() : this.groups);
for(int i = start; i < displayed + start; i ++){ for(int i = start; i < displayed + start; i ++){
int wave = i; int wave = i;

View File

@@ -0,0 +1,24 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
import io.anuke.mindustry.world.Tile;
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)
);
}
@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);
in.floor = tile.floor();
if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block();
in.ore = tile.ore();
}
}

View File

@@ -0,0 +1,78 @@
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.layout.Table;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.blocks.OreBlock;
public abstract class FilterOption{
public static final Predicate<Block> floorsOnly = b -> (b instanceof Floor && !(b instanceof OreBlock)) && Core.atlas.isFound(b.icon(Icon.full));
public static final Predicate<Block> wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full));
public abstract void build(Table table);
static class SliderOption extends FilterOption{
final String name;
final FloatProvider getter;
final FloatConsumer setter;
final float min, max;
SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max){
this.name = name;
this.getter = getter;
this.setter = setter;
this.min = min;
this.max = max;
}
@Override
public void build(Table table){
table.add(name);
table.row();
table.addSlider(min, max, (max-min)/100f, setter).get().setValue(getter.get());
}
}
static class BlockOption extends FilterOption{
final String name;
final Supplier<Block> supplier;
final Consumer<Block> consumer;
final Predicate<Block> filter;
BlockOption(String name, Supplier<Block> supplier, Consumer<Block> consumer, Predicate<Block> filter){
this.name = name;
this.supplier = supplier;
this.consumer = consumer;
this.filter = filter;
}
@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);
}, () -> {
FloatingDialog dialog = new FloatingDialog("");
dialog.setFillParent(false);
int i = 0;
for(Block block : Vars.content.blocks()){
if(!filter.test(block)) continue;
dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> {
consumer.accept(block);
dialog.hide();
});
if(++i % 10 == 0) dialog.cont.row();
}
dialog.show();
});
}
}
}

View File

@@ -0,0 +1,63 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.noise.Simplex;
import io.anuke.mindustry.editor.MapEditor;
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 GenerateInput in;
public FilterOption[] options;
protected abstract void apply();
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;
}
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;
}
public void options(FilterOption... options){
this.options = options;
}
public final void apply(GenerateInput in){
this.in = in;
apply();
}
public static class GenerateInput{
public Floor srcfloor;
public Block srcblock;
public Block srcore;
public int x, y;
public MapEditor editor;
public Block floor, block, ore;
Simplex noise = new Simplex();
public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){
this.editor = editor;
this.floor = this.srcfloor = (Floor)floor;
this.block = this.srcblock = block;
this.ore = srcore = ore;
this.x = x;
this.y = y;
}
public void randomize(){
noise.setSeed(Mathf.random(99999999));
}
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));
}
}
}

View File

@@ -0,0 +1,35 @@
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 NoiseFilter extends GenerateFilter{
float scl = 40, threshold = 0.5f, octaves = 3f, falloff = 0.5f;
Block floor = Blocks.stone, block = Blocks.rocks;
{
options(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 100f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 20f),
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);
if(noise > threshold){
in.floor = floor;
if(wallsOnly.test(in.srcblock)) in.block = block;
}
}
}

View File

@@ -9,159 +9,158 @@ import io.anuke.mindustry.type.ItemStack;
public class DefaultWaves{ public class DefaultWaves{
private static Array<SpawnGroup> spawns; private static Array<SpawnGroup> spawns;
public static Array<SpawnGroup> getDefaultSpawns(){ public static Array<SpawnGroup> get(){
if(spawns == null && UnitTypes.dagger != null){ if(spawns == null && UnitTypes.dagger != null){
spawns = Array.with( spawns = Array.with(
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
end = 8; end = 8;
unitScaling = 2; unitScaling = 2;
}}, }},
new SpawnGroup(UnitTypes.wraith){{ new SpawnGroup(UnitTypes.wraith){{
begin = 12; begin = 12;
end = 14; end = 14;
unitScaling = 2; unitScaling = 2;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 11; begin = 11;
unitScaling = 2; unitScaling = 2;
spacing = 2; spacing = 2;
max = 4; max = 4;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 9; begin = 9;
spacing = 3; spacing = 3;
unitScaling = 2; unitScaling = 2;
end = 30; end = 30;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 10; begin = 8;
unitScaling = 2; unitScaling = 1;
unitAmount = 1; unitAmount = 1;
spacing = 2; spacing = 2;
end = 30; end = 30;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 28; begin = 28;
spacing = 3; spacing = 3;
unitScaling = 1; unitScaling = 1;
end = 40; end = 40;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 45; begin = 45;
spacing = 3; spacing = 3;
unitScaling = 2; unitScaling = 2;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
}}, }},
new SpawnGroup(UnitTypes.titan){{ new SpawnGroup(UnitTypes.titan){{
begin = 120; begin = 120;
spacing = 2; spacing = 2;
unitScaling = 3; unitScaling = 3;
unitAmount = 5; unitAmount = 5;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
}}, }},
new SpawnGroup(UnitTypes.wraith){{ new SpawnGroup(UnitTypes.wraith){{
begin = 16; begin = 16;
unitScaling = 2; unitScaling = 1;
spacing = 2; spacing = 2;
end = 39; max = 7;
max = 7; }},
}},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 82; begin = 82;
spacing = 3; spacing = 3;
unitAmount = 4; unitAmount = 4;
unitScaling = 3; unitScaling = 3;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 41; begin = 41;
spacing = 5; spacing = 5;
unitAmount = 1; unitAmount = 1;
unitScaling = 3; unitScaling = 3;
effect = StatusEffects.shielded; effect = StatusEffects.shielded;
max = 10; max = 10;
}}, }},
new SpawnGroup(UnitTypes.fortress){{ new SpawnGroup(UnitTypes.fortress){{
begin = 40; begin = 40;
spacing = 5; spacing = 5;
unitAmount = 2; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
max = 10; max = 10;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 35; begin = 35;
spacing = 3; spacing = 3;
unitAmount = 4; unitAmount = 4;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
items = new ItemStack(Items.blastCompound, 60); items = new ItemStack(Items.blastCompound, 60);
end = 60; end = 60;
}}, }},
new SpawnGroup(UnitTypes.dagger){{ new SpawnGroup(UnitTypes.dagger){{
begin = 42; begin = 42;
spacing = 3; spacing = 3;
unitAmount = 4; unitAmount = 4;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
items = new ItemStack(Items.pyratite, 100); items = new ItemStack(Items.pyratite, 100);
end = 130; end = 130;
}}, }},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 40; begin = 40;
unitAmount = 2; unitAmount = 2;
spacing = 2; spacing = 2;
unitScaling = 3; unitScaling = 3;
max = 8; max = 8;
}}, }},
new SpawnGroup(UnitTypes.wraith){{ new SpawnGroup(UnitTypes.wraith){{
begin = 50; begin = 50;
unitAmount = 4; unitAmount = 4;
unitScaling = 3; unitScaling = 3;
spacing = 5; spacing = 5;
effect = StatusEffects.overdrive; effect = StatusEffects.overdrive;
max = 8; max = 8;
}}, }},
new SpawnGroup(UnitTypes.revenant){{ new SpawnGroup(UnitTypes.revenant){{
begin = 50; begin = 50;
unitAmount = 2; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
spacing = 5; spacing = 5;
max = 8; max = 8;
}}, }},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 53; begin = 53;
unitAmount = 2; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
spacing = 4; spacing = 4;
max = 8; max = 8;
end = 74; end = 74;
}}, }},
new SpawnGroup(UnitTypes.ghoul){{ new SpawnGroup(UnitTypes.ghoul){{
begin = 53; begin = 53;
unitAmount = 2; unitAmount = 2;
unitScaling = 3; unitScaling = 3;
spacing = 4; spacing = 4;
max = 8; max = 8;
end = 74; end = 74;
}} }}
); );
} }
return spawns == null ? new Array<>() : spawns; return spawns == null ? new Array<>() : spawns;

View File

@@ -9,13 +9,13 @@ public enum RulePreset{
waveTimer = true; waveTimer = true;
waves = true; waves = true;
unitDrops = true; unitDrops = true;
spawns = DefaultWaves.getDefaultSpawns(); spawns = DefaultWaves.get();
}}), }}),
sandbox(() -> new Rules(){{ sandbox(() -> new Rules(){{
infiniteResources = true; infiniteResources = true;
waves = true; waves = true;
waveTimer = false; waveTimer = false;
spawns = DefaultWaves.getDefaultSpawns(); spawns = DefaultWaves.get();
}}), }}),
attack(() -> new Rules(){{ attack(() -> new Rules(){{
enemyCheat = true; enemyCheat = true;

View File

@@ -28,5 +28,5 @@ public class Rules{
/**Zone ID, -1 for invalid zone.*/ /**Zone ID, -1 for invalid zone.*/
public byte zone = -1; public byte zone = -1;
/**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/
public transient Array<SpawnGroup> spawns = DefaultWaves.getDefaultSpawns(); public transient Array<SpawnGroup> spawns = DefaultWaves.get();
} }

View File

@@ -137,7 +137,7 @@ public class MinimapRenderer implements Disposable{
private int colorFor(Tile tile){ private int colorFor(Tile tile){
tile = tile.target(); tile = tile.target();
return MapIO.colorFor(tile.floor(), tile.block(), tile.oreBlock(), tile.getTeam()); return MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam());
} }
@Override @Override

View File

@@ -105,7 +105,7 @@ public class MapIO{
for(int x = 0; x < pixmap.getWidth(); x++){ for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){ for(int y = 0; y < pixmap.getHeight(); y++){
Tile tile = tiles[x][y]; Tile tile = tiles[x][y];
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.oreBlock(), tile.getTeam())); pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam()));
} }
} }
return pixmap; return pixmap;

View File

@@ -13,7 +13,7 @@ import io.anuke.mindustry.io.MapIO;
import static io.anuke.mindustry.Vars.world; import static io.anuke.mindustry.Vars.world;
public class Map{ public class Map implements Comparable<Map>{
/** Whether this is a custom map.*/ /** Whether this is a custom map.*/
public final boolean custom; public final boolean custom;
/** Metadata. Author description, display name, etc.*/ /** Metadata. Author description, display name, etc.*/
@@ -54,10 +54,10 @@ public class Map{
}catch(Exception e){ }catch(Exception e){
Log.err("Malformed waves: {0}", tags.get("waves")); Log.err("Malformed waves: {0}", tags.get("waves"));
e.printStackTrace(); e.printStackTrace();
return DefaultWaves.getDefaultSpawns(); return DefaultWaves.get();
} }
}else{ }else{
return DefaultWaves.getDefaultSpawns(); return DefaultWaves.get();
} }
} }
@@ -90,6 +90,16 @@ public class Map{
return tags.containsKey(name); return tags.containsKey(name);
} }
@Override
public int compareTo(Map map){
int type = -Boolean.compare(custom, map.custom);
if(type != 0){
return type;
}else{
return name().compareTo(map.name());
}
}
@Override @Override
public String toString(){ public String toString(){
return "Map{" + return "Map{" +

View File

@@ -113,6 +113,7 @@ public class Maps implements Disposable{
map.texture = new Texture(MapIO.generatePreview(data)); map.texture = new Texture(MapIO.generatePreview(data));
} }
maps.add(map); maps.add(map);
maps.sort();
}catch(IOException e){ }catch(IOException e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -181,6 +182,7 @@ public class Maps implements Disposable{
} }
maps.add(map); maps.add(map);
maps.sort();
} }
private void loadCustomMaps(){ private void loadCustomMaps(){

View File

@@ -340,6 +340,6 @@ public class PlacementFragment extends Fragment{
/** Returns the block currently being hovered over in the world. */ /** Returns the block currently being hovered over in the world. */
Block tileDisplayBlock(){ Block tileDisplayBlock(){
return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.oreBlock() != Blocks.air ? hoverTile.oreBlock() : null; return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.ore() != Blocks.air ? hoverTile.ore() : null;
} }
} }

View File

@@ -0,0 +1,25 @@
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
}
}

View File

@@ -345,7 +345,7 @@ public class Tile implements Position, TargetTrait{
this.ore = 0; this.ore = 0;
} }
public Floor oreBlock(){ public Floor ore(){
return (Floor)content.block(ore); return (Floor)content.block(ore);
} }

View File

@@ -18,6 +18,11 @@ public class BlockPart extends Block{
hasPower = hasItems = hasLiquids = true; hasPower = hasItems = hasLiquids = true;
} }
@Override
public boolean synthetic(){
return true;
}
@Override @Override
public boolean isHidden(){ public boolean isHidden(){
return true; return true;

View File

@@ -109,7 +109,7 @@ public class Floor extends Block{
Mathf.random.setSeed(tile.pos()); Mathf.random.setSeed(tile.pos());
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
Floor floor = tile.oreBlock(); Floor floor = tile.ore();
if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case
floor.draw(tile); floor.draw(tile);
} }