Minor world load time optimization

This commit is contained in:
Anuken
2018-06-28 15:48:21 -04:00
parent 53cbc0fb8b
commit 4b11511bd1
3 changed files with 84 additions and 73 deletions

View File

@ -174,25 +174,30 @@ public class World extends Module{
/**Loads up a procedural map. This does not call play(), but calls reset().*/ /**Loads up a procedural map. This does not call play(), but calls reset().*/
public void loadProceduralMap(){ public void loadProceduralMap(){
Timers.mark(); Timers.mark();
MapTileData data = WorldGenerator.generate(); Timers.mark();
Map map = new Map("generated-map", new MapMeta(0, new ObjectMap<>(), data.width(), data.height(), null), true, () -> null);
logic.reset(); logic.reset();
beginMapLoad(); beginMapLoad();
int width = 400, height = 400;
Tile[][] tiles = createTiles(width, height);
Map map = new Map("Generated Map", new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null);
setMap(map); setMap(map);
int width = map.meta.width, height = map.meta.height;
Tile[][] tiles = createTiles(data.width(), data.height());
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize); EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
WorldGenerator.generate(tiles, data, true, Mathf.random(9999999)); Timers.mark();
WorldGenerator.generateMap(tiles, Mathf.random(9999999));
Log.info("Time to generate base map: {0}", Timers.elapsed());
Log.info("Time to generate fully without additional events: {0}", Timers.elapsed());
endMapLoad(); endMapLoad();
Log.info("Time to generate: {0}", Timers.elapsed()); Log.info("Full time to generate: {0}", Timers.elapsed());
} }
public void setMap(Map map){ public void setMap(Map map){
@ -214,7 +219,7 @@ public class World extends Module{
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize); EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
WorldGenerator.generate(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), seed); WorldGenerator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), seed);
endMapLoad(); endMapLoad();
} }

View File

