mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-18 18:42:30 +00:00
Implement new profiling system, begin work on structures.
This commit is contained in:
parent
c8e564c2d3
commit
5669a0e9c4
8
pom.xml
8
pom.xml
@ -95,7 +95,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.polydev</groupId>
|
<groupId>org.polydev</groupId>
|
||||||
<artifactId>gaea</artifactId>
|
<artifactId>gaea</artifactId>
|
||||||
<version>1.10.42</version>
|
<version>1.10.45</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.lucko</groupId>
|
<groupId>me.lucko</groupId>
|
||||||
@ -114,6 +114,12 @@
|
|||||||
<version>7.2.0-SNAPSHOT</version>
|
<version>7.2.0-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>RELEASE</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -1,8 +1,12 @@
|
|||||||
package com.dfsek.terra;
|
package com.dfsek.terra;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class MaxMin {
|
public class MaxMin implements Iterable<Integer> {
|
||||||
private final int min;
|
private final int min;
|
||||||
private final int max;
|
private final int max;
|
||||||
public MaxMin(int min, int max) {
|
public MaxMin(int min, int max) {
|
||||||
@ -21,7 +25,39 @@ public class MaxMin {
|
|||||||
public int getMin() {
|
public int getMin() {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int get(Random r) {
|
public int get(Random r) {
|
||||||
return r.nextInt((max-min)+1)+min;
|
return r.nextInt((max-min)+1)+min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Min: " + getMin() + " Max:" + getMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<Integer> iterator() {
|
||||||
|
return new MaxMinIterator(this);
|
||||||
|
}
|
||||||
|
private static class MaxMinIterator implements Iterator<Integer> {
|
||||||
|
private Integer current;
|
||||||
|
private final MaxMin m;
|
||||||
|
|
||||||
|
public MaxMinIterator(MaxMin m) {
|
||||||
|
this.m = m;
|
||||||
|
current = m.getMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return current < m.getMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer next() {
|
||||||
|
current++;
|
||||||
|
return current - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,11 @@ package com.dfsek.terra;
|
|||||||
|
|
||||||
import com.dfsek.terra.config.ConfigUtil;
|
import com.dfsek.terra.config.ConfigUtil;
|
||||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||||
import com.dfsek.terra.structure.StructureManager;
|
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import me.lucko.commodore.Commodore;
|
import me.lucko.commodore.Commodore;
|
||||||
import me.lucko.commodore.CommodoreProvider;
|
import me.lucko.commodore.CommodoreProvider;
|
||||||
import me.lucko.commodore.file.CommodoreFileFormat;
|
import me.lucko.commodore.file.CommodoreFileFormat;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.PluginCommand;
|
import org.bukkit.command.PluginCommand;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
@ -18,13 +16,10 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class Terra extends JavaPlugin {
|
public class Terra extends JavaPlugin {
|
||||||
private static FileConfiguration config;
|
private static FileConfiguration config;
|
||||||
private static Terra instance;
|
private static Terra instance;
|
||||||
private static StructureManager manager;
|
|
||||||
|
|
||||||
public static Terra getInstance() {
|
public static Terra getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
@ -38,7 +33,6 @@ public class Terra extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
ConfigUtil.loadConfig(this);
|
ConfigUtil.loadConfig(this);
|
||||||
manager = new StructureManager(this);
|
|
||||||
|
|
||||||
PluginCommand command = getCommand("terra");
|
PluginCommand command = getCommand("terra");
|
||||||
command.setExecutor(new TerraCommand());
|
command.setExecutor(new TerraCommand());
|
||||||
@ -67,10 +61,6 @@ public class Terra extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StructureManager getStructureManager() {
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) {
|
public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) {
|
||||||
return new TerraChunkGenerator();
|
return new TerraChunkGenerator();
|
||||||
|
@ -9,6 +9,7 @@ import com.dfsek.terra.config.genconfig.OreConfig;
|
|||||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||||
import com.dfsek.terra.image.WorldImageGenerator;
|
import com.dfsek.terra.image.WorldImageGenerator;
|
||||||
import com.dfsek.terra.structure.GaeaStructure;
|
import com.dfsek.terra.structure.GaeaStructure;
|
||||||
|
import com.dfsek.terra.structure.InitializationException;
|
||||||
import com.dfsek.terra.structure.StructureSpawn;
|
import com.dfsek.terra.structure.StructureSpawn;
|
||||||
import com.sk89q.worldedit.IncompleteRegionException;
|
import com.sk89q.worldedit.IncompleteRegionException;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
@ -158,7 +159,13 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
|
|||||||
BlockVector3 max = selection.getMaximumPoint();
|
BlockVector3 max = selection.getMaximumPoint();
|
||||||
Location l1 = new Location(pl.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ());
|
Location l1 = new Location(pl.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ());
|
||||||
Location l2 = new Location(pl.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ());
|
Location l2 = new Location(pl.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ());
|
||||||
GaeaStructure structure = new GaeaStructure(l1, l2, args[2]);
|
GaeaStructure structure = null;
|
||||||
|
try {
|
||||||
|
structure = new GaeaStructure(l1, l2, args[2]);
|
||||||
|
} catch(InitializationException e) {
|
||||||
|
sender.sendMessage(e.getMessage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
File file = new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[2] + ".tstructure");
|
File file = new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[2] + ".tstructure");
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
@ -173,14 +180,14 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
|
|||||||
try {
|
try {
|
||||||
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[2] + ".tstructure"));
|
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[2] + ".tstructure"));
|
||||||
if("true".equals(args[3])) struc.paste(pl.getLocation());
|
if("true".equals(args[3])) struc.paste(pl.getLocation());
|
||||||
else struc.paste(pl.getLocation(), pl.getLocation().getChunk());
|
//else struc.paste(pl.getLocation(), pl.getLocation().getChunk());
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
sender.sendMessage("Structure not found.");
|
sender.sendMessage("Structure not found.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if("getspawn".equals(args[1])) {
|
} else if("getspawn".equals(args[1])) {
|
||||||
Vector v = new StructureSpawn(500, 100).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed());
|
Vector v = new StructureSpawn(250, 250).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed());
|
||||||
sender.sendMessage(v.getBlockX() + ":" + v.getBlockZ());
|
sender.sendMessage(v.getBlockX() + ":" + v.getBlockZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,12 @@ public class TerraProfiler extends WorldProfiler {
|
|||||||
private static final Map<World, TerraProfiler> profilerMap = new HashMap<>();
|
private static final Map<World, TerraProfiler> profilerMap = new HashMap<>();
|
||||||
public TerraProfiler(World w) {
|
public TerraProfiler(World w) {
|
||||||
super(w);
|
super(w);
|
||||||
this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime")
|
this
|
||||||
.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "ChunkBaseGenTime")
|
|
||||||
.addMeasurement(new Measurement(2000000, DataType.PERIOD_MILLISECONDS), "BiomeSetTime")
|
|
||||||
.addMeasurement(new Measurement(25000000, DataType.PERIOD_MILLISECONDS), "TreeGenTime")
|
.addMeasurement(new Measurement(25000000, DataType.PERIOD_MILLISECONDS), "TreeGenTime")
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
|
||||||
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
||||||
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime")
|
||||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveBlockUpdate");
|
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveBlockUpdate");
|
||||||
profilerMap.put(w, this);
|
profilerMap.put(w, this);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
|||||||
|
|
||||||
public TerraChunkGenerator() {
|
public TerraChunkGenerator() {
|
||||||
super(ChunkInterpolator.InterpolationType.TRILINEAR);
|
super(ChunkInterpolator.InterpolationType.TRILINEAR);
|
||||||
popMan.attach(new StructurePopulator());
|
|
||||||
popMan.attach(new TreePopulator());
|
popMan.attach(new TreePopulator());
|
||||||
popMan.attach(new FloraPopulator());
|
popMan.attach(new FloraPopulator());
|
||||||
popMan.attach(new OrePopulator());
|
popMan.attach(new OrePopulator());
|
||||||
|
@ -22,9 +22,10 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class CavePopulator extends BlockPopulator {
|
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 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
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||||
ProfileFuture cave = TerraProfiler.fromWorld(world).measure("CaveTime");
|
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
|
||||||
for(CarverConfig c : CarverConfig.getCarvers()) {
|
for(CarverConfig c : CarverConfig.getCarvers()) {
|
||||||
Map<Location, Material> shiftCandidate = new HashMap<>();
|
Map<Location, Material> shiftCandidate = new HashMap<>();
|
||||||
Set<Block> updateNeeded = new HashSet<>();
|
Set<Block> updateNeeded = new HashSet<>();
|
||||||
@ -34,24 +35,26 @@ public class CavePopulator extends BlockPopulator {
|
|||||||
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
||||||
Material m = b.getType();
|
Material m = b.getType();
|
||||||
if(e.getValue().equals(CarvingData.CarvingType.CENTER) && c.isReplaceableInner(m)) {
|
if(e.getValue().equals(CarvingData.CarvingType.CENTER) && c.isReplaceableInner(m)) {
|
||||||
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
|
if(c.getShiftedBlocks().containsKey(b.getType()))
|
||||||
|
shiftCandidate.put(b.getLocation(), b.getType());
|
||||||
b.setBlockData(c.getPaletteInner(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
b.setBlockData(c.getPaletteInner(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
||||||
} else if(e.getValue().equals(CarvingData.CarvingType.WALL) && c.isReplaceableOuter(m)){
|
} else if(e.getValue().equals(CarvingData.CarvingType.WALL) && c.isReplaceableOuter(m)) {
|
||||||
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
|
if(c.getShiftedBlocks().containsKey(b.getType()))
|
||||||
|
shiftCandidate.put(b.getLocation(), b.getType());
|
||||||
b.setBlockData(c.getPaletteOuter(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
b.setBlockData(c.getPaletteOuter(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
||||||
} else if(e.getValue().equals(CarvingData.CarvingType.TOP) && c.isReplaceableTop(m)){
|
} else if(e.getValue().equals(CarvingData.CarvingType.TOP) && c.isReplaceableTop(m)) {
|
||||||
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
|
if(c.getShiftedBlocks().containsKey(b.getType()))
|
||||||
|
shiftCandidate.put(b.getLocation(), b.getType());
|
||||||
b.setBlockData(c.getPaletteTop(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
b.setBlockData(c.getPaletteTop(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
||||||
} else if(e.getValue().equals(CarvingData.CarvingType.BOTTOM) && c.isReplaceableBottom(m)){
|
} else if(e.getValue().equals(CarvingData.CarvingType.BOTTOM) && c.isReplaceableBottom(m)) {
|
||||||
if(c.getShiftedBlocks().containsKey(b.getType())) shiftCandidate.put(b.getLocation(), b.getType());
|
if(c.getShiftedBlocks().containsKey(b.getType()))
|
||||||
|
shiftCandidate.put(b.getLocation(), b.getType());
|
||||||
b.setBlockData(c.getPaletteBottom(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
b.setBlockData(c.getPaletteBottom(v.getBlockY()).get(random), c.getUpdateBlocks().contains(m));
|
||||||
}
|
}
|
||||||
if(c.getUpdateBlocks().contains(m)) {
|
if(c.getUpdateBlocks().contains(m)) {
|
||||||
updateNeeded.add(b);
|
updateNeeded.add(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i = 0;
|
|
||||||
int j = 0;
|
|
||||||
for(Location l : shiftCandidate.keySet()) {
|
for(Location l : shiftCandidate.keySet()) {
|
||||||
Location mut = l.clone();
|
Location mut = l.clone();
|
||||||
Material orig = l.getBlock().getType();
|
Material orig = l.getBlock().getType();
|
||||||
@ -60,18 +63,18 @@ public class CavePopulator extends BlockPopulator {
|
|||||||
try {
|
try {
|
||||||
if(c.getShiftedBlocks().get(shiftCandidate.get(l)).contains(mut.getBlock().getType())) {
|
if(c.getShiftedBlocks().get(shiftCandidate.get(l)).contains(mut.getBlock().getType())) {
|
||||||
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
|
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
} catch(NullPointerException ignored) {}
|
} catch(NullPointerException ignore) {}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("CaveBlockUpdate")) {
|
||||||
for(Block b : updateNeeded) {
|
for(Block b : updateNeeded) {
|
||||||
BlockData orig = b.getBlockData();
|
BlockData orig = b.getBlockData();
|
||||||
b.setBlockData(Material.AIR.createBlockData(), true);
|
b.setBlockData(AIR, false);
|
||||||
b.setBlockData(orig, true);
|
b.setBlockData(orig, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(cave != null) cave.complete();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
|||||||
Set<Chunk> pop = new HashSet<>();
|
Set<Chunk> pop = new HashSet<>();
|
||||||
@Override
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||||
|
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("FloraTime")) {
|
||||||
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated flora in chunk: " + chunk);
|
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated flora in chunk: " + chunk);
|
||||||
pop.add(chunk);
|
pop.add(chunk);
|
||||||
ProfileFuture flora = TerraProfiler.fromWorld(world).measure("FloraTime");
|
|
||||||
for(int x = 0; x < 16; x++) {
|
for(int x = 0; x < 16; x++) {
|
||||||
for(int z = 0; z < 16; z++) {
|
for(int z = 0; z < 16; z++) {
|
||||||
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
|
UserDefinedBiome biome = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
|
||||||
@ -35,11 +35,12 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
|||||||
for(int i = 0; i < c.getFloraAttempts(); i++) {
|
for(int i = 0; i < c.getFloraAttempts(); i++) {
|
||||||
Flora item = biome.getDecorator().getFlora().get(random);
|
Flora item = biome.getDecorator().getFlora().get(random);
|
||||||
Block highest = item.getHighestValidSpawnAt(chunk, x, z);
|
Block highest = item.getHighestValidSpawnAt(chunk, x, z);
|
||||||
if(highest != null && c.getFloraHeights(item).isInRange(highest.getY())) item.plant(highest.getLocation());
|
if(highest != null && c.getFloraHeights(item).isInRange(highest.getY()))
|
||||||
|
item.plant(highest.getLocation());
|
||||||
|
}
|
||||||
|
} catch(NullPointerException ignore) {}
|
||||||
}
|
}
|
||||||
} catch(NullPointerException ignored) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(flora!=null) flora.complete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.dfsek.terra.population;
|
package com.dfsek.terra.population;
|
||||||
|
|
||||||
import com.dfsek.terra.MaxMin;
|
import com.dfsek.terra.MaxMin;
|
||||||
|
import com.dfsek.terra.TerraProfiler;
|
||||||
import com.dfsek.terra.biome.TerraBiomeGrid;
|
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||||
import com.dfsek.terra.config.genconfig.BiomeConfig;
|
import com.dfsek.terra.config.genconfig.BiomeConfig;
|
||||||
@ -11,6 +12,7 @@ import org.bukkit.World;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.polydev.gaea.biome.Biome;
|
import org.polydev.gaea.biome.Biome;
|
||||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||||
|
import org.polydev.gaea.profiler.ProfileFuture;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@ -18,6 +20,7 @@ import java.util.Random;
|
|||||||
public class OrePopulator extends GaeaBlockPopulator {
|
public class OrePopulator extends GaeaBlockPopulator {
|
||||||
@Override
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||||
|
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
|
||||||
Location l = chunk.getBlock(8, 0, 0).getLocation();
|
Location l = chunk.getBlock(8, 0, 0).getLocation();
|
||||||
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
|
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
|
||||||
for(Map.Entry<OreConfig, MaxMin> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
|
for(Map.Entry<OreConfig, MaxMin> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
|
||||||
@ -30,4 +33,5 @@ public class OrePopulator extends GaeaBlockPopulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package com.dfsek.terra.population;
|
package com.dfsek.terra.population;
|
||||||
|
|
||||||
import com.dfsek.terra.Terra;
|
import com.dfsek.terra.Terra;
|
||||||
|
import com.dfsek.terra.TerraProfiler;
|
||||||
import com.dfsek.terra.structure.GaeaStructure;
|
import com.dfsek.terra.structure.GaeaStructure;
|
||||||
import com.dfsek.terra.structure.StructureSpawn;
|
import com.dfsek.terra.structure.StructureSpawn;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.generator.BlockPopulator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||||
|
import org.polydev.gaea.profiler.ProfileFuture;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -16,23 +19,18 @@ import java.util.HashSet;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class StructurePopulator extends GaeaBlockPopulator {
|
public class StructurePopulator extends BlockPopulator {
|
||||||
StructureSpawn spawnTest = new StructureSpawn(100, 5);
|
StructureSpawn spawnTest = new StructureSpawn(250, 250);
|
||||||
Set<Chunk> pop = new HashSet<>();
|
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
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
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);
|
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("StructureTime")) {
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import java.util.Random;
|
|||||||
public class TreePopulator extends GaeaBlockPopulator {
|
public class TreePopulator extends GaeaBlockPopulator {
|
||||||
@Override
|
@Override
|
||||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||||
ProfileFuture tree = TerraProfiler.fromWorld(world).measure("TreeGenTime");
|
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("TreeGenTime")) {
|
||||||
int x = random.nextInt(16); // Decrease chances of chunk-crossing trees
|
int x = random.nextInt(16); // Decrease chances of chunk-crossing trees
|
||||||
int z = random.nextInt(16);
|
int z = random.nextInt(16);
|
||||||
Location origin = chunk.getBlock(x, 0, z).getLocation();
|
Location origin = chunk.getBlock(x, 0, z).getLocation();
|
||||||
@ -33,11 +33,11 @@ public class TreePopulator extends GaeaBlockPopulator {
|
|||||||
numTrees++;
|
numTrees++;
|
||||||
try {
|
try {
|
||||||
b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance());
|
b.getDecorator().getTrees().get(random).plant(origin, random, false, Terra.getInstance());
|
||||||
} catch(NullPointerException ignored) {}
|
} catch(NullPointerException ignore) {}
|
||||||
if(numTrees >= b.getDecorator().getTreeDensity()) break;
|
if(numTrees >= b.getDecorator().getTreeDensity()) break;
|
||||||
x = random.nextInt(16); // Decrease chances of chunk-crossing trees
|
x = random.nextInt(16); // Decrease chances of chunk-crossing trees
|
||||||
z = random.nextInt(16);
|
z = random.nextInt(16);
|
||||||
}
|
}
|
||||||
if(tree!=null) tree.complete();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
package com.dfsek.terra.structure;
|
package com.dfsek.terra.structure;
|
||||||
|
|
||||||
|
import com.dfsek.terra.MaxMin;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -16,14 +20,18 @@ import java.io.ObjectOutputStream;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class GaeaStructure implements Serializable {
|
public class GaeaStructure implements Serializable {
|
||||||
public static final long serialVersionUID = -6664585217063842035L;
|
public static final long serialVersionUID = -6664585217063842035L;
|
||||||
private final StructureContainedBlock[][][] structure;
|
private final StructureContainedBlock[][][] structure;
|
||||||
|
private final GaeaStructureInfo structureInfo;
|
||||||
private final String id;
|
private final String id;
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
|
|
||||||
public static GaeaStructure load(File f) throws IOException {
|
@NotNull
|
||||||
|
public static GaeaStructure load(@NotNull File f) throws IOException {
|
||||||
try {
|
try {
|
||||||
return fromFile(f);
|
return fromFile(f);
|
||||||
} catch(ClassNotFoundException e) {
|
} catch(ClassNotFoundException e) {
|
||||||
@ -31,7 +39,8 @@ public class GaeaStructure implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GaeaStructure(Location l1, Location l2, String id) {
|
public GaeaStructure(@NotNull Location l1, @NotNull Location l2, @NotNull String id) throws InitializationException {
|
||||||
|
int centerX = -1, centerZ = -1;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
if(l1.getX() > l2.getX() || l1.getY() > l2.getY() || l1.getZ() > l2.getZ()) throw new IllegalArgumentException("Invalid locations provided!");
|
if(l1.getX() > l2.getX() || l1.getY() > l2.getY() || l1.getZ() > l2.getZ()) throw new IllegalArgumentException("Invalid locations provided!");
|
||||||
@ -39,13 +48,32 @@ public class GaeaStructure implements Serializable {
|
|||||||
for(int x = 0; x <= l2.getBlockX()-l1.getBlockX(); x++) {
|
for(int x = 0; x <= l2.getBlockX()-l1.getBlockX(); x++) {
|
||||||
for(int y = 0; y <= l2.getBlockY()-l1.getBlockY(); y++) {
|
for(int y = 0; y <= l2.getBlockY()-l1.getBlockY(); y++) {
|
||||||
for(int z = 0; z <= l2.getBlockZ()-l1.getBlockZ(); z++) {
|
for(int z = 0; z <= l2.getBlockZ()-l1.getBlockZ(); z++) {
|
||||||
structure[x][y][z] = new StructureContainedBlock(x, y, z, Objects.requireNonNull(l1.getWorld()).getBlockAt(l1.clone().add(x, y, z)));
|
Block b = Objects.requireNonNull(l1.getWorld()).getBlockAt(l1.clone().add(x, y, z));
|
||||||
|
BlockData d = b.getBlockData();
|
||||||
|
if(d instanceof Sign) {
|
||||||
|
Sign s = (Sign) b.getState();
|
||||||
|
if(s.getLine(0).equals("[TERRA]")) {
|
||||||
|
d = Bukkit.createBlockData(s.getLine(2)+s.getLine(3));
|
||||||
|
if(s.getLine(1).equals("[CENTER]")) {
|
||||||
|
centerX = x;
|
||||||
|
centerZ = z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
structure[x][y][z] = new StructureContainedBlock(x, y, z, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(centerX == -1 || centerZ == -1) throw new InitializationException("No structure center specified.");
|
||||||
|
structureInfo = new GaeaStructureInfo(l2.getBlockX()-l1.getBlockX(), l2.getBlockY()-l1.getBlockY(), l2.getBlockZ()-l1.getBlockZ(), centerX, centerZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void paste(Location origin) {
|
@NotNull
|
||||||
|
public GaeaStructureInfo getStructureInfo() {
|
||||||
|
return structureInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paste(@NotNull Location origin) {
|
||||||
for(StructureContainedBlock[][] bList2 : structure) {
|
for(StructureContainedBlock[][] bList2 : structure) {
|
||||||
for(StructureContainedBlock[] bList1 : bList2) {
|
for(StructureContainedBlock[] bList1 : bList2) {
|
||||||
for(StructureContainedBlock block : bList1) {
|
for(StructureContainedBlock block : bList1) {
|
||||||
@ -57,46 +85,54 @@ public class GaeaStructure implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void paste(Location origin, Chunk c) {
|
private StructureContainedBlock[][][] executeForBlocksInRange(MaxMin xM, MaxMin yM, MaxMin zM, Consumer<StructureContainedBlock> exec) {
|
||||||
for(StructureContainedBlock[][] bList2 : structure) {
|
StructureContainedBlock[][][] temp = new StructureContainedBlock[xM.getMax()-xM.getMin()+1][yM.getMax()-yM.getMin()+1][zM.getMax()-zM.getMin()+1];
|
||||||
for(StructureContainedBlock[] bList1 : bList2) {
|
for(int x : xM) {
|
||||||
for(StructureContainedBlock block : bList1) {
|
for(int y : yM) {
|
||||||
Location newLoc = origin.clone().add(block.getX(), block.getY(), block.getZ());
|
for(int z : zM) {
|
||||||
BlockData data = block.getBlockData();
|
if(isInStructure(x, y, z)) exec.accept(structure[x][y][z]);
|
||||||
if(newLoc.getChunk().equals(c) && !data.getMaterial().equals(Material.STRUCTURE_VOID)) newLoc.getBlock().setBlockData(block.getBlockData());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(File f) throws IOException {
|
private boolean isInStructure(int x, int y, int z) {
|
||||||
|
return x < structure.length && y < structure[0].length && z < structure[0][0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(@NotNull File f) throws IOException {
|
||||||
toFile(this, f);
|
toFile(this, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GaeaStructure fromFile(File f) throws IOException, ClassNotFoundException {
|
@NotNull
|
||||||
|
private static GaeaStructure fromFile(@NotNull File f) throws IOException, ClassNotFoundException {
|
||||||
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
|
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
|
||||||
Object o = ois.readObject();
|
Object o = ois.readObject();
|
||||||
ois.close();
|
ois.close();
|
||||||
return (GaeaStructure) o;
|
return (GaeaStructure) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GaeaStructure fromStream(InputStream f) throws IOException, ClassNotFoundException {
|
@NotNull
|
||||||
|
public static GaeaStructure fromStream(@NotNull InputStream f) throws IOException, ClassNotFoundException {
|
||||||
ObjectInputStream ois = new ObjectInputStream(f);
|
ObjectInputStream ois = new ObjectInputStream(f);
|
||||||
Object o = ois.readObject();
|
Object o = ois.readObject();
|
||||||
ois.close();
|
ois.close();
|
||||||
return (GaeaStructure) o;
|
return (GaeaStructure) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void toFile(Serializable o, File f) throws IOException {
|
private static void toFile(@NotNull Serializable o, @NotNull File f) throws IOException {
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
||||||
oos.writeObject(o);
|
oos.writeObject(o);
|
||||||
oos.close();
|
oos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.dfsek.terra.structure;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class GaeaStructureInfo implements Serializable {
|
||||||
|
public static final long serialVersionUID = -175639605885943678L;
|
||||||
|
private final int sizeX;
|
||||||
|
private final int sizeY;
|
||||||
|
private final int sizeZ;
|
||||||
|
private final int centerX;
|
||||||
|
private final int centerZ;
|
||||||
|
public GaeaStructureInfo(int sizeX, int sizeY, int sizeZ, int centerX, int centerZ) {
|
||||||
|
this.sizeX = sizeX;
|
||||||
|
this.sizeY = sizeY;
|
||||||
|
this.sizeZ = sizeZ;
|
||||||
|
this.centerX = centerX;
|
||||||
|
this.centerZ = centerZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeX() {
|
||||||
|
return sizeX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeZ() {
|
||||||
|
return sizeZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeY() {
|
||||||
|
return sizeY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCenterX() {
|
||||||
|
return centerX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCenterZ() {
|
||||||
|
return centerZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMaxHorizontal() {
|
||||||
|
return Math.sqrt(Math.pow(sizeX, 2) + Math.pow(sizeZ, 2));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.dfsek.terra.structure;
|
||||||
|
|
||||||
|
public class InitializationException extends Exception {
|
||||||
|
public InitializationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import org.bukkit.Bukkit;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.block.BlockDamageEvent;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@ -14,11 +15,11 @@ public class StructureContainedBlock implements Serializable {
|
|||||||
private final int x;
|
private final int x;
|
||||||
private final int y;
|
private final int y;
|
||||||
private final int z;
|
private final int z;
|
||||||
public StructureContainedBlock(int x, int y, int z, Block block) {
|
public StructureContainedBlock(int x, int y, int z, BlockData block) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.bl = block.getBlockData();
|
this.bl = block;
|
||||||
dataString = bl.getAsString(false);
|
dataString = bl.getAsString(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package com.dfsek.terra.structure;
|
|
||||||
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class StructureManager {
|
|
||||||
private static StructureManager singleton;
|
|
||||||
private Logger logger;
|
|
||||||
private final Map<UUID, GaeaStructure> structures = new HashMap<>();
|
|
||||||
public StructureManager(JavaPlugin main) {
|
|
||||||
if(singleton!= null) throw new IllegalStateException("Only one instance of StructureManager may exist at a given time.");
|
|
||||||
this.logger = main.getLogger();
|
|
||||||
logger.info("Initializing StructureManager...");
|
|
||||||
singleton = this;
|
|
||||||
}
|
|
||||||
public GaeaStructure get(UUID uuid) {
|
|
||||||
return structures.get(uuid);
|
|
||||||
}
|
|
||||||
public void load(File file) throws IOException {
|
|
||||||
GaeaStructure s = GaeaStructure.load(file);
|
|
||||||
structures.put(s.getUuid(), s);
|
|
||||||
}
|
|
||||||
}
|
|
17
src/test/java/MaxMinTest.java
Normal file
17
src/test/java/MaxMinTest.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import com.dfsek.terra.MaxMin;
|
||||||
|
import org.jetbrains.annotations.TestOnly;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class MaxMinTest {
|
||||||
|
@Test
|
||||||
|
public void iterator() {
|
||||||
|
MaxMin m = new MaxMin(0, 100);
|
||||||
|
int i = 0;
|
||||||
|
for(int mint : m) {
|
||||||
|
assertEquals(i, mint);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
assertEquals(100, i);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user