Implement new profiling system, begin work on structures.

This commit is contained in:
dfsek
2020-09-26 19:45:58 -07:00
parent c8e564c2d3
commit 5669a0e9c4
17 changed files with 291 additions and 172 deletions

View File

@@ -22,56 +22,59 @@ import java.util.Set;
public class CavePopulator extends BlockPopulator {
private static final Map<Material, BlockData> shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time.
private static final BlockData AIR = Material.AIR.createBlockData();
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
ProfileFuture cave = TerraProfiler.fromWorld(world).measure("CaveTime");
for(CarverConfig c : CarverConfig.getCarvers()) {
Map<Location, Material> shiftCandidate = new HashMap<>();
Set<Block> updateNeeded = new HashSet<>();
Map<Vector, CarvingData.CarvingType> blocks = c.getCarver().carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks();
for(Map.Entry<Vector, CarvingData.CarvingType> e : blocks.entrySet()) {
Vector v = e.getKey();
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
Material m = b.getType();
if(e.getValue().equals(CarvingData.CarvingType.CENTER) && c.isReplaceableInner(m)) {
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteInner(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.WALL) && c.isReplaceableOuter(m)){
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteOuter(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.TOP) && c.isReplaceableTop(m)){
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteTop(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.BOTTOM) && c.isReplaceableBottom(m)){
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteBottom(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
}
if(c.getUpdateBlocks().contains(m)) {
updateNeeded.add(b);
}
}
int i = 0;
int j = 0;
for(Location l : shiftCandidate.keySet()) {
Location mut = l.clone();
Material orig = l.getBlock().getType();
do mut.subtract(0, 1, 0);
while(mut.getBlock().getType().equals(orig));
try {
if(c.getShiftedBlocks().get(shiftCandidate.get(l)).contains(mut.getBlock().getType())) {
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
j++;
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
for(CarverConfig c : CarverConfig.getCarvers()) {
Map<Location, Material> shiftCandidate = new HashMap<>();
Set<Block> updateNeeded = new HashSet<>();
Map<Vector, CarvingData.CarvingType> blocks = c.getCarver().carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks();
for(Map.Entry<Vector, CarvingData.CarvingType> e : blocks.entrySet()) {
Vector v = e.getKey();
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
Material m = b.getType();
if(e.getValue().equals(CarvingData.CarvingType.CENTER) && c.isReplaceableInner(m)) {
if(c.getShiftedBlocks().containsKey(b.getType()))
shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteInner(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.WALL) && c.isReplaceableOuter(m)) {
if(c.getShiftedBlocks().containsKey(b.getType()))
shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteOuter(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.TOP) && c.isReplaceableTop(m)) {
if(c.getShiftedBlocks().containsKey(b.getType()))
shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteTop(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
} else if(e.getValue().equals(CarvingData.CarvingType.BOTTOM) && c.isReplaceableBottom(m)) {
if(c.getShiftedBlocks().containsKey(b.getType()))
shiftCandidate.put(b.getLocation(), b.getType());
b.setBlockData(c.getPaletteBottom(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
}
} catch(NullPointerException ignored) {}
i++;
if(c.getUpdateBlocks().contains(m)) {
updateNeeded.add(b);
}
}
for(Location l : shiftCandidate.keySet()) {
Location mut = l.clone();
Material orig = l.getBlock().getType();
do mut.subtract(0, 1, 0);
while(mut.getBlock().getType().equals(orig));
try {
if(c.getShiftedBlocks().get(shiftCandidate.get(l)).contains(mut.getBlock().getType())) {
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
}
} catch(NullPointerException ignore) {}
}
try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("CaveBlockUpdate")) {
for(Block b : updateNeeded) {
BlockData orig = b.getBlockData();
b.setBlockData(AIR, false);
b.setBlockData(orig, true);
}
}
}
for(Block b : updateNeeded) {
BlockData orig = b.getBlockData();
b.setBlockData(Material.AIR.createBlockData(), true);
b.setBlockData(orig, true);
}
}
if(cave != null) cave.complete();
}
}
}

View File

@@ -22,24 +22,25 @@ public class FloraPopulator extends GaeaBlockPopulator {
Set<Chunk> pop = new HashSet<>();
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated flora in chunk: " + chunk);
pop.add(chunk);
ProfileFuture flora = TerraProfiler.fromWorld(world).measure("FloraTime");
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
if(biome.getDecorator().getFloraChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFloraChance())
continue;
try {
BiomeConfig c = BiomeConfig.fromBiome(biome);
for(int i = 0; i < c.getFloraAttempts(); i++) {
Flora item = biome.getDecorator().getFlora().get(random);
Block highest = item.getHighestValidSpawnAt(chunk, x, z);
if(highest != null && c.getFloraHeights(item).isInRange(highest.getY())) item.plant(highest.getLocation());
}
} catch(NullPointerException ignored) {}
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("FloraTime")) {
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated flora in chunk: " + chunk);
pop.add(chunk);
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
if(biome.getDecorator().getFloraChance() <= 0 || random.nextInt(100) > biome.getDecorator().getFloraChance())
continue;
try {
BiomeConfig c = BiomeConfig.fromBiome(biome);
for(int i = 0; i < c.getFloraAttempts(); i++) {
Flora item = biome.getDecorator().getFlora().get(random);
Block highest = item.getHighestValidSpawnAt(chunk, x, z);
if(highest != null && c.getFloraHeights(item).isInRange(highest.getY()))
item.plant(highest.getLocation());
}
} catch(NullPointerException ignore) {}
}
}
}
if(flora!=null) flora.complete();
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.population;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.BiomeConfig;
@@ -11,6 +12,7 @@ import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.biome.Biome;
import org.polydev.gaea.population.GaeaBlockPopulator;
import org.polydev.gaea.profiler.ProfileFuture;
import java.util.Map;
import java.util.Random;
@@ -18,15 +20,17 @@ import java.util.Random;
public class OrePopulator extends GaeaBlockPopulator {
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
Location l = chunk.getBlock(8, 0, 0).getLocation();
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
for(Map.Entry<OreConfig, MaxMin> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
int num = e.getValue().get(random);
for(int i = 0; i < num; i++) {
int x = random.nextInt(16);
int z = random.nextInt(16);
int y = BiomeConfig.fromBiome((UserDefinedBiome) b).getOreHeight(e.getKey()).get(random);
e.getKey().doVein(chunk.getBlock(x, y, z).getLocation(), random);
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
Location l = chunk.getBlock(8, 0, 0).getLocation();
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
for(Map.Entry<OreConfig, MaxMin> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
int num = e.getValue().get(random);
for(int i = 0; i < num; i++) {
int x = random.nextInt(16);
int z = random.nextInt(16);
int y = BiomeConfig.fromBiome((UserDefinedBiome) b).getOreHeight(e.getKey()).get(random);
e.getKey().doVein(chunk.getBlock(x, y, z).getLocation(), random);
}
}
}
}

View File

@@ -1,14 +1,17 @@
package com.dfsek.terra.population;
import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.structure.GaeaStructure;
import com.dfsek.terra.structure.StructureSpawn;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.population.GaeaBlockPopulator;
import org.polydev.gaea.profiler.ProfileFuture;
import java.io.File;
import java.io.IOException;
@@ -16,23 +19,18 @@ import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class StructurePopulator extends GaeaBlockPopulator {
StructureSpawn spawnTest = new StructureSpawn(100, 5);
Set<Chunk> pop = new HashSet<>();
public class StructurePopulator extends BlockPopulator {
StructureSpawn spawnTest = new StructureSpawn(250, 250);
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", "demo2.tstructure"));
double horizontal = struc.getStructureInfo().getMaxHorizontal()/16D + 1D;
public StructurePopulator() throws IOException {
}
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated structures in chunk: " + chunk);
pop.add(chunk);
Location near = spawnTest.getNearestSpawn((chunk.getX() << 4) + 8, (chunk.getZ() << 4), world.getSeed()).toLocation(world);
if(near.getChunk().equals(chunk)) {
Terra.getInstance().getLogger().info("Spawning structure at " + near.toString() + " in chunk " + chunk);
try {
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", "demo.tstructure"));
near.setY(world.getHighestBlockYAt(near));
struc.paste(near);
} catch(IOException e) {
e.printStackTrace();
}
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("StructureTime")) {
}
}
}

View File

@@ -18,26 +18,26 @@ import java.util.Random;
public class TreePopulator extends GaeaBlockPopulator {
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
ProfileFuture tree = TerraProfiler.fromWorld(world).measure("TreeGenTime");
int x = random.nextInt(16); // Decrease chances of chunk-crossing trees
int z = random.nextInt(16);
Location origin = chunk.getBlock(x, 0, z).getLocation();
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
if(((UserDefinedDecorator) b.getDecorator()).getTreeChance() < random.nextInt(100)) return;
int numTrees = 0;
for(int i = 0; i < 48; i++) {
int y = WorldUtil.getHighestValidSpawnAt(chunk, x, z);
if(y <= 0) continue;
origin = chunk.getBlock(x, y, z).getLocation().add(0, 1, 0);
b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
numTrees++;
try {
b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance());
} catch(NullPointerException ignored) {}
if(numTrees >= b.getDecorator().getTreeDensity()) break;
x = random.nextInt(16); // Decrease chances of chunk-crossing trees
z = random.nextInt(16);
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("TreeGenTime")) {
int x = random.nextInt(16); // Decrease chances of chunk-crossing trees
int z = random.nextInt(16);
Location origin = chunk.getBlock(x, 0, z).getLocation();
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
if(((UserDefinedDecorator) b.getDecorator()).getTreeChance() < random.nextInt(100)) return;
int numTrees = 0;
for(int i = 0; i < 48; i++) {
int y = WorldUtil.getHighestValidSpawnAt(chunk, x, z);
if(y <= 0) continue;
origin = chunk.getBlock(x, y, z).getLocation().add(0, 1, 0);
b = TerraBiomeGrid.fromWorld(world).getBiome(origin);
numTrees++;
try {
b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance());
} catch(NullPointerException ignore) {}
if(numTrees >= b.getDecorator().getTreeDensity()) break;
x = random.nextInt(16); // Decrease chances of chunk-crossing trees
z = random.nextInt(16);
}
}
if(tree!=null) tree.complete();
}
}