Merge branch '6.0' of https://github.com/Anuken/Mindustry into object-config

# Conflicts:
#	core/src/mindustry/entities/traits/BuilderTrait.java
#	core/src/mindustry/entities/type/TileEntity.java
#	core/src/mindustry/game/EventType.java
#	core/src/mindustry/game/Schematics.java
#	core/src/mindustry/input/InputHandler.java
#	core/src/mindustry/io/TypeIO.java
#	core/src/mindustry/world/Block.java
#	core/src/mindustry/world/blocks/distribution/Sorter.java
This commit is contained in:
Anuken
2020-03-03 21:33:03 -05:00
1356 changed files with 28653 additions and 24877 deletions

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

@@ -1,16 +1,16 @@
package mindustry.io;
import arc.struct.*;
import arc.files.*;
import arc.graphics.*;
import arc.graphics.Pixmap.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.io.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.*;
import mindustry.maps.*;
import mindustry.world.*;
import mindustry.world.LegacyColorMapper.*;
import mindustry.world.blocks.storage.*;
import java.io.*;
@@ -19,7 +19,6 @@ import java.util.zip.*;
import static mindustry.Vars.*;
/** Reads and writes map files. */
//TODO does this class even need to exist??? move to Maps?
public class MapIO{
private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
@@ -81,7 +80,7 @@ public class MapIO{
@Override
public void setBlock(Block type){
super.setBlock(type);
int c = colorFor(Blocks.air, block(), Blocks.air, getTeam());
int c = colorFor(Blocks.air, block(), Blocks.air, team());
if(c != black){
walls.draw(x, floors.getHeight() - 1 - y, c);
floors.draw(x, floors.getHeight() - 1 - y + 1, shade);
@@ -133,12 +132,12 @@ public class MapIO{
}
}
public static Pixmap generatePreview(Tile[][] tiles){
Pixmap pixmap = new Pixmap(tiles.length, tiles[0].length, Format.RGBA8888);
public static Pixmap generatePreview(Tiles tiles){
Pixmap pixmap = new Pixmap(tiles.width, tiles.height, Format.RGBA8888);
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
Tile tile = tiles[x][y];
pixmap.draw(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.overlay(), tile.getTeam()));
Tile tile = tiles.getn(x, y);
pixmap.draw(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.overlay(), tile.team()));
}
}
return pixmap;
@@ -148,32 +147,45 @@ public class MapIO{
if(wall.synthetic()){
return team.color.rgba();
}
return Color.rgba8888(wall.solid ? wall.color : ore == Blocks.air ? floor.color : ore.color);
return Color.rgba8888(wall.solid ? wall.mapColor : ore == Blocks.air ? floor.mapColor : ore.mapColor);
}
/** Reads a pixmap in the 3.5 pixmap format. */
public static void readPixmap(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];
public static Pixmap writeImage(Tiles tiles){
Pixmap pix = new Pixmap(tiles.width, tiles.height);
for(Tile tile : tiles){
//while synthetic blocks are possible, most of their data is lost, so in order to avoid questions like
//"why is there air under my drill" and "why are all my conveyors facing right", they are disabled
int color = tile.block().hasColor && !tile.block().synthetic() ? tile.block().mapColor.rgba() : tile.floor().mapColor.rgba();
pix.draw(tile.x, tiles.height - 1 - tile.y, color);
}
return pix;
}
tile.setFloor(block.floor);
tile.setBlock(block.wall);
if(block.ore != null) tile.setOverlay(block.ore);
public static void readImage(Pixmap pixmap, Tiles tiles){
for(Tile tile : tiles){
int color = pixmap.getPixel(tile.x, pixmap.getHeight() - 1 - tile.y);
Block block = ColorMapper.get(color);
//place core
if(color == Color.rgba8888(Color.green)){
//actual core parts
tile.setBlock(Blocks.coreShard);
tile.setTeam(Team.sharded);
if(block.isFloor()){
tile.setFloor(block.asFloor());
}else if(block.isMultiblock()){
tile.set(block, Team.derelict);
}else{
tile.setBlock(block);
}
}
//guess at floors by grabbing a random adjacent floor
for(Tile tile : tiles){
if(tile.floor() == Blocks.air && tile.block() != Blocks.air){
for(Point2 p : Geometry.d4){
Tile other = tiles.get(tile.x + p.x, tile.y + p.y);
if(other != null && other.floor() != Blocks.air){
tile.setFloor(other.floor());
break;
}
}
}
}
}
interface TileProvider{
Tile get(int x, int y);
}
}
}

