Implement chunk serialization

This commit is contained in:
dfsek 2020-09-26 01:17:46 -07:00
parent f727e9d297
commit c8e564c2d3
19 changed files with 166 additions and 36 deletions

View File

@ -95,13 +95,7 @@
<dependency> <dependency>
<groupId>org.polydev</groupId> <groupId>org.polydev</groupId>
<artifactId>gaea</artifactId> <artifactId>gaea</artifactId>
<version>1.10.17</version> <version>1.10.42</version>
</dependency>
<dependency>
<groupId>javax.vecmath</groupId>
<artifactId>vecmath</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>me.lucko</groupId> <groupId>me.lucko</groupId>

View File

@ -2,10 +2,13 @@ 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.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;
@ -15,10 +18,13 @@ 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;
@ -26,13 +32,13 @@ public class Terra extends JavaPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
super.onDisable(); TerraChunkGenerator.saveAll();
} }
@Override @Override
public void onEnable() { public void onEnable() {
ConfigUtil.loadConfig(this); ConfigUtil.loadConfig(this);
//getCommand("terra").setExecutor(new TerraCommand()); manager = new StructureManager(this);
PluginCommand command = getCommand("terra"); PluginCommand command = getCommand("terra");
command.setExecutor(new TerraCommand()); command.setExecutor(new TerraCommand());
@ -46,6 +52,7 @@ public class Terra extends JavaPlugin {
} else getLogger().severe("Brigadier is not properly supported! Commands will NOT work properly!"); } else getLogger().severe("Brigadier is not properly supported! Commands will NOT work properly!");
saveDefaultConfig(); saveDefaultConfig();
config = getConfig(); config = getConfig();
Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, TerraChunkGenerator::saveAll, ConfigUtil.dataSave, ConfigUtil.dataSave);
instance = this; instance = this;
} }
@ -60,6 +67,10 @@ 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();

View File

@ -16,6 +16,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -30,6 +31,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Random; import java.util.Random;
public class TerraCommand implements CommandExecutor, TabExecutor { public class TerraCommand implements CommandExecutor, TabExecutor {
@ -123,6 +125,10 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
} }
} }
break; break;
case "save-data":
TerraChunkGenerator.saveAll();
sender.sendMessage("Saved population data.");
return true;
case "structure": case "structure":
if(! (sender instanceof Player)) { if(! (sender instanceof Player)) {
sender.sendMessage("Command is for players only."); sender.sendMessage("Command is for players only.");
@ -152,13 +158,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); GaeaStructure structure = new GaeaStructure(l1, l2, args[2]);
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();
file.createNewFile(); file.createNewFile();
structure.save(file); structure.save(file);
sender.sendMessage("Saved to " + file.getPath()); sender.sendMessage("Saved structure with ID " + structure.getId() + ", UUID: " + structure.getUuid().toString() + " to " + file.getPath());
} catch(IOException e) { } catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -174,7 +180,7 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
} }
return true; return true;
} else if("getspawn".equals(args[1])) { } else if("getspawn".equals(args[1])) {
Vector v = new StructureSpawn(50, 25).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed()); Vector v = new StructureSpawn(500, 100).getNearestSpawn(pl.getLocation().getBlockX(), pl.getLocation().getBlockZ(), pl.getWorld().getSeed());
sender.sendMessage(v.getBlockX() + ":" + v.getBlockZ()); sender.sendMessage(v.getBlockX() + ":" + v.getBlockZ());
} }
} }

View File

@ -1,5 +1,7 @@
package com.dfsek.terra.biome; package com.dfsek.terra.biome;
import com.dfsek.terra.generation.UserDefinedDecorator;
import com.dfsek.terra.generation.UserDefinedGenerator;
import org.polydev.gaea.biome.Biome; import org.polydev.gaea.biome.Biome;
import org.polydev.gaea.biome.Generator; import org.polydev.gaea.biome.Generator;
import org.polydev.gaea.biome.Decorator; import org.polydev.gaea.biome.Decorator;

View File

