Persistent unit IDs

This commit is contained in:
Anuken
2021-11-29 10:02:03 -05:00
parent 117fd3769e
commit e2576f1538
16 changed files with 74 additions and 34 deletions
@@ -0,0 +1,84 @@
package mindustry.io.versions;
import arc.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ctype.*;
import mindustry.ui.dialogs.JoinDialog.*;
import java.io.*;
public class LegacyIO{
/** Maps old unit names to new ones. */
public static final StringMap unitMap = StringMap.of(
"titan", "mace",
"chaos-array", "scepter",
"eradicator", "reign",
"eruptor", "atrax",
"wraith", "flare",
"ghoul", "horizon",
"revenant", "zenith",
"lich", "antumbra",
"reaper", "eclipse",
"draug", "mono",
"phantom", "poly",
"spirit", "poly"
);
public static Seq<Server> readServers(){
Seq<Server> arr = new Seq<>();
try{
byte[] bytes = Core.settings.getBytes("server-list");
DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes));
int length = stream.readInt();
if(length > 0){
//name of type, irrelevant
stream.readUTF();
for(int i = 0; i < length; i++){
Server server = new Server();
server.ip = stream.readUTF();
server.port = stream.readInt();
arr.add(server);
}
}
}catch(Exception e){
e.printStackTrace();
}
return arr;
}
public static void readResearch(){
try{
byte[] bytes = Core.settings.getBytes("unlocks");
DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes));
int length = stream.readInt();
if(length > 0){
stream.readUTF(); //name of key type
stream.readUTF(); //name of value type
//each element is an array list
for(int i = 0; i < length; i++){
ContentType type = ContentType.all[stream.readInt()];
int arrLength = stream.readInt();
if(arrLength > 0){
stream.readUTF(); //type of contents (String)
for(int j = 0; j < arrLength; j++){
String name = stream.readUTF();
Content out = Vars.content.getByName(type, name);
if(out instanceof UnlockableContent u){
u.quietUnlock();
}
}
}
}
}
}catch(Exception e){
Log.err(e);
}
}
}
@@ -0,0 +1,118 @@
package mindustry.io.versions;
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.*;
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++){
Block block = content.block(stream.readShort());
Tile tile = context.tile(i);
if(block == null) block = Blocks.air;
//occupied by multiblock part
boolean occupied = tile.build != null && !tile.isCenter() && (tile.build.block == block || block == Blocks.air);
//do not override occupied cells
if(!occupied){
tile.setBlock(block);
}
if(block.hasBuilding()){
try{
readChunk(stream, true, in -> {
byte version = in.readByte();
//legacy impl of Building#read()
tile.build.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.build.rotation = rotation;
if(tile.build.items != null) tile.build.items.read(Reads.get(stream), true);
if(tile.build.power != null) tile.build.power.read(Reads.get(stream), true);
if(tile.build.liquids != null) tile.build.liquids.read(Reads.get(stream), true);
if(tile.build.cons != null) tile.build.cons.read(Reads.get(stream), true);
//read only from subclasses!
tile.build.read(Reads.get(in), version);
});
}catch(Throwable e){
throw new IOException("Failed to read tile entity of block: " + block, e);
}
context.onReadBuilding();
}else{
int consecutives = stream.readUnsignedByte();
//air is a waste of time and may mess up multiblocks
if(block != Blocks.air){
for(int j = i + 1; j < i + 1 + consecutives; j++){
context.tile(j).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
skipChunk(stream, true);
}
}
}
}
@@ -0,0 +1,37 @@
package mindustry.io.versions;
import arc.func.*;
import arc.util.io.*;
import mindustry.gen.*;
import mindustry.io.*;
import java.io.*;
/** This version did not read/write entity IDs to the save. */
public class LegacySaveVersion2 extends SaveVersion{
public LegacySaveVersion2(int version){
super(version);
}
@Override
public void readWorldEntities(DataInput stream) throws IOException{
//entityMapping is null in older save versions, so use the default
Prov[] mapping = this.entityMapping == null ? EntityMapping.idMap : this.entityMapping;
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
readChunk(stream, true, in -> {
int typeid = in.readUnsignedByte();
if(mapping[typeid] == null){
in.skipBytes(lastRegionLength - 1);
return;
}
Entityc entity = (Entityc)mapping[typeid].get();
entity.read(Reads.get(in));
entity.add();
});
}
}
}
+15
View File
@@ -0,0 +1,15 @@
package mindustry.io.versions;
import java.io.*;
public class Save1 extends LegacySaveVersion{
public Save1(){
super(1);
}
@Override
public void readEntities(DataInput stream) throws IOException{
readLegacyEntities(stream);
}
}
+15
View File
@@ -0,0 +1,15 @@
package mindustry.io.versions;
import java.io.*;
public class Save2 extends LegacySaveVersion{
public Save2(){
super(2);
}
@Override
public void readEntities(DataInput stream) throws IOException{
readLegacyEntities(stream);
}
}
+30
View File
@@ -0,0 +1,30 @@
package mindustry.io.versions;
import mindustry.game.*;
import mindustry.game.Teams.*;
import java.io.*;
import static mindustry.Vars.*;
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.blocks.addLast(new BlockPlan(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
}
}
readLegacyEntities(stream);
}
}
+2 -10
View File
@@ -1,22 +1,14 @@
package mindustry.io.versions;
import mindustry.io.*;
import java.io.*;
/** This version only writes entities, no entity ID mappings. */
public class Save4 extends SaveVersion{
/** This version only reads entities, no entity ID mappings. */
public class Save4 extends LegacySaveVersion2{
public Save4(){
super(4);
}
@Override
public void writeEntities(DataOutput stream) throws IOException{
writeTeamBlocks(stream);
writeWorldEntities(stream);
}
@Override
public void readEntities(DataInput stream) throws IOException{
readTeamBlocks(stream);
+2 -3
View File
@@ -1,8 +1,7 @@
package mindustry.io.versions;
import mindustry.io.*;
public class Save5 extends SaveVersion{
/** Uses the legacy readWorldEntities function without entity IDs. */
public class Save5 extends LegacySaveVersion2{
public Save5(){
super(5);
+10
View File
@@ -0,0 +1,10 @@
package mindustry.io.versions;
import mindustry.io.*;
public class Save6 extends SaveVersion{
public Save6(){
super(6);
}
}