many things

This commit is contained in:
Anuken
2019-05-06 14:34:21 -04:00
parent 20fbe2fbbe
commit 51f9ad5a2c
50 changed files with 424 additions and 613 deletions

View File

@@ -117,7 +117,7 @@ public class NetClient implements ApplicationListener{
}
//called on all clients
@Remote(called = Loc.server, targets = Loc.server)
@Remote(called = Loc.server, targets = Loc.server, variants = Variant.both)
public static void sendMessage(String message, String sender, Player playersender){
if(Vars.ui != null){
Vars.ui.chatfrag.addMessage(message, sender);

View File

@@ -202,6 +202,7 @@ public class World implements ApplicationListener{
return state.rules.zone;
}
//TODO move to Control
public void playZone(Zone zone){
ui.loadAnd(() -> {
logic.reset();

View File

@@ -72,6 +72,11 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
}
}
@Override
public byte version(){
return 0;
}
@Override
public float lifetime(){
return lifetime;
@@ -151,7 +156,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
}
@Override
public void readSave(DataInput stream) throws IOException{
public void readSave(DataInput stream, byte version) throws IOException{
this.loadedPosition = stream.readInt();
this.lifetime = stream.readFloat();
this.time = stream.readFloat();

View File

@@ -143,6 +143,11 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
return liquid.flammability * amount;
}
@Override
public byte version(){
return 0;
}
@Override
public void hitbox(Rectangle rectangle){
rectangle.setCenter(x, y).setSize(tilesize);
@@ -245,7 +250,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
}
@Override
public void readSave(DataInput stream) throws IOException{
public void readSave(DataInput stream, byte version) throws IOException{
this.loadedPosition = stream.readInt();
this.x = stream.readFloat();
this.y = stream.readFloat();

View File

@@ -4,4 +4,5 @@ package io.anuke.mindustry.entities.traits;
* Marks an entity as serializable.
*/
public interface SaveTrait extends Entity, TypeTrait, Saveable{
byte version();
}

View File

@@ -4,6 +4,5 @@ import java.io.*;
public interface Saveable{
void writeSave(DataOutput stream) throws IOException;
void readSave(DataInput stream) throws IOException;
void readSave(DataInput stream, byte version) throws IOException;
}

View File

@@ -41,15 +41,6 @@ public interface SyncTrait extends Entity, TypeTrait{
return true;
}
/** Whether this entity is clipped and not synced when out of viewport. */
default boolean isClipped(){
return true;
}
default float clipSize(){
return (this instanceof DrawTrait ? ((DrawTrait)this).drawSize() : 8f);
}
//Read and write sync data, usually position
void write(DataOutput data) throws IOException;

View File

@@ -23,9 +23,7 @@ public interface TypeTrait{
lastRegisteredID[0]++;
}
/**
* Registers a syncable type by ID.
*/
/**Gets a syncable type by ID.*/
static Supplier<? extends TypeTrait> getTypeByID(int id){
if(id == -1){
throw new IllegalArgumentException("Attempt to retrieve invalid entity type ID! Did you forget to set it in ContentLoader.registerTypes()?");

View File

@@ -304,11 +304,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
return type.hitsize * 10;
}
@Override
public float clipSize(){
return isBoss() ? 10000000000f : super.clipSize();
}
@Override
public void onDeath(){
Call.onUnitDeath(this);
@@ -336,6 +331,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
return unitGroups[team.ordinal()];
}
@Override
public byte version(){
return 0;
}
@Override
public void writeSave(DataOutput stream) throws IOException{
super.writeSave(stream);
@@ -344,8 +344,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
}
@Override
public void readSave(DataInput stream) throws IOException{
super.readSave(stream);
public void readSave(DataInput stream, byte version) throws IOException{
super.readSave(stream, version);
byte type = stream.readByte();
this.spawner = stream.readInt();
@@ -363,7 +363,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
@Override
public void read(DataInput data) throws IOException{
float lastx = x, lasty = y, lastrot = rotation;
super.readSave(data);
super.readSave(data, version());
this.type = content.getByID(ContentType.unit, data.readByte());
this.spawner = data.readInt();

View File

@@ -817,8 +817,8 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
//region read and write methods
@Override
public boolean isClipped(){
return false;
public byte version(){
return 0;
}
@Override
@@ -833,7 +833,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
}
@Override
public void readSave(DataInput stream) throws IOException{
public void readSave(DataInput stream, byte version) throws IOException{
boolean local = stream.readBoolean();
if(local){
@@ -844,14 +844,14 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
lastSpawner = (SpawnerTrait)stile.entity;
}
Player player = headless ? this : Vars.player;
player.readSaveSuper(stream);
player.readSaveSuper(stream, version);
player.mech = content.getByID(ContentType.mech, mechid);
player.dead = false;
}
}
private void readSaveSuper(DataInput stream) throws IOException{
super.readSave(stream);
private void readSaveSuper(DataInput stream, byte version) throws IOException{
super.readSave(stream, version);
add();
}
@@ -873,7 +873,9 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
@Override
public void read(DataInput buffer) throws IOException{
float lastx = x, lasty = y, lastrot = rotation, lastvx = velocity.x, lastvy = velocity.y;
super.readSave(buffer);
super.readSave(buffer, version());
name = TypeIO.readStringData(buffer);
byte bools = buffer.readByte();
isAdmin = (bools & 1) != 0;

View File

@@ -124,7 +124,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
}
@CallSuper
public void read(DataInput stream) throws IOException{
public void read(DataInput stream, byte revision) throws IOException{
health = stream.readUnsignedShort();
byte tr = stream.readByte();
byte team = Pack.leftByte(tr);
@@ -139,6 +139,11 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
if(cons != null) cons.read(stream);
}
/** Returns the version of this TileEntity IO code.*/
public byte version(){
return 0;
}
public boolean collide(Bullet other){
return true;
}

View File

@@ -138,7 +138,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
}
@Override
public void readSave(DataInput stream) throws IOException{
public void readSave(DataInput stream, byte version) throws IOException{
byte team = stream.readByte();
boolean dead = stream.readBoolean();
float x = stream.readFloat();
@@ -150,7 +150,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
byte itemID = stream.readByte();
short itemAmount = stream.readShort();
this.status.readSave(stream);
this.status.readSave(stream, version);
this.item.amount = itemAmount;
this.item.item = content.item(itemID);
this.dead = dead;

View File

@@ -130,7 +130,7 @@ public class Statuses implements Saveable{
}
@Override
public void readSave(DataInput stream) throws IOException{
public void readSave(DataInput stream, byte version) throws IOException{
for(StatusEntry effect : statuses){
Pools.free(effect);
}

View File

@@ -52,7 +52,7 @@ public class Saves{
SaveSlot slot = new SaveSlot(index);
saves.add(slot);
saveMap.put(slot.index, slot);
slot.meta = SaveIO.getData(index);
slot.meta = SaveIO.getMeta(index);
nextSlot = Math.max(index + 1, nextSlot);
}
}
@@ -134,7 +134,7 @@ public class Saves{
slot.setName(file.nameWithoutExtension());
saves.add(slot);
saveMap.put(slot.index, slot);
slot.meta = SaveIO.getData(slot.index);
slot.meta = SaveIO.getMeta(slot.index);
current = slot;
saveSlots();
return slot;
@@ -172,7 +172,7 @@ public class Saves{
public void load() throws SaveException{
try{
SaveIO.loadFromSlot(index);
meta = SaveIO.getData(index);
meta = SaveIO.getMeta(index);
current = this;
totalPlaytime = meta.timePlayed;
}catch(Exception e){
@@ -186,7 +186,7 @@ public class Saves{
totalPlaytime = time;
SaveIO.saveToSlot(index);
meta = SaveIO.getData(index);
meta = SaveIO.getMeta(index);
if(!state.is(State.menu)){
current = this;
}

View File

@@ -0,0 +1,180 @@
package io.anuke.mindustry.io;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.Pixmap;
import io.anuke.arc.util.Pack;
import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.MapIO.TileProvider;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock;
import io.anuke.mindustry.world.blocks.BlockPart;
import io.anuke.mindustry.world.blocks.Floor;
import java.io.*;
import java.util.zip.InflaterInputStream;
import static io.anuke.mindustry.Vars.bufferSize;
import static io.anuke.mindustry.Vars.content;
/** Map IO for the "old" .mmap format.
* Differentiate between legacy maps and new maps by checking the extension (or the header).*/
public class LegacyMapIO{
public static Map readMap(FileHandle file, boolean custom) throws IOException{
try(DataInputStream stream = new DataInputStream(file.read(1024))){
ObjectMap<String, String> tags = new ObjectMap<>();
//meta is uncompressed
int version = stream.readInt();
int build = stream.readInt();
short width = stream.readShort(), height = stream.readShort();
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i++){
String name = stream.readUTF();
String value = stream.readUTF();
tags.put(name, value);
}
return new Map(file, width, height, tags, custom, version, build);
}
}
public static void readTiles(Map map, Tile[][] tiles) throws IOException{
readTiles(map, (x, y) -> tiles[x][y]);
}
public static void readTiles(Map map, TileProvider tiles) throws IOException{
readTiles(map.file, map.width, map.height, tiles);
}
private static void readTiles(FileHandle file, int width, int height, Tile[][] tiles) throws IOException{
readTiles(file, width, height, (x, y) -> tiles[x][y]);
}
private static void readTiles(FileHandle file, int width, int height, TileProvider tiles) throws IOException{
try(BufferedInputStream input = file.read(bufferSize)){
//read map
{
DataInputStream stream = new DataInputStream(input);
stream.readInt(); //version
stream.readInt(); //build
stream.readInt(); //width + height
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i++){
stream.readUTF(); //key
stream.readUTF(); //val
}
}
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
try{
SaveIO.getSaveWriter().readContentHeader(stream);
//read floor and create tiles first
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
byte floorid = stream.readByte();
byte oreid = stream.readByte();
int consecutives = stream.readUnsignedByte();
Tile tile = tiles.get(x, y);
tile.setFloor((Floor)content.block(floorid));
tile.setOverlay(content.block(oreid));
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
Tile newTile = tiles.get(newx, newy);
newTile.setFloor((Floor)content.block(floorid));
newTile.setOverlay(content.block(oreid));
}
i += consecutives;
}
//read blocks
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
Block block = content.block(stream.readByte());
Tile tile = tiles.get(x, y);
tile.setBlock(block);
if(tile.entity != null){
byte tr = stream.readByte();
stream.readShort(); //read health (which is actually irrelevant)
byte team = Pack.leftByte(tr);
byte rotation = Pack.rightByte(tr);
tile.setTeam(Team.all[team]);
tile.entity.health = tile.block().health;
tile.rotation(rotation);
if(tile.block() == Blocks.liquidSource || tile.block() == Blocks.unloader || tile.block() == Blocks.sorter){
stream.readByte(); //these blocks have an extra config byte, read it
}
}else{ //no entity/part, read consecutives
int consecutives = stream.readUnsignedByte();
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
tiles.get(newx, newy).setBlock(block);
}
i += consecutives;
}
}
}finally{
content.setTemporaryMapper(null);
}
}
}
}
/** Reads a pixmap in the 3.5 pixmap format. */
public static void readLegacyPixmap(Pixmap pixmap, Tile[][] tiles){
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y);
LegacyBlock block = LegacyColorMapper.get(color);
Tile tile = tiles[x][y];
tile.setFloor(block.floor);
tile.setBlock(block.wall);
if(block.ore != null) tile.setOverlay(block.ore);
//place core
if(color == Color.rgba8888(Color.GREEN)){
for(int dx = 0; dx < 3; dx++){
for(int dy = 0; dy < 3; dy++){
int worldx = dx - 1 + x;
int worldy = dy - 1 + y;
//multiblock parts
if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){
Tile write = tiles[worldx][worldy];
write.setBlock(BlockPart.get(dx - 1, dy - 1));
write.setTeam(Team.blue);
}
}
}
//actual core parts
tile.setBlock(Blocks.coreShard);
tile.setTeam(Team.blue);
}
}
}
}
}

View File

@@ -1,30 +1,21 @@
package io.anuke.mindustry.io;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.collection.ObjectMap.Entry;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.Pixmap;
import io.anuke.arc.graphics.Pixmap.Format;
import io.anuke.arc.util.*;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock;
import io.anuke.mindustry.world.blocks.BlockPart;
import io.anuke.mindustry.world.blocks.Floor;
import java.io.*;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import static io.anuke.mindustry.Vars.bufferSize;
import static io.anuke.mindustry.Vars.content;
import java.io.IOException;
import java.io.InputStream;
/** Reads and writes map files. */
public class MapIO{
public static final int version = 1;
private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
public static boolean isImage(FileHandle file){
@@ -53,9 +44,9 @@ public class MapIO{
}
@Override
public void setOverlayID(byte b){
if(b != 0)
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(floor(), Blocks.air, content.block(b), getTeam()));
public void setOverlay(Block type){
if(type != Blocks.air)
floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(floor(), Blocks.air, type, getTeam()));
}
@Override
@@ -68,13 +59,10 @@ public class MapIO{
}
}
};
readTiles(map, (x, y) -> {
tile.x = (short)x;
tile.y = (short)y;
return tile;
});
floors.drawPixmap(walls, 0, 0);
walls.dispose();
//TODO actually generate the preview
return floors;
}
@@ -96,255 +84,6 @@ public class MapIO{
return Color.rgba8888(wall.solid ? wall.color : ore == Blocks.air ? floor.color : ore.color);
}
public static void writeMap(FileHandle file, Map map, Tile[][] tiles) throws IOException{
OutputStream output = file.write(false, bufferSize);
{
DataOutputStream stream = new DataOutputStream(output);
stream.writeInt(version);
stream.writeInt(Version.build);
stream.writeShort(tiles.length);
stream.writeShort(tiles[0].length);
stream.writeByte((byte)map.tags.size);
for(Entry<String, String> entry : map.tags.entries()){
stream.writeUTF(entry.key);
stream.writeUTF(entry.value);
}
}
try(DataOutputStream stream = new DataOutputStream(new DeflaterOutputStream(output))){
int width = map.width, height = map.height;
SaveIO.getSaveWriter().writeContentHeader(stream);
//floor first
for(int i = 0; i < tiles.length * tiles[0].length; i++){
Tile tile = tiles[i % width][i / width];
stream.writeByte(tile.getFloorID());
stream.writeByte(tile.overlayID());
int consecutives = 0;
for(int j = i + 1; j < width * height && consecutives < 255; j++){
Tile nextTile = tiles[j % width][j / width];
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.overlayID() != tile.overlayID()){
break;
}
consecutives++;
}
stream.writeByte(consecutives);
i += consecutives;
}
//then blocks
for(int i = 0; i < tiles.length * tiles[0].length; i++){
Tile tile = tiles[i % width][i / width];
stream.writeByte(tile.getBlockID());
if(tile.block() instanceof BlockPart){
stream.writeByte(tile.getLinkByte());
}else if(tile.entity != null){
stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.rotation())); //team + rotation
stream.writeShort(/*(short)tile.entity.health*/tile.block().health); //health
if(tile.block() == Blocks.liquidSource || tile.block() == Blocks.unloader || tile.block() == Blocks.sorter){
stream.writeByte(-1); //write an meaningless byte here, just a fallback thing
}
}else{
//write consecutive non-entity blocks
int consecutives = 0;
for(int j = i + 1; j < width * height && consecutives < 255; j++){
Tile nextTile = tiles[j % width][j / width];
if(nextTile.block() != tile.block()){
break;
}
consecutives++;
}
stream.writeByte(consecutives);
i += consecutives;
}
}
}
}
public static Map readMap(FileHandle file, boolean custom) throws IOException{
try(DataInputStream stream = new DataInputStream(file.read(1024))){
ObjectMap<String, String> tags = new ObjectMap<>();
//meta is uncompressed
int version = stream.readInt();
if(version == 0){
return readLegacyMap(file, custom);
}
int build = stream.readInt();
short width = stream.readShort(), height = stream.readShort();
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i++){
String name = stream.readUTF();
String value = stream.readUTF();
tags.put(name, value);
}
return new Map(file, width, height, tags, custom, version, build);
}
}
/** Reads tiles from a map, version-agnostic. */
public static void readTiles(Map map, Tile[][] tiles) throws IOException{
readTiles(map, (x, y) -> tiles[x][y]);
}
/** Reads tiles from a map, version-agnostic. */
public static void readTiles(Map map, TileProvider tiles) throws IOException{
if(map.version == 0){
readLegacyMmapTiles(map.file, tiles);
}else if(map.version == version){
readTiles(map.file, map.width, map.height, tiles);
}else{
throw new IOException("Unknown map version. What?");
}
}
/** Reads tiles from a map in the new build-65 format. */
private static void readTiles(FileHandle file, int width, int height, Tile[][] tiles) throws IOException{
readTiles(file, width, height, (x, y) -> tiles[x][y]);
}
/** Reads tiles from a map in the new build-65 format. */
private static void readTiles(FileHandle file, int width, int height, TileProvider tiles) throws IOException{
try(BufferedInputStream input = file.read(bufferSize)){
//read map
{
DataInputStream stream = new DataInputStream(input);
stream.readInt(); //version
stream.readInt(); //build
stream.readInt(); //width + height
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i++){
stream.readUTF(); //key
stream.readUTF(); //val
}
}
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
MappableContent[][] c = SaveIO.getSaveWriter().readContentHeader(stream);
try{
content.setTemporaryMapper(c);
//read floor and create tiles first
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
byte floorid = stream.readByte();
byte oreid = stream.readByte();
int consecutives = stream.readUnsignedByte();
Tile tile = tiles.get(x, y);
tile.setFloor((Floor)content.block(floorid));
tile.setOverlay(content.block(oreid));
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
Tile newTile = tiles.get(newx, newy);
newTile.setFloor((Floor)content.block(floorid));
newTile.setOverlay(content.block(oreid));
}
i += consecutives;
}
//read blocks
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
Block block = content.block(stream.readByte());
Tile tile = tiles.get(x, y);
tile.setBlock(block);
if(tile.entity != null){
byte tr = stream.readByte();
short health = stream.readShort();
byte team = Pack.leftByte(tr);
byte rotation = Pack.rightByte(tr);
tile.setTeam(Team.all[team]);
tile.entity.health = /*health*/tile.block().health;
tile.rotation(rotation);
if(tile.block() == Blocks.liquidSource || tile.block() == Blocks.unloader || tile.block() == Blocks.sorter){
stream.readByte(); //these blocks have an extra config byte, read it
}
}else{ //no entity/part, read consecutives
int consecutives = stream.readUnsignedByte();
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
tiles.get(newx, newy).setBlock(block);
}
i += consecutives;
}
}
}finally{
content.setTemporaryMapper(null);
}
}
}
}
//region legacy IO
/** Reads a pixmap in the 3.5 pixmap format. */
public static void readLegacyPixmap(Pixmap pixmap, Tile[][] tiles){
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y);
LegacyBlock block = LegacyColorMapper.get(color);
Tile tile = tiles[x][y];
tile.setFloor(block.floor);
tile.setBlock(block.wall);
if(block.ore != null) tile.setOverlay(block.ore);
//place core
if(color == Color.rgba8888(Color.GREEN)){
for(int dx = 0; dx < 3; dx++){
for(int dy = 0; dy < 3; dy++){
int worldx = dx - 1 + x;
int worldy = dy - 1 + y;
//multiblock parts
if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){
Tile write = tiles[worldx][worldy];
write.setBlock(BlockPart.get(dx - 1, dy - 1));
write.setTeam(Team.blue);
}
}
}
//actual core parts
tile.setBlock(Blocks.coreShard);
tile.setTeam(Team.blue);
}
}
}
}
//endregion
interface TileProvider{
Tile get(int x, int y);
}