@ -127,12 +127,12 @@ public class SaveIO{
public static void load(FileHandle file){ public static void load(FileHandle file){
try { try {
load(file.read()); load(new InflaterInputStream(file.read()));
}catch (RuntimeException e){ }catch (RuntimeException e){
e.printStackTrace(); e.printStackTrace();
FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension());
if(backup.exists()){ if(backup.exists()){
load(backup.read()); load(new InflaterInputStream(backup.read()));
} }
} }
} }
@ -143,7 +143,7 @@ public class SaveIO{
DataInputStream stream; DataInputStream stream;
try{ try{
stream = new DataInputStream(new InflaterInputStream(is)); stream = new DataInputStream(is);
int version = stream.readInt(); int version = stream.readInt();
SaveFileVersion ver = versions.get(version); SaveFileVersion ver = versions.get(version);

View File

@ -11,14 +11,12 @@ import io.anuke.mindustry.content.blocks.OreBlocks;
import io.anuke.mindustry.content.blocks.StorageBlocks; import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.MapTileData; import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.DataPosition;
import io.anuke.mindustry.io.MapTileData.TileDataMarker; import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.noise.RidgedPerlin; import io.anuke.ucore.noise.RidgedPerlin;
import io.anuke.ucore.noise.Simplex; import io.anuke.ucore.noise.Simplex;
import io.anuke.ucore.util.Bits;
import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.SeedRandom; import io.anuke.ucore.util.SeedRandom;
@ -31,42 +29,40 @@ public class WorldGenerator {
static int oreIndex = 0; static int oreIndex = 0;
/**Should fill spawns with the correct spawnpoints.*/ /**Should fill spawns with the correct spawnpoints.*/
public static void generate(Tile[][] tiles, MapTileData data, boolean genOres, int seed){ public static void loadTileData(Tile[][] tiles, MapTileData data, boolean genOres, int seed){
oreIndex = 0;
Array<OreEntry> ores = Array.with(
new OreEntry(Items.tungsten, 0.3f, seed),
new OreEntry(Items.coal, 0.284f, seed),
new OreEntry(Items.lead, 0.28f, seed),
new OreEntry(Items.titanium, 0.27f, seed),
new OreEntry(Items.thorium, 0.26f, seed)
);
IntArray multiblocks = new IntArray();
data.position(0, 0); data.position(0, 0);
TileDataMarker marker = data.newDataMarker(); TileDataMarker marker = data.newDataMarker();
for(int y = 0; y < data.height(); y ++){ for(int y = 0; y < data.height(); y ++){
for(int x = 0; x < data.width(); x ++){ for(int x = 0; x < data.width(); x ++){
data.read(marker); data.read(marker);
tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.blockpart.id ? 0 : marker.wall, marker.rotation, marker.team, marker.elevation);
}
}
Tile tile = new Tile(x, y, marker.floor, marker.wall == Blocks.blockpart.id ? 0 : marker.wall, marker.rotation, marker.team, marker.elevation); prepareTiles(tiles, seed, genOres);
}
Team team = Team.all[marker.team]; public static void prepareTiles(Tile[][] tiles, int seed, boolean genOres){
//find multiblocks
IntArray multiblocks = new IntArray();
if(tile.block().isMultiblock()){ for(int x = 0; x < tiles.length; x ++) {
multiblocks.add(tile.packedPosition()); for (int y = 0; y < tiles[0].length; y++) {
} Tile tile = tiles[x][y];
Team team = tile.getTeam();
if(tile.block() == StorageBlocks.core && if(tile.block() == StorageBlocks.core &&
state.teams.has(team)){ state.teams.has(team)){
state.teams.get(team).cores.add(tile); state.teams.get(team).cores.add(tile);
} }
tiles[x][y] = tile; if(tiles[x][y].block().isMultiblock()){
multiblocks.add(tiles[x][y].packedPosition());
//TODO ores, plants, extra decoration? }
} }
} }
@ -99,8 +95,8 @@ public class WorldGenerator {
} }
//update cliffs, occlusion data //update cliffs, occlusion data
for(int x = 0; x < data.width(); x ++){ for(int x = 0; x < tiles.length; x ++){
for(int y = 0; y < data.height(); y ++) { for(int y = 0; y < tiles[0].length; y ++) {
Tile tile = tiles[x][y]; Tile tile = tiles[x][y];
tile.updateOcclusion(); tile.updateOcclusion();
@ -112,10 +108,19 @@ public class WorldGenerator {
} }
} }
if(genOres) { oreIndex = 0;
for (int x = 0; x < data.width(); x++) { if(genOres) {
for (int y = 0; y < data.height(); y++) { Array<OreEntry> ores = Array.with(
new OreEntry(Items.tungsten, 0.3f, seed),
new OreEntry(Items.coal, 0.284f, seed),
new OreEntry(Items.lead, 0.28f, seed),
new OreEntry(Items.titanium, 0.27f, seed),
new OreEntry(Items.thorium, 0.26f, seed)
);
for (int x = 0; x < tiles.length; x++) {
for (int y = 0; y < tiles[0].length; y++) {
Tile tile = tiles[x][y]; Tile tile = tiles[x][y];
@ -137,15 +142,14 @@ public class WorldGenerator {
} }
} }
public static MapTileData generate(){ public static void generateMap(Tile[][] tiles, int seed){
Simplex sim = new Simplex(Mathf.random(99999)); Simplex sim = new Simplex(Mathf.random(99999));
Simplex sim2 = new Simplex(Mathf.random(99999)); Simplex sim2 = new Simplex(Mathf.random(99999));
Simplex sim3 = new Simplex(Mathf.random(99999)); Simplex sim3 = new Simplex(Mathf.random(99999));
SeedRandom random = new SeedRandom(Mathf.random(99999)); SeedRandom random = new SeedRandom(Mathf.random(99999));
MapTileData data = new MapTileData(400, 400); int width = tiles.length, height = tiles[0].length;
TileDataMarker marker = data.newDataMarker();
ObjectMap<Block, Block> decoration = new ObjectMap<>(); ObjectMap<Block, Block> decoration = new ObjectMap<>();
@ -155,16 +159,17 @@ public class WorldGenerator {
decoration.put(Blocks.snow, Blocks.icerock); decoration.put(Blocks.snow, Blocks.icerock);
decoration.put(Blocks.blackstone, Blocks.blackrock); decoration.put(Blocks.blackstone, Blocks.blackrock);
for (int x = 0; x < data.width(); x++) { for (int x = 0; x < width; x++) {
for (int y = 0; y < data.height(); y++) { for (int y = 0; y < height; y++) {
marker.floor = (byte)Blocks.stone.id; Block floor = Blocks.stone;
Block wall = Blocks.air;
double elevation = sim.octaveNoise2D(3, 0.5, 1f/100, x, y) * 4.1 - 1; double elevation = sim.octaveNoise2D(3, 0.5, 1f/100, x, y) * 4.1 - 1;
double temp = sim3.octaveNoise2D(7, 0.53, 1f/320f, x, y); double temp = sim3.octaveNoise2D(7, 0.53, 1f/320f, x, y);
double r = sim2.octaveNoise2D(1, 0.6, 1f/70, x, y); double r = sim2.octaveNoise2D(1, 0.6, 1f/70, x, y);
double edgeDist = Math.max(data.width()/2, data.height()/2) - Math.max(Math.abs(x - data.width()/2), Math.abs(y - data.height()/2)); double edgeDist = Math.max(width/2, height/2) - Math.max(Math.abs(x - width/2), Math.abs(y - height/2));
double dst = Vector2.dst(data.width()/2, data.height()/2, x, y); double dst = Vector2.dst(width/2, height/2, x, y);
double elevDip = 30; double elevDip = 30;
double border = 14; double border = 14;
@ -174,53 +179,53 @@ public class WorldGenerator {
} }
if(temp < 0.35){ if(temp < 0.35){
marker.floor = (byte)Blocks.snow.id; floor = Blocks.snow;
}else if(temp < 0.45){ }else if(temp < 0.45){
marker.floor = (byte)Blocks.stone.id; floor = Blocks.stone;
}else if(temp < 0.65){ }else if(temp < 0.65){
marker.floor = (byte)Blocks.grass.id; floor = Blocks.grass;
}else if(temp < 0.8){ }else if(temp < 0.8){
marker.floor = (byte)Blocks.sand.id; floor = Blocks.sand;
}else if(temp < 0.9){ }else if(temp < 0.9){
marker.floor = (byte)Blocks.blackstone.id; floor = Blocks.blackstone;
elevation = 0f; elevation = 0f;
}else{ }else{
marker.floor = (byte)Blocks.lava.id; floor = Blocks.lava;
} }
if(dst < elevDip){ if(dst < elevDip){
elevation -= (elevDip - dst)/elevDip * 3.0; elevation -= (elevDip - dst)/elevDip * 3.0;
}else if(r > 0.9){ }else if(r > 0.9){
marker.floor = (byte)Blocks.water.id; floor = Blocks.water;
elevation = 0; elevation = 0;
if(r > 0.94){ if(r > 0.94){
marker.floor = (byte)Blocks.deepwater.id; floor = Blocks.deepwater;
} }
} }
marker.elevation = (byte)Math.max(elevation, 0); if(wall == Blocks.air && decoration.containsKey(floor) && random.chance(0.03)){
wall = decoration.get(floor);
if(marker.wall == 0 && decoration.containsKey(Block.getByID(marker.floor)) && random.chance(0.03)){
marker.wall = (byte)decoration.get(Block.getByID(marker.floor)).id;
} }
data.write(marker); Tile tile = new Tile(x, y, (byte)floor.id, (byte)wall.id);
tile.elevation = (byte)Math.max(elevation, 0);
marker.wall = 0; tiles[x][y] = tile;
} }
} }
for (int x = 0; x < data.width(); x++) { for (int x = 0; x < width; x++) {
for (int y = 0; y < data.height(); y++) { for (int y = 0; y < height; y++) {
byte elevation = data.read(x, y, DataPosition.elevation); Tile tile = tiles[x][y];
byte elevation = tile.elevation;
for(GridPoint2 point : Geometry.d4){ for(GridPoint2 point : Geometry.d4){
if(!Mathf.inBounds(x + point.x, y + point.y, data.width(), data.height())) continue; if(!Mathf.inBounds(x + point.x, y + point.y, width, height)) continue;
if(data.read(x + point.x, y + point.y, DataPosition.elevation) < elevation){ if(tiles[x + point.x][y + point.y].elevation < elevation){
if(Mathf.chance(0.05)){ if(Mathf.chance(0.05)){
data.write(x, y, DataPosition.elevation, (byte)-1); tile.elevation = -1;
} }
break; break;
} }
@ -228,9 +233,10 @@ public class WorldGenerator {
} }
} }
data.write(data.width()/2, data.height()/2, DataPosition.wall, (byte)StorageBlocks.core.id); tiles[width/2][height/2].setBlock(StorageBlocks.core);
data.write(data.width()/2, data.height()/2, DataPosition.rotationTeam, Bits.packByte((byte)0, (byte)Team.blue.ordinal())); tiles[width/2][height/2].setTeam(Team.blue);
return data;
prepareTiles(tiles, seed, true);
} }
static class OreEntry{ static class OreEntry{