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

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

View File

@@ -15,8 +15,10 @@ import mindustry.core.GameState.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Saves.*;
import mindustry.gen.*;
import mindustry.input.*;
import mindustry.io.SaveIO.*;
import mindustry.maps.Map;
import mindustry.type.*;
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);
//the restart dialog can show info for any number of scenarios
Call.onGameOver(event.winner);
//TODO set meta to indicate game over
/*
if(state.rules.zone != null && !net.client()){
//remove zone save on game over
if(saves.getZoneSlot() != null && !state.rules.tutorial){
saves.getZoneSlot().delete();
}
}
}*/
});
//autohost for pvp maps
@@ -174,7 +178,7 @@ public class Control implements ApplicationListener, Loadable{
});
Events.on(UnitDestroyEvent.class, e -> {
if(world.isZone()){
if(world.isCampaign()){
data.unlockContent(e.unit.type());
}
});
@@ -234,7 +238,7 @@ public class Control implements ApplicationListener, Loadable{
logic.reset();
world.loadMap(map, rules);
state.rules = rules;
state.rules.zone = null;
state.rules.sector = null;
state.rules.editor = false;
logic.play();
if(settings.getBool("savecreate") && !world.isInvalidMap()){
@@ -246,13 +250,30 @@ public class Control implements ApplicationListener, Loadable{
public void playSector(Sector sector){
ui.loadAnd(() -> {
net.reset();
logic.reset();
world.loadSector(sector);
logic.play();
control.saves.zoneSave();
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();
zone.rules.get(state.rules);
state.rules.zone = zone;
//TODO assign zone!!
//state.rules.zone = zone;
for(Tilec core : state.teams.playerCores()){
for(ItemStack stack : zone.getStartingItems()){
core.items().add(stack.item, stack.amount);
@@ -420,7 +442,7 @@ public class Control implements ApplicationListener, Loadable{
if(!state.is(State.menu)){
input.update();
if(world.isZone()){
if(world.isCampaign()){
for(Tilec tile : state.teams.cores(player.team())){
for(Item item : content.items()){
if(tile.items().has(item)){

View File

@@ -31,8 +31,9 @@ public class Logic implements ApplicationListener{
public Logic(){
Events.on(WaveEvent.class, event -> {
if(world.isZone()){
world.getZone().updateWave(state.wave);
if(world.isCampaign()){
//TODO implement
//world.getSector().updateWave(state.wave);
}
});
@@ -100,7 +101,7 @@ public class Logic implements ApplicationListener{
Events.fire(new PlayEvent());
//add starting items
if(!world.isZone()){
if(!world.isCampaign()){
for(TeamData team : state.teams.getActive()){
if(team.hasCore()){
Tilec entity = team.core();
@@ -129,7 +130,7 @@ public class Logic implements ApplicationListener{
public void runWave(){
spawner.spawnEnemies();
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());
}
@@ -151,7 +152,7 @@ public class Logic implements ApplicationListener{
}
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
Call.launchZone();
}else{
@@ -172,8 +173,9 @@ public class Logic implements ApplicationListener{
Fx.launch.at(tile);
}
if(world.getZone() != null){
world.getZone().setLaunched();
if(world.isCampaign()){
//TODO implement
//world.getSector().setLaunched();
}
Time.runTask(30f, () -> {

View File

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

View File

@@ -178,12 +178,12 @@ public class World{
return generating;
}
public boolean isZone(){
return getZone() != null;
public boolean isCampaign(){
return getSector() != null;
}
public Zone getZone(){
return state.rules.zone;
public Sector getSector(){
return state.rules.sector;
}
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. */
public final boolean unlockedCur(){
return Vars.data.isUnlocked(this) || !Vars.world.isZone();
return Vars.data.isUnlocked(this) || !Vars.world.isCampaign();
}
public final boolean locked(){

View File

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

View File

@@ -52,11 +52,16 @@ abstract class EntityComp{
@InternalImpl
abstract boolean serialize();
@MethodPriority(1)
void read(DataInput input) throws IOException{
//TODO dynamic io
afterRead();
}
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{
@Import float x, y;
float hitSize;
float lastX, lastY;
transient float lastX, lastY, hitSize;
@Override
public void update(){

View File

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

View File

@@ -3,40 +3,42 @@ package mindustry.entities.def;
import arc.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.game.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.world.*;
import mindustry.world.consumers.*;
import mindustry.world.modules.*;
import java.io.*;
import static mindustry.Vars.*;
@EntityDef(value = {Tilec.class}, isFinal = false)
@EntityDef(value = {Tilec.class}, isFinal = false, genio = false, serialize = false)
@Component
abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
static final float timeToSleep = 60f * 1;
static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
static int sleepingEntities = 0;
Tile tile;
Block block;
Array<Tile> proximity = new Array<>(8);
transient Tile tile;
transient Block block;
transient Array<Tile> proximity = new Array<>(8);
PowerModule power;
ItemModule items;
LiquidModule liquids;
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 float sleepTime;
private transient boolean sleeping;
private transient float sleepTime;
/** Sets this tile entity data to this tile, and adds it if necessary. */
@Override
@@ -60,6 +62,33 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
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
public void applyBoost(float intensity, float duration){
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.*/
//TODO implement
@Override
public byte version(){
return 0;

View File

@@ -19,7 +19,7 @@ import static mindustry.Vars.*;
@Component
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;
private UnitController controller;
@@ -98,6 +98,12 @@ abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitbox
lookAt(angleTo(pos));
}
@Override
public void afterRead(){
//set up type info after reading
type(this.type);
}
@Override
public void update(){
drag(type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f));

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,8 @@
package mindustry.game;
import mindustry.annotations.Annotations.Serialize;
import arc.struct.Array;
import arc.struct.ObjectIntMap;
import arc.math.Mathf;
import arc.math.*;
import arc.struct.*;
import mindustry.annotations.Annotations.*;
import mindustry.type.*;
@Serialize
@@ -23,21 +22,24 @@ public class Stats{
/** Friendly buildings destroyed. */
public int buildingsDestroyed;
public RankResult calculateRank(Zone zone, boolean launched){
public RankResult calculateRank(Sector zone, boolean launched){
float score = 0;
//TODO implement wave/attack mode based score
/*
if(launched && zone.getRules().attackMode){
score += 3f;
}else if(wavesLasted >= zone.conditionWave){
//each new launch period adds onto the rank 'points'
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
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){
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){
unit.hitbox(Tmp.r1);
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.content.*;
import mindustry.ctype.*;
import mindustry.ctype.ContentType;
import mindustry.game.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -69,6 +68,19 @@ public class JsonIO{
json.setElementType(Rules.class, "spawns", SpawnGroup.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>(){
@Override
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){
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){
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){
if(!entity.serialize()) continue;
@@ -251,6 +254,7 @@ public abstract class SaveVersion extends SaveFileReader{
byte typeid = in.readByte();
Syncc sync = (Syncc)EntityMapping.map(typeid).get();
sync.read(in);
sync.add();
});
}
}

View File

@@ -3,6 +3,7 @@ package mindustry.maps.generators;
import arc.math.*;
import arc.math.geom.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.game.*;
import mindustry.io.*;
import mindustry.maps.*;
@@ -47,10 +48,10 @@ public class MapGenerator extends Generator{
SaveIO.load(map.file);
for(Tile tile : tiles){
if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && world.getZone() != null){
for(Item item : world.getZone().resources){
if(Mathf.chance(0.3)){
tile.entity.items().add(item, Math.min(Mathf.random(500), tile.block().itemCapacity));
if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && world.getSector() != null){
for(Content content : world.getSector().resources){
if(content instanceof Item && Mathf.chance(0.3)){
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.*/
public int detail = 3;
/** 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. */
public float radius = 1f;
public Planet(String name){
public Planet(String name, int size){
super(name);
}
@Override
public void load(){
mesh = new PlanetMesh(detail, generator);
}
this.size = 3;
@Override
public void init(){
grid = PlanetGrid.newGrid(size);
sectors = new Array<>(grid.tiles.length);
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. */
public Sector getSector(Ptile tile){
return sectors.get(tile.id);

View File

@@ -2,18 +2,39 @@ package mindustry.type;
import arc.math.geom.*;
import arc.util.*;
import mindustry.ctype.*;
import mindustry.graphics.PlanetGrid.*;
import static mindustry.Vars.state;
/** A small section of a planet. */
public class Sector{
public final SectorRect rect;
public final Planet planet;
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){
this.planet = planet;
this.tile = tile;
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.

View File

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

View File

@@ -194,7 +194,7 @@ public class LoadDialog extends FloatingDialog{
net.reset();
slot.load();
state.rules.editor = false;
state.rules.zone = null;
state.rules.sector = null;
state.set(State.playing);
}catch(SaveException 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.row();
if(world.isZone()){
if(world.isCampaign()){
cont.addImageTextButton("$techtree", Icon.tree, ui.tech::show);
}else{
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);
if(!state.rules.tutorial){
if(!world.isZone() && !state.isEditor()){
if(!world.isCampaign() && !state.isEditor()){
cont.row();
cont.addImageTextButton("$savegame", Icon.save, save::show);
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("$settings", Icon.settings, ui.settings::show);
if(!world.isZone() && !state.isEditor()){
if(!world.isCampaign() && !state.isEditor()){
cont.addRowImageTextButton("$save", Icon.save, save::show);
cont.row();

View File

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

View File

@@ -440,7 +440,7 @@ public class PlacementFragment extends Fragment{
}
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. */

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. */
public void useContent(Tile tile, UnlockableContent content){
//only unlocks content in zones
if(!headless && tile.team() == player.team() && world.isZone()){
if(!headless && tile.team() == player.team() && world.isCampaign()){
logic.handleContent(content);
}
}

View File

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

View File

@@ -24,7 +24,7 @@ public class ItemSelection{
int i = 0;
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();
button.changed(() -> consumer.get(button.isChecked() ? item : null));

View File

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

View File

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

View File

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

View File

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

View File

@@ -46,7 +46,7 @@ public class ItemTurret extends CooledTurret{
@Override
public void build(Tile tile, Table table){
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)));
table.add(image).size(8 * 4);
@@ -162,8 +162,8 @@ public class ItemTurret extends CooledTurret{
}
@Override
public void read(DataInput stream) throws IOException{
super.read(stream);
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
byte amount = stream.readByte();
for(int i = 0; i < amount; i++){
Item item = Vars.content.item(stream.readByte());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,6 +7,8 @@ import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import java.io.*;
public class OverflowGate extends Block{
public float speed = 1f;
public boolean invert = false;
@@ -120,5 +122,13 @@ public class OverflowGate extends Block{
Item lastItem;
Tile lastInput;
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
public void read(DataInput stream) throws IOException{
super.read(stream);
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
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 mindustry.entities.*;
import mindustry.gen.*;
import mindustry.gen.*;
import mindustry.net.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*;
@@ -157,8 +156,8 @@ public class MessageBlock extends Block{
}
@Override
public void read(DataInput stream) throws IOException{
super.read(stream);
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
message = stream.readUTF();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -73,7 +73,7 @@ public class LaunchPad extends StorageBlock{
public void update(Tile tile){
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()){
Events.fire(Trigger.itemLaunch);
Fx.padlaunch.at(tile);

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,7 +35,7 @@ public class ConsumeItemFilter extends Consume{
@Override
public void build(Tile tile, Table table){
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);
}

View File

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