New item bars / Map bugfixes / Stub wave editing

This commit is contained in:
Anuken 2019-03-13 21:26:53 -04:00
parent ecb77b0283
commit f2662045ed
31 changed files with 163 additions and 56 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View File

@ -194,11 +194,15 @@ editor.oregen.info = Ore Generation:
editor.mapinfo = Map Info
editor.author = Author:
editor.description = Description:
editor.waves = Waves:
editor.default = [LIGHT_GRAY]<Default>
edit = Edit...
editor.name = Name:
editor.teams = Teams
editor.elevation = Elevation
editor.errorload = Error loading file:\n[accent]{0}
editor.errorsave = Error saving file:\n[accent]{0}
editor.errorname = Map has no name defined.
editor.generate = Generate
editor.resize = Resize
editor.loadmap = Load Map
@ -309,6 +313,7 @@ blocks.poweroutput = Power Output: {0}
blocks.powercapacity = Power Capacity
blocks.powershot = Power/Shot
blocks.targetsair = Targets Air
blocks.items = Items: {0}
blocks.itemsmoved = Move Speed
blocks.shootrange = Range
blocks.size = Size

View File

@ -250,7 +250,7 @@ public class Blocks implements ContentList{
shale = new Floor("shale"){{
variants = 3;
attributes.set(Attribute.oil, 0.3f);
attributes.set(Attribute.oil, 0.15f);
}};
shaleRocks = new StaticWall("shalerocks"){{

View File

@ -199,7 +199,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
private void save(){
String name = editor.getTags().get("name", "");
String name = editor.getTags().get("name", "").trim();
if(name.isEmpty()){
infoDialog.show();

View File

@ -9,22 +9,16 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
public class MapInfoDialog extends FloatingDialog{
private final MapEditor editor;
private TextArea description;
private TextField author;
private TextField name;
private final WaveInfoDialog waveinfo;
public MapInfoDialog(MapEditor editor){
super("$editor.mapinfo");
this.editor = editor;
this.waveinfo = new WaveInfoDialog(editor);
addCloseButton();
shown(this::setup);
hidden(() -> {
});
}
private void setup(){
@ -36,7 +30,7 @@ public class MapInfoDialog extends FloatingDialog{
cont.defaults().padTop(15);
name = cont.addField(tags.get("name", ""), text -> {
TextField name = cont.addField(tags.get("name", ""), text -> {
tags.put("name", text);
}).size(400, 55f).get();
name.setMessageText("$unknown");
@ -45,7 +39,7 @@ public class MapInfoDialog extends FloatingDialog{
cont.add("$editor.description").padRight(8).left();
description = cont.addArea(tags.get("description", ""), "textarea", text -> {
TextArea description = cont.addArea(tags.get("description", ""), "textarea", text -> {
tags.put("description", text);
}).size(400f, 140f).get();
@ -53,13 +47,22 @@ public class MapInfoDialog extends FloatingDialog{
cont.add("$editor.author").padRight(8).left();
author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> {
TextField author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> {
tags.put("author", text);
Core.settings.put("mapAuthor", text);
Core.settings.save();
}).size(400, 55f).get();
author.setMessageText("$unknown");
cont.row();
cont.add("$editor.waves").padRight(8).left();
cont.table(t -> {
t.add().growX();
t.label(() -> tags.containsKey("waves") ? "" : Core.bundle.get("editor.default")).left();
t.add().growX();
t.addButton("$edit", waveinfo::show).growY().width(200f);
}).size(400, 55f);
name.change();
description.change();
author.change();

View File

@ -56,7 +56,7 @@ public class MapLoadDialog extends FloatingDialog{
for(Map map : world.maps.all()){
TextButton button = new TextButton(map.getDisplayName(), "toggle");
TextButton button = new TextButton(map.name(), "toggle");
button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f);
button.getCells().reverse();
button.clicked(() -> selected = map);

View File

@ -0,0 +1,18 @@
package io.anuke.mindustry.editor;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
public class WaveInfoDialog extends FloatingDialog{
private final MapEditor editor;
public WaveInfoDialog(MapEditor editor){
super("$editor.waves");
this.editor = editor;
shown(this::setup);
}
void setup(){
}
}

View File

@ -1,20 +1,26 @@
package io.anuke.mindustry.game;
import io.anuke.arc.util.serialization.Json;
import io.anuke.arc.util.serialization.Json.Serializable;
import io.anuke.arc.util.serialization.JsonValue;
import io.anuke.mindustry.entities.type.BaseUnit;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.StatusEffect;
import io.anuke.mindustry.type.UnitType;
import static io.anuke.mindustry.Vars.content;
/**
* A spawn group defines spawn information for a specific type of unit, with optional extra information like
* weapon equipped, ammo used, and status effects.
* Each spawn group can have multiple sub-groups spawned in different areas of the map.
*/
public class SpawnGroup{
public class SpawnGroup implements Serializable{
protected static final int never = Integer.MAX_VALUE;
/**The unit type spawned*/
public final UnitType type;
public UnitType type;
/**When this spawn should end*/
protected int end = never;
/**When this spawn should start*/
@ -36,6 +42,10 @@ public class SpawnGroup{
this.type = type;
}
public SpawnGroup(){
//serialization use only
}
/**Returns the amount of units spawned on a specific wave.*/
public int getUnitsSpawned(int wave){
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
@ -64,6 +74,30 @@ public class SpawnGroup{
return unit;
}
@Override
public void write (Json json) {
json.writeObjectStart();
json.writeValue("type", type.name);
json.writeValue("begin", begin);
json.writeValue("end", end);
json.writeValue("spacing", spacing);
json.writeValue("max", max);
json.writeValue("scaling", unitScaling);
json.writeValue("amount", unitAmount);
json.writeObjectEnd();
}
@Override
public void read (Json json, JsonValue data) {
type = content.getByName(ContentType.unit, data.getString("type", "dagger"));
begin = data.getInt("begin", 0);
end = data.getInt("end", never);
spacing = data.getInt("spacing", 1);
max = data.getInt("spacing", 40);
unitScaling = data.getFloat("scaling", never);
unitAmount = data.getInt("amount", 1);
}
@Override
public String toString(){
return "SpawnGroup{" +

View File

@ -28,9 +28,9 @@ public class Stats{
public RankResult calculateRank(Zone zone, boolean launched){
float score = 0;
//each new launch period adds onto the rank 1.5 'points'
//each new launch period adds onto the rank 'points'
if(wavesLasted >= zone.conditionWave){
score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.5f;
score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.3f;
}
int capacity = zone.loadout.core().itemCapacity;
@ -42,7 +42,7 @@ public class Stats{
frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size;
}
score += frac*2.4f;
score += frac*2.0f;
if(!launched){
score *= 0.5f;

View File

@ -5,6 +5,7 @@ import io.anuke.arc.graphics.Color;
public class Pal{
public static final Color
items = Color.valueOf("2ea756"),
command = Color.valueOf("eab678"),
bulletYellow = Color.valueOf("ffeec9"),

View File

@ -19,7 +19,7 @@ public class SaveMeta{
this.build = build;
this.timestamp = timestamp;
this.timePlayed = timePlayed;
this.map = world.maps.all().find(m -> m.fileName().equals(map));
this.map = world.maps.all().find(m -> m.name().equals(map));
this.wave = wave;
this.rules = rules;
}

View File

@ -34,7 +34,7 @@ public class Save16 extends SaveFileVersion{
state.rules.spawns = content.<Zone>getByID(ContentType.zone, state.rules.zone).rules.get().spawns;
}
String mapname = stream.readUTF();
Map map = world.maps.all().find(m -> m.fileName().equals(mapname));
Map map = world.maps.all().find(m -> m.name().equals(mapname));
if(map == null) map = new Map(customMapDirectory.child(mapname), 1, 1, new ObjectMap<>(), true);
world.setMap(map);
@ -62,7 +62,7 @@ public class Save16 extends SaveFileVersion{
//--GENERAL STATE--
Serialization.writeRules(stream, state.rules);
stream.writeUTF(world.getMap().fileName()); //map name
stream.writeUTF(world.getMap().name()); //map name
stream.writeInt(state.wave); //wave
stream.writeFloat(state.wavetime); //wave countdown

View File

@ -12,7 +12,7 @@ public class Map{
public final boolean custom;
/** Metadata. Author description, display name, etc.*/
public final ObjectMap<String, String> tags;
/** Base file of this map.*/
/** Base file of this map. File can be named anything at all.*/
public final FileHandle file;
/** Format version.*/
public final int version;
@ -41,23 +41,15 @@ public class Map{
this(file, width, height, tags, custom, MapIO.version);
}
public String fileName(){
return file.nameWithoutExtension();
}
public int getHightScore(){
return Core.settings.getInt("hiscore" + fileName(), 0);
return Core.settings.getInt("hiscore" + file.nameWithoutExtension(), 0);
}
public void setHighScore(int score){
Core.settings.put("hiscore" + fileName(), score);
Core.settings.put("hiscore" + file.nameWithoutExtension(), score);
Vars.data.modified();
}
public String getDisplayName(){
return tags.get("name", fileName());
}
public String author(){
return tag("author");
}
@ -74,6 +66,10 @@ public class Map{
return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown");
}
public boolean hasTag(String name){
return tags.containsKey(name);
}
@Override
public String toString(){
return "Map{" +

View File

@ -8,6 +8,7 @@ import io.anuke.arc.graphics.Texture;
import io.anuke.arc.util.Disposable;
import io.anuke.arc.util.Log;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.serialization.Json;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.world.Tile;
@ -16,10 +17,15 @@ import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
public class Maps implements Disposable{
/** List of all built-in maps. */
/** List of all built-in maps. Filenames only.*/
private static final String[] defaultMapNames = {"Fortress"};
/** All maps stored in an ordered array. */
private Array<Map> maps = new Array<>();
/** Serializer for meta.*/
private Json json = new Json();
public Maps(){
}
/** Returns a list of all maps, including custom ones. */
public Array<Map> all(){
@ -78,10 +84,11 @@ public class Maps implements Disposable{
ObjectMap<String, String> tags = new ObjectMap<>(baseTags);
String name = tags.get("name");
if(name == null) throw new IllegalArgumentException("Can't save a map with no name. How did this happen?");
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
//FileHandle file = customMapDirectory.child(name + "." + mapExtension);
FileHandle file;
//find map with the same exact display name
Map other = maps.find(m -> m.getDisplayName().equals(name));
Map other = maps.find(m -> m.name().equals(name));
if(other != null){
//dispose of map if it's already there
@ -90,6 +97,9 @@ public class Maps implements Disposable{
other.texture = null;
}
maps.remove(other);
file = other.file;
}else{
file = findFile();
}
//create map, write it, etc etc etc
@ -106,12 +116,11 @@ public class Maps implements Disposable{
}
/** Import a map, then save it. This updates all values and stored data necessary. */
public void importMap(FileHandle file, Map map) throws IOException{
file.copyTo(customMapDirectory.child(map.name() + ".mmap"));
if(!headless){
map.texture = new Texture(MapIO.generatePreview(map));
}
maps.add(map);
public void importMap(FileHandle file) throws IOException{
FileHandle dest = findFile();
file.copyTo(dest);
loadMap(dest, true);
}
/** Removes a map completely. */
@ -125,9 +134,23 @@ public class Maps implements Disposable{
map.file.delete();
}
/** Find a new filename to put a map to.*/
private FileHandle findFile(){
//find a map name that isn't used.
int i = maps.size;
while(customMapDirectory.child("map_" + i + "." + mapExtension).exists()){
i ++;
}
return customMapDirectory.child("map_" + i + "." + mapExtension);
}
private void loadMap(FileHandle file, boolean custom) throws IOException{
Map map = MapIO.readMap(file, custom);
if(map.name() == null){
throw new IOException("Map name cannot be empty! File: " + file);
}
if(!headless){
map.texture = new Texture(MapIO.generatePreview(map));
}

View File

@ -104,7 +104,7 @@ public class CustomGameDialog extends FloatingDialog{
image.getImageCell().size(images);
image.top();
image.row();
image.add("[accent]" + map.getDisplayName()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center);
image.add("[accent]" + map.name()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center);
image.row();
image.label((() -> Core.bundle.format("level.highscore", map.getHightScore()))).pad(3f);

View File

@ -113,7 +113,7 @@ public class LoadDialog extends FloatingDialog{
button.defaults().padBottom(3);
button.row();
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().getDisplayName())));
button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().name())));
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.row();

View File

@ -30,29 +30,33 @@ public class MapsDialog extends FloatingDialog{
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
try{
Map map = MapIO.readMap(file, true);
String name = map.tags.get("name", file.nameWithoutExtension());
String name = map.tags.get("name");
if(name == null){
ui.showError("$editor.errorname");
return;
}
Map conflict = world.maps.all().find(m -> m.fileName().equals(file.nameWithoutExtension()) || m.name().equals(file.name()));
Map conflict = world.maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){
ui.showError(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
try{
world.maps.importMap(file, map);
world.maps.importMap(file);
setup();
}catch(Exception e){
ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
Log.err(e);
}
});
}else{
world.maps.importMap(file, map);
world.maps.importMap(file);
setup();
}
}catch(Exception e){
ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
Log.err(e);
}
}, true, mapExtension);
@ -88,7 +92,7 @@ public class MapsDialog extends FloatingDialog{
TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(9);
button.add(map.getDisplayName()).width(mapsize - 18f).center().get().setEllipsis(true);
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
button.row();
button.addImage("white").growX().pad(4).color(Color.GRAY);
button.row();
@ -128,7 +132,7 @@ public class MapsDialog extends FloatingDialog{
t.add("$editor.name").padRight(10).color(Color.GRAY).padTop(0);
t.row();
t.add(map.getDisplayName()).growX().wrap().padTop(2);
t.add(map.name()).growX().wrap().padTop(2);
t.row();
t.add("$editor.author").padRight(10).color(Color.GRAY);
t.row();

View File

@ -398,6 +398,10 @@ public class Block extends BlockStorage{
bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("blocks.powerbalance", Float.isNaN(entity.power.satisfaction * capacity) ? "<ERROR>" : (int)(entity.power.satisfaction * capacity)) :
Core.bundle.get("blocks.power"), () -> Pal.powerBar, () -> entity.power.satisfaction));
}
if(hasItems && configurable){
bars.add("items", entity -> new Bar(() -> Core.bundle.format("blocks.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity));
}
}
public boolean isSolidFor(Tile tile){

View File

@ -21,6 +21,12 @@ public class LiquidJunction extends LiquidBlock{
stats.remove(BlockStat.liquidCapacity);
}
@Override
public void setBars(){
super.setBars();
bars.remove("liquid");
}
@Override
public void draw(Tile tile){
Draw.rect(name, tile.worldx(), tile.worldy());

View File

@ -13,6 +13,12 @@ public class ItemSource extends Sorter{
solid = true;
}
@Override
public void setBars(){
super.setBars();
bars.remove("items");
}
@Override
public boolean outputsItems(){
return true;

View File

@ -41,6 +41,12 @@ public class Unloader extends Block implements SelectionTrait{
return !(block instanceof StorageBlock);
}
@Override
public void setBars(){
super.setBars();
bars.remove("items");
}
@Override
public void playerPlaced(Tile tile){
Core.app.post(() -> Call.setSortedUnloaderItem(null, tile, lastItem));

View File

@ -20,6 +20,7 @@ public class DesktopLauncher extends Lwjgl3Application{
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setTitle("Mindustry");
config.setMaximized(true);
config.setBackBufferConfig(8, 8, 8, 8, 0, 0, 0);
config.setWindowedMode(960, 540);
config.setWindowIcon("sprites/icon.png");

View File

@ -54,9 +54,9 @@ public class DesktopPlatform extends Platform{
if(world.getMap() == null){
presence.details = "Unknown Map";
}else if(!state.rules.waves){
presence.details = Strings.capitalize(world.getMap().getDisplayName());
presence.details = Strings.capitalize(world.getMap().name());
}else{
presence.details = Strings.capitalize(world.getMap().getDisplayName()) + " | Wave " + state.wave;
presence.details = Strings.capitalize(world.getMap().name()) + " | Wave " + state.wave;
presence.largeImageText = "Wave " + state.wave;
}

View File

@ -228,7 +228,7 @@ public class ServerControl implements ApplicationListener{
host();
}catch(MapException e){
Log.err(e.map.getDisplayName() + ": " + e.getMessage());
Log.err(e.map.name() + ": " + e.getMessage());
}
});
@ -664,7 +664,7 @@ public class ServerControl implements ApplicationListener{
try{
r.run();
}catch(MapException e){
Log.err(e.map.getDisplayName() + ": " + e.getMessage());
Log.err(e.map.name() + ": " + e.getMessage());
Net.closeServer();
}
}