diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index 21e19e33e..0cb058215 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -419,14 +419,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { if (createCopy) { copy.storeBiomes(currentBiomes); } - for (int z = 0, i = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, i++) { - final BiomeType biome = biomes[i]; - if (biome != null) { - final Biome craftBiome = BukkitAdapter.adapt(biome); - BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(craftBiome); - for (int y = 0; y < FaweCache.IMP.WORLD_HEIGHT; y++) { - currentBiomes.setBiome(x >> 2, y >> 2, z >> 2, nmsBiome); + for (int y = 0, i = 0; y < 64; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, i++) { + final BiomeType biome = biomes[i]; + if (biome != null) { + final Biome craftBiome = BukkitAdapter.adapt(biome); + BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(craftBiome); + currentBiomes.setBiome(x, y, z, nmsBiome); } } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index a4d4c1227..a2538a143 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -421,14 +421,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { if (createCopy) { copy.storeBiomes(currentBiomes); } - for (int z = 0, i = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, i++) { - final BiomeType biome = biomes[i]; - if (biome != null) { - final Biome craftBiome = BukkitAdapter.adapt(biome); - BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(craftBiome); - for (int y = 0; y < FaweCache.IMP.WORLD_HEIGHT; y++) { - currentBiomes.setBiome(x >> 2, y >> 2, z >> 2, nmsBiome); + for (int y = 0, i = 0; y < 64; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, i++) { + final BiomeType biome = biomes[i]; + if (biome != null) { + final Biome craftBiome = BukkitAdapter.adapt(biome); + BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(craftBiome); + currentBiomes.setBiome(x, y, z, nmsBiome); } } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java index e61453ddf..e19038d48 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java @@ -59,6 +59,7 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import java.util.AbstractSet; import java.util.Arrays; import java.util.Collection; @@ -72,7 +73,6 @@ import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.function.Function; -import javax.annotation.Nullable; import static org.slf4j.LoggerFactory.getLogger; @@ -424,14 +424,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks { if (createCopy) { copy.storeBiomes(currentBiomes); } - for (int z = 0, i = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, i++) { - final BiomeType biome = biomes[i]; - if (biome != null) { - final Biome craftBiome = BukkitAdapter.adapt(biome); - BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(nmsWorld.r().b(IRegistry.ay), craftBiome); - for (int y = 0; y < FaweCache.IMP.WORLD_HEIGHT; y++) { - currentBiomes.setBiome(x >> 2, y >> 2, z >> 2, nmsBiome); + for (int y = 0, i = 0; y < 64; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, i++) { + final BiomeType biome = biomes[i]; + if (biome != null) { + final Biome craftBiome = BukkitAdapter.adapt(biome); + BiomeBase nmsBiome = CraftBlock.biomeToBiomeBase(nmsWorld.r().b(IRegistry.ay), craftBiome); + currentBiomes.setBiome(x, y, z, nmsBiome); } } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index e59bc0ae3..89aa3ad69 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -67,6 +67,7 @@ import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BukkitPlayer extends AbstractPlayerActor { @@ -74,19 +75,29 @@ public class BukkitPlayer extends AbstractPlayerActor { private final Player player; private final WorldEditPlugin plugin; private final PermissionAttachment permAttachment; - - public BukkitPlayer(Player player) { - super(getExistingMap(WorldEditPlugin.getInstance(), player)); + /** + * This constructs a new {@link BukkitPlayer} for the given {@link Player}. + * + * @param player The corresponding {@link Player} or null if you need a null WorldEdit player for some reason. + */ + public BukkitPlayer(@Nullable Player player) { + super(player != null ? getExistingMap(WorldEditPlugin.getInstance(), player) : new ConcurrentHashMap<>()); this.plugin = WorldEditPlugin.getInstance(); this.player = player; this.permAttachment = plugin.getPermissionAttachmentManager().getOrAddAttachment(player); } - public BukkitPlayer(WorldEditPlugin plugin, Player player) { + /** + * This constructs a new {@link BukkitPlayer} for the given {@link Player}. + * + * @param plugin The running instance of {@link WorldEditPlugin} + * @param player The corresponding {@link Player} or null if you need a null WorldEdit player for some reason. + */ + public BukkitPlayer(@Nonnull WorldEditPlugin plugin, @Nullable Player player) { this.plugin = plugin; this.player = player; this.permAttachment = plugin.getPermissionAttachmentManager().getOrAddAttachment(player); - if (Settings.IMP.CLIPBOARD.USE_DISK) { + if (player != null && Settings.IMP.CLIPBOARD.USE_DISK) { loadClipboardFromDisk(); } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Regenerator.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Regenerator.java index cbf099142..4bf5f1a7f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Regenerator.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/Regenerator.java @@ -11,6 +11,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.RegenOptions; +import com.sk89q.worldedit.world.biome.BiomeType; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -266,9 +267,13 @@ public abstract class Regenerator factory = (AreaFactory) initAreaFactoryMethod.invoke(null, biomeconfig.b(), biomeconfig.c(), (LongFunction) (l -> new FastWorldGenContextArea(seed, l))); - genLayerField.set(chunkManager, new FastGenLayer(factory)); + if (options.hasBiomeType()) { + BiomeBase biome = IRegistry.BIOME.get(MinecraftKey.a(options.getBiomeType().getId())); + chunkManager = new SingleBiomeWorldChunkManagerOverworld(biome); + } else { + chunkManager = new WorldChunkManagerOverworld(biomeconfig); + //replace genlayer + genLayerField.set(chunkManager, new FastGenLayer(factory)); + } return chunkManager; } + private static class SingleBiomeWorldChunkManagerOverworld extends WorldChunkManager { + + private final BiomeBase biome; + + public SingleBiomeWorldChunkManagerOverworld(BiomeBase biome) { + super(ImmutableSet.of(biome)); + this.biome = biome; + } + + @Override + public BiomeBase getBiome(int i, int i1, int i2) { + return biome; + } + } + private static class FastWorldGenContextArea implements AreaContextTransformed { private final ConcurrentHashMap sharedAreaMap = new ConcurrentHashMap<>(); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R1.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R1.java index af66ef955..7ac07b920 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R1.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R1.java @@ -6,6 +6,7 @@ import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitGetBlocks_1_16_1; import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; import com.mojang.serialization.Dynamic; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.bukkit.adapter.Regenerator; @@ -17,6 +18,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Path; +import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -53,15 +55,14 @@ import net.minecraft.server.v1_16_R1.GeneratorSettings; import net.minecraft.server.v1_16_R1.GeneratorSettingsFlat; import net.minecraft.server.v1_16_R1.IChunkAccess; import net.minecraft.server.v1_16_R1.IRegistry; -import net.minecraft.server.v1_16_R1.IRegistryCustom; import net.minecraft.server.v1_16_R1.LightEngineThreaded; import net.minecraft.server.v1_16_R1.LinearCongruentialGenerator; +import net.minecraft.server.v1_16_R1.MinecraftKey; import net.minecraft.server.v1_16_R1.MinecraftServer; import net.minecraft.server.v1_16_R1.NBTBase; import net.minecraft.server.v1_16_R1.NBTTagCompound; import net.minecraft.server.v1_16_R1.NoiseGeneratorPerlin; import net.minecraft.server.v1_16_R1.ProtoChunk; -import net.minecraft.server.v1_16_R1.RegistryReadOps; import net.minecraft.server.v1_16_R1.ResourceKey; import net.minecraft.server.v1_16_R1.World; import net.minecraft.server.v1_16_R1.WorldChunkManager; @@ -201,6 +202,16 @@ public class Regen_v1_16_R1 extends Regenerator factory = (AreaFactory) initAreaFactoryMethod.invoke(null, legacyBiomeInitLayer, largebiomes ? 6 : 4, 4, (LongFunction) (l -> new FastWorldGenContextArea(seed, l))); - genLayerField.set(chunkManager, new FastGenLayer(factory)); + AreaFactory factory = (AreaFactory) initAreaFactoryMethod.invoke(null, legacyBiomeInitLayer, largeBiomes ? 6 : 4, 4, (LongFunction) (l -> new FastWorldGenContextArea(seed, l))); + if (options.hasBiomeType()) { + BiomeBase biome = IRegistry.BIOME.get(MinecraftKey.a(options.getBiomeType().getId())); + chunkManager = new SingleBiomeWorldChunkManagerOverworld(biome); + } else { + chunkManager = new WorldChunkManagerOverworld(seed, legacyBiomeInitLayer, largeBiomes); + //replace genLayer + genLayerField.set(chunkManager, new FastGenLayer(factory)); + } return chunkManager; } + private static class SingleBiomeWorldChunkManagerOverworld extends WorldChunkManager { + + private final BiomeBase biome; + + public SingleBiomeWorldChunkManagerOverworld(BiomeBase biome) { + super(Arrays.asList(biome)); + this.biome = biome; + } + + @Override + protected Codec a() { + return WorldChunkManagerOverworld.e; + } + + @Override + public BiomeBase getBiome(int i, int i1, int i2) { + return biome; + } + } + private static class FastWorldGenContextArea implements AreaContextTransformed { private final ConcurrentHashMap sharedAreaMap = new ConcurrentHashMap<>(); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R2.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R2.java index af58d56cf..9bbee25ed 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R2.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R2.java @@ -6,6 +6,7 @@ import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.bukkit.adapter.mc1_16_2.BukkitGetBlocks_1_16_2; import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; import com.mojang.serialization.Dynamic; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.bukkit.adapter.Regenerator; @@ -28,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; import java.util.function.LongFunction; import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.annotation.Nullable; import net.minecraft.server.v1_16_R2.Area; import net.minecraft.server.v1_16_R2.AreaContextTransformed; @@ -56,11 +58,14 @@ import net.minecraft.server.v1_16_R2.IRegistry; import net.minecraft.server.v1_16_R2.IRegistryCustom; import net.minecraft.server.v1_16_R2.LightEngineThreaded; import net.minecraft.server.v1_16_R2.LinearCongruentialGenerator; +import net.minecraft.server.v1_16_R2.MinecraftKey; import net.minecraft.server.v1_16_R2.MinecraftServer; import net.minecraft.server.v1_16_R2.NBTBase; import net.minecraft.server.v1_16_R2.NBTTagCompound; import net.minecraft.server.v1_16_R2.NoiseGeneratorPerlin; import net.minecraft.server.v1_16_R2.ProtoChunk; +import net.minecraft.server.v1_16_R2.RegistryGeneration; +import net.minecraft.server.v1_16_R2.RegistryMaterials; import net.minecraft.server.v1_16_R2.RegistryReadOps; import net.minecraft.server.v1_16_R2.ResourceKey; import net.minecraft.server.v1_16_R2.World; @@ -202,6 +207,16 @@ public class Regen_v1_16_R2 extends Regenerator biomeRegistry = (IRegistry) biomeRegistryField.get(chunkManager); - chunkManager = new WorldChunkManagerOverworld(seed, legacyBiomeInitLayer, largebiomes, biomeRegistry); + IRegistry biomeRegistrynms = (IRegistry) biomeRegistryField.get(chunkManager); + IRegistry biomeRegistry; + if (options.hasBiomeType()) { + BiomeBase biome = RegistryGeneration.WORLDGEN_BIOME.get(MinecraftKey.a(options.getBiomeType().getId())); + biomeRegistry = new RegistryMaterials<>(ResourceKey.a(new MinecraftKey("fawe_biomes")), Lifecycle.experimental()); + ((RegistryMaterials) biomeRegistry).a(0, RegistryGeneration.WORLDGEN_BIOME.c(biome).get(), biome, Lifecycle.experimental()); + } else { + biomeRegistry = biomeRegistrynms; + } + chunkManager = new FastWorldChunkManagerOverworld(seed, legacyBiomeInitLayer, largebiomes, biomeRegistry); //replace genLayer AreaFactory factory = (AreaFactory) initAreaFactoryMethod.invoke(null, legacyBiomeInitLayer, largebiomes ? 6 : 4, 4, (LongFunction) (l -> new FastWorldGenContextArea(seed, l))); - genLayerField.set(chunkManager, new FastGenLayer(factory)); + ((FastWorldChunkManagerOverworld) chunkManager).genLayer = new FastGenLayer(factory); return chunkManager; } + private static class FastWorldChunkManagerOverworld extends WorldChunkManager { + + private GenLayer genLayer; + private final IRegistry k; + private final boolean isSingleRegistry; + + public FastWorldChunkManagerOverworld(long seed, boolean legacyBiomeInitLayer, boolean largeBiomes, IRegistry biomeRegistry) { + super(biomeRegistry.g().collect(Collectors.toList())); + this.k = biomeRegistry; + this.isSingleRegistry = biomeRegistry.d().size() == 1; + this.genLayer = GenLayers.a(seed, legacyBiomeInitLayer, largeBiomes ? 6 : 4, 4); + } + + @Override + protected Codec a() { + return WorldChunkManagerOverworld.e; + } + + @Override + public BiomeBase getBiome(int i, int i1, int i2) { + if (this.isSingleRegistry) { + return this.k.fromId(0); + } + return this.genLayer.a(this.k, i, i2); + } + } + + private static class FastWorldGenContextArea implements AreaContextTransformed { private final ConcurrentHashMap sharedAreaMap = new ConcurrentHashMap<>(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index cf2f9485b..dab5fc305 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -242,7 +242,7 @@ public class Fawe { String dateString = br.readLine(); br.close(); this.version = FaweVersion.tryParse(versionString, commitString, dateString); - Settings.IMP.DATE = new Date(100 + version.year, version.month, version.day).toGMTString(); + Settings.IMP.DATE = new Date(100 + version.year, version.month, version.day).toString(); Settings.IMP.BUILD = "https://ci.athion.net/job/FastAsyncWorldEdit-1.16/" + version.build; Settings.IMP.COMMIT = "https://github.com/IntellectualSites/FastAsyncWorldEdit/commit/" + Integer.toHexString(version.hash); } catch (Throwable ignored) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java index 1395fa4af..73ed38ce8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java @@ -60,6 +60,12 @@ public interface IChunkSet extends IBlocks, OutputExtent { Set getEntityRemoves(); + /** + * This will return only biomes SET to the EXTENT or QUEUE. This will NOT return the current biomes in the world. + * This is used for history purposes. + * + * @return Array of biomes set + */ BiomeType[] getBiomes(); default boolean hasBiomes() { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java index fcb899b58..249b3e1b0 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java @@ -57,7 +57,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { if (biomes == null) { return null; } - return biomes[(z << 4) | x]; + return biomes[y << 2 | z & 12 | x >> 2]; } @Override @@ -88,9 +88,9 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { if (biomes == null) { - biomes = new BiomeType[256]; + biomes = new BiomeType[1024]; } - biomes[x + (z << 4)] = biome; + biomes[y << 2 | z & 12 | x >> 2] = biome; return true; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java index 3babb36c8..0dd9ab884 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java @@ -159,11 +159,13 @@ public class FallbackChunkGet implements IChunkGet { } BiomeType[] biomes = set.getBiomes(); if (biomes != null) { - for (int z = 0, i = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, i++) { - BiomeType biome = biomes[i]; - if (biome != null) { - extent.setBiome(bx + x, 0, bz + z, biome); + for (int y = 0, i = 0; y < 64; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, i++) { + BiomeType biome = biomes[i]; + if (biome != null) { + extent.setBiome(bx + (x << 2), y << 2, bz + (z << 2), biome); + } } } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java index 1ca097b80..9c4122fac 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java @@ -94,7 +94,8 @@ public class ChunkHolder> implements IQueueChunk { @Override public BiomeType[] getBiomes() { - return delegate.set(this).getBiomes(); // TODO return get? + // Uses set as this method is only used to retrieve biomes that have been set to the extent/chunk. + return delegate.set(this).getBiomes(); } @Override public char[][] getLight() { @@ -218,8 +219,7 @@ public class ChunkHolder> implements IQueueChunk { } @Override - public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y, - int z) { + public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y, int z) { return chunk.chunkExisting.getFullBlock(x, y, z); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 83dbe1149..5c3c91203 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -36,8 +36,6 @@ public class Settings extends Config { "fawe. permission. See the Permissions page for supported region plugins." }) public boolean REGION_RESTRICTIONS = true; - @Comment("FAWE will skip chunks when there's not enough memory available") - public boolean PREVENT_CRASHES = false; @Comment({ "FAWE will cancel non admin edits when memory consumption exceeds this %", " - Bypass with `/wea` or `//fast` or `fawe.bypass`", @@ -80,9 +78,6 @@ public class Settings extends Config { "Specific aspects can be turned on and off further below" }) public boolean PLOTSQUARED_HOOK = true; - @Comment({"Send anonymous FAWE statistics to https://bstats.org/.", - "Please keep this setting enabled. It helps us identifying which parts of FAWE are used the most to organize future updates better."}) - public boolean BSTATS = true; } @Comment("Paths for various directories") diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java index e2cecd706..dac042616 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java @@ -50,7 +50,7 @@ public class MCAChunk implements IChunk { public final boolean[] hasSections = new boolean[16]; public boolean hasBiomes = false; - public final BiomeType[] biomes = new BiomeType[256]; + public final BiomeType[] biomes = new BiomeType[1024]; public final char[] blocks = new char[65536]; @@ -481,7 +481,7 @@ public class MCAChunk implements IChunk { @Override public BiomeType getBiomeType(int x, int y, int z) { - return this.biomes[(z << 4) | x]; + return this.biomes[y << 2 | z & 12 | x >> 2]; } @Override @@ -505,7 +505,7 @@ public class MCAChunk implements IChunk { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { setModified(); - biomes[x + (z << 4)] = biome; //TODO Support 3D Biomes + biomes[y << 2 | z & 12 | x >> 2] = biome; return true; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index 15f372e1e..f05338fa1 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -98,7 +98,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public boolean setBiome(BlockVector3 position, BiomeType newBiome) { BiomeType oldBiome = this.getBiome(position); if (oldBiome.getId() != newBiome.getId()) { - this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockZ(), oldBiome, newBiome); + this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockY(), position.getBlockZ(), oldBiome, newBiome); return getExtent().setBiome(position, newBiome); } else { return false; @@ -109,7 +109,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public boolean setBiome(int x, int y, int z, BiomeType newBiome) { BiomeType oldBiome = this.getBiome(BlockVector3.at(x, y, z)); if (oldBiome.getId() != newBiome.getId()) { - this.changeSet.addBiomeChange(x, z, oldBiome, newBiome); + this.changeSet.addBiomeChange(x, y, z, oldBiome, newBiome); return getExtent().setBiome(x, y, z, newBiome); } else { return false; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java index 5d63474c3..5313dcf4a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java @@ -46,7 +46,7 @@ public class NullChangeSet extends AbstractChangeSet { } @Override - public void addBiomeChange(int x, int z, BiomeType from, BiomeType to) { + public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java index b3edc1cc4..73ab7309b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java @@ -57,6 +57,12 @@ public class VisualExtent extends AbstractDelegateExtent { return false; } + @Override + public boolean setBiome(BlockVector3 position, BiomeType biome) { + // Do nothing + return false; + } + public void clear() { IQueueExtent queue = (IQueueExtent) getExtent(); queue.cancel(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java b/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java index db2b83226..2fb27950f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java @@ -4,11 +4,12 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.history.UndoContext; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.math.MutableBlockVector2; +import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.world.biome.BiomeTypes; public class MutableBiomeChange implements Change { - private MutableBlockVector2 mutable = new MutableBlockVector2(); + private final MutableBlockVector3 mutable = new MutableBlockVector3(); private int from; private int to; @@ -17,8 +18,8 @@ public class MutableBiomeChange implements Change { this.to = 0; } - public void setBiome(int x, int z, int from, int to) { - mutable.setComponents(x, z); + public void setBiome(int x, int y, int z, int from, int to) { + mutable.setComponents(x, y, z); this.from = from; this.to = to; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java index 88d9a923d..c41457655 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java @@ -188,13 +188,15 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { BiomeType[] biomes = set.getBiomes(); if (biomes != null) { - for (int z = 0, index = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, index++) { - BiomeType newBiome = biomes[index]; - if (newBiome != null) { - BiomeType oldBiome = get.getBiomeType(x, 0, z); - if (oldBiome != newBiome) { - addBiomeChange(bx + x, bz + z, oldBiome, newBiome); + for (int y = 0, index = 0; y < 64; y++) { + for (int z = 0; z < 4; z++) { + for (int x = 0; x < 4; x++, index++) { + BiomeType newBiome = biomes[index]; + if (newBiome != null) { + BiomeType oldBiome = get.getBiomeType(x, y, z); + if (oldBiome != newBiome) { + addBiomeChange(bx + (x << 2), y << 2,bz + (z << 2), oldBiome, newBiome); + } } } } @@ -216,7 +218,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { public abstract void addEntityCreate(CompoundTag tag); - public abstract void addBiomeChange(int x, int z, BiomeType from, BiomeType to); + public abstract void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to); public Iterator getIterator(BlockBag blockBag, int mode, boolean redo) { return getIterator(redo); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java index f4a6af0d5..54e2ddeb5 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java @@ -69,8 +69,8 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { } @Override - public void addBiomeChange(int x, int z, BiomeType from, BiomeType to) { - parent.addBiomeChange(x, z, from, to); + public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { + parent.addBiomeChange(x, y, z, from, to); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java index 3059013f0..83bcee1ce 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java @@ -68,7 +68,7 @@ public class CFIChangeSet extends AbstractChangeSet { } @Override - public void addBiomeChange(int x, int z, BiomeType from, BiomeType to) { + public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { throw new UnsupportedOperationException("Only CFI operations are supported"); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java index 3eb4d6cb7..aa90fa9bc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java @@ -321,7 +321,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } @Override - public void addBiomeChange(int x, int z, BiomeType from, BiomeType to) { + public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { blockSize++; try { FaweOutputStream os = getBiomeOS(); @@ -333,6 +333,7 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { os.write((byte) (z >> 16)); os.write((byte) (z >> 8)); os.write((byte) (z)); + os.write((byte) (y)); os.writeVarInt(from.getInternalId()); os.writeVarInt(to.getInternalId()); } catch (Throwable e) { @@ -462,9 +463,10 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { if (int1 != -1) { int x = ((int1 << 24) + (is.read() << 16) + (is.read() << 8) + is.read()); int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()); + int y = is.read(); int from = is.readVarInt(); int to = is.readVarInt(); - change.setBiome(x, z, from, to); + change.setBiome(x, y, z, from, to); return change; } } catch (EOFException ignored) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index b0dcd3035..aa2160029 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -185,7 +185,7 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - setBiome(getIndex(x, y, z), biome); + setBiome(getIndex(x, 0, z), biome); return true; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java index 1f6a36ff2..e9531246e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java @@ -4,7 +4,6 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.AbstractDelegateExtent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; @@ -56,7 +55,7 @@ public class MultiTransform extends RandomTransform { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { // don't use streams for each block place, it'd be incredibly slow boolean result = false; for (AbstractDelegateExtent extent : extents) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java index 32117eba1..fea7bcd3f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java @@ -2,9 +2,7 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector2; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -13,7 +11,6 @@ public class OffsetExtent extends ResettableExtent { private final int dx; private final int dy; private final int dz; - private transient MutableBlockVector2 mutable = new MutableBlockVector2(); public OffsetExtent(Extent parent, int dx, int dy, int dz) { super(parent); @@ -23,9 +20,9 @@ public class OffsetExtent extends ResettableExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { return getExtent() - .setBiome(mutable.setComponents(position.getBlockX() + dx, position.getBlockZ() + dz), + .setBiome(position.getBlockX() + dx, position.getBlockY() + dy, position.getBlockZ() + dz, biome); } @@ -46,10 +43,4 @@ public class OffsetExtent extends ResettableExtent { throws WorldEditException { return getExtent().setBlock(x + dx, y + dy, z + dz, block); } - - @Override - public ResettableExtent setExtent(Extent extent) { - mutable = new MutableBlockVector2(); - return super.setExtent(extent); - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java index a1ff5f79a..51a07bee2 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java @@ -8,7 +8,6 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; @@ -100,7 +99,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { if (!limit.MAX_CHANGES()) { WEManager.IMP.cancelEditSafe(this, FaweCache.MAX_CHANGES); return false; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java index f275d4d45..d6251e798 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java @@ -2,9 +2,7 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector2; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -16,7 +14,6 @@ public class RandomOffsetTransform extends ResettableExtent { private final int dy; private final int dz; private transient SplittableRandom random; - private transient MutableBlockVector2 mutable = new MutableBlockVector2(); public RandomOffsetTransform(Extent parent, int dx, int dy, int dz) { super(parent); @@ -27,10 +24,11 @@ public class RandomOffsetTransform extends ResettableExtent { } @Override - public boolean setBiome(BlockVector2 pos, BiomeType biome) { + public boolean setBiome(BlockVector3 pos, BiomeType biome) { int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx; + int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy; int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz; - return getExtent().setBiome(mutable.setComponents(x, z), biome); + return getExtent().setBiome(x, y, z, biome); } @Override @@ -54,7 +52,6 @@ public class RandomOffsetTransform extends ResettableExtent { @Override public ResettableExtent setExtent(Extent extent) { random = new SplittableRandom(); - mutable = new MutableBlockVector2(); return super.setExtent(extent); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java index 2e3364543..fc7edc33c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java @@ -4,7 +4,6 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.MutableBlockVector3; import com.sk89q.worldedit.util.Location; @@ -82,17 +81,20 @@ public class ScaleTransform extends ResettableExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { boolean result = false; - MutableBlockVector3 pos = new MutableBlockVector3( - getPos(position.getBlockX(), 0, position.getBlockZ())); + MutableBlockVector3 pos = new MutableBlockVector3(getPos(position)); double sx = pos.getX(); + double sy = pos.getY(); double sz = pos.getZ(); - double ex = pos.getX() + dx; - double ez = pos.getZ() + dz; - for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { - for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { - result |= super.setBiome(pos.toBlockVector2(), biome); + double ex = sx + dx; + double ey = Math.min(maxy, sy + dy); + double ez = sz + dz; + for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) { + for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) { + for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) { + result |= super.setBiome(pos, biome); + } } } return result; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SelectTransform.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SelectTransform.java index 0a7f0937a..a0bf46070 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SelectTransform.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SelectTransform.java @@ -52,7 +52,7 @@ public abstract class SelectTransform extends ResettableExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { return getExtent(position).setBiome(position, biome); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/IncendoPaster.java b/worldedit-core/src/main/java/com/boydti/fawe/util/IncendoPaster.java index fdb0a06f9..f1b1a739f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/IncendoPaster.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/IncendoPaster.java @@ -232,6 +232,7 @@ public final class IncendoPaster implements Paster { RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); b.append("Uptime: ").append(TimeUnit.MINUTES.convert(rb.getUptime(), TimeUnit.MILLISECONDS)) .append(" minutes").append('\n'); + b.append("JVM Flags: ").append(rb.getInputArguments()).append('\n'); b.append("Free Memory: ").append(runtime.freeMemory() / 1024 / 1024).append(" MB").append('\n'); b.append("Max Memory: ").append(runtime.maxMemory() / 1024 / 1024).append(" MB").append('\n'); b.append("Total Memory: ").append(runtime.totalMemory() / 1024 / 1024).append(" MB").append('\n'); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java index 1a8100ec0..ff2ab4a3b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java @@ -29,6 +29,7 @@ import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.AbstractWorld; +import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -242,6 +243,11 @@ public class WorldWrapper extends AbstractWorld { return parent.regenerate(region, session); } + @Override + public boolean regenerate(Region region, Extent extent, RegenOptions options) { + return parent.regenerate(region, extent, options); + } + @Override public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { return TaskManager.IMP.sync(() -> { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index d357d111d..be2a307b9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -63,7 +63,9 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import org.enginehub.piston.annotation.Command; @@ -609,15 +611,26 @@ public class RegionCommands { @CommandPermissions("worldedit.regen") @Logging(REGION) @Confirm(Confirm.Processor.REGION) - public void regenerateChunk(Actor actor, World world, LocalSession session, EditSession editSession, - @Selection Region region) throws WorldEditException { + void regenerate(Actor actor, World world, LocalSession session, EditSession editSession, + @Selection Region region, + @Arg(desc = "The seed to regenerate with, otherwise uses world seed", def = "") + Long seed, + @Switch(name = 'b', desc = "Regenerate biomes as well") + boolean regenBiomes, + @Arg(desc = "Biome to apply for this regeneration (only works in overworld)", def = "") + BiomeType biomeType) throws WorldEditException { Mask mask = session.getMask(); boolean success; try { - session.setMask((Mask) null); - session.setSourceMask((Mask) null); + session.setMask(null); + session.setSourceMask(null); actor.printInfo(TranslatableComponent.of("fawe.regen.time")); - success = world.regenerate(region, editSession); + RegenOptions options = RegenOptions.builder() + .seed(seed) + .regenBiomes(regenBiomes) + .biomeType(biomeType) + .build(); + success = world.regenerate(region, editSession, options); } finally { session.setMask(mask); session.setSourceMask(mask); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java index 7d5c26fb7..290dca4b6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java @@ -52,7 +52,8 @@ public @interface Confirm { * (long) value; long max = 2 << 18; if (max != -1 && area > max) { - actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.region", pos1, pos2, getArgs(context))); + actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.region", + pos1, pos2, getArgs(context), region.getHeight() * area)); return confirm(actor, context); } return true; @@ -63,8 +64,9 @@ public @interface Confirm { public boolean passes(Actor actor, InjectedValueAccess context, double value) { int max = WorldEdit.getInstance().getConfiguration().maxRadius; if (max != -1 && value > max) { - actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.region", value, max, getArgs(context))); - return Processor.confirm(actor, context); + actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.radius", + value, max, getArgs(context))); + return confirm(actor, context); } return true; } @@ -74,8 +76,9 @@ public @interface Confirm { public boolean passes(Actor actor, InjectedValueAccess context, double value) { int max = 50; //TODO configurable, get Key.of(Method.class) @Limit if (max != -1 && value > max) { - actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.region", value, max, getArgs(context))); - return Processor.confirm(actor, context); + actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.limit", + value, max, getArgs(context))); + return confirm(actor, context); } return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index 96192928a..d41f92849 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -38,6 +38,7 @@ import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.ROCAngleMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.RichOffsetMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.SimplexMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.SurfaceMaskParser; @@ -97,6 +98,7 @@ public final class MaskFactory extends AbstractFactory { register(new FalseMaskParser(worldEdit)); register(new LiquidMaskParser(worldEdit)); //register(new RadiusMaskParser(worldEdit)); TODO: Adapt to work with FAWE's Chunk I/O + register(new RichOffsetMaskParser(worldEdit)); register(new ROCAngleMaskParser(worldEdit)); register(new SimplexMaskParser(worldEdit)); register(new SurfaceMaskParser(worldEdit)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RichOffsetMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RichOffsetMaskParser.java new file mode 100644 index 000000000..0139dd224 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RichOffsetMaskParser.java @@ -0,0 +1,51 @@ +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.SuggestionHelper; +import com.sk89q.worldedit.extension.factory.parser.RichParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.MaskIntersection; +import com.sk89q.worldedit.function.mask.Masks; +import com.sk89q.worldedit.function.mask.OffsetMask; +import com.sk89q.worldedit.math.BlockVector3; +import org.jetbrains.annotations.NotNull; + +import java.util.stream.Stream; + +public class RichOffsetMaskParser extends RichParser { + + /** + * Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}. + * + * @param worldEdit the worldedit instance. + */ + public RichOffsetMaskParser(WorldEdit worldEdit) { + super(worldEdit, "#offset"); + } + + @Override + protected Stream getSuggestions(String argumentInput, int index) { + if (index < 3) { + return SuggestionHelper.suggestPositiveIntegers(argumentInput); + } + if (index == 3) { + return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + } + return Stream.empty(); + } + + @Override + protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException { + if (arguments.length != 4) { + return null; + } + int x = Integer.parseInt(arguments[0]); + int y = Integer.parseInt(arguments[1]); + int z = Integer.parseInt(arguments[2]); + Mask submask = worldEdit.getMaskFactory().parseFromInput(arguments[3], context); + OffsetMask offsetMask = new OffsetMask(submask, BlockVector3.at(x, y, z)); + return new MaskIntersection(offsetMask, Masks.negate(submask)); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index 5a222f0cf..4ead8d92d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -192,7 +192,7 @@ public interface Actor extends Identifiable, SessionOwner, Subject, MapMetadatab if (confirm == null) { return false; } - queueAction(confirm::signal); + confirm.signal(); return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java index 3b47245fd..1d0078eef 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java @@ -31,7 +31,6 @@ import com.boydti.fawe.beta.implementation.filter.block.FilterBlock; import com.google.common.cache.LoadingCache; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -93,11 +92,6 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce return this.mask.test(location) && super.setBlock(location, block); } - @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { - return this.mask.test(position.toBlockVector3()) && super.setBiome(position, biome); - } - @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { return this.mask.test(BlockVector3.at(x, y, z)) && super.setBiome(x, y, z, biome); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java index 6ef2dd34d..3532bfeac 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java @@ -94,7 +94,11 @@ public interface OutputExtent { */ @Deprecated default boolean setBiome(BlockVector2 position, BiomeType biome) { - return setBiome(position.toBlockVector3(), biome); + boolean result = false; + for (int y = 0; y < 256; y ++) { + result |= setBiome(position.toBlockVector3().mutY(y), biome); + } + return result; } @NonAbstractForCompatibility( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java index 5488ee124..73b6f9b37 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java @@ -10,7 +10,6 @@ import com.sk89q.worldedit.function.generator.Resource; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; @@ -199,7 +198,7 @@ public class PassthroughExtent extends AbstractDelegateExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { return getExtent().setBiome(position, biome); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/ChunkLoadingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/ChunkLoadingExtent.java index 6e2cb413b..84bc7e88d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/ChunkLoadingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/ChunkLoadingExtent.java @@ -71,9 +71,9 @@ public class ChunkLoadingExtent extends AbstractDelegateExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { if (enabled) { - world.checkLoadedChunk(position.toBlockVector3()); + world.checkLoadedChunk(position); } return super.setBiome(position, biome); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java index cc19952bf..811bbde75 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java @@ -25,7 +25,6 @@ import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BiomeType; @@ -88,7 +87,7 @@ public class WatchdogTickingExtent extends AbstractDelegateExtent { } @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { + public boolean setBiome(BlockVector3 position, BiomeType biome) { onOperation(); return super.setBiome(position, biome); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/ConfirmHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/ConfirmHandler.java index 05ae8671f..9af58efea 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/ConfirmHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/ConfirmHandler.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.internal.command; +import com.boydti.fawe.config.Settings; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -46,6 +47,10 @@ public class ConfirmHandler implements CommandCallListener { return; } Actor actor = actorOpt.get(); + // don't check confirmation if actor doesn't need to confirm + if (!Settings.IMP.getLimit(actor).CONFIRM_LARGE) { + return; + } if (!confirmAnnotation.value().passes(actor, parameters, 1)) { throw new StopExecutionException(TextComponent.empty()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/RegenOptions.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/RegenOptions.java index 3fcb79307..6cf2b80b2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/RegenOptions.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/RegenOptions.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.world; import com.google.auto.value.AutoValue; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.biome.BiomeType; import java.util.OptionalLong; import javax.annotation.Nullable; @@ -38,7 +39,7 @@ public abstract class RegenOptions { * @return the builder */ public static Builder builder() { - return new AutoValue_RegenOptions.Builder().seed(OptionalLong.empty()).regenBiomes(false); + return new AutoValue_RegenOptions.Builder().seed(OptionalLong.empty()).regenBiomes(false).biomeType(null); } @AutoValue.Builder @@ -69,6 +70,13 @@ public abstract class RegenOptions { */ public abstract Builder regenBiomes(boolean regenBiomes); + /** + * Defines the {@code BiomeType} the regenerator should use for regeneration. Defaults to {@code null}. + * @param biomeType the {@code BiomeType} to be used for regeneration + * @return this builder + */ + public abstract Builder biomeType(@Nullable BiomeType biomeType); + /** * Build the options object. * @@ -99,4 +107,10 @@ public abstract class RegenOptions { return isRegenBiomes(); } + @Nullable public abstract BiomeType getBiomeType(); + + public boolean hasBiomeType() { + return getBiomeType() != null; + } + } diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index a074f2ed0..5e9d7f986 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -108,6 +108,8 @@ "fawe.cancel.worldedit.cancel.count": "Cancelled {0} edits.", "fawe.cancel.worldedit.cancel.reason.confirm": "Use //confirm to execute {2}", "fawe.cancel.worldedit.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}", + "fawe.cancel.worldedit.cancel.reason.confirm.radius": "Your radius is large ({0} > {1}). Use //confirm to execute {2}", + "fawe.cancel.worldedit.cancel.reason.confirm.limit": "You're exceeding your limit for this action ({0} > {1}). Use //confirm to execute {2}", "fawe.cancel.worldedit.cancel.reason": "Your WorldEdit action was cancelled: {0}.", "fawe.cancel.worldedit.cancel.reason.manual": "Manual cancellation", "fawe.cancel.worldedit.cancel.reason.low.memory": "Low memory", @@ -505,6 +507,8 @@ "worldedit.sideeffect.lighting.description": "Updates block lighting", "worldedit.sideeffect.neighbors": "Neighbors", "worldedit.sideeffect.neighbors.description": "Notifies nearby blocks of changes", + "worldedit.sideeffect.update": "Update", + "worldedit.sideeffect.update.description": "Notifies the changed block", "worldedit.sideeffect.validation": "Validation", "worldedit.sideeffect.validation.description": "Validates and fixes inconsistent world state, such as disconnected blocks", "worldedit.sideeffect.entity_ai": "Entity AI",