Barely functional IO

This commit is contained in:
Anuken
2020-02-13 19:26:36 -05:00
parent ad248e2e20
commit e3621f44da
68 changed files with 323 additions and 497 deletions

View File

@@ -73,10 +73,16 @@ public class Annotations{
/** Indicates an entity definition. */ /** Indicates an entity definition. */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface EntityDef{ public @interface EntityDef{
/** List of component interfaces */
Class[] value(); Class[] value();
/** Whether the class is final */
boolean isFinal() default true; boolean isFinal() default true;
/** If true, entities are recycled. */
boolean pooled() default false; boolean pooled() default false;
/** Whether to serialize (makes the serialize method return this value) */
boolean serialize() default true; boolean serialize() default true;
/** Whether to generate IO code */
boolean genio() default true;
} }
/** Indicates an internal interface for entity components. */ /** Indicates an internal interface for entity components. */

View File

@@ -45,6 +45,12 @@ public abstract class BaseProcessor extends AbstractProcessor{
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char"); || type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
} }
public static boolean instanceOf(String type, String other){
TypeElement a = elementu.getTypeElement(type);
TypeElement b = elementu.getTypeElement(other);
return a != null && b != null && typeu.isSubtype(a.asType(), b.asType());
}
public static String getDefault(String value){ public static String getDefault(String value){
switch(value){ switch(value){
case "float": case "float":

View File

@@ -5,10 +5,9 @@ import com.squareup.javapoet.*;
import com.squareup.javapoet.MethodSpec.*; import com.squareup.javapoet.MethodSpec.*;
import mindustry.annotations.*; import mindustry.annotations.*;
import javax.lang.model.element.*; import static mindustry.annotations.BaseProcessor.instanceOf;
public class EntityIO{ public class EntityIO{
final TypeElement contentElem = BaseProcessor.elementu.getTypeElement("mindustry.ctype.Content");
final MethodSpec.Builder builder; final MethodSpec.Builder builder;
final boolean write; final boolean write;
@@ -18,13 +17,12 @@ public class EntityIO{
} }
void io(TypeName type, String field) throws Exception{ void io(TypeName type, String field) throws Exception{
TypeElement element = BaseProcessor.elementu.getTypeElement(type.toString());
if(type.isPrimitive()){ if(type.isPrimitive()){
s(type.toString(), field); s(type.toString(), field);
}else if(type.toString().equals("java.lang.String")){ }else if(type.toString().equals("java.lang.String")){
s("UTF", field); s("UTF", field);
}else if(element != null && BaseProcessor.typeu.isSubtype(element.asType(), contentElem.asType())){ }else if(instanceOf(type.toString(), "mindustry.ctype.Content")){
if(write){ if(write){
s("short", field + ".id"); s("short", field + ".id");
}else{ }else{

View File

@@ -327,8 +327,10 @@ public class EntityProcess extends BaseProcessor{
//SPECIAL CASE: I/O code //SPECIAL CASE: I/O code
//note that serialization is generated even for non-serializing entities for manual usage //note that serialization is generated even for non-serializing entities for manual usage
if(first.name().equals("read") || first.name().equals("write")){ if((first.name().equals("read") || first.name().equals("write")) && ann.genio()){
EntityIO writer = new EntityIO(mbuilder, first.name().equals("write")); EntityIO writer = new EntityIO(mbuilder, first.name().equals("write"));
//subclasses *have* to call this method
mbuilder.addAnnotation(CallSuper.class);
//write or read each non-transient field //write or read each non-transient field
for(FieldSpec spec : builder.fieldSpecs){ for(FieldSpec spec : builder.fieldSpecs){
if(!spec.hasModifier(Modifier.TRANSIENT) && !spec.hasModifier(Modifier.STATIC) && !spec.hasModifier(Modifier.FINAL)){ if(!spec.hasModifier(Modifier.TRANSIENT) && !spec.hasModifier(Modifier.STATIC) && !spec.hasModifier(Modifier.FINAL)){

View File

@@ -10,7 +10,7 @@ public class Planets implements ContentList{
@Override @Override
public void load(){ public void load(){
starter = new Planet("//TODO"){{ starter = new Planet("TODO", 3){{
detail = 6; detail = 6;
generator = new TestPlanetGenerator(); generator = new TestPlanetGenerator();
}}; }};

View File

@@ -15,8 +15,10 @@ import mindustry.core.GameState.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.game.Saves.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.input.*; import mindustry.input.*;
import mindustry.io.SaveIO.*;
import mindustry.maps.Map; import mindustry.maps.Map;
import mindustry.type.*; import mindustry.type.*;
import mindustry.ui.dialogs.*; import mindustry.ui.dialogs.*;
@@ -102,12 +104,14 @@ public class Control implements ApplicationListener, Loadable{
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
//the restart dialog can show info for any number of scenarios //the restart dialog can show info for any number of scenarios
Call.onGameOver(event.winner); Call.onGameOver(event.winner);
//TODO set meta to indicate game over
/*
if(state.rules.zone != null && !net.client()){ if(state.rules.zone != null && !net.client()){
//remove zone save on game over //remove zone save on game over
if(saves.getZoneSlot() != null && !state.rules.tutorial){ if(saves.getZoneSlot() != null && !state.rules.tutorial){
saves.getZoneSlot().delete(); saves.getZoneSlot().delete();
} }
} }*/
}); });
//autohost for pvp maps //autohost for pvp maps
@@ -174,7 +178,7 @@ public class Control implements ApplicationListener, Loadable{
}); });
Events.on(UnitDestroyEvent.class, e -> { Events.on(UnitDestroyEvent.class, e -> {
if(world.isZone()){ if(world.isCampaign()){
data.unlockContent(e.unit.type()); data.unlockContent(e.unit.type());
} }
}); });
@@ -234,7 +238,7 @@ public class Control implements ApplicationListener, Loadable{
logic.reset(); logic.reset();
world.loadMap(map, rules); world.loadMap(map, rules);
state.rules = rules; state.rules = rules;
state.rules.zone = null; state.rules.sector = null;
state.rules.editor = false; state.rules.editor = false;
logic.play(); logic.play();
if(settings.getBool("savecreate") && !world.isInvalidMap()){ if(settings.getBool("savecreate") && !world.isInvalidMap()){
@@ -246,13 +250,30 @@ public class Control implements ApplicationListener, Loadable{
public void playSector(Sector sector){ public void playSector(Sector sector){
ui.loadAnd(() -> { ui.loadAnd(() -> {
net.reset();
logic.reset();
world.loadSector(sector);
logic.play();
control.saves.zoneSave();
ui.planet.hide(); ui.planet.hide();
Events.fire(Trigger.newGame); SaveSlot slot = saves.getSectorSave(sector);
if(slot != null){
try{
net.reset();
slot.load();
state.rules.sector = sector;
state.set(State.playing);
}catch(SaveException e){
Log.err(e);
ui.showErrorMessage("$save.corrupted");
slot.delete();
playSector(sector);
}
ui.planet.hide();
}else{
net.reset();
logic.reset();
world.loadSector(sector);
state.rules.sector = sector;
logic.play();
control.saves.saveSector(sector);
Events.fire(Trigger.newGame);
}
}); });
} }
@@ -291,7 +312,8 @@ public class Control implements ApplicationListener, Loadable{
world.endMapLoad(); world.endMapLoad();
zone.rules.get(state.rules); zone.rules.get(state.rules);
state.rules.zone = zone; //TODO assign zone!!
//state.rules.zone = zone;
for(Tilec core : state.teams.playerCores()){ for(Tilec core : state.teams.playerCores()){
for(ItemStack stack : zone.getStartingItems()){ for(ItemStack stack : zone.getStartingItems()){
core.items().add(stack.item, stack.amount); core.items().add(stack.item, stack.amount);
@@ -420,7 +442,7 @@ public class Control implements ApplicationListener, Loadable{
if(!state.is(State.menu)){ if(!state.is(State.menu)){
input.update(); input.update();
if(world.isZone()){ if(world.isCampaign()){
for(Tilec tile : state.teams.cores(player.team())){ for(Tilec tile : state.teams.cores(player.team())){
for(Item item : content.items()){ for(Item item : content.items()){
if(tile.items().has(item)){ if(tile.items().has(item)){

View File

@@ -31,8 +31,9 @@ public class Logic implements ApplicationListener{
public Logic(){ public Logic(){
Events.on(WaveEvent.class, event -> { Events.on(WaveEvent.class, event -> {
if(world.isZone()){ if(world.isCampaign()){
world.getZone().updateWave(state.wave); //TODO implement
//world.getSector().updateWave(state.wave);
} }
}); });
@@ -100,7 +101,7 @@ public class Logic implements ApplicationListener{
Events.fire(new PlayEvent()); Events.fire(new PlayEvent());
//add starting items //add starting items
if(!world.isZone()){ if(!world.isCampaign()){
for(TeamData team : state.teams.getActive()){ for(TeamData team : state.teams.getActive()){
if(team.hasCore()){ if(team.hasCore()){
Tilec entity = team.core(); Tilec entity = team.core();
@@ -129,7 +130,7 @@ public class Logic implements ApplicationListener{
public void runWave(){ public void runWave(){
spawner.spawnEnemies(); spawner.spawnEnemies();
state.wave++; state.wave++;
state.wavetime = world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * state.rules.launchWaveMultiplier : state.rules.waveSpacing; state.wavetime = world.isCampaign() && world.getSector().isLaunchWave(state.wave) ? state.rules.waveSpacing * state.rules.launchWaveMultiplier : state.rules.waveSpacing;
Events.fire(new WaveEvent()); Events.fire(new WaveEvent());
} }
@@ -151,7 +152,7 @@ public class Logic implements ApplicationListener{
} }
if(alive != null && !state.gameOver){ if(alive != null && !state.gameOver){
if(world.isZone() && alive == state.rules.defaultTeam){ if(world.isCampaign() && alive == state.rules.defaultTeam){
//in attack maps, a victorious game over is equivalent to a launch //in attack maps, a victorious game over is equivalent to a launch
Call.launchZone(); Call.launchZone();
}else{ }else{
@@ -172,8 +173,9 @@ public class Logic implements ApplicationListener{
Fx.launch.at(tile); Fx.launch.at(tile);
} }
if(world.getZone() != null){ if(world.isCampaign()){
world.getZone().setLaunched(); //TODO implement
//world.getSector().setLaunched();
} }
Time.runTask(30f, () -> { Time.runTask(30f, () -> {

View File

@@ -407,7 +407,7 @@ public class NetClient implements ApplicationListener{
Log.warn("Missing entity at {0}. Skipping block snapshot.", tile); Log.warn("Missing entity at {0}. Skipping block snapshot.", tile);
break; break;
} }
tile.entity.read(input); tile.entity.read(input, tile.entity.version());
} }
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();

View File

@@ -178,12 +178,12 @@ public class World{
return generating; return generating;
} }
public boolean isZone(){ public boolean isCampaign(){
return getZone() != null; return getSector() != null;
} }
public Zone getZone(){ public Sector getSector(){
return state.rules.zone; return state.rules.sector;
} }
public void loadGenerator(int width, int height, Cons<Tiles> generator){ public void loadGenerator(int width, int height, Cons<Tiles> generator){

View File

@@ -70,7 +70,7 @@ public abstract class UnlockableContent extends MappableContent{
/** @return whether this content is unlocked, or the player is in a custom game. */ /** @return whether this content is unlocked, or the player is in a custom game. */
public final boolean unlockedCur(){ public final boolean unlockedCur(){
return Vars.data.isUnlocked(this) || !Vars.world.isZone(); return Vars.data.isUnlocked(this) || !Vars.world.isCampaign();
} }
public final boolean locked(){ public final boolean locked(){

View File

@@ -266,7 +266,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
state.teams = new Teams(); state.teams = new Teams();
player.reset(); player.reset();
state.rules = Gamemode.editor.apply(lastSavedRules.copy()); state.rules = Gamemode.editor.apply(lastSavedRules.copy());
state.rules.zone = null; state.rules.sector = null;
world.setMap(new Map(StringMap.of( world.setMap(new Map(StringMap.of(
"name", "Editor Playtesting", "name", "Editor Playtesting",
"width", editor.width(), "width", editor.width(),

View File

@@ -52,11 +52,16 @@ abstract class EntityComp{
@InternalImpl @InternalImpl
abstract boolean serialize(); abstract boolean serialize();
@MethodPriority(1)
void read(DataInput input) throws IOException{ void read(DataInput input) throws IOException{
//TODO dynamic io afterRead();
} }
void write(DataOutput output) throws IOException{ void write(DataOutput output) throws IOException{
//TODO dynamic io
}
void afterRead(){
} }
} }

View File

@@ -9,8 +9,7 @@ import mindustry.gen.*;
abstract class HitboxComp implements Posc, QuadTreeObject{ abstract class HitboxComp implements Posc, QuadTreeObject{
@Import float x, y; @Import float x, y;
float hitSize; transient float lastX, lastY, hitSize;
float lastX, lastY;
@Override @Override
public void update(){ public void update(){

View File

@@ -22,9 +22,7 @@ abstract class StatusComp implements Posc, Flyingc{
private Array<StatusEntry> statuses = new Array<>(); private Array<StatusEntry> statuses = new Array<>();
private Bits applied = new Bits(content.getBy(ContentType.status).size); private Bits applied = new Bits(content.getBy(ContentType.status).size);
@ReadOnly float speedMultiplier; @ReadOnly transient float speedMultiplier, damageMultiplier, armorMultiplier;
@ReadOnly float damageMultiplier;
@ReadOnly float armorMultiplier;
/** @return damage taken based on status armor multipliers */ /** @return damage taken based on status armor multipliers */
float getShieldDamage(float amount){ float getShieldDamage(float amount){

View File

@@ -3,40 +3,42 @@ package mindustry.entities.def;
import arc.*; import arc.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.game.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.consumers.*; import mindustry.world.consumers.*;
import mindustry.world.modules.*; import mindustry.world.modules.*;
import java.io.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@EntityDef(value = {Tilec.class}, isFinal = false) @EntityDef(value = {Tilec.class}, isFinal = false, genio = false, serialize = false)
@Component @Component
abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
static final float timeToSleep = 60f * 1; static final float timeToSleep = 60f * 1;
static final ObjectSet<Tile> tmpTiles = new ObjectSet<>(); static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
static int sleepingEntities = 0; static int sleepingEntities = 0;
Tile tile; transient Tile tile;
Block block; transient Block block;
Array<Tile> proximity = new Array<>(8); transient Array<Tile> proximity = new Array<>(8);
PowerModule power; PowerModule power;
ItemModule items; ItemModule items;
LiquidModule liquids; LiquidModule liquids;
ConsumeModule cons; ConsumeModule cons;
private float timeScale = 1f, timeScaleDuration; private transient float timeScale = 1f, timeScaleDuration;
private @Nullable SoundLoop sound; private transient @Nullable SoundLoop sound;
private boolean sleeping; private transient boolean sleeping;
private float sleepTime; private transient float sleepTime;
/** Sets this tile entity data to this tile, and adds it if necessary. */ /** Sets this tile entity data to this tile, and adds it if necessary. */
@Override @Override
@@ -60,6 +62,33 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
return this; return this;
} }
@CallSuper
public void write(DataOutput output) throws IOException{
output.writeFloat(health());
output.writeByte(tile.rotation());
output.writeByte(tile.getTeamID());
if(items != null) items.write(output);
if(power != null) power.write(output);
if(liquids != null) liquids.write(output);
if(cons != null) cons.write(output);
}
@CallSuper
@Override
public void read(DataInput input, byte revision) throws IOException{
health(input.readFloat());
byte rotation = input.readByte();
byte team = input.readByte();
tile.setTeam(Team.get(team));
tile.rotation(rotation);
if(items != null) items.read(input);
if(power != null) power.read(input);
if(liquids != null) liquids.read(input);
if(cons != null) cons.read(input);
}
@Override @Override
public void applyBoost(float intensity, float duration){ public void applyBoost(float intensity, float duration){
timeScale = Math.max(timeScale, intensity); timeScale = Math.max(timeScale, intensity);
@@ -116,6 +145,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
} }
/** Returns the version of this TileEntity IO code.*/ /** Returns the version of this TileEntity IO code.*/
//TODO implement
@Override @Override
public byte version(){ public byte version(){
return 0; return 0;

View File

@@ -19,7 +19,7 @@ import static mindustry.Vars.*;
@Component @Component
abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitboxc, Rotc, Massc, Unitc, Weaponsc, Drawc, Boundedc, abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitboxc, Rotc, Massc, Unitc, Weaponsc, Drawc, Boundedc,
DrawLayerGroundc, DrawLayerFlyingc, DrawLayerGroundShadowsc, DrawLayerFlyingShadowsc{ DrawLayerGroundc, DrawLayerFlyingc, DrawLayerGroundShadowsc, DrawLayerFlyingShadowsc, Syncc{
@Import float x, y, rotation; @Import float x, y, rotation;
private UnitController controller; private UnitController controller;
@@ -98,6 +98,12 @@ abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitbox
lookAt(angleTo(pos)); lookAt(angleTo(pos));
} }
@Override
public void afterRead(){
//set up type info after reading
type(this.type);
}
@Override @Override
public void update(){ public void update(){
drag(type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f)); drag(type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f));

View File

@@ -57,7 +57,7 @@ public class Rules{
/** How many times longer a launch wave takes. */ /** How many times longer a launch wave takes. */
public float launchWaveMultiplier = 2f; public float launchWaveMultiplier = 2f;
/** Zone for saves that have them.*/ /** Zone for saves that have them.*/
public Zone zone; public Sector sector;
/** Spawn layout. */ /** Spawn layout. */
public Array<SpawnGroup> spawns = new Array<>(); public Array<SpawnGroup> spawns = new Array<>();
/** Determines if there should be limited respawns. */ /** Determines if there should be limited respawns. */

View File

@@ -6,6 +6,7 @@ import arc.struct.*;
import arc.files.*; import arc.files.*;
import arc.graphics.*; import arc.graphics.*;
import arc.util.*; import arc.util.*;
import arc.util.ArcAnnotate.*;
import arc.util.async.*; import arc.util.async.*;
import mindustry.*; import mindustry.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
@@ -23,11 +24,11 @@ import static mindustry.Vars.*;
public class Saves{ public class Saves{
private Array<SaveSlot> saves = new Array<>(); private Array<SaveSlot> saves = new Array<>();
private SaveSlot current; private @Nullable SaveSlot current;
private @Nullable SaveSlot lastSectorSave;
private AsyncExecutor previewExecutor = new AsyncExecutor(1); private AsyncExecutor previewExecutor = new AsyncExecutor(1);
private boolean saving; private boolean saving;
private float time; private float time;
private Fi zoneFile;
private long totalPlaytime; private long totalPlaytime;
private long lastTimestamp; private long lastTimestamp;
@@ -46,7 +47,6 @@ public class Saves{
public void load(){ public void load(){
saves.clear(); saves.clear();
zoneFile = saveDirectory.child("-1.msav");
for(Fi file : saveDirectory.list()){ for(Fi file : saveDirectory.list()){
if(!file.name().contains("backup") && SaveIO.isSaveValid(file)){ if(!file.name().contains("backup") && SaveIO.isSaveValid(file)){
@@ -55,9 +55,15 @@ public class Saves{
slot.meta = SaveIO.getMeta(file); slot.meta = SaveIO.getMeta(file);
} }
} }
lastSectorSave = saves.find(s -> s.isSector() && s.getName().equals(Core.settings.getString("last-sector-save", "<<none>>")));
} }
public SaveSlot getCurrent(){ public @Nullable SaveSlot getLastSector(){
return lastSectorSave;
}
public @Nullable SaveSlot getCurrent(){
return current; return current;
} }
@@ -80,7 +86,7 @@ public class Saves{
Time.runTask(2f, () -> { Time.runTask(2f, () -> {
try{ try{
current.save(); current.save();
}catch(Exception e){ }catch(Throwable e){
e.printStackTrace(); e.printStackTrace();
} }
saving = false; saving = false;
@@ -105,12 +111,26 @@ public class Saves{
return saving; return saving;
} }
public void zoneSave(){ public Fi getSectorFile(Sector sector){
SaveSlot slot = new SaveSlot(zoneFile); return saveDirectory.child("sector-" + sector.planet.name + "-" + sector.id + "." + saveExtension);
slot.setName("zone"); }
saves.remove(s -> s.file.equals(zoneFile));
saves.add(slot); public @Nullable SaveSlot getSectorSave(Sector sector){
Fi fi = getSectorFile(sector);
return saves.find(s -> s.isSector() && s.file.equals(fi));
}
public void saveSector(Sector sector){
SaveSlot slot = getSectorSave(sector);
if(slot == null){
slot = new SaveSlot(getSectorFile(sector));
slot.setName(slot.file.nameWithoutExtension());
saves.add(slot);
}
slot.save(); slot.save();
lastSectorSave = slot;
Log.info("Saving " + slot.getName());
Core.settings.putSave("last-sector-save", slot.getName());
} }
public SaveSlot addSave(String name){ public SaveSlot addSave(String name){
@@ -131,11 +151,6 @@ public class Saves{
return slot; return slot;
} }
public SaveSlot getZoneSlot(){
SaveSlot slot = getSaveSlots().find(s -> s.file.equals(zoneFile));
return slot == null || slot.getZone() == null ? null : slot;
}
public Fi getNextSlotFile(){ public Fi getNextSlotFile(){
int i = 0; int i = 0;
Fi file; Fi file;
@@ -150,7 +165,6 @@ public class Saves{
} }
public class SaveSlot{ public class SaveSlot{
//public final int index;
public final Fi file; public final Fi file;
boolean requestedPreview; boolean requestedPreview;
SaveMeta meta; SaveMeta meta;
@@ -225,7 +239,7 @@ public class Saves{
} }
public boolean isHidden(){ public boolean isHidden(){
return getZone() != null; return isSector();
} }
public String getPlayTime(){ public String getPlayTime(){
@@ -268,8 +282,12 @@ public class Saves{
return meta.mods; return meta.mods;
} }
public Zone getZone(){ public Sector getSector(){
return meta == null || meta.rules == null ? null : meta.rules.zone; return meta == null || meta.rules == null ? null : meta.rules.sector;
}
public boolean isSector(){
return getSector() != null;
} }
public Gamemode mode(){ public Gamemode mode(){

View File

@@ -19,7 +19,7 @@ public class SpawnGroup implements Serializable{
public static final int never = Integer.MAX_VALUE; public static final int never = Integer.MAX_VALUE;
/** The unit type spawned */ /** The unit type spawned */
public UnitType type; public UnitType type = UnitTypes.dagger;
/** When this spawn should end */ /** When this spawn should end */
public int end = never; public int end = never;
/** When this spawn should start */ /** When this spawn should start */
@@ -73,6 +73,7 @@ public class SpawnGroup implements Serializable{
@Override @Override
public void write(Json json){ public void write(Json json){
if(type == null) type = UnitTypes.dagger;
json.writeValue("type", type.name); json.writeValue("type", type.name);
if(begin != 0) json.writeValue("begin", begin); if(begin != 0) json.writeValue("begin", begin);
if(end != never) json.writeValue("end", end); if(end != never) json.writeValue("end", end);

View File

@@ -1,9 +1,8 @@
package mindustry.game; package mindustry.game;
import mindustry.annotations.Annotations.Serialize; import arc.math.*;
import arc.struct.Array; import arc.struct.*;
import arc.struct.ObjectIntMap; import mindustry.annotations.Annotations.*;
import arc.math.Mathf;
import mindustry.type.*; import mindustry.type.*;
@Serialize @Serialize
@@ -23,21 +22,24 @@ public class Stats{
/** Friendly buildings destroyed. */ /** Friendly buildings destroyed. */
public int buildingsDestroyed; public int buildingsDestroyed;
public RankResult calculateRank(Zone zone, boolean launched){ public RankResult calculateRank(Sector zone, boolean launched){
float score = 0; float score = 0;
//TODO implement wave/attack mode based score
/*
if(launched && zone.getRules().attackMode){ if(launched && zone.getRules().attackMode){
score += 3f; score += 3f;
}else if(wavesLasted >= zone.conditionWave){ }else if(wavesLasted >= zone.conditionWave){
//each new launch period adds onto the rank 'points' //each new launch period adds onto the rank 'points'
score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.2f; score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.2f;
} }*/
int capacity = zone.loadout.findCore().itemCapacity; //TODO implement
int capacity = 3000;//zone.loadout.findCore().itemCapacity;
//weigh used fractions //weigh used fractions
float frac = 0f; float frac = 0f;
Array<Item> obtainable = Array.with(zone.resources).select(i -> i.type == ItemType.material); Array<Item> obtainable = Array.with(zone.resources).select(i -> i instanceof Item && ((Item)i).type == ItemType.material).as(Item.class);
for(Item item : obtainable){ for(Item item : obtainable){
frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size;
} }

View File

@@ -159,7 +159,7 @@ public class DesktopInput extends InputHandler{
if(unit != null){ if(unit != null){
unit.hitbox(Tmp.r1); unit.hitbox(Tmp.r1);
if(Tmp.r1.contains(Core.input.mouseWorld())){ if(Tmp.r1.contains(Core.input.mouseWorld())){
//player.unit(unit); player.unit(unit);
} }
} }
} }

View File

@@ -5,7 +5,6 @@ import arc.util.serialization.Json.*;
import mindustry.*; import mindustry.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.ctype.ContentType;
import mindustry.game.*; import mindustry.game.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
@@ -69,6 +68,19 @@ public class JsonIO{
json.setElementType(Rules.class, "spawns", SpawnGroup.class); json.setElementType(Rules.class, "spawns", SpawnGroup.class);
json.setElementType(Rules.class, "loadout", ItemStack.class); json.setElementType(Rules.class, "loadout", ItemStack.class);
json.setSerializer(Sector.class, new Serializer<Sector>(){
@Override
public void write(Json json, Sector object, Class knownType){
json.writeValue(object.planet.name + "-" + object.id);
}
@Override
public Sector read(Json json, JsonValue jsonData, Class type){
String[] split = jsonData.asString().split("-");
return Vars.content.<Planet>getByName(ContentType.planet, split[0]).sectors.get(Integer.parseInt(split[1]));
}
});
json.setSerializer(Zone.class, new Serializer<Zone>(){ json.setSerializer(Zone.class, new Serializer<Zone>(){
@Override @Override
public void write(Json json, Zone object, Class knownType){ public void write(Json json, Zone object, Class knownType){

View File

@@ -186,7 +186,10 @@ public abstract class SaveVersion extends SaveFileReader{
if(tile.entity != null){ if(tile.entity != null){
try{ try{
readChunk(stream, true, in -> tile.entity.read(in)); readChunk(stream, true, in -> {
byte revision = in.readByte();
tile.entity.read(in, revision);
});
}catch(Exception e){ }catch(Exception e){
throw new IOException("Failed to read tile entity of block: " + block, e); throw new IOException("Failed to read tile entity of block: " + block, e);
} }
@@ -222,7 +225,7 @@ public abstract class SaveVersion extends SaveFileReader{
} }
} }
stream.writeInt(Groups.sync.size()); stream.writeInt(Groups.sync.count(Entityc::serialize));
for(Syncc entity : Groups.sync){ for(Syncc entity : Groups.sync){
if(!entity.serialize()) continue; if(!entity.serialize()) continue;
@@ -251,6 +254,7 @@ public abstract class SaveVersion extends SaveFileReader{
byte typeid = in.readByte(); byte typeid = in.readByte();
Syncc sync = (Syncc)EntityMapping.map(typeid).get(); Syncc sync = (Syncc)EntityMapping.map(typeid).get();
sync.read(in); sync.read(in);
sync.add();
}); });
} }
} }

View File

@@ -3,6 +3,7 @@ package mindustry.maps.generators;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.io.*; import mindustry.io.*;
import mindustry.maps.*; import mindustry.maps.*;
@@ -47,10 +48,10 @@ public class MapGenerator extends Generator{
SaveIO.load(map.file); SaveIO.load(map.file);
for(Tile tile : tiles){ for(Tile tile : tiles){
if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && world.getZone() != null){ if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && world.getSector() != null){
for(Item item : world.getZone().resources){ for(Content content : world.getSector().resources){
if(Mathf.chance(0.3)){ if(content instanceof Item && Mathf.chance(0.3)){
tile.entity.items().add(item, Math.min(Mathf.random(500), tile.block().itemCapacity)); tile.entity.items().add((Item)content, Math.min(Mathf.random(500), tile.block().itemCapacity));
} }
} }
} }

View File

@@ -22,21 +22,15 @@ public class Planet extends UnlockableContent{
/** Detail in divisions. Must be between 1 and 10. 6 is a good number for this.*/ /** Detail in divisions. Must be between 1 and 10. 6 is a good number for this.*/
public int detail = 3; public int detail = 3;
/** Size in terms of divisions. This only controls the amount of sectors on the planet, not the visuals. */ /** Size in terms of divisions. This only controls the amount of sectors on the planet, not the visuals. */
public int size = 3; public int size;
/** Radius of the mesh/sphere. */ /** Radius of the mesh/sphere. */
public float radius = 1f; public float radius = 1f;
public Planet(String name){ public Planet(String name, int size){
super(name); super(name);
}
@Override this.size = 3;
public void load(){
mesh = new PlanetMesh(detail, generator);
}
@Override
public void init(){
grid = PlanetGrid.newGrid(size); grid = PlanetGrid.newGrid(size);
sectors = new Array<>(grid.tiles.length); sectors = new Array<>(grid.tiles.length);
for(int i = 0; i < grid.tiles.length; i++){ for(int i = 0; i < grid.tiles.length; i++){
@@ -44,6 +38,11 @@ public class Planet extends UnlockableContent{
} }
} }
@Override
public void load(){
mesh = new PlanetMesh(detail, generator);
}
/** Gets a sector a tile position. */ /** Gets a sector a tile position. */
public Sector getSector(Ptile tile){ public Sector getSector(Ptile tile){
return sectors.get(tile.id); return sectors.get(tile.id);

View File

@@ -2,18 +2,39 @@ package mindustry.type;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import mindustry.ctype.*;
import mindustry.graphics.PlanetGrid.*; import mindustry.graphics.PlanetGrid.*;
import static mindustry.Vars.state;
/** A small section of a planet. */ /** A small section of a planet. */
public class Sector{ public class Sector{
public final SectorRect rect; public final SectorRect rect;
public final Planet planet; public final Planet planet;
public final Ptile tile; public final Ptile tile;
public final int id;
//TODO generate a class file with 2D arrays of resources for each sector for each planet
public final Content[] resources = {};
//TODO implement a dynamic (?) launch period
public int launchPeriod = 10;
public Sector(Planet planet, Ptile tile){ public Sector(Planet planet, Ptile tile){
this.planet = planet; this.planet = planet;
this.tile = tile; this.tile = tile;
this.rect = makeRect(); this.rect = makeRect();
this.id = tile.id;
}
//TODO implement
public boolean isLaunchWave(int wave){
return metCondition() && wave % launchPeriod == 0;
}
public boolean metCondition(){
//TODO implement
return false;
} }
/** Projects this sector onto a 4-corner square for use in map gen. /** Projects this sector onto a 4-corner square for use in map gen.

View File

@@ -91,6 +91,6 @@ public class DatabaseDialog extends FloatingDialog{
} }
boolean unlocked(UnlockableContent content){ boolean unlocked(UnlockableContent content){
return (!Vars.world.isZone() && !Vars.state.is(State.menu)) || content.unlocked(); return (!Vars.world.isCampaign() && !Vars.state.is(State.menu)) || content.unlocked();
} }
} }

View File

@@ -1,319 +0,0 @@
package mindustry.ui.dialogs;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.input.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.*;
import arc.scene.event.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.scene.utils.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.game.EventType.*;
import mindustry.game.Saves.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.io.SaveIO.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.ui.layout.*;
import mindustry.ui.layout.TreeLayout.*;
import static mindustry.Vars.*;
//TODO remove (legacy, no longer needed)
public class DeployDialog extends FloatingDialog{
private final float nodeSize = Scl.scl(230f);
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
private ZoneInfoDialog info = new ZoneInfoDialog();
private Rect bounds = new Rect();
private View view = new View();
public DeployDialog(){
super("", Styles.fullDialog);
treeLayout();
Events.on(ContentReloadEvent.class, e -> treeLayout());
addCloseButton();
buttons.addImageTextButton("$techtree", Icon.tree, () -> ui.tech.show()).size(230f, 64f);
shown(this::setup);
//view input.
addListener(new InputListener(){
@Override
public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){
view.setScale(Mathf.clamp(view.getScaleX() - amountY / 40f, 0.25f, 1f));
view.setOrigin(Align.center);
view.setTransform(true);
return true;
}
@Override
public boolean mouseMoved(InputEvent event, float x, float y){
view.requestScroll();
return super.mouseMoved(event, x, y);
}
});
addListener(new ElementGestureListener(){
@Override
public void zoom(InputEvent event, float initialDistance, float distance){
if(view.lastZoom < 0){
view.lastZoom = view.getScaleX();
}
view.setScale(Mathf.clamp(distance / initialDistance * view.lastZoom, 0.25f, 1f));
view.setOrigin(Align.center);
view.setTransform(true);
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
view.lastZoom = view.getScaleX();
}
@Override
public void pan(InputEvent event, float x, float y, float deltaX, float deltaY){
view.panX += deltaX / view.getScaleX();
view.panY += deltaY / view.getScaleY();
view.moved = true;
view.clamp();
}
});
}
void treeLayout(){
nodes.clear();
ZoneNode root = new ZoneNode(Zones.groundZero, null);
BranchTreeLayout layout = new BranchTreeLayout();
layout.gapBetweenLevels = layout.gapBetweenNodes = Scl.scl(60f);
layout.gapBetweenNodes = Scl.scl(120f);
layout.layout(root);
bounds.set(layout.getBounds());
bounds.y += nodeSize*0.4f;
}
void setup(){
platform.updateRPC();
cont.clear();
titleTable.remove();
margin(0f).marginBottom(8);
Stack stack = new Stack();
stack.add(new Image(new Texture("sprites/backgrounds/stars.png"){{
setFilter(TextureFilter.Linear);
}}).setScaling(Scaling.fill));
stack.add(new Image(new Texture("sprites/backgrounds/planet-zero.png"){{
setFilter(TextureFilter.Linear);
}}){{
float[] time = {0};
setColor(Color.grays(0.3f));
setScale(1.5f);
update(() -> {
setOrigin(Align.center);
time[0] += Core.graphics.getDeltaTime() * 10f;
setTranslation(Mathf.sin(time[0], 60f, 70f) + view.panX / 30f, Mathf.cos(time[0], 140f, 80f) + (view.panY + 200) / 30f);
});
}}.setScaling(Scaling.fit));
if(control.saves.getZoneSlot() != null){
float size = 250f;
stack.add(new Table(t -> {
SaveSlot slot = control.saves.getZoneSlot();
Stack sub = new Stack();
if(slot.getZone() != null){
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.grays(0.1f)).grow()));
//sub.add(new Table(f -> f.margin(4f).add(new Image(slot.getZone().preview).setScaling(Scaling.fit)).update(img -> {
//TextureRegionDrawable draw = (TextureRegionDrawable)img.getDrawable();
//if(draw.getRegion().getTexture().isDisposed()){
// draw.setRegion(slot.getZone().preview);
// }
Texture text = slot.previewTexture();
//if(draw.getRegion() == slot.getZone().preview && text != null){
// draw.setRegion(new TextureRegion(text));
//}
// }).color(Color.darkGray).grow()));
}
TextButton button = Elements.newButton(Core.bundle.format("resume", slot.getZone().localizedName), Styles.squaret, () -> {
control.saves.getZoneSlot().cautiousLoad(() -> {
hide();
ui.loadAnd(() -> {
logic.reset();
net.reset();
try{
slot.load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
Core.app.post(() -> ui.showInfo("$save.corrupted"));
show();
}
});
});
});
sub.add(button);
t.add(sub).size(size);
String color = "[lightgray]";
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();
t.row();
t.addButton("$abandon", () -> {
ui.showConfirm("$warning", "$abandon.text", () -> {
slot.delete();
setup();
});
}).width(size).height(50f).padTop(3);
}));
}else{
stack.add(view = new View());
}
stack.add(new ItemsDisplay());
cont.add(stack).grow();
//set up direct and indirect children
for(ZoneNode node : nodes){
node.allChildren.clear();
node.allChildren.addAll(node.children);
for(ZoneNode other : nodes){
if(other.zone.requirements.contains(req -> req.zone() == node.zone)){
node.allChildren.add(other);
}
}
}
view.setOrigin(Align.center);
view.setTransform(true);
}
boolean hidden(Zone zone){
return zone.requirements.contains(o -> o.zone() != null && o.zone().locked());
}
void buildButton(Zone zone, Button button){
button.setDisabled(() -> hidden(zone));
button.clicked(() -> {
if(!view.moved){
info.show(zone);
}
});
if(zone.unlocked() && !hidden(zone)){
button.labelWrap(zone.localizedName).style(Styles.outlineLabel).width(140).growX().get().setAlignment(Align.center);
}else{
Cons<Element> flasher = zone.canUnlock() && !hidden(zone) ? e -> e.update(() -> e.getColor().set(Color.white).lerp(Pal.accent, Mathf.absin(3f, 1f))) : e -> {};
flasher.get(button.addImage(Icon.lock).get());
button.row();
flasher.get(button.add("$locked").get());
}
}
class View extends Group{
float panX = 0, panY = -200, lastZoom = -1;
boolean moved = false;
{
for(ZoneNode node : nodes){
Stack stack = new Stack();
Tmp.v1.set(node.width, node.height);
//if(node.zone.preview != null){
// Tmp.v1.set(Scaling.fit.apply(node.zone.preview.getWidth(), node.zone.preview.getHeight(), node.width, node.height));
//}
// stack.setSize(Tmp.v1.x, Tmp.v1.y);
// stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.grays(0.2f)).grow()));
stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
Button button = new Button(Styles.squaret);
buildButton(node.zone, button);
stack.add(button);
addChild(stack);
}
released(() -> moved = false);
}
void clamp(){
float pad = nodeSize;
float ox = width/2f, oy = height/2f;
float rx = bounds.x + panX + ox, ry = panY + oy + bounds.y;
float rw = bounds.width, rh = bounds.height;
rx = Mathf.clamp(rx, -rw + pad, Core.graphics.getWidth() - pad);
ry = Mathf.clamp(ry, pad, Core.graphics.getHeight() - rh - pad);
panX = rx - bounds.x - ox;
panY = ry - bounds.y - oy;
}
@Override
public void drawChildren(){
clamp();
float offsetX = panX + width / 2f, offsetY = panY + height / 2f;
for(ZoneNode node : nodes){
for(ZoneNode child : node.allChildren){
Lines.stroke(Scl.scl(4f), node.zone.locked() || child.zone.locked() ? Pal.gray : Pal.gray);
Draw.alpha(parentAlpha);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}
Draw.reset();
super.drawChildren();
}
}
class ZoneNode extends TreeNode<ZoneNode>{
final Array<Zone> arr = new Array<>();
final Array<ZoneNode> allChildren = new Array<>();
final Zone zone;
ZoneNode(Zone zone, ZoneNode parent){
this.zone = zone;
this.parent = parent;
this.width = this.height = nodeSize;
//this.height /= 2f;
nodes.add(this);
arr.selectFrom(content.zones(), other -> other.requirements.size > 0 && other.requirements.first().zone() == zone);
children = new ZoneNode[arr.size];
for(int i = 0; i < children.length; i++){
children[i] = new ZoneNode(arr.get(i), this);
}
}
}
}

View File

@@ -66,7 +66,7 @@ public class GameOverDialog extends FloatingDialog{
t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime())); t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime()));
t.row(); t.row();
} }
if(world.isZone() && !state.stats.itemsDelivered.isEmpty()){ if(world.isCampaign() && !state.stats.itemsDelivered.isEmpty()){
t.add("$stat.delivered"); t.add("$stat.delivered");
t.row(); t.row();
for(Item item : content.items()){ for(Item item : content.items()){
@@ -80,14 +80,14 @@ public class GameOverDialog extends FloatingDialog{
} }
} }
if(world.isZone()){ if(world.isCampaign()){
RankResult result = state.stats.calculateRank(world.getZone(), state.launched); RankResult result = state.stats.calculateRank(world.getSector(), state.launched);
t.add(Core.bundle.format("stat.rank", result.rank + result.modifier)); t.add(Core.bundle.format("stat.rank", result.rank + result.modifier));
t.row(); t.row();
} }
}).pad(12); }).pad(12);
if(world.isZone()){ if(world.isCampaign()){
buttons.addButton("$continue", () -> { buttons.addButton("$continue", () -> {
hide(); hide();
state.set(State.menu); state.set(State.menu);

View File

@@ -194,7 +194,7 @@ public class LoadDialog extends FloatingDialog{
net.reset(); net.reset();
slot.load(); slot.load();
state.rules.editor = false; state.rules.editor = false;
state.rules.zone = null; state.rules.sector = null;
state.set(State.playing); state.set(State.playing);
}catch(SaveException e){ }catch(SaveException e){
Log.err(e); Log.err(e);

View File

@@ -41,7 +41,7 @@ public class PausedDialog extends FloatingDialog{
cont.addImageTextButton("$back", Icon.left, this::hide).colspan(2).width(dw * 2 + 20f); cont.addImageTextButton("$back", Icon.left, this::hide).colspan(2).width(dw * 2 + 20f);
cont.row(); cont.row();
if(world.isZone()){ if(world.isCampaign()){
cont.addImageTextButton("$techtree", Icon.tree, ui.tech::show); cont.addImageTextButton("$techtree", Icon.tree, ui.tech::show);
}else{ }else{
cont.addImageTextButton("$database", Icon.book, ui.database::show); cont.addImageTextButton("$database", Icon.book, ui.database::show);
@@ -49,7 +49,7 @@ public class PausedDialog extends FloatingDialog{
cont.addImageTextButton("$settings", Icon.settings, ui.settings::show); cont.addImageTextButton("$settings", Icon.settings, ui.settings::show);
if(!state.rules.tutorial){ if(!state.rules.tutorial){
if(!world.isZone() && !state.isEditor()){ if(!world.isCampaign() && !state.isEditor()){
cont.row(); cont.row();
cont.addImageTextButton("$savegame", Icon.save, save::show); cont.addImageTextButton("$savegame", Icon.save, save::show);
cont.addImageTextButton("$loadgame", Icon.upload, load::show).disabled(b -> net.active()); cont.addImageTextButton("$loadgame", Icon.upload, load::show).disabled(b -> net.active());
@@ -79,7 +79,7 @@ public class PausedDialog extends FloatingDialog{
cont.addRowImageTextButton("$back", Icon.play, this::hide); cont.addRowImageTextButton("$back", Icon.play, this::hide);
cont.addRowImageTextButton("$settings", Icon.settings, ui.settings::show); cont.addRowImageTextButton("$settings", Icon.settings, ui.settings::show);
if(!world.isZone() && !state.isEditor()){ if(!world.isCampaign() && !state.isEditor()){
cont.addRowImageTextButton("$save", Icon.save, save::show); cont.addRowImageTextButton("$save", Icon.save, save::show);
cont.row(); cont.row();

View File

@@ -84,7 +84,7 @@ public class HudFragment extends Fragment{
}else{ }else{
ui.chatfrag.toggle(); ui.chatfrag.toggle();
} }
}else if(world.isZone()){ }else if(world.isCampaign()){
ui.tech.show(); ui.tech.show();
}else{ }else{
ui.database.show(); ui.database.show();
@@ -497,10 +497,10 @@ public class HudFragment extends Fragment{
} }
private boolean inLaunchWave(){ private boolean inLaunchWave(){
return world.isZone() && return world.isCampaign() &&
world.getZone().metCondition() && world.getSector().metCondition() &&
!net.client() && !net.client() &&
state.wave % world.getZone().launchPeriod == 0 && !spawner.isSpawning(); state.wave % world.getSector().launchPeriod == 0 && !spawner.isSpawning();
} }
private boolean canLaunch(){ private boolean canLaunch(){
@@ -559,7 +559,7 @@ public class HudFragment extends Fragment{
}else{ }else{
builder.append(Core.bundle.get("launch")); builder.append(Core.bundle.get("launch"));
builder.append("\n"); builder.append("\n");
builder.append(Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod)); builder.append(Core.bundle.format("launch.next", state.wave + world.getSector().launchPeriod));
builder.append("\n"); builder.append("\n");
} }
builder.append("[]\n"); builder.append("[]\n");

View File

@@ -440,7 +440,7 @@ public class PlacementFragment extends Fragment{
} }
boolean unlocked(Block block){ boolean unlocked(Block block){
return !world.isZone() || data.isUnlocked(block); return !world.isCampaign() || data.isUnlocked(block);
} }
/** Returns the currently displayed block in the top box. */ /** Returns the currently displayed block in the top box. */

View File

@@ -370,7 +370,7 @@ public class Block extends BlockStorage{
/** Call when some content is produced. This unlocks the content if it is applicable. */ /** Call when some content is produced. This unlocks the content if it is applicable. */
public void useContent(Tile tile, UnlockableContent content){ public void useContent(Tile tile, UnlockableContent content){
//only unlocks content in zones //only unlocks content in zones
if(!headless && tile.team() == player.team() && world.isZone()){ if(!headless && tile.team() == player.team() && world.isCampaign()){
logic.handleContent(content); logic.handleContent(content);
} }
} }

View File

@@ -365,8 +365,8 @@ public class BuildBlock extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
progress = stream.readFloat(); progress = stream.readFloat();
short pid = stream.readShort(); short pid = stream.readShort();
short rid = stream.readShort(); short rid = stream.readShort();

View File

@@ -24,7 +24,7 @@ public class ItemSelection{
int i = 0; int i = 0;
for(T item : items){ for(T item : items){
if(!data.isUnlocked(item) && world.isZone()) continue; if(!data.isUnlocked(item) && world.isCampaign()) continue;
ImageButton button = cont.addImageButton(Tex.whiteui, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).group(group).get(); ImageButton button = cont.addImageButton(Tex.whiteui, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).group(group).get();
button.changed(() -> consumer.get(button.isChecked() ? item : null)); button.changed(() -> consumer.get(button.isChecked() ? item : null));

View File

@@ -9,7 +9,6 @@ import arc.math.geom.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
import java.io.*; import java.io.*;
@@ -99,8 +98,8 @@ public class Door extends Wall{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
open = stream.readBoolean(); open = stream.readBoolean();
} }
} }

View File

@@ -181,8 +181,8 @@ public class ForceProjector extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
broken = stream.readBoolean(); broken = stream.readBoolean();
buildup = stream.readFloat(); buildup = stream.readFloat();
radscl = stream.readFloat(); radscl = stream.readFloat();

View File

@@ -133,8 +133,8 @@ public class MendProjector extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
heat = stream.readFloat(); heat = stream.readFloat();
phaseHeat = stream.readFloat(); phaseHeat = stream.readFloat();
} }

View File

@@ -131,8 +131,8 @@ public class OverdriveProjector extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
heat = stream.readFloat(); heat = stream.readFloat();
phaseHeat = stream.readFloat(); phaseHeat = stream.readFloat();
} }

View File

@@ -46,7 +46,7 @@ public class ItemTurret extends CooledTurret{
@Override @Override
public void build(Tile tile, Table table){ public void build(Tile tile, Table table){
MultiReqImage image = new MultiReqImage(); MultiReqImage image = new MultiReqImage();
content.items().each(i -> filter.get(i) && (!world.isZone() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)), content.items().each(i -> filter.get(i) && (!world.isCampaign() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)),
() -> tile.entity != null && !((ItemTurretEntity)tile.entity).ammo.isEmpty() && ((ItemEntry)tile.<ItemTurretEntity>ent().ammo.peek()).item == item))); () -> tile.entity != null && !((ItemTurretEntity)tile.entity).ammo.isEmpty() && ((ItemEntry)tile.<ItemTurretEntity>ent().ammo.peek()).item == item)));
table.add(image).size(8 * 4); table.add(image).size(8 * 4);
@@ -162,8 +162,8 @@ public class ItemTurret extends CooledTurret{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
byte amount = stream.readByte(); byte amount = stream.readByte();
for(int i = 0; i < amount; i++){ for(int i = 0; i < amount; i++){
Item item = Vars.content.item(stream.readByte()); Item item = Vars.content.item(stream.readByte());

View File

@@ -327,8 +327,8 @@ public abstract class Turret extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
reload = stream.readFloat(); reload = stream.readFloat();
rotation = stream.readFloat(); rotation = stream.readFloat();
} }

View File

@@ -47,8 +47,8 @@ public class BufferedItemBridge extends ExtendingItemBridge{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
buffer.read(stream); buffer.read(stream);
} }
} }

View File

@@ -361,8 +361,8 @@ public class Conveyor extends Block implements Autotiler{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
int amount = stream.readInt(); int amount = stream.readInt();
len = Math.min(amount, capacity); len = Math.min(amount, capacity);

View File

@@ -389,8 +389,8 @@ public class ItemBridge extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
link = stream.readInt(); link = stream.readInt();
uptime = stream.readFloat(); uptime = stream.readFloat();
byte links = stream.readByte(); byte links = stream.readByte();

View File

@@ -95,8 +95,8 @@ public class Junction extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
buffer.read(stream); buffer.read(stream);
} }
} }

View File

@@ -340,8 +340,8 @@ public class MassDriver extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
link = stream.readInt(); link = stream.readInt();
rotation = stream.readFloat(); rotation = stream.readFloat();
state = DriverState.values()[stream.readByte()]; state = DriverState.values()[stream.readByte()];

View File

@@ -7,6 +7,8 @@ import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
import java.io.*;
public class OverflowGate extends Block{ public class OverflowGate extends Block{
public float speed = 1f; public float speed = 1f;
public boolean invert = false; public boolean invert = false;
@@ -120,5 +122,13 @@ public class OverflowGate extends Block{
Item lastItem; Item lastItem;
Tile lastInput; Tile lastInput;
float time; float time;
@Override
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
if(revision == 1){
new DirectionalItemBuffer(25, 50f).read(stream);
}
}
} }
} }

View File

@@ -162,9 +162,13 @@ public class Sorter extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
sortItem = content.item(stream.readShort()); sortItem = content.item(stream.readShort());
if(revision == 1){
new DirectionalItemBuffer(20, 45f).read(stream);
}
} }
} }
} }

View File

@@ -12,7 +12,6 @@ import arc.util.*;
import arc.util.pooling.*; import arc.util.pooling.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.gen.*;
import mindustry.net.*; import mindustry.net.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.ui.dialogs.*; import mindustry.ui.dialogs.*;
@@ -157,8 +156,8 @@ public class MessageBlock extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
message = stream.readUTF(); message = stream.readUTF();
} }
} }

View File

@@ -171,8 +171,8 @@ public class ImpactReactor extends PowerGenerator{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
warmup = stream.readFloat(); warmup = stream.readFloat();
} }
} }

View File

@@ -5,7 +5,6 @@ import arc.graphics.g2d.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.world.*; import mindustry.world.*;
@@ -87,8 +86,8 @@ public class LightBlock extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
color = stream.readInt(); color = stream.readInt();
} }
} }

View File

@@ -192,8 +192,8 @@ public class NuclearReactor extends PowerGenerator{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
heat = stream.readFloat(); heat = stream.readFloat();
} }
} }

View File

@@ -65,8 +65,8 @@ public class PowerGenerator extends PowerDistributor{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
productionEfficiency = stream.readFloat(); productionEfficiency = stream.readFloat();
} }
} }

View File

@@ -126,8 +126,8 @@ public class Cultivator extends GenericCrafter{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
warmup = stream.readFloat(); warmup = stream.readFloat();
} }
} }

View File

@@ -158,8 +158,8 @@ public class GenericCrafter extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
progress = stream.readFloat(); progress = stream.readFloat();
warmup = stream.readFloat(); warmup = stream.readFloat();
} }

View File

@@ -107,8 +107,8 @@ public class ItemSource extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
outputItem = content.item(stream.readShort()); outputItem = content.item(stream.readShort());
} }
} }

View File

@@ -103,8 +103,8 @@ public class LiquidSource extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
byte id = stream.readByte(); byte id = stream.readByte();
source = id == -1 ? null : content.liquid(id); source = id == -1 ? null : content.liquid(id);
} }

View File

@@ -73,7 +73,7 @@ public class LaunchPad extends StorageBlock{
public void update(Tile tile){ public void update(Tile tile){
Tilec entity = tile.entity; Tilec entity = tile.entity;
if(world.isZone() && entity.consValid() && entity.items().total() >= itemCapacity && entity.timer(timerLaunch, launchTime / entity.timeScale())){ if(world.isCampaign() && entity.consValid() && entity.items().total() >= itemCapacity && entity.timer(timerLaunch, launchTime / entity.timeScale())){
for(Item item : Vars.content.items()){ for(Item item : Vars.content.items()){
Events.fire(Trigger.itemLaunch); Events.fire(Trigger.itemLaunch);
Fx.padlaunch.at(tile); Fx.padlaunch.at(tile);

View File

@@ -144,8 +144,8 @@ public class Unloader extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
byte id = stream.readByte(); byte id = stream.readByte();
sortItem = id == -1 ? null : content.items().get(id); sortItem = id == -1 ? null : content.items().get(id);
} }

View File

@@ -132,8 +132,8 @@ public class CommandCenter extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
command = UnitCommand.all[stream.readByte()]; command = UnitCommand.all[stream.readByte()];
} }
} }

View File

@@ -148,8 +148,8 @@ public class MechPad extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
progress = stream.readFloat(); progress = stream.readFloat();
time = stream.readFloat(); time = stream.readFloat();
heat = stream.readFloat(); heat = stream.readFloat();

View File

@@ -196,8 +196,8 @@ public class UnitFactory extends Block{
} }
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream); super.read(stream, revision);
buildTime = stream.readFloat(); buildTime = stream.readFloat();
spawned = stream.readInt(); spawned = stream.readInt();
} }

View File

@@ -35,7 +35,7 @@ public class ConsumeItemFilter extends Consume{
@Override @Override
public void build(Tile tile, Table table){ public void build(Tile tile, Table table){
MultiReqImage image = new MultiReqImage(); MultiReqImage image = new MultiReqImage();
content.items().each(i -> filter.get(i) && (!world.isZone() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium), 1), () -> tile.entity != null && tile.entity.items() != null && tile.entity.items().has(item)))); content.items().each(i -> filter.get(i) && (!world.isCampaign() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium), 1), () -> tile.entity != null && tile.entity.items() != null && tile.entity.items().has(item))));
table.add(image).size(8 * 4); table.add(image).size(8 * 4);
} }

View File

@@ -8,7 +8,7 @@ public enum BuildVisibility{
shown(() -> true), shown(() -> true),
debugOnly(() -> false), debugOnly(() -> false),
sandboxOnly(() -> Vars.state.rules.infiniteResources), sandboxOnly(() -> Vars.state.rules.infiniteResources),
campaignOnly(() -> Vars.world.isZone()), campaignOnly(() -> Vars.world.isCampaign()),
lightingOnly(() -> Vars.state.rules.lighting); lightingOnly(() -> Vars.state.rules.lighting);
private final Boolp visible; private final Boolp visible;

View File

@@ -255,7 +255,8 @@ public class DesktopLauncher extends ClientLauncher{
if(inGame){ if(inGame){
if(world.getMap() != null){ if(world.getMap() != null){
gameMapWithWave = world.isZone() ? world.getZone().localizedName : Strings.capitalize(world.getMap().name()); //TODO implement nice name for sector
gameMapWithWave = Strings.capitalize(world.getMap().name());
} }
if(state.rules.waves){ if(state.rules.waves){
gameMapWithWave += " | Wave " + state.wave; gameMapWithWave += " | Wave " + state.wave;

View File

@@ -349,7 +349,7 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
currentLobby = steamID; currentLobby = steamID;
smat.setLobbyData(steamID, "name", player.name()); smat.setLobbyData(steamID, "name", player.name());
smat.setLobbyData(steamID, "mapname", world.getMap() == null ? "Unknown" : state.rules.zone == null ? world.getMap().name() : state.rules.zone.localizedName); smat.setLobbyData(steamID, "mapname", world.getMap().name());
smat.setLobbyData(steamID, "version", Version.build + ""); smat.setLobbyData(steamID, "version", Version.build + "");
smat.setLobbyData(steamID, "versionType", Version.type); smat.setLobbyData(steamID, "versionType", Version.type);
smat.setLobbyData(steamID, "wave", state.wave + ""); smat.setLobbyData(steamID, "wave", state.wave + "");

View File

@@ -187,9 +187,10 @@ public class SStats implements SteamUserStatsCallback{
Events.on(LoseEvent.class, e -> { Events.on(LoseEvent.class, e -> {
if(campaign()){ if(campaign()){
if(world.getZone().metCondition() && (state.wave - world.getZone().conditionWave) / world.getZone().launchPeriod >= 1){ //TODO implement
skipLaunching2Death.complete(); //if(world.getSector().metCondition() && (state.wave - world.getSector().conditionWave) / world.getSector().launchPeriod >= 1){
} // skipLaunching2Death.complete();
//}
} }
}); });
@@ -239,7 +240,7 @@ public class SStats implements SteamUserStatsCallback{
SStat.attacksWon.add(); SStat.attacksWon.add();
} }
RankResult result = state.stats.calculateRank(world.getZone(), state.launched); RankResult result = state.stats.calculateRank(world.getSector(), state.launched);
if(result.rank == Rank.S) earnSRank.complete(); if(result.rank == Rank.S) earnSRank.complete();
if(result.rank == Rank.SS) earnSSRank.complete(); if(result.rank == Rank.SS) earnSSRank.complete();
} }
@@ -273,7 +274,7 @@ public class SStats implements SteamUserStatsCallback{
} }
private boolean campaign(){ private boolean campaign(){
return Vars.world.isZone(); return Vars.world.isCampaign();
} }
@Override @Override