@ -13,17 +13,21 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.File; import java.io.File;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ConfigUtil { public class ConfigUtil {
public static boolean debug; public static boolean debug;
public static long dataSave;
public static void loadConfig(JavaPlugin main) { public static void loadConfig(JavaPlugin main) {
main.saveDefaultConfig(); main.saveDefaultConfig();
FileConfiguration config = main.getConfig(); FileConfiguration config = main.getConfig();
debug = config.getBoolean("debug", false); debug = config.getBoolean("debug", false);
dataSave = Duration.parse(Objects.requireNonNull(config.getString("data-save", "PT6M"))).toMillis()/20L;
Logger logger = main.getLogger(); Logger logger = main.getLogger();
logger.info("Loading config values"); logger.info("Loading config values");

View File

@ -3,8 +3,8 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin; import com.dfsek.terra.MaxMin;
import com.dfsek.terra.TerraTree; import com.dfsek.terra.TerraTree;
import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedDecorator; import com.dfsek.terra.generation.UserDefinedDecorator;
import com.dfsek.terra.biome.UserDefinedGenerator; import com.dfsek.terra.generation.UserDefinedGenerator;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigUtil; import com.dfsek.terra.config.ConfigUtil;
import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.config.TerraConfigObject;

View File

@ -2,14 +2,11 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin; import com.dfsek.terra.MaxMin;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.ConfigLoader;
import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.config.TerraConfigObject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.polydev.gaea.math.ProbabilityCollection; import org.polydev.gaea.math.ProbabilityCollection;
import java.io.File; import java.io.File;
@ -123,6 +120,8 @@ public class CarverConfig extends TerraConfigObject {
replaceIsBlacklistInner = getBoolean("palette.inner.replace-blacklist", false); replaceIsBlacklistInner = getBoolean("palette.inner.replace-blacklist", false);
replaceIsBlacklistOuter = getBoolean("palette.outer.replace-blacklist", false); replaceIsBlacklistOuter = getBoolean("palette.outer.replace-blacklist", false);
replaceIsBlacklistTop = getBoolean("palette.top.replace-blacklist", false);
replaceIsBlacklistBottom = getBoolean("palette.bottom.replace-blacklist", false);
double[] start = new double[] {getDouble("start.x"), getDouble("start.y"), getDouble("start.z")}; double[] start = new double[] {getDouble("start.x"), getDouble("start.y"), getDouble("start.z")};
double[] mutate = new double[] {getDouble("mutate.x"), getDouble("mutate.y"), getDouble("mutate.z"), getDouble("mutate.radius")}; double[] mutate = new double[] {getDouble("mutate.x"), getDouble("mutate.y"), getDouble("mutate.z"), getDouble("mutate.radius")};

View File

@ -5,6 +5,7 @@ import com.dfsek.terra.config.WorldConfig;
import com.dfsek.terra.population.CavePopulator; import com.dfsek.terra.population.CavePopulator;
import com.dfsek.terra.population.FloraPopulator; import com.dfsek.terra.population.FloraPopulator;
import com.dfsek.terra.population.OrePopulator; import com.dfsek.terra.population.OrePopulator;
import com.dfsek.terra.population.StructurePopulator;
import com.dfsek.terra.population.TreePopulator; import com.dfsek.terra.population.TreePopulator;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
@ -18,17 +19,25 @@ import org.polydev.gaea.math.ChunkInterpolator;
import org.polydev.gaea.math.FastNoise; import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.population.PopulationManager; import org.polydev.gaea.population.PopulationManager;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Random; import java.util.Random;
public class TerraChunkGenerator extends GaeaChunkGenerator { public class TerraChunkGenerator extends GaeaChunkGenerator {
private static final BlockData STONE = Material.STONE.createBlockData(); private static final BlockData STONE = Material.STONE.createBlockData();
private static final BlockData WATER = Material.WATER.createBlockData(); private static final BlockData WATER = Material.WATER.createBlockData();
private final PopulationManager popMan = new PopulationManager(); private final PopulationManager popMan = new PopulationManager();
private boolean needsLoad = true;
private static final Map<World, PopulationManager> popMap = new HashMap<>();
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());
@ -36,6 +45,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
@Override @Override
public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, FastNoise fastNoise) { public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, FastNoise fastNoise) {
if(needsLoad) load(world);
ChunkData chunk = createChunkData(world); ChunkData chunk = createChunkData(world);
int sea = WorldConfig.fromWorld(world).seaLevel; int sea = WorldConfig.fromWorld(world).seaLevel;
for(byte x = 0; x < 16; x++) { for(byte x = 0; x < 16; x++) {
@ -49,6 +59,31 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
return chunk; return chunk;
} }
private void load(World w) {
try {
popMan.loadBlocks(w);
} catch(IOException e) {
if(e instanceof FileNotFoundException) {
Bukkit.getLogger().warning("[Terra] No population chunks were loaded. If this is your first time starting your server with Terra, or if you are creating a new world, this is normal.");
} else e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
popMap.put(w, popMan);
needsLoad = false;
}
public static void saveAll() {
for(Map.Entry<World, PopulationManager> e : popMap.entrySet()) {
try {
e.getValue().saveBlocks(e.getKey());
Bukkit.getLogger().info("[Terra] Saved data for world " + e.getKey().getName());
} catch(IOException ioException) {
ioException.printStackTrace();
}
}
}
@Override @Override
public int getNoiseOctaves(World world) { public int getNoiseOctaves(World world) {
return 4; return 4;

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.biome; package com.dfsek.terra.generation;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.polydev.gaea.biome.Decorator; import org.polydev.gaea.biome.Decorator;

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.biome; package com.dfsek.terra.generation;
import com.dfsek.terra.math.NoiseFunction2; import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3; import com.dfsek.terra.math.NoiseFunction3;

View File

@ -21,6 +21,7 @@ import java.util.Random;
import java.util.Set; 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.
@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"); ProfileFuture cave = TerraProfiler.fromWorld(world).measure("CaveTime");
@ -34,16 +35,16 @@ public class CavePopulator extends BlockPopulator {
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), false); 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), false); 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), false); 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), false); 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);
@ -58,7 +59,7 @@ public class CavePopulator extends BlockPopulator {
while(mut.getBlock().getType().equals(orig)); while(mut.getBlock().getType().equals(orig));
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().setType(shiftCandidate.get(l)); mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
j++; j++;
} }
} catch(NullPointerException ignored) {} } catch(NullPointerException ignored) {}