View File

@@ -1,11 +1,9 @@
package mindustry.io;
import arc.struct.ObjectMap;
import arc.struct.ObjectMap.Entry;
import arc.struct.StringMap;
import arc.util.io.CounterInputStream;
import arc.util.io.ReusableByteOutStream;
import mindustry.world.WorldContext;
import arc.struct.*;
import arc.struct.ObjectMap.*;
import arc.util.io.*;
import mindustry.world.*;
import java.io.*;
@@ -14,7 +12,9 @@ public abstract class SaveFileReader{
protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput);
protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream();
protected final DataOutputStream dataBytesSmall = new DataOutputStream(byteOutputSmall);
protected final ObjectMap<String, String> fallback = ObjectMap.of();
protected final ObjectMap<String, String> fallback = ObjectMap.of(
"dart-mech-pad", "dart-ship-pad"
);
protected void region(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{
counter.resetCount();

View File

@@ -5,6 +5,7 @@ import arc.files.Fi;
import arc.util.io.CounterInputStream;
import arc.util.io.FastDeflaterOutputStream;
import mindustry.Vars;
import mindustry.io.legacy.*;
import mindustry.io.versions.*;
import mindustry.world.WorldContext;
@@ -18,7 +19,7 @@ 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<SaveVersion> versions = new IntMap<>();
public static final Array<SaveVersion> versionArray = Array.with(new Save1(), new Save2(), new Save3());
public static final Array<SaveVersion> versionArray = Array.with(new Save1(), new Save2(), new Save3(), new Save4());
static{
for(SaveVersion version : versionArray){

View File

@@ -6,13 +6,10 @@ import arc.util.io.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.ctype.ContentType;
import mindustry.entities.*;
import mindustry.entities.traits.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.maps.*;
import mindustry.type.*;
import mindustry.world.*;
import java.io.*;
@@ -128,7 +125,7 @@ public abstract class SaveVersion extends SaveFileReader{
if(tile.entity != null){
writeChunk(stream, true, out -> {
out.writeByte(tile.entity.version());
tile.entity.write(out);
tile.entity.writeAll(Writes.get(out));
});
}else{
//write consecutive non-entity blocks
@@ -190,8 +187,8 @@ public abstract class SaveVersion extends SaveFileReader{
if(tile.entity != null){
try{
readChunk(stream, true, in -> {
byte version = in.readByte();
tile.entity.read(in, version);
byte revision = in.readByte();
tile.entity.readAll(Reads.get(in), revision);
});
}catch(Exception e){
throw new IOException("Failed to read tile entity of block: " + block, e);
@@ -228,30 +225,14 @@ public abstract class SaveVersion extends SaveFileReader{
}
}
//write entity chunk
int groups = 0;
stream.writeInt(Groups.sync.count(Entityc::serialize));
for(Syncc entity : Groups.sync){
if(!entity.serialize()) continue;
for(EntityGroup<?> group : entities.all()){
if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){
groups++;
}
}
stream.writeByte(groups);
for(EntityGroup<?> group : entities.all()){
if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){
stream.writeInt(group.size());
for(Entity entity : group.all()){
SaveTrait save = (SaveTrait)entity;
//each entity is a separate chunk.
writeChunk(stream, true, out -> {
out.writeByte(save.getTypeID().id);
out.writeByte(save.version());
save.writeSave(out);
});
}
}
writeChunk(stream, true, out -> {
out.writeByte(entity.classId());
entity.write(Writes.get(out));
});
}
}
@@ -266,19 +247,14 @@ public abstract class SaveVersion extends SaveFileReader{
}
}
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
//TODO throw exception on read fail
readChunk(stream, true, in -> {
byte typeid = in.readByte();
byte version = in.readByte();
SaveTrait trait = (SaveTrait)content.<TypeID>getByID(ContentType.typeid, typeid).constructor.get();
trait.readSave(in, version);
});
}
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
readChunk(stream, true, in -> {
byte typeid = in.readByte();
Syncc sync = (Syncc)EntityMapping.map(typeid).get();
sync.read(Reads.get(in));
sync.add();
});
}
}

View File

@@ -3,16 +3,13 @@ package mindustry.io;
import arc.graphics.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.entities.Effects.*;
import mindustry.entities.bullet.*;
import mindustry.entities.traits.BuilderTrait.*;
import mindustry.entities.traits.*;
import mindustry.entities.type.*;
import mindustry.entities.units.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.net.Administration.*;
import mindustry.net.Packets.*;
import mindustry.type.*;
@@ -25,173 +22,105 @@ import static mindustry.Vars.*;
/** Class for specifying read/write methods for code generation. */
@SuppressWarnings("unused")
@TypeIOHandler
public class TypeIO{
@WriteClass(Object.class)
public static void writeObject(ByteBuffer buffer, Object object){
public static void writeObject(Writes write, Object object){
if(object == null){
buffer.put((byte)0);
write.b((byte)0);
}else if(object instanceof Integer){
buffer.put((byte)1);
buffer.putInt((Integer)object);
write.b((byte)1);
write.i((Integer)object);
}else if(object instanceof Long){
buffer.put((byte)2);
buffer.putLong((Long)object);
write.b((byte)2);
write.l((Long)object);
}else if(object instanceof Float){
buffer.put((byte)3);
buffer.putFloat((Float)object);
write.b((byte)3);
write.f((Float)object);
}else if(object instanceof String){
buffer.put((byte)4);
writeString(buffer, (String)object);
write.b((byte)4);
writeString(write, (String)object);
writeString(write, (String)object);
}else if(object instanceof Content){
Content map = (Content)object;
buffer.put((byte)5);
buffer.put((byte)map.getContentType().ordinal());
buffer.putShort(map.id);
write.b((byte)5);
write.b((byte)map.getContentType().ordinal());
write.s(map.id);
}else if(object instanceof IntArray){
buffer.put((byte)6);
write.b((byte)6);
IntArray arr = (IntArray)object;
buffer.putShort((short)arr.size);
write.s((short)arr.size);
for(int i = 0; i < arr.size; i++){
buffer.putInt(arr.items[i]);
write.i(arr.items[i]);
}
}else if(object instanceof Point2){
buffer.put((byte)7);
buffer.putInt(((Point2)object).x);
buffer.putInt(((Point2)object).y);
write.b((byte)7);
write.i(((Point2)object).x);
write.i(((Point2)object).y);
}else{
throw new IllegalArgumentException("Unknown object type: " + object.getClass());
}
}
@ReadClass(Object.class)
public static Object readObject(ByteBuffer buffer){
byte type = buffer.get();
public static Object readObject(Reads read){
byte type = read.b();
switch(type){
case 0: return null;
case 1: return buffer.getInt();
case 2: return buffer.getLong();
case 3: return buffer.getFloat();
case 4: return readString(buffer);
case 5: return content.getByID(ContentType.all[buffer.get()], buffer.getShort());
case 6: short length = buffer.getShort(); IntArray arr = new IntArray(); for(int i = 0; i < length; i ++) arr.add(buffer.getInt()); return arr;
case 7: return new Point2(buffer.getInt(), buffer.getInt());
case 1: return read.i();
case 2: return read.l();
case 3: return read.f();
case 4: return readString(read);
case 5: return content.getByID(ContentType.all[read.b()], read.s());
case 6: short length = read.s(); IntArray arr = new IntArray(); for(int i = 0; i < length; i ++) arr.add(read.i()); return arr;
case 7: return new Point2(read.i(), read.i());
default: throw new IllegalArgumentException("Unknown object type: " + type);
}
}
@WriteClass(Player.class)
public static void writePlayer(ByteBuffer buffer, Player player){
if(player == null){
buffer.putInt(-1);
}else{
buffer.putInt(player.id);
}
public static void writeEntity(Writes write, Entityc entity){
write.i(entity == null ? -1 : entity.id());
}
@ReadClass(Player.class)
public static Player readPlayer(ByteBuffer buffer){
int id = buffer.getInt();
return id == -1 ? null : playerGroup.getByID(id);
public static <T extends Entityc> T readEntity(Reads read){
return (T)Groups.all.getByID(read.i());
}
@WriteClass(Unit.class)
public static void writeUnit(ByteBuffer buffer, Unit unit){
if(unit.getGroup() == null){
buffer.put((byte)-1);
return;
}
buffer.put((byte)unit.getGroup().getID());
buffer.putInt(unit.getID());
public static void writeTile(Writes write, Tile tile){
write.i(tile == null ? Pos.get(-1, -1) : tile.pos());
}
@ReadClass(Unit.class)
public static Unit readUnit(ByteBuffer buffer){
byte gid = buffer.get();
if(gid == -1) return null;
int id = buffer.getInt();
return (Unit)entities.get(gid).getByID(id);
public static Tile readTile(Reads read){
return world.tile(read.i());
}
@WriteClass(ShooterTrait.class)
public static void writeShooter(ByteBuffer buffer, ShooterTrait trait){
buffer.put((byte)trait.getGroup().getID());
buffer.putInt(trait.getID());
public static void writeBlock(Writes write, Block block){
write.s(block.id);
}
@ReadClass(ShooterTrait.class)
public static ShooterTrait readShooter(ByteBuffer buffer){
byte gid = buffer.get();
int id = buffer.getInt();
return (ShooterTrait)entities.get(gid).getByID(id);
public static Block readBlock(Reads read){
return content.block(read.s());
}
@WriteClass(Bullet.class)
public static void writeBullet(ByteBuffer buffer, Bullet bullet){
buffer.putInt(bullet.getID());
}
@ReadClass(Bullet.class)
public static Bullet readBullet(ByteBuffer buffer){
int id = buffer.getInt();
return bulletGroup.getByID(id);
}
@WriteClass(BaseUnit.class)
public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){
buffer.put((byte) (int)unit.getTeam().id);
buffer.putInt(unit.getID());
}
@ReadClass(BaseUnit.class)
public static BaseUnit readBaseUnit(ByteBuffer buffer){
byte tid = buffer.get();
int id = buffer.getInt();
return unitGroup.getByID(id);
}
@WriteClass(Tile.class)
public static void writeTile(ByteBuffer buffer, Tile tile){
buffer.putInt(tile == null ? Pos.get(-1, -1) : tile.pos());
}
@ReadClass(Tile.class)
public static Tile readTile(ByteBuffer buffer){
return world.tile(buffer.getInt());
}
@WriteClass(Block.class)
public static void writeBlock(ByteBuffer buffer, Block block){
buffer.putShort(block.id);
}
@ReadClass(Block.class)
public static Block readBlock(ByteBuffer buffer){
return content.block(buffer.getShort());
}
@WriteClass(BuildRequest[].class)
public static void writeRequests(ByteBuffer buffer, BuildRequest[] requests){
buffer.putShort((short)requests.length);
public static void writeRequests(Writes write, BuildRequest[] requests){
write.s((short)requests.length);
for(BuildRequest request : requests){
buffer.put(request.breaking ? (byte)1 : 0);
buffer.putInt(Pos.get(request.x, request.y));
write.b(request.breaking ? (byte)1 : 0);
write.i(Pos.get(request.x, request.y));
if(!request.breaking){
buffer.putShort(request.block.id);
buffer.put((byte)request.rotation);
buffer.put(request.hasConfig ? (byte)1 : 0);
buffer.putInt(request.config);
write.s(request.block.id);
write.b((byte)request.rotation);
write.b(request.hasConfig ? (byte)1 : 0);
write.i(request.config);
}
}
}
@ReadClass(BuildRequest[].class)
public static BuildRequest[] readRequests(ByteBuffer buffer){
short reqamount = buffer.getShort();
public static BuildRequest[] readRequests(Reads read){
short reqamount = read.s();
BuildRequest[] reqs = new BuildRequest[reqamount];
for(int i = 0; i < reqamount; i++){
byte type = buffer.get();
int position = buffer.getInt();
byte type = read.b();
int position = read.i();
BuildRequest currentRequest;
if(world.tile(position) == null){
@@ -201,10 +130,10 @@ public class TypeIO{
if(type == 1){ //remove
currentRequest = new BuildRequest(Pos.x(position), Pos.y(position));
}else{ //place
short block = buffer.getShort();
byte rotation = buffer.get();
boolean hasConfig = buffer.get() == 1;
int config = buffer.getInt();
short block = read.s();
byte rotation = read.b();
boolean hasConfig = read.b() == 1;
int config = read.i();
currentRequest = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block));
if(hasConfig){
currentRequest.configure(config);
@@ -217,183 +146,152 @@ public class TypeIO{
return reqs;
}
@WriteClass(KickReason.class)
public static void writeKick(ByteBuffer buffer, KickReason reason){
buffer.put((byte)reason.ordinal());
public static void writeKick(Writes write, KickReason reason){
write.b((byte)reason.ordinal());
}
@ReadClass(KickReason.class)
public static KickReason readKick(ByteBuffer buffer){
return KickReason.values()[buffer.get()];
public static KickReason readKick(Reads read){
return KickReason.values()[read.b()];
}
@WriteClass(Rules.class)
public static void writeRules(ByteBuffer buffer, Rules rules){
public static void writeRules(Writes write, Rules rules){
String string = JsonIO.write(rules);
byte[] bytes = string.getBytes(charset);
buffer.putInt(bytes.length);
buffer.put(bytes);
write.i(bytes.length);
write.b(bytes);
}
@ReadClass(Rules.class)
public static Rules readRules(ByteBuffer buffer){
int length = buffer.getInt();
byte[] bytes = new byte[length];
buffer.get(bytes);
String string = new String(bytes, charset);
public static Rules readRules(Reads read){
int length = read.i();
String string = new String(read.b(new byte[length]), charset);
return JsonIO.read(Rules.class, string);
}
@WriteClass(Team.class)
public static void writeTeam(ByteBuffer buffer, Team reason){
buffer.put((byte) (int)reason.id);
public static void writeTeam(Writes write, Team reason){
write.b(reason.id);
}
@ReadClass(Team.class)
public static Team readTeam(ByteBuffer buffer){
return Team.get(buffer.get());
public static Team readTeam(Reads read){
return Team.get(read.b());
}
@WriteClass(UnitCommand.class)
public static void writeUnitCommand(ByteBuffer buffer, UnitCommand reason){
buffer.put((byte)reason.ordinal());
public static void writeUnitCommand(Writes write, UnitCommand reason){
write.b((byte)reason.ordinal());
}
@ReadClass(UnitCommand.class)
public static UnitCommand readUnitCommand(ByteBuffer buffer){
return UnitCommand.all[buffer.get()];
public static UnitCommand readUnitCommand(Reads read){
return UnitCommand.all[read.b()];
}
@WriteClass(AdminAction.class)
public static void writeAction(ByteBuffer buffer, AdminAction reason){
buffer.put((byte)reason.ordinal());
public static void writeAction(Writes write, AdminAction reason){
write.b((byte)reason.ordinal());
}
@ReadClass(AdminAction.class)
public static AdminAction readAction(ByteBuffer buffer){
return AdminAction.values()[buffer.get()];
public static AdminAction readAction(Reads read){
return AdminAction.values()[read.b()];
}
@WriteClass(Effect.class)
public static void writeEffect(ByteBuffer buffer, Effect effect){
buffer.putShort((short)effect.id);
public static void writeUnitDef(Writes write, UnitType effect){
write.s(effect.id);
}
@ReadClass(Effect.class)
public static Effect readEffect(ByteBuffer buffer){
return Effects.getEffect(buffer.getShort());
public static UnitType readUnitDef(Reads read){
return content.getByID(ContentType.unit, read.s());
}
@WriteClass(UnitType.class)
public static void writeUnitType(ByteBuffer buffer, UnitType effect){
buffer.putShort(effect.id);
public static void writeColor(Writes write, Color color){
write.i(Color.rgba8888(color));
}
@ReadClass(UnitType.class)
public static UnitType readUnitType(ByteBuffer buffer){
return content.getByID(ContentType.unit, buffer.getShort());
public static Color readColor(Reads read){
return new Color(read.i());
}
@WriteClass(Color.class)
public static void writeColor(ByteBuffer buffer, Color color){
buffer.putInt(Color.rgba8888(color));
public static void writeLiquid(Writes write, Liquid liquid){
write.s(liquid == null ? -1 : liquid.id);
}
@ReadClass(Color.class)
public static Color readColor(ByteBuffer buffer){
return new Color(buffer.getInt());
}
@WriteClass(Mech.class)
public static void writeMech(ByteBuffer buffer, Mech mech){
buffer.put((byte)mech.id);
}
@ReadClass(Mech.class)
public static Mech readMech(ByteBuffer buffer){
return content.getByID(ContentType.mech, buffer.get());
}
@WriteClass(Liquid.class)
public static void writeLiquid(ByteBuffer buffer, Liquid liquid){
buffer.putShort(liquid == null ? -1 : liquid.id);
}
@ReadClass(Liquid.class)
public static Liquid readLiquid(ByteBuffer buffer){
short id = buffer.getShort();
public static Liquid readLiquid(Reads read){
short id = read.s();
return id == -1 ? null : content.liquid(id);
}
@WriteClass(BulletType.class)
public static void writeBulletType(ByteBuffer buffer, BulletType type){
buffer.putShort(type.id);
public static void writeBulletType(Writes write, BulletType type){
write.s(type.id);
}
@ReadClass(BulletType.class)
public static BulletType readBulletType(ByteBuffer buffer){
return content.getByID(ContentType.bullet, buffer.getShort());
public static BulletType readBulletType(Reads read){
return content.getByID(ContentType.bullet, read.s());
}
@WriteClass(Item.class)
public static void writeItem(ByteBuffer buffer, Item item){
buffer.putShort(item == null ? -1 : item.id);
public static void writeItem(Writes write, Item item){
write.s(item == null ? -1 : item.id);
}
@ReadClass(Item.class)
public static Item readItem(ByteBuffer buffer){
short id = buffer.getShort();
public static Item readItem(Reads read){
short id = read.s();
return id == -1 ? null : content.item(id);
}
@WriteClass(String.class)
public static void writeString(ByteBuffer buffer, String string){
public static void writeString(Writes write, String string){
if(string != null){
byte[] bytes = string.getBytes(charset);
buffer.putShort((short)bytes.length);
buffer.put(bytes);
write.s((short)bytes.length);
write.b(bytes);
}else{
buffer.putShort((short)-1);
write.s((short)-1);
}
}
@ReadClass(String.class)
public static String readString(ByteBuffer buffer){
short slength = buffer.getShort();
public static String readString(Reads read){
short slength = read.s();
if(slength != -1){
return new String(read.b(new byte[slength]), charset);
}else{
return null;
}
}
public static void writeString(ByteBuffer write, String string){
if(string != null){
byte[] bytes = string.getBytes(charset);
write.putShort((short)bytes.length);
write.put(bytes);
}else{
write.putShort((short)-1);
}
}
public static String readString(ByteBuffer read){
short slength = read.getShort();
if(slength != -1){
byte[] bytes = new byte[slength];
buffer.get(bytes);
read.get(bytes);
return new String(bytes, charset);
}else{
return null;
}
}
@WriteClass(byte[].class)
public static void writeBytes(ByteBuffer buffer, byte[] bytes){
buffer.putShort((short)bytes.length);
buffer.put(bytes);
public static void writeBytes(Writes write, byte[] bytes){
write.s((short)bytes.length);
write.b(bytes);
}
@ReadClass(byte[].class)
public static byte[] readBytes(ByteBuffer buffer){
short length = buffer.getShort();
byte[] bytes = new byte[length];
buffer.get(bytes);
return bytes;
public static byte[] readBytes(Reads read){
short length = read.s();
return read.b(new byte[length]);
}
@WriteClass(TraceInfo.class)
public static void writeTraceInfo(ByteBuffer buffer, TraceInfo trace){
writeString(buffer, trace.ip);
writeString(buffer, trace.uuid);
buffer.put(trace.modded ? (byte)1 : 0);
buffer.put(trace.mobile ? (byte)1 : 0);
public static void writeTraceInfo(Writes write, TraceInfo trace){
writeString(write, trace.ip);
writeString(write, trace.uuid);
write.b(trace.modded ? (byte)1 : 0);
write.b(trace.mobile ? (byte)1 : 0);
}
@ReadClass(TraceInfo.class)
public static TraceInfo readTraceInfo(ByteBuffer buffer){
return new TraceInfo(readString(buffer), readString(buffer), buffer.get() == 1, buffer.get() == 1);
public static TraceInfo readTraceInfo(Reads read){
return new TraceInfo(readString(read), readString(read), read.b() == 1, read.b() == 1);
}
public static void writeStringData(DataOutput buffer, String string) throws IOException{

View File

@@ -0,0 +1,109 @@
package mindustry.io.legacy;
import arc.util.*;
import arc.util.io.*;
import mindustry.content.*;
import mindustry.game.*;
import mindustry.io.*;
import mindustry.world.*;
import java.io.*;
import static mindustry.Vars.content;
public abstract class LegacySaveVersion extends SaveVersion{
public LegacySaveVersion(int version){
super(version);
}
@Override
public void readMap(DataInput stream, WorldContext context) throws IOException{
int width = stream.readUnsignedShort();
int height = stream.readUnsignedShort();
boolean generating = context.isGenerating();
if(!generating) context.begin();
try{
context.resize(width, height);
//read floor and create tiles first
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
short floorid = stream.readShort();
short oreid = stream.readShort();
int consecutives = stream.readUnsignedByte();
if(content.block(floorid) == Blocks.air) floorid = Blocks.stone.id;
context.create(x, y, floorid, oreid, (short)0);
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
context.create(newx, newy, floorid, oreid, (short)0);
}
i += consecutives;
}
//read blocks
for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
Block block = content.block(stream.readShort());
Tile tile = context.tile(x, y);
if(block == null) block = Blocks.air;
tile.setBlock(block);
if(tile.entity != null){
try{
readChunk(stream, true, in -> {
byte version = in.readByte();
//legacy impl of TileEntity#read()
tile.entity.health(stream.readUnsignedShort());
byte packedrot = stream.readByte();
byte team = Pack.leftByte(packedrot) == 8 ? stream.readByte() : Pack.leftByte(packedrot);
byte rotation = Pack.rightByte(packedrot);
tile.setTeam(Team.get(team));
tile.rotation(rotation);
if(tile.entity.items() != null) tile.entity.items().read(Reads.get(stream));
if(tile.entity.power() != null) tile.entity.power().read(Reads.get(stream));
if(tile.entity.liquids() != null) tile.entity.liquids().read(Reads.get(stream));
if(tile.entity.cons() != null) tile.entity.cons().read(Reads.get(stream));
//read only from subclasses!
tile.entity.read(Reads.get(in), version);
});
}catch(Exception e){
throw new IOException("Failed to read tile entity of block: " + block, e);
}
}else{
int consecutives = stream.readUnsignedByte();
for(int j = i + 1; j < i + 1 + consecutives; j++){
int newx = j % width, newy = j / width;
context.tile(newx, newy).setBlock(block);
}
i += consecutives;
}
}
}finally{
if(!generating) context.end();
}
}
public void readLegacyEntities(DataInput stream) throws IOException{
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
//simply skip all the entities
skipRegion(stream, true);
}
}
}
}

View File

@@ -1,10 +1,4 @@
package mindustry.io.versions;
import arc.func.Prov;
import mindustry.entities.type.Bullet;
import mindustry.entities.effect.*;
import mindustry.entities.type.Player;
import mindustry.entities.type.base.*;
package mindustry.io.legacy;
/*
Latest data: [build 81]
@@ -77,9 +71,9 @@ public class LegacyTypeTable{
11 = Wraith
12 = Ghoul
13 = Revenant
*/
private static final Prov[] build81Table = {
Player::new,
Playerc::new,
Fire::new,
Puddle::new,
MinerDrone::new,
@@ -96,7 +90,7 @@ public class LegacyTypeTable{
};
private static final Prov[] build80Table = {
Player::new,
Playerc::new,
Fire::new,
Puddle::new,
Bullet::new,
@@ -115,7 +109,7 @@ public class LegacyTypeTable{
};
private static final Prov[] build79Table = {
Player::new,
Playerc::new,
Fire::new,
Puddle::new,
Bullet::new,
@@ -141,5 +135,5 @@ public class LegacyTypeTable{
}else{
return build79Table;
}
}
}*/
}

View File

@@ -0,0 +1,15 @@
package mindustry.io.legacy;
import java.io.*;
public class Save1 extends LegacySaveVersion{
public Save1(){
super(1);
}
@Override
public void readEntities(DataInput stream) throws IOException{
readLegacyEntities(stream);
}
}

View File

@@ -0,0 +1,15 @@
package mindustry.io.legacy;
import java.io.*;
public class Save2 extends LegacySaveVersion{
public Save2(){
super(2);
}
@Override
public void readEntities(DataInput stream) throws IOException{
readLegacyEntities(stream);
}
}

View File

@@ -0,0 +1,29 @@
package mindustry.io.legacy;
import mindustry.game.*;
import mindustry.game.Teams.*;
import java.io.*;
import static mindustry.Vars.content;
public class Save3 extends LegacySaveVersion{
public Save3(){
super(3);
}
@Override
public void readEntities(DataInput stream) throws IOException{
int teamc = stream.readInt();
for(int i = 0; i < teamc; i++){
Team team = Team.get(stream.readInt());
TeamData data = team.data();
int blocks = stream.readInt();
for(int j = 0; j < blocks; j++){
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
}
}
readLegacyEntities(stream);
}
}

View File

@@ -1,32 +0,0 @@
package mindustry.io.versions;
import arc.func.*;
import mindustry.entities.traits.*;
import java.io.*;
public class Save1 extends Save2{
public Save1(){
version = 1;
}
@Override
public void readEntities(DataInput stream) throws IOException{
Prov[] table = LegacyTypeTable.getTable(lastReadBuild);
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
readChunk(stream, true, in -> {
byte typeid = in.readByte();
byte version = in.readByte();
SaveTrait trait = (SaveTrait)table[typeid].get();
trait.readSave(in, version);
});
}
}
}
}

View File

@@ -1,35 +0,0 @@
package mindustry.io.versions;
import mindustry.ctype.ContentType;
import mindustry.entities.traits.*;
import mindustry.io.*;
import mindustry.type.TypeID;
import java.io.*;
import static mindustry.Vars.content;
public class Save2 extends SaveVersion{
public Save2(){
super(2);
}
@Override
public void readEntities(DataInput stream) throws IOException{
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
//TODO throw exception on read fail
readChunk(stream, true, in -> {
byte typeid = in.readByte();
byte version = in.readByte();
SaveTrait trait = (SaveTrait)content.<TypeID>getByID(ContentType.typeid, typeid).constructor.get();
trait.readSave(in, version);
});
}
}
}
}

View File

@@ -1,9 +0,0 @@
package mindustry.io.versions;
import mindustry.io.*;
public class Save3 extends SaveVersion{
public Save3(){
super(3);
}
}

View File

@@ -0,0 +1,10 @@
package mindustry.io.versions;
import mindustry.io.*;
public class Save4 extends SaveVersion{
public Save4(){
super(4);
}
}