From 5db149434190f809030942ad943becc9a479ea5d Mon Sep 17 00:00:00 2001 From: dfsek Date: Fri, 25 Dec 2020 20:43:41 -0700 Subject: [PATCH] implement script structures with chunkification(tm) --- .../structures/script/StructureScript.java | 8 +++++ .../structure/buffer/StructureBuffer.java | 9 +++++ .../terra/population/StructurePopulator.java | 12 +++---- .../structure/load/LoadFullCommand.java | 36 +++++++++---------- .../structure/load/LoadRawCommand.java | 7 ++-- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java index d090cba7c..acf7b147d 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -2,6 +2,7 @@ package com.dfsek.terra.api.structures.script; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.structures.parser.Parser; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Block; @@ -65,6 +66,13 @@ public class StructureScript { return !level.equals(Block.ReturnLevel.FAIL); } + public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) { + StructureBuffer buffer = new StructureBuffer(location); + Block.ReturnLevel level = block.apply(buffer, rotation, random, 0); + buffer.paste(chunk); + return !level.equals(Block.ReturnLevel.FAIL); + } + public void executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) { block.apply(buffer, rotation, random, recursions); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java index e2e527a1f..3d6ef9494 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java @@ -2,8 +2,10 @@ package com.dfsek.terra.api.structures.structure.buffer; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; import com.dfsek.terra.api.structures.structure.buffer.items.Mark; +import net.jafama.FastMath; import java.util.HashMap; import java.util.Map; @@ -17,7 +19,14 @@ public class StructureBuffer implements Buffer { } public void paste() { + bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3)))); + } + + public void paste(Chunk chunk) { bufferedItemMap.forEach(((vector3, item) -> { + Location current = origin.clone().add(vector3); + if(FastMath.floorDiv(current.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(current.getBlockZ(), 16) != chunk.getZ()) + return; item.paste(origin.clone().add(vector3)); })); } diff --git a/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java b/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java index f99c6bcc5..68c397f69 100644 --- a/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java +++ b/common/src/main/java/com/dfsek/terra/population/StructurePopulator.java @@ -1,19 +1,19 @@ package com.dfsek.terra.population; import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.profiler.ProfileFuture; import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.master.TerraBiomeGrid; import com.dfsek.terra.config.base.ConfigPack; -import com.dfsek.terra.debug.Debug; import com.dfsek.terra.generation.items.TerraStructure; -import com.dfsek.terra.util.PopulationUtil; import net.jafama.FastMath; import org.jetbrains.annotations.NotNull; @@ -31,7 +31,6 @@ public class StructurePopulator implements TerraBlockPopulator { public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) { TerraWorld tw = main.getWorld(world); try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) { - Random random = PopulationUtil.getRandom(chunk); int cx = (chunk.getX() << 4); int cz = (chunk.getZ() << 4); if(!tw.isSafe()) return; @@ -40,13 +39,10 @@ public class StructurePopulator implements TerraBlockPopulator { for(TerraStructure conf : config.getStructures()) { Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); - if(!(FastMath.floorDiv(spawn.getBlockX(), 16) == chunk.getX()) || !(FastMath.floorDiv(spawn.getBlockZ(), 16) == chunk.getZ())) - continue; - if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(conf)) continue; - Debug.info("Generating structure at (" + spawn.getBlockX() + ", " + spawn.getBlockY() + ", " + spawn.getBlockZ() + ")"); - conf.getStructure().execute(spawn.setY(conf.getSpawnStart().get(random)), random, Rotation.fromDegrees(90 * random.nextInt(4))); + Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed())); + conf.getStructure().execute(spawn.setY(conf.getSpawnStart().get(random)), chunk, random, Rotation.fromDegrees(90 * random.nextInt(4))); } } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java index 9c41388d1..b16ba77f9 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadFullCommand.java @@ -1,6 +1,13 @@ package com.dfsek.terra.bukkit.command.command.structure.load; +import com.dfsek.terra.TerraWorld; +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.bukkit.BukkitChunk; +import com.dfsek.terra.bukkit.BukkitWorld; import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.util.PopulationUtil; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -21,25 +28,18 @@ public class LoadFullCommand extends LoadCommand implements DebugCommand { @Override public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - /* - try { - Rotation r; - try { - r = Rotation.fromDegrees(Integer.parseInt(args[1])); - } catch(NumberFormatException e) { - LangUtil.send("command.structure.invalid-rotation", sender, args[1]); - return true; - } - Structure struc = Structure.load(new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure")); - if(chunk) struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r, (TerraBukkitPlugin) getMain()); - else struc.paste(sender.getLocation(), r, (TerraBukkitPlugin) getMain()); - //sender.sendMessage(String.valueOf(struc.checkSpawns(sender.getLocation(), r))); - } catch(IOException e) { - e.printStackTrace(); - LangUtil.send("command.structure.invalid", sender, args[0]); - } + TerraWorld terraWorld = getMain().getWorld(new BukkitWorld(sender.getWorld())); + long t = System.nanoTime(); + FastRandom chunk = PopulationUtil.getRandom(new BukkitChunk(sender.getLocation().getChunk())); - */ + if(this.chunk) { + terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(new Location(new BukkitWorld(sender.getWorld()), sender.getLocation().getX(), sender.getLocation().getY(), sender.getLocation().getZ()), new BukkitChunk(sender.getLocation().getChunk()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); + } else { + terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(new Location(new BukkitWorld(sender.getWorld()), sender.getLocation().getX(), sender.getLocation().getY(), sender.getLocation().getZ()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); + } + long l = System.nanoTime() - t; + + sender.sendMessage("Took " + ((double) l) / 1000000 + "ms"); return true; } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java index 43964e9f4..aadd39e12 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/structure/load/LoadRawCommand.java @@ -4,8 +4,10 @@ import com.dfsek.terra.TerraWorld; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.bukkit.BukkitChunk; import com.dfsek.terra.bukkit.BukkitWorld; import com.dfsek.terra.bukkit.command.DebugCommand; +import com.dfsek.terra.util.PopulationUtil; import org.bukkit.block.Sign; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -14,7 +16,6 @@ import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; -import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; public class LoadRawCommand extends LoadCommand implements DebugCommand { @@ -37,7 +38,9 @@ public class LoadRawCommand extends LoadCommand implements DebugCommand { TerraWorld terraWorld = getMain().getWorld(new BukkitWorld(sender.getWorld())); long t = System.nanoTime(); - terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(new Location(new BukkitWorld(sender.getWorld()), sender.getLocation().getX(), sender.getLocation().getY(), sender.getLocation().getZ()), new FastRandom(), Rotation.fromDegrees(90 * ThreadLocalRandom.current().nextInt(4))); + FastRandom chunk = PopulationUtil.getRandom(new BukkitChunk(sender.getLocation().getChunk())); + + terraWorld.getConfig().getScriptRegistry().get(args[0]).execute(new Location(new BukkitWorld(sender.getWorld()), sender.getLocation().getX(), sender.getLocation().getY(), sender.getLocation().getZ()), chunk, Rotation.fromDegrees(90 * chunk.nextInt(4))); long l = System.nanoTime() - t; sender.sendMessage("Took " + ((double) l) / 1000000 + "ms");