View File

@ -4,6 +4,7 @@ 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;
import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -13,11 +14,16 @@ import org.polydev.gaea.population.GaeaBlockPopulator;
import org.polydev.gaea.profiler.ProfileFuture; import org.polydev.gaea.profiler.ProfileFuture;
import org.polydev.gaea.world.Flora; import org.polydev.gaea.world.Flora;
import java.util.HashSet;
import java.util.Random; import java.util.Random;
import java.util.Set;
public class FloraPopulator extends GaeaBlockPopulator { public class FloraPopulator extends GaeaBlockPopulator {
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) {
if(pop.contains(chunk)) Bukkit.getLogger().warning("Already populated flora in chunk: " + chunk);
pop.add(chunk);
ProfileFuture flora = TerraProfiler.fromWorld(world).measure("FloraTime"); 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++) {

View File

@ -0,0 +1,38 @@
package com.dfsek.terra.population;
import com.dfsek.terra.Terra;
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.jetbrains.annotations.NotNull;
import org.polydev.gaea.population.GaeaBlockPopulator;
import java.io.File;
import java.io.IOException;
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<>();
@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();
}
}
}
}

View File

@ -3,7 +3,7 @@ package com.dfsek.terra.population;
import com.dfsek.terra.Terra; import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid; import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedDecorator; import com.dfsek.terra.generation.UserDefinedDecorator;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;

View File

@ -15,10 +15,13 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import java.util.UUID;
public class GaeaStructure implements Serializable { public class GaeaStructure implements Serializable {
public static final long serialVersionUID = -6664585217063842034L; public static final long serialVersionUID = -6664585217063842035L;
private final StructureContainedBlock[][][] structure; private final StructureContainedBlock[][][] structure;
private final String id;
private final UUID uuid;
public static GaeaStructure load(File f) throws IOException { public static GaeaStructure load(File f) throws IOException {
try { try {
@ -28,7 +31,9 @@ public class GaeaStructure implements Serializable {
} }
} }
public GaeaStructure(Location l1, Location l2) { public GaeaStructure(Location l1, Location l2, String id) {
this.id = id;
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!");
structure = new StructureContainedBlock[l2.getBlockX()-l1.getBlockX()+1][l2.getBlockY()-l1.getBlockY()+1][l2.getBlockZ()-l1.getBlockZ()+1]; structure = new StructureContainedBlock[l2.getBlockX()-l1.getBlockX()+1][l2.getBlockY()-l1.getBlockY()+1][l2.getBlockZ()-l1.getBlockZ()+1];
for(int x = 0; x <= l2.getBlockX()-l1.getBlockX(); x++) { for(int x = 0; x <= l2.getBlockX()-l1.getBlockX(); x++) {
@ -87,4 +92,12 @@ public class GaeaStructure implements Serializable {
oos.writeObject(o); oos.writeObject(o);
oos.close(); oos.close();
} }
public String getId() {
return id;
}
public UUID getUuid() {
return uuid;
}
} }

View File

@ -0,0 +1,29 @@
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);
}
}

View File

@ -33,13 +33,11 @@ public class StructureSpawn {
return shortest; return shortest;
} }
private Vector getStructureChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { private Vector getStructureChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
if(ConfigUtil.debug) Bukkit.getLogger().info("Structure chunk: " + structureChunkX + ":" + structureChunkZ);
Random r = new Random(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed)); Random r = new Random(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed));
int offsetX = r.nextInt(width); int offsetX = r.nextInt(width);
int offsetZ = r.nextInt(width); int offsetZ = r.nextInt(width);
int sx = structureChunkX * (width + 2*separation) + offsetX; int sx = structureChunkX * (width + 2*separation) + offsetX;
int sz = structureChunkZ * (width + 2*separation) + offsetZ; int sz = structureChunkZ * (width + 2*separation) + offsetZ;
if(ConfigUtil.debug) Bukkit.getLogger().info("Structure coords: " + sx + ":" + sz);
return new Vector(sx, 0, sz); return new Vector(sx, 0, sz);
} }
} }

View File

@ -35,4 +35,5 @@ terra {
} }
getspawn; getspawn;
} }
save-data;
} }

File diff suppressed because one or more lines are too long