View File

@@ -8,25 +8,11 @@ import io.anuke.arc.util.io.ReusableByteOutStream;
import java.io.*;
/**
* Format:
* - version of format: int
* (begin deflating)
* - regions begin
* 1. meta tags (short length, key-val UTF pairs)
* 2. map data
*/
public abstract class SaveFileVersion{
public final int version;
public abstract class SaveFileReader{
protected final ReusableByteOutStream byteOutput = new ReusableByteOutStream();
protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput);
protected final ObjectMap<String, String> fallback = ObjectMap.of("alpha-dart-mech-pad", "dart-mech-pad");
public SaveFileVersion(int version){
this.version = version;
}
protected void region(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{
int length;
try{
@@ -62,10 +48,10 @@ public abstract class SaveFileVersion{
if(!isByte){
output.writeInt(length);
}else{
if(length > 255){
throw new IOException("Byte write length exceeded: " + length + " > 255");
if(length > Short.MAX_VALUE){
throw new IOException("Byte write length exceeded: " + length + " > " + Short.MAX_VALUE);
}
output.writeByte(length);
output.writeShort(length);
}
output.write(byteOutput.getBytes(), 0, length);
}
@@ -76,7 +62,7 @@ public abstract class SaveFileVersion{
/** Reads a chunk of some length. Use the runner for reading to catch more descriptive errors. */
public int readChunk(DataInput input, boolean isByte, IORunner<DataInput> runner) throws IOException{
int length = isByte ? input.readUnsignedByte() : input.readInt();
int length = isByte ? input.readUnsignedShort() : input.readInt();
runner.accept(input);
return length;
}

View File

@@ -17,16 +17,16 @@ import static io.anuke.mindustry.Vars.*;
public class SaveIO{
/** Format header. This is the string 'MSAV' in ASCII. */
public static final byte[] header = {77, 83, 65, 86};
public static final IntMap<SaveFileVersion> versions = new IntMap<>();
public static final Array<SaveFileVersion> versionArray = Array.with(new Save1());
public static final IntMap<SaveVersion> versions = new IntMap<>();
public static final Array<SaveVersion> versionArray = Array.with(new Save1());
static{
for(SaveFileVersion version : versionArray){
for(SaveVersion version : versionArray){
versions.put(version.version, version);
}
}
public static SaveFileVersion getSaveWriter(){
public static SaveVersion getSaveWriter(){
return versionArray.peek();
}
@@ -64,7 +64,7 @@ public class SaveIO{
public static boolean isSaveValid(DataInputStream stream){
try{
getData(stream);
getMeta(stream);
return true;
}catch(Exception e){
e.printStackTrace();
@@ -72,15 +72,15 @@ public class SaveIO{
}
}
public static SaveMeta getData(int slot){
return getData(getSlotStream(slot));
public static SaveMeta getMeta(int slot){
return getMeta(getSlotStream(slot));
}
public static SaveMeta getData(DataInputStream stream){
public static SaveMeta getMeta(DataInputStream stream){
try{
int version = stream.readInt();
SaveMeta meta = versions.get(version).getData(stream);
SaveMeta meta = versions.get(version).getMeta(stream);
stream.close();
return meta;
}catch(IOException e){
@@ -141,7 +141,7 @@ public class SaveIO{
logic.reset();
readHeader(stream);
int version = stream.readInt();
SaveFileVersion ver = versions.get(version);
SaveVersion ver = versions.get(version);
ver.read(stream, counter);
}catch(Exception e){
@@ -151,7 +151,7 @@ public class SaveIO{
}
}
public static SaveFileVersion getVersion(){
public static SaveVersion getVersion(){
return versionArray.peek();
}

View File

@@ -5,6 +5,7 @@ import io.anuke.mindustry.maps.Map;
import static io.anuke.mindustry.Vars.world;
//TODO consider removing and replacing with a raw StringMap
public class SaveMeta{
public int version;
public int build;

View File

@@ -8,6 +8,7 @@ import io.anuke.mindustry.entities.Entities;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
@@ -16,10 +17,17 @@ import java.io.*;
import static io.anuke.mindustry.Vars.*;
public abstract class BaseSaveVersion extends SaveFileVersion{
public abstract class SaveVersion extends SaveFileReader{
public final int version;
public BaseSaveVersion(int version){
super(version);
public SaveVersion(int version){
this.version = version;
}
public SaveMeta getMeta(DataInput stream) throws IOException{
stream.readInt(); //length of data, doesn't matter here
StringMap map = readStringMap(stream);
return new SaveMeta(map.getInt("version"), map.getLong("saved"), map.getLong("playtime"), map.getInt("build"), map.get("mapname"), map.getInt("wave"), Serialization.readRulesStringJson(map.get("rules", "{}")));
}
public void write(DataOutputStream stream) throws IOException{
@@ -36,6 +44,28 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
region("entities", stream, counter, this::readEntities);
}
public void writeMeta(DataOutput stream) throws IOException{
writeStringMap(stream, StringMap.of(
"saved", Time.millis(),
"playtime", headless ? 0 : control.saves.getTotalPlaytime(),
"build", Version.build,
"mapname", world.getMap().name(),
"wave", state.wave,
"wavetime", state.wavetime,
"stats", Serialization.writeStatsJson(state.stats),
"rules", Serialization.writeRulesJson(state.rules)
));
}
public void readMeta(DataInput stream) throws IOException{
StringMap map = readStringMap(stream);
state.wave = map.getInt("wave");
state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing);
state.stats = Serialization.readStatsStringJson(map.get("stats", "{}"));
state.rules = Serialization.readRulesStringJson(map.get("rules", "{}"));
}
public void writeMap(DataOutput stream) throws IOException{
//write world size
stream.writeShort(world.width());
@@ -68,8 +98,10 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
stream.writeShort(tile.blockID());
if(tile.entity != null){
//TODO chunks, backward compat
tile.entity.write(stream);
writeChunk(stream, true, out -> {
out.writeByte(tile.entity.version());
tile.entity.write(stream);
});
}else{
//write consecutive non-entity blocks
int consecutives = 0;
@@ -123,8 +155,10 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
tile.setBlock(block);
if(tile.entity != null){
//TODO chunks, backward compat
tile.entity.read(stream);
readChunk(stream, true, in -> {
byte version = in.readByte();
tile.entity.read(stream, version);
});
}else{
int consecutives = stream.readUnsignedByte();
@@ -157,11 +191,12 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){
stream.writeInt(group.size());
for(Entity entity : group.all()){
//TODO chunks, backward compat
SaveTrait save = (SaveTrait)entity;
//each entity is a separate chunk.
writeChunk(stream, true, out -> {
stream.writeByte(((SaveTrait)entity).getTypeID());
((SaveTrait)entity).writeSave(out);
stream.writeByte(save.getTypeID());
stream.writeByte(save.version());
save.writeSave(out);
});
}
}
@@ -174,10 +209,13 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
//TODO chunks, backwards compat
byte typeid = stream.readByte();
SaveTrait trait = (SaveTrait)TypeTrait.getTypeByID(typeid).get();
trait.readSave(stream);
//TODO throw exception on read fail
readChunk(stream, true, in -> {
byte typeid = stream.readByte();
byte version = stream.readByte();
SaveTrait trait = (SaveTrait)TypeTrait.getTypeByID(typeid).get();
trait.readSave(stream, version);
});
}
}
}
@@ -223,26 +261,4 @@ public abstract class BaseSaveVersion extends SaveFileVersion{
}
}
}
public void writeMeta(DataOutput stream) throws IOException{
writeStringMap(stream, StringMap.of(
"saved", Time.millis(),
"playtime", headless ? 0 : control.saves.getTotalPlaytime(),
"build", Version.build,
"mapname", world.getMap().name(),
"wave", state.wave,
"wavetime", state.wavetime//,
//"stats", Serialization.writeStatsStreamJson(state.stats),
//"rules", Serialization.writeRulesStreamJson(state.rules),
));
}
public void readMeta(DataInput stream) throws IOException{
StringMap map = readStringMap(stream);
//TODO read rules, stats
state.wave = map.getInt("wave");
state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing);
}
}

View File

@@ -1,83 +1,10 @@
package io.anuke.mindustry.io.versions;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.io.SaveFileVersion;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.io.SaveVersion;
import java.io.*;
import static io.anuke.mindustry.Vars.*;
public class Save1 extends SaveFileVersion{
public class Save1 extends SaveVersion{
public Save1(){
super(1);
}
@Override
public void read(DataInputStream stream) throws IOException{
stream.readLong(); //time
stream.readLong(); //total playtime
stream.readInt(); //build
//general state
state.rules = Serialization.readRulesStreamJson(stream);
String mapname = stream.readUTF();
Map map = world.maps.all().find(m -> m.name().equals(mapname));
if(map == null) map = new Map(customMapDirectory.child(mapname), 1, 1, new ObjectMap<>(), true);
world.setMap(map);
state.rules.spawns = map.getWaves();
if(content.getByID(ContentType.zone, state.rules.zone) != null){
Rules rules = content.<Zone>getByID(ContentType.zone, state.rules.zone).rules.get();
if(rules.spawns != DefaultWaves.get()){
state.rules.spawns = rules.spawns;
}
}
int wave = stream.readInt();
float wavetime = stream.readFloat();
state.wave = wave;
state.wavetime = wavetime;
state.stats = Serialization.readStats(stream);
world.spawner.read(stream);
content.setTemporaryMapper(readContentHeader(stream));
readEntities(stream);
readMap(stream);
}
@Override
public void write(DataOutputStream stream) throws IOException{
//--META--
stream.writeInt(version); //version id
stream.writeLong(Time.millis()); //last saved
stream.writeLong(headless ? 0 : control.saves.getTotalPlaytime()); //playtime
stream.writeInt(Version.build); //build
//--GENERAL STATE--
Serialization.writeRulesStreamJson(stream, state.rules);
stream.writeUTF(world.getMap().name()); //map name
stream.writeInt(state.wave); //wave
stream.writeFloat(state.wavetime); //wave countdown
Serialization.writeStats(stream, state.stats);
world.spawner.write(stream);
writeContentHeader(stream);
//--ENTITIES--
writeEntities(stream);
writeMap(stream);
}
}

View File

@@ -9,7 +9,6 @@ import io.anuke.arc.util.Log;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.game.DefaultWaves;
import io.anuke.mindustry.game.SpawnGroup;
import io.anuke.mindustry.io.MapIO;
import static io.anuke.mindustry.Vars.world;
@@ -44,7 +43,11 @@ public class Map implements Comparable<Map>{
}
public Map(FileHandle file, int width, int height, ObjectMap<String, String> tags, boolean custom){
this(file, width, height, tags, custom, MapIO.version);
this(file, width, height, tags, custom, -1);
}
public Map(ObjectMap<String, String> tags){
this(Vars.customMapDirectory.child(tags.get("name", "unknown")), 0, 0, tags, true);
}
public Array<SpawnGroup> getWaves(){

View File

@@ -6,7 +6,6 @@ import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.customMapDirectory;
import static io.anuke.mindustry.Vars.world;
public abstract class RandomGenerator extends Generator{
@@ -32,7 +31,7 @@ public abstract class RandomGenerator extends Generator{
decorate(tiles);
world.setMap(new Map(customMapDirectory.child("generated"), 0, 0, new ObjectMap<>(), true));
world.setMap(new Map(new ObjectMap<>()));
}
public abstract void decorate(Tile[][] tiles);

View File

@@ -14,7 +14,8 @@ public class Administration{
public Administration(){
Core.settings.defaults(
"strict", true
"strict", true,
"servername", "Server"
);
load();

View File

@@ -1,19 +1,17 @@
package io.anuke.mindustry.net;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.collection.ObjectMap.Entry;
import io.anuke.arc.Core;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.entities.Entities;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Teams.TeamData;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.world.Tile;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.*;
@@ -22,44 +20,16 @@ public class NetworkIO{
public static void writeWorld(Player player, OutputStream os){
try(DataOutputStream stream = new DataOutputStream(os)){
//--GENERAL STATE--
Serialization.writeRules(stream, state.rules);
stream.writeUTF(world.getMap().name()); //map name
SaveIO.getSaveWriter().writeStringMap(stream, world.getMap().tags);
//write tags
ObjectMap<String, String> tags = world.getMap().tags;
stream.writeByte(tags.size);
for(Entry<String, String> entry : tags.entries()){
stream.writeUTF(entry.key);
stream.writeUTF(entry.value);
}
stream.writeInt(state.wave); //wave
stream.writeFloat(state.wavetime); //wave countdown
stream.writeInt(state.wave);
stream.writeFloat(state.wavetime);
stream.writeInt(player.id);
player.write(stream);
SaveIO.getSaveWriter().writeMap(stream);
stream.write(Team.all.length);
//write team data
for(Team team : Team.all){
TeamData data = state.teams.get(team);
stream.writeByte(team.ordinal());
stream.writeByte(data.enemies.size());
for(Team enemy : data.enemies){
stream.writeByte(enemy.ordinal());
}
stream.writeByte(data.cores.size);
for(Tile tile : data.cores){
stream.writeInt(tile.pos());
}
}
}catch(IOException e){
throw new RuntimeException(e);
}
@@ -69,25 +39,11 @@ public class NetworkIO{
try(DataInputStream stream = new DataInputStream(is)){
Time.clear();
//general state
state.rules = Serialization.readRules(stream);
String map = stream.readUTF();
world.setMap(new Map(SaveIO.getSaveWriter().readStringMap(stream)));
ObjectMap<String, String> tags = new ObjectMap<>();
byte tagSize = stream.readByte();
for(int i = 0; i < tagSize; i++){
String key = stream.readUTF();
String value = stream.readUTF();
tags.put(key, value);
}
int wave = stream.readInt();
float wavetime = stream.readFloat();
state.wave = wave;
state.wavetime = wavetime;
state.wave = stream.readInt();
state.wavetime = stream.readFloat();
Entities.clear();
int id = stream.readInt();
@@ -96,81 +52,60 @@ public class NetworkIO{
player.resetID(id);
player.add();
//map
SaveIO.getSaveWriter().readMap(stream);
world.setMap(new Map(customMapDirectory.child(map), 0, 0, new ObjectMap<>(), true));
state.teams = new Teams();
byte teams = stream.readByte();
for(int i = 0; i < teams; i++){
Team team = Team.all[stream.readByte()];
byte enemies = stream.readByte();
Team[] enemyArr = new Team[enemies];
for(int j = 0; j < enemies; j++){
enemyArr[j] = Team.all[stream.readByte()];
}
state.teams.add(team, enemyArr);
byte cores = stream.readByte();
for(int j = 0; j < cores; j++){
state.teams.get(team).cores.add(world.tile(stream.readInt()));
}
}
}catch(IOException e){
throw new RuntimeException(e);
}
}
public static ByteBuffer writeServerData(){
int maxlen = 32;
String host = (headless ? "Server" : player.name);
String name = (headless ? Core.settings.getString("servername") : player.name);
String map = world.getMap() == null ? "None" : world.getMap().name();
host = host.substring(0, Math.min(host.length(), maxlen));
map = map.substring(0, Math.min(map.length(), maxlen));
ByteBuffer buffer = ByteBuffer.allocate(256);
ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.put((byte)host.getBytes(charset).length);
buffer.put(host.getBytes(charset));
buffer.put((byte)map.getBytes(charset).length);
buffer.put(map.getBytes(charset));
writeString(buffer, name, 100);
writeString(buffer, map);
buffer.putInt(playerGroup.size());
buffer.putInt(state.wave);
buffer.putInt(Version.build);
buffer.put((byte)Version.type.getBytes(charset).length);
buffer.put(Version.type.getBytes(charset));
writeString(buffer, Version.type);
//TODO additional information:
// - gamemode ID/name (just pick the closest one?)
return buffer;
}
public static Host readServerData(String hostAddress, ByteBuffer buffer){
byte hlength = buffer.get();
byte[] hb = new byte[hlength];
buffer.get(hb);
byte mlength = buffer.get();
byte[] mb = new byte[mlength];
buffer.get(mb);
String host = new String(hb, charset);
String map = new String(mb, charset);
String host = readString(buffer);
String map = readString(buffer);
int players = buffer.getInt();
int wave = buffer.getInt();
int version = buffer.getInt();
byte tlength = buffer.get();
byte[] tb = new byte[tlength];
buffer.get(tb);
String vertype = new String(tb, charset);
String vertype = readString(buffer);
return new Host(host, hostAddress, map, wave, players, version, vertype);
}
private static void writeString(ByteBuffer buffer, String string, int maxlen){
byte[] bytes = string.getBytes(charset);
//truncating this way may lead to wierd encoding errors at the ends of strings...
if(bytes.length > maxlen){
bytes = Arrays.copyOfRange(bytes, 0, maxlen);
}
buffer.put((byte)bytes.length);
buffer.put(bytes);
}
private static void writeString(ByteBuffer buffer, String string){
writeString(buffer, string, 32);
}
private static String readString(ByteBuffer buffer){
short length = (short)(buffer.get() & 0xff);
byte[] bytes = new byte[length];
buffer.get(bytes);
return new String(bytes, charset);
}
}

View File

@@ -164,9 +164,9 @@ public class JoinDialog extends FloatingDialog{
server.content.clear();
server.content.table(t -> {
t.add(versionString).left();
t.add("[lightgray]" + host.name).width(targetWidth() - 10f).left().get().setEllipsis(true);
t.row();
t.add("[lightgray]" + Core.bundle.format("server.hostname", host.name)).width(targetWidth() - 10f).left().get().setEllipsis(true);
t.add(versionString).left();
t.row();
t.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players) :
Core.bundle.format("players.single", host.players))).left();

View File

@@ -319,8 +319,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

@@ -90,8 +90,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

@@ -212,8 +212,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

@@ -154,8 +154,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

@@ -153,8 +153,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

@@ -131,8 +131,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

@@ -53,8 +53,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

@@ -376,8 +376,8 @@ public class Conveyor 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);
convey.clear();
int amount = stream.readInt();
convey.ensureCapacity(Math.min(amount, 10));

View File

@@ -340,8 +340,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

@@ -94,8 +94,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);
for(Buffer b : buffers){
b.read(stream);
}

View File

@@ -328,8 +328,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

@@ -134,14 +134,13 @@ public class Sorter extends Block{
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);
stream.writeByte(sortItem == null ? -1 : sortItem.id);
stream.writeShort(sortItem == null ? -1 : sortItem.id);
}
@Override
public void read(DataInput stream) throws IOException{
super.read(stream);
byte b = stream.readByte();
sortItem = b == -1 ? null : content.items().get(b);
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
sortItem = content.item(stream.readShort());
}
}
}

View File

@@ -172,8 +172,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

@@ -188,8 +188,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

@@ -68,8 +68,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

@@ -123,8 +123,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

@@ -156,8 +156,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

@@ -121,8 +121,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

@@ -109,8 +109,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

@@ -185,8 +185,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

@@ -198,13 +198,12 @@ public class UnitFactory extends Block{
public void write(DataOutput stream) throws IOException{
super.write(stream);
stream.writeFloat(buildTime);
stream.writeFloat(0f);
stream.writeInt(spawned);
}
@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();
}