mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-25 23:53:44 +02:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			fix/miniMe
			...
			feature/v6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 70baca7145 | ||
|   | 2a90015037 | ||
|   | f17aa377b7 | ||
|   | e159fa054d | ||
|   | 058c65e34c | ||
|   | 8608604306 | ||
|   | 8d0cc68721 | ||
|   | 2a79c0a419 | ||
|   | 90d42b8b9f | 
| @@ -25,17 +25,18 @@ | ||||
|  */ | ||||
| package com.plotsquared.bukkit.generator; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.bukkit.queue.LimitedRegionWrapperQueue; | ||||
| import com.plotsquared.core.generator.HybridPlotWorld; | ||||
| import com.plotsquared.core.generator.IndependentPlotGenerator; | ||||
| import com.plotsquared.core.location.ChunkWrapper; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.location.UncheckedWorldLocation; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.plot.world.SinglePlotArea; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.sk89q.worldedit.bukkit.BukkitWorld; | ||||
| import org.bukkit.Chunk; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.generator.BlockPopulator; | ||||
| import org.bukkit.generator.LimitedRegion; | ||||
| import org.bukkit.generator.WorldInfo; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.Random; | ||||
| @@ -43,35 +44,51 @@ import java.util.Random; | ||||
| final class BlockStatePopulator extends BlockPopulator { | ||||
|  | ||||
|     private final IndependentPlotGenerator plotGenerator; | ||||
|     private final PlotAreaManager plotAreaManager; | ||||
|  | ||||
|     private QueueCoordinator queue; | ||||
|     /** | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public BlockStatePopulator( | ||||
|             final @NonNull IndependentPlotGenerator plotGenerator | ||||
|     ) { | ||||
|         this.plotGenerator = plotGenerator; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @deprecated Use {@link BlockStatePopulator#BlockStatePopulator(IndependentPlotGenerator)} as plotAreManager is unused | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public BlockStatePopulator( | ||||
|             final @NonNull IndependentPlotGenerator plotGenerator, | ||||
|             final @NonNull PlotAreaManager plotAreaManager | ||||
|     ) { | ||||
|         this.plotGenerator = plotGenerator; | ||||
|         this.plotAreaManager = plotAreaManager; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void populate(final @NonNull World world, final @NonNull Random random, final @NonNull Chunk source) { | ||||
|         if (this.queue == null) { | ||||
|             this.queue = PlotSquared.platform().globalBlockQueue().getNewQueue(new BukkitWorld(world)); | ||||
|         } | ||||
|         final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null); | ||||
|         if (area == null) { | ||||
|     public void populate( | ||||
|             @NonNull final WorldInfo worldInfo, | ||||
|             @NonNull final Random random, | ||||
|             final int chunkX, | ||||
|             final int chunkZ, | ||||
|             @NonNull final LimitedRegion limitedRegion | ||||
|     ) { | ||||
|         PlotArea area = UncheckedWorldLocation.at(worldInfo.getName(), chunkX << 4, 0, chunkZ << 4).getPlotArea(); | ||||
|         if (area == null || (area instanceof HybridPlotWorld hpw && !hpw.populationNeeded()) || area instanceof SinglePlotArea) { | ||||
|             return; | ||||
|         } | ||||
|         final ChunkWrapper wrap = new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ()); | ||||
|         final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z, | ||||
|                 com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(world), | ||||
|                 com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(world) - 1 | ||||
|         LimitedRegionWrapperQueue wrapped = new LimitedRegionWrapperQueue(limitedRegion); | ||||
|         // It is possible for the region to be larger than the chunk, but there is no reason for P2 to need to populate | ||||
|         // outside of the actual chunk area. | ||||
|         Location min = UncheckedWorldLocation.at(worldInfo.getName(), chunkX << 4, worldInfo.getMinHeight(), chunkZ << 4); | ||||
|         Location max = UncheckedWorldLocation.at( | ||||
|                 worldInfo.getName(), | ||||
|                 (chunkX << 4) + 15, | ||||
|                 worldInfo.getMaxHeight(), | ||||
|                 (chunkZ << 4) + 15 | ||||
|         ); | ||||
|         if (this.plotGenerator.populateChunk(chunk, area)) { | ||||
|             this.queue.enqueue(); | ||||
|         } | ||||
|         ScopedQueueCoordinator offsetChunkQueue = new ScopedQueueCoordinator(wrapped, min, max); | ||||
|         this.plotGenerator.populateChunk(offsetChunkQueue, area); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -49,8 +49,7 @@ import java.util.List; | ||||
| import java.util.Random; | ||||
| import java.util.Set; | ||||
|  | ||||
| public class BukkitPlotGenerator extends ChunkGenerator | ||||
|         implements GeneratorWrapper<ChunkGenerator> { | ||||
| public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> { | ||||
|  | ||||
|     @SuppressWarnings("unused") | ||||
|     public final boolean PAPER_ASYNC_SAFE = true; | ||||
| @@ -73,7 +72,12 @@ public class BukkitPlotGenerator extends ChunkGenerator | ||||
|         this.plotGenerator = generator; | ||||
|         this.platformGenerator = this; | ||||
|         this.populators = new ArrayList<>(); | ||||
|         this.populators.add(new BlockStatePopulator(this.plotGenerator, this.plotAreaManager)); | ||||
|         int minecraftMinorVersion = PlotSquared.platform().serverVersion()[1]; | ||||
|         if (minecraftMinorVersion >= 17) { | ||||
|             this.populators.add(new BlockStatePopulator(this.plotGenerator)); | ||||
|         } else { | ||||
|             this.populators.add(new LegacyBlockStatePopulator(this.plotGenerator)); | ||||
|         } | ||||
|         this.full = true; | ||||
|     } | ||||
|  | ||||
| @@ -159,7 +163,6 @@ public class BukkitPlotGenerator extends ChunkGenerator | ||||
|             @NonNull World world, @NonNull Random random, int x, int z, | ||||
|             @NonNull BiomeGrid biome | ||||
|     ) { | ||||
|  | ||||
|         int minY = BukkitWorld.getMinWorldHeight(world); | ||||
|         int maxY = BukkitWorld.getMaxWorldHeight(world); | ||||
|         GenChunk result = new GenChunk(minY, maxY); | ||||
|   | ||||
| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|  *       _____  _       _    _____                                _ | ||||
|  *      |  __ \| |     | |  / ____|                              | | | ||||
|  *      | |__) | | ___ | |_| (___   __ _ _   _  __ _ _ __ ___  __| | | ||||
|  *      |  ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | | ||||
|  *      | |    | | (_) | |_ ____) | (_| | |_| | (_| | | |  __/ (_| | | ||||
|  *      |_|    |_|\___/ \__|_____/ \__, |\__,_|\__,_|_|  \___|\__,_| | ||||
|  *                                    | | | ||||
|  *                                    |_| | ||||
|  *            PlotSquared plot management system for Minecraft | ||||
|  *               Copyright (C) 2014 - 2022 IntellectualSites | ||||
|  * | ||||
|  *     This program is free software: you can redistribute it and/or modify | ||||
|  *     it under the terms of the GNU General Public License as published by | ||||
|  *     the Free Software Foundation, either version 3 of the License, or | ||||
|  *     (at your option) any later version. | ||||
|  * | ||||
|  *     This program is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public License | ||||
|  *     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.bukkit.generator; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.generator.HybridPlotWorld; | ||||
| import com.plotsquared.core.generator.IndependentPlotGenerator; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.location.UncheckedWorldLocation; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.world.SinglePlotArea; | ||||
| import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.sk89q.worldedit.bukkit.BukkitWorld; | ||||
| import com.sk89q.worldedit.util.SideEffectSet; | ||||
| import org.bukkit.Chunk; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.generator.BlockPopulator; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Random; | ||||
|  | ||||
| final class LegacyBlockStatePopulator extends BlockPopulator { | ||||
|  | ||||
|     private final IndependentPlotGenerator plotGenerator; | ||||
|  | ||||
|     /** | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public LegacyBlockStatePopulator( | ||||
|             final @NonNull IndependentPlotGenerator plotGenerator | ||||
|     ) { | ||||
|         this.plotGenerator = plotGenerator; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void populate(@NotNull final World world, @NotNull final Random random, @NotNull final Chunk source) { | ||||
|         int chunkMinX = source.getX() << 4; | ||||
|         int chunkMinZ = source.getZ() << 4; | ||||
|         PlotArea area = Location.at(world.getName(), chunkMinX, 0, chunkMinZ).getPlotArea(); | ||||
|         if (area == null || (area instanceof HybridPlotWorld hpw && !hpw.populationNeeded()) || area instanceof SinglePlotArea) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(new BukkitWorld(world)); | ||||
|         queue.setForceSync(true); | ||||
|         queue.setSideEffectSet(SideEffectSet.none()); | ||||
|         queue.setBiomesEnabled(false); | ||||
|         queue.setChunkObject(source); | ||||
|         Location min = UncheckedWorldLocation.at(world.getName(), chunkMinX, world.getMinHeight(), chunkMinZ); | ||||
|         Location max = UncheckedWorldLocation.at(world.getName(), chunkMinX + 15, world.getMaxHeight(), chunkMinZ + 15); | ||||
|         ScopedQueueCoordinator offsetChunkQueue = new ScopedQueueCoordinator(queue, min, max); | ||||
|         this.plotGenerator.populateChunk(offsetChunkQueue, area); | ||||
|         queue.enqueue(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,128 @@ | ||||
| /* | ||||
|  *       _____  _       _    _____                                _ | ||||
|  *      |  __ \| |     | |  / ____|                              | | | ||||
|  *      | |__) | | ___ | |_| (___   __ _ _   _  __ _ _ __ ___  __| | | ||||
|  *      |  ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | | ||||
|  *      | |    | | (_) | |_ ____) | (_| | |_| | (_| | | |  __/ (_| | | ||||
|  *      |_|    |_|\___/ \__|_____/ \__, |\__,_|\__,_|_|  \___|\__,_| | ||||
|  *                                    | | | ||||
|  *                                    |_| | ||||
|  *            PlotSquared plot management system for Minecraft | ||||
|  *               Copyright (C) 2014 - 2022 IntellectualSites | ||||
|  * | ||||
|  *     This program is free software: you can redistribute it and/or modify | ||||
|  *     it under the terms of the GNU General Public License as published by | ||||
|  *     the Free Software Foundation, either version 3 of the License, or | ||||
|  *     (at your option) any later version. | ||||
|  * | ||||
|  *     This program is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public License | ||||
|  *     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.bukkit.queue; | ||||
|  | ||||
| import com.plotsquared.bukkit.schematic.StateWrapper; | ||||
| import com.plotsquared.core.queue.DelegateQueueCoordinator; | ||||
| import com.sk89q.jnbt.CompoundTag; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.entity.Entity; | ||||
| import com.sk89q.worldedit.function.pattern.Pattern; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import com.sk89q.worldedit.world.block.BaseBlock; | ||||
| import com.sk89q.worldedit.world.block.BlockState; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.Location; | ||||
| import org.bukkit.entity.EntityType; | ||||
| import org.bukkit.generator.LimitedRegion; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| /** | ||||
|  * Wraps a {@link LimitedRegion} inside a {@link com.plotsquared.core.queue.QueueCoordinator} so it can be written to. | ||||
|  * | ||||
|  * @since TODO | ||||
|  */ | ||||
| public class LimitedRegionWrapperQueue extends DelegateQueueCoordinator { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + LimitedRegionWrapperQueue.class.getSimpleName()); | ||||
|  | ||||
|     private final LimitedRegion limitedRegion; | ||||
|  | ||||
|     /** | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public LimitedRegionWrapperQueue(LimitedRegion limitedRegion) { | ||||
|         super(null); | ||||
|         this.limitedRegion = limitedRegion; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) { | ||||
|         return setBlock(x, y, z, pattern.applyBlock(BlockVector3.at(x, y, z))); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean setBlock(final int x, final int y, final int z, @NonNull final BaseBlock id) { | ||||
|         boolean result = setBlock(x, y, z, id.toImmutableState()); | ||||
|         if (result && id.hasNbtData()) { | ||||
|             CompoundTag tag = id.getNbtData(); | ||||
|             StateWrapper sw = new StateWrapper(tag); | ||||
|             try { | ||||
|                 sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock()); | ||||
|             } catch (IllegalArgumentException e) { | ||||
|                 LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean setBlock(final int x, final int y, final int z, @NonNull final BlockState id) { | ||||
|         try { | ||||
|             limitedRegion.setType(x, y, z, BukkitAdapter.adapt(id.getBlockType())); | ||||
|             limitedRegion.setBlockData(x, y, z, BukkitAdapter.adapt(id)); | ||||
|         } catch (IllegalArgumentException e) { | ||||
|             LOGGER.error("Error attempting to populate block into the world at location {},{},{}", x, y, z, e); | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean setEntity(@NonNull final Entity entity) { | ||||
|         EntityType type = BukkitAdapter.adapt(entity.getState().getType()); | ||||
|         double x = entity.getLocation().getX(); | ||||
|         double y = entity.getLocation().getY(); | ||||
|         double z = entity.getLocation().getZ(); | ||||
|         Location location = new Location(limitedRegion.getWorld(), x, y, z); | ||||
|         try { | ||||
|             limitedRegion.spawnEntity(location, type); | ||||
|         } catch (IllegalArgumentException e) { | ||||
|             LOGGER.error("Error attempting to populate entity into the world at location {},{},{}", (int) x, (int) y, (int) z, e); | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean setTile(final int x, final int y, final int z, @NonNull final CompoundTag tag) { | ||||
|         StateWrapper sw = new StateWrapper(tag); | ||||
|         try { | ||||
|             return sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock()); | ||||
|         } catch (IllegalArgumentException e) { | ||||
|             LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isSettingTiles() { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -35,11 +35,13 @@ import com.sk89q.jnbt.Tag; | ||||
| import com.sk89q.worldedit.blocks.BaseItemStack; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.world.item.ItemType; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.ChatColor; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.block.Block; | ||||
| import org.bukkit.block.Container; | ||||
| import org.bukkit.block.Sign; | ||||
| import org.bukkit.block.Skull; | ||||
| import org.bukkit.enchantments.Enchantment; | ||||
| import org.bukkit.inventory.Inventory; | ||||
| import org.bukkit.inventory.InventoryHolder; | ||||
| @@ -57,6 +59,11 @@ public class StateWrapper { | ||||
|     public org.bukkit.block.BlockState state = null; | ||||
|     public CompoundTag tag = null; | ||||
|  | ||||
|     /** | ||||
|      * @deprecated in favour of using WE methods for obtaining NBT, specifically by obtaining a | ||||
|      *         {@link com.sk89q.worldedit.world.block.BaseBlock} and then using {@link com.sk89q.worldedit.world.block.BaseBlock#getNbtData()} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public StateWrapper(org.bukkit.block.BlockState state) { | ||||
|         this.state = state; | ||||
|     } | ||||
| @@ -230,10 +237,37 @@ public class StateWrapper { | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|             case "skull" -> { | ||||
|                 if (state instanceof Skull skull) { | ||||
|                     CompoundTag skullOwner = ((CompoundTag) this.tag.getValue().get("SkullOwner")); | ||||
|                     if (skullOwner == null) { | ||||
|                         return true; | ||||
|                     } | ||||
|                     String player = skullOwner.getString("Name"); | ||||
|                     if (player == null || player.isEmpty()) { | ||||
|                         return false; | ||||
|                     } | ||||
|                     try { | ||||
|                         skull.setOwningPlayer(Bukkit.getOfflinePlayer(player)); | ||||
|                         skull.update(true); | ||||
|                     } catch (Exception e) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                     return true; | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a CompoundTag of the contents of a block's inventory (chest, furnace, etc.). | ||||
|      * | ||||
|      * @deprecated in favour of using WorldEdit methods for obtaining NBT, specifically by obtaining a | ||||
|      *         {@link com.sk89q.worldedit.world.block.BaseBlock} and then using {@link com.sk89q.worldedit.world.block.BaseBlock#getNbtData()} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public CompoundTag getTag() { | ||||
|         if (this.tag != null) { | ||||
|             return this.tag; | ||||
|   | ||||
| @@ -35,13 +35,23 @@ import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.PlotId; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.sk89q.worldedit.entity.BaseEntity; | ||||
| import com.sk89q.worldedit.entity.Entity; | ||||
| import com.sk89q.worldedit.extent.Extent; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import com.sk89q.worldedit.math.Vector3; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import com.sk89q.worldedit.regions.RegionOperationException; | ||||
| import com.sk89q.worldedit.world.NullWorld; | ||||
| import com.sk89q.worldedit.world.biome.BiomeType; | ||||
| import com.sk89q.worldedit.world.block.BaseBlock; | ||||
| import com.sk89q.worldedit.world.block.BlockTypes; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| public class HybridGen extends IndependentPlotGenerator { | ||||
|  | ||||
|     private static final CuboidRegion CHUNK = new CuboidRegion(BlockVector3.ZERO, BlockVector3.at(15, 396, 15)); | ||||
|     private final HybridPlotWorldFactory hybridPlotWorldFactory; | ||||
|  | ||||
|     @Inject | ||||
| @@ -55,12 +65,17 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|     } | ||||
|  | ||||
|     private void placeSchem( | ||||
|             HybridPlotWorld world, ScopedQueueCoordinator result, short relativeX, | ||||
|             short relativeZ, int x, int z, boolean isRoad | ||||
|             HybridPlotWorld world, | ||||
|             ScopedQueueCoordinator result, | ||||
|             short relativeX, | ||||
|             short relativeZ, | ||||
|             int x, | ||||
|             int z, | ||||
|             boolean isRoad, | ||||
|             boolean isPopulating | ||||
|     ) { | ||||
|         int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT); | ||||
|         if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad | ||||
|                 && Settings.Schematics.PASTE_ON_TOP)) { | ||||
|         if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) { | ||||
|             minY = world.SCHEM_Y; | ||||
|         } else { | ||||
|             minY = world.getMinBuildHeight(); | ||||
| @@ -69,10 +84,12 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         if (blocks != null) { | ||||
|             for (int y = 0; y < blocks.length; y++) { | ||||
|                 if (blocks[y] != null) { | ||||
|                     if (!isPopulating || blocks[y].hasNbtData()) { | ||||
|                         result.setBlock(x, minY + y, z, blocks[y]); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         BiomeType biome = world.G_SCH_B.get(MathMan.pair(relativeX, relativeZ)); | ||||
|         if (biome != null) { | ||||
|             result.setBiome(x, z, biome); | ||||
| @@ -121,42 +138,38 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         short[] relativeX = new short[16]; | ||||
|         boolean[] insideRoadX = new boolean[16]; | ||||
|         boolean[] insideWallX = new boolean[16]; | ||||
|         short offsetX = relativeOffsetX; | ||||
|         for (short i = 0; i < 16; i++) { | ||||
|             short v = (short) (relativeOffsetX + i); | ||||
|             while (v >= hybridPlotWorld.SIZE) { | ||||
|                 v -= hybridPlotWorld.SIZE; | ||||
|             if (offsetX >= hybridPlotWorld.SIZE) { | ||||
|                 offsetX -= hybridPlotWorld.SIZE; | ||||
|             } | ||||
|             relativeX[i] = v; | ||||
|             relativeX[i] = offsetX; | ||||
|             if (hybridPlotWorld.ROAD_WIDTH != 0) { | ||||
|                 insideRoadX[i] = | ||||
|                         v < hybridPlotWorld.PATH_WIDTH_LOWER || v > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideWallX[i] = | ||||
|                         v == hybridPlotWorld.PATH_WIDTH_LOWER || v == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideRoadX[i] = offsetX < hybridPlotWorld.PATH_WIDTH_LOWER || offsetX > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideWallX[i] = offsetX == hybridPlotWorld.PATH_WIDTH_LOWER || offsetX == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|             } | ||||
|             offsetX++; | ||||
|         } | ||||
|         // The Z-coordinate of a given Z coordinate, relative to the | ||||
|         // plot (Counting from the corner with the least positive | ||||
|         // coordinates) | ||||
|         short[] relativeZ = new short[16]; | ||||
|         // Whether or not the given Z coordinate belongs to the road | ||||
|         boolean[] insideRoadZ = new boolean[16]; | ||||
|         // Whether or not the given Z coordinate belongs to the wall | ||||
|         boolean[] insideWallZ = new boolean[16]; | ||||
|         short offsetZ = relativeOffsetZ; | ||||
|         for (short i = 0; i < 16; i++) { | ||||
|             short v = (short) (relativeOffsetZ + i); | ||||
|             while (v >= hybridPlotWorld.SIZE) { | ||||
|                 v -= hybridPlotWorld.SIZE; | ||||
|             if (offsetZ >= hybridPlotWorld.SIZE) { | ||||
|                 offsetZ -= hybridPlotWorld.SIZE; | ||||
|             } | ||||
|             relativeZ[i] = v; | ||||
|             relativeZ[i] = offsetZ; | ||||
|             if (hybridPlotWorld.ROAD_WIDTH != 0) { | ||||
|                 insideRoadZ[i] = | ||||
|                         v < hybridPlotWorld.PATH_WIDTH_LOWER || v > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideWallZ[i] = | ||||
|                         v == hybridPlotWorld.PATH_WIDTH_LOWER || v == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideRoadZ[i] = offsetZ < hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideWallZ[i] = offsetZ == hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|             } | ||||
|             offsetZ++; | ||||
|         } | ||||
|         // generation | ||||
|         int startY = hybridPlotWorld.getMinGenHeight() + (hybridPlotWorld.PLOT_BEDROCK ? 1: 0); | ||||
|         int startY = hybridPlotWorld.getMinGenHeight() + (hybridPlotWorld.PLOT_BEDROCK ? 1 : 0); | ||||
|         for (short x = 0; x < 16; x++) { | ||||
|             if (insideRoadX[x]) { | ||||
|                 for (short z = 0; z < 16; z++) { | ||||
| @@ -165,7 +178,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                         result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); | ||||
|                     } | ||||
|                     if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                         placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true); | ||||
|                         placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (insideWallX[x]) { | ||||
| @@ -176,9 +189,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                             result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); | ||||
|                         } | ||||
|                         if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, | ||||
|                                     true | ||||
|                             ); | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false); | ||||
|                         } | ||||
|                     } else { | ||||
|                         // wall | ||||
| @@ -187,14 +198,10 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                         } | ||||
|                         if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                             if (hybridPlotWorld.PLACE_TOP_BLOCK) { | ||||
|                                 result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, | ||||
|                                         hybridPlotWorld.WALL_BLOCK.toPattern() | ||||
|                                 ); | ||||
|                                 result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, hybridPlotWorld.WALL_BLOCK.toPattern()); | ||||
|                             } | ||||
|                         } else { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, | ||||
|                                     true | ||||
|                             ); | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -206,9 +213,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                             result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); | ||||
|                         } | ||||
|                         if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, | ||||
|                                     true | ||||
|                             ); | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false); | ||||
|                         } | ||||
|                     } else if (insideWallZ[z]) { | ||||
|                         // wall | ||||
| @@ -217,27 +222,19 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                         } | ||||
|                         if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                             if (hybridPlotWorld.PLACE_TOP_BLOCK) { | ||||
|                                 result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, | ||||
|                                         hybridPlotWorld.WALL_BLOCK.toPattern() | ||||
|                                 ); | ||||
|                                 result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, hybridPlotWorld.WALL_BLOCK.toPattern()); | ||||
|                             } | ||||
|                         } else { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, | ||||
|                                     true | ||||
|                             ); | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false); | ||||
|                         } | ||||
|                     } else { | ||||
|                         // plot | ||||
|                         for (int y = startY; y < hybridPlotWorld.PLOT_HEIGHT; y++) { | ||||
|                             result.setBlock(x, y, z, hybridPlotWorld.MAIN_BLOCK.toPattern()); | ||||
|                         } | ||||
|                         result.setBlock(x, hybridPlotWorld.PLOT_HEIGHT, z, | ||||
|                                 hybridPlotWorld.TOP_BLOCK.toPattern() | ||||
|                         ); | ||||
|                         result.setBlock(x, hybridPlotWorld.PLOT_HEIGHT, z, hybridPlotWorld.TOP_BLOCK.toPattern()); | ||||
|                         if (hybridPlotWorld.PLOT_SCHEMATIC) { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, | ||||
|                                     false | ||||
|                             ); | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, false, false); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -245,6 +242,138 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean populateChunk(final ScopedQueueCoordinator result, final PlotArea settings) { | ||||
|         HybridPlotWorld hybridPlotWorld = (HybridPlotWorld) settings; | ||||
|         if (!hybridPlotWorld.populationNeeded()) { | ||||
|             return false; | ||||
|         } | ||||
|         // Coords | ||||
|         Location min = result.getMin(); | ||||
|         int bx = min.getX() - hybridPlotWorld.ROAD_OFFSET_X; | ||||
|         int bz = min.getZ() - hybridPlotWorld.ROAD_OFFSET_Z; | ||||
|         // The relative X-coordinate (within the plot) of the minimum X coordinate | ||||
|         // contained in the scoped queue | ||||
|         short relativeOffsetX; | ||||
|         if (bx < 0) { | ||||
|             relativeOffsetX = (short) (hybridPlotWorld.SIZE + (bx % hybridPlotWorld.SIZE)); | ||||
|         } else { | ||||
|             relativeOffsetX = (short) (bx % hybridPlotWorld.SIZE); | ||||
|         } | ||||
|         // The relative Z-coordinate (within the plot) of the minimum Z coordinate | ||||
|         // contained in the scoped queue | ||||
|         short relativeOffsetZ; | ||||
|         if (bz < 0) { | ||||
|             relativeOffsetZ = (short) (hybridPlotWorld.SIZE + (bz % hybridPlotWorld.SIZE)); | ||||
|         } else { | ||||
|             relativeOffsetZ = (short) (bz % hybridPlotWorld.SIZE); | ||||
|         } | ||||
|         boolean allRoad = true; | ||||
|         boolean overlap = false; | ||||
|  | ||||
|         // The X-coordinate of a given X coordinate, relative to the | ||||
|         // plot (Counting from the corner with the least positive | ||||
|         // coordinates) | ||||
|         short[] relativeX = new short[16]; | ||||
|         boolean[] insideRoadX = new boolean[16]; | ||||
|         boolean[] insideWallX = new boolean[16]; | ||||
|         short offsetX = relativeOffsetX; | ||||
|         for (short i = 0; i < 16; i++) { | ||||
|             if (offsetX >= hybridPlotWorld.SIZE) { | ||||
|                 offsetX -= hybridPlotWorld.SIZE; | ||||
|                 overlap = true; | ||||
|             } | ||||
|             relativeX[i] = offsetX; | ||||
|             if (hybridPlotWorld.ROAD_WIDTH != 0) { | ||||
|                 boolean insideRoad = offsetX < hybridPlotWorld.PATH_WIDTH_LOWER || offsetX > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 boolean insideWall = offsetX == hybridPlotWorld.PATH_WIDTH_LOWER || offsetX == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideRoadX[i] = insideRoad; | ||||
|                 insideWallX[i] = insideWall; | ||||
|                 allRoad &= insideRoad && insideWall; | ||||
|             } | ||||
|             offsetX++; | ||||
|         } | ||||
|  | ||||
|         // The Z-coordinate of a given Z coordinate, relative to the | ||||
|         // plot (Counting from the corner with the least positive | ||||
|         // coordinates) | ||||
|         short[] relativeZ = new short[16]; | ||||
|         boolean[] insideRoadZ = new boolean[16]; | ||||
|         boolean[] insideWallZ = new boolean[16]; | ||||
|         short offsetZ = relativeOffsetZ; | ||||
|         for (short i = 0; i < 16; i++) { | ||||
|             if (offsetZ >= hybridPlotWorld.SIZE) { | ||||
|                 offsetZ -= hybridPlotWorld.SIZE; | ||||
|                 overlap = true; | ||||
|             } | ||||
|             relativeZ[i] = offsetZ; | ||||
|             if (hybridPlotWorld.ROAD_WIDTH != 0) { | ||||
|                 boolean insideRoad = offsetZ < hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ > hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 boolean insideWall = offsetZ == hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ == hybridPlotWorld.PATH_WIDTH_UPPER; | ||||
|                 insideRoadZ[i] = insideRoad; | ||||
|                 insideWallZ[i] = insideWall; | ||||
|                 allRoad &= insideRoad && insideWall; | ||||
|             } | ||||
|             offsetZ++; | ||||
|         } | ||||
|         for (short x = 0; x < 16; x++) { | ||||
|             if (insideRoadX[x] || insideWallX[x]) { | ||||
|                 if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                     for (short z = 0; z < 16; z++) { | ||||
|                         placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, true); | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 for (short z = 0; z < 16; z++) { | ||||
|                     if (insideRoadZ[z] || insideWallZ[z]) { | ||||
|                         if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|                             placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, true); | ||||
|                         } | ||||
|                     } else if (hybridPlotWorld.PLOT_SCHEMATIC) { | ||||
|                         placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, false, true); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (!allRoad && hybridPlotWorld.getPlotSchematicEntities() != null && !hybridPlotWorld | ||||
|                 .getPlotSchematicEntities() | ||||
|                 .isEmpty()) { | ||||
|             CuboidRegion region = CHUNK.clone(); | ||||
|             try { | ||||
|                 region.shift(hybridPlotWorld | ||||
|                         .getPlotSchematicMinPoint() | ||||
|                         .add(relativeOffsetX, 0, relativeOffsetZ) | ||||
|                         .subtract(hybridPlotWorld.PATH_WIDTH_LOWER + 1, 0, hybridPlotWorld.PATH_WIDTH_LOWER + 1)); | ||||
|                 for (Entity entity : hybridPlotWorld.getPlotSchematicEntities()) { | ||||
|                     if (region.contains(entity.getLocation().toVector().toBlockPoint())) { | ||||
|                         Vector3 pos = (entity.getLocation().toVector() | ||||
|                                 .subtract(region.getMinimumPoint().withY(hybridPlotWorld.getPlotSchematicMinPoint().getY()).toVector3())) | ||||
|                                 .add(min.getBlockVector3().withY(hybridPlotWorld.SCHEM_Y).toVector3()); | ||||
|                         result.setEntity(new PopulatingEntity( | ||||
|                                 entity, | ||||
|                                 new com.sk89q.worldedit.util.Location(NullWorld.getInstance(), pos) | ||||
|                         )); | ||||
|                     } | ||||
|                 } | ||||
|             } catch (RegionOperationException e) { | ||||
|                 throw new RuntimeException(e); | ||||
|             } | ||||
|             if (overlap) { | ||||
|                 try { | ||||
|                     region.shift(BlockVector3.at(-hybridPlotWorld.SIZE, 0, -hybridPlotWorld.SIZE)); | ||||
|                     for (Entity entity : hybridPlotWorld.getPlotSchematicEntities()) { | ||||
|                         if (region.contains(entity.getLocation().toVector().toBlockPoint())) { | ||||
|                             result.setEntity(entity); | ||||
|                         } | ||||
|                     } | ||||
|                 } catch (RegionOperationException e) { | ||||
|                     throw new RuntimeException(e); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) { | ||||
|         return this.hybridPlotWorldFactory.create(world, id, this, min, max); | ||||
| @@ -255,4 +384,58 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         // All initialization is done in the PlotArea class | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Wrapper to allow a WorldEdit {@link Entity} to effectively have a mutable location as the location in its NBT should be changed | ||||
|      * when set to the world. | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     private static final class PopulatingEntity implements Entity { | ||||
|  | ||||
|         private final Entity parent; | ||||
|         private com.sk89q.worldedit.util.Location location; | ||||
|  | ||||
|         /** | ||||
|          * @since TODO | ||||
|          */ | ||||
|         private PopulatingEntity(Entity parent, com.sk89q.worldedit.util.Location location) { | ||||
|             this.parent = parent; | ||||
|             this.location = location; | ||||
|         } | ||||
|  | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public BaseEntity getState() { | ||||
|             return parent.getState(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean remove() { | ||||
|             return parent.remove(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public com.sk89q.worldedit.util.Location getLocation() { | ||||
|             return location; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean setLocation(final com.sk89q.worldedit.util.Location location) { | ||||
|             this.location = location; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Extent getExtent() { | ||||
|             return parent.getExtent(); | ||||
|         } | ||||
|  | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public <T> T getFacet(final Class<? extends T> cls) { | ||||
|             return parent.getFacet(cls); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -40,11 +40,13 @@ import com.plotsquared.core.plot.PlotId; | ||||
| import com.plotsquared.core.plot.PlotManager; | ||||
| import com.plotsquared.core.plot.schematic.Schematic; | ||||
| import com.plotsquared.core.queue.GlobalBlockQueue; | ||||
| import com.plotsquared.core.util.AnnotationHelper; | ||||
| import com.plotsquared.core.util.FileUtils; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.SchematicHandler; | ||||
| import com.sk89q.jnbt.CompoundTag; | ||||
| import com.sk89q.jnbt.CompoundTagBuilder; | ||||
| import com.sk89q.worldedit.entity.Entity; | ||||
| import com.sk89q.worldedit.extent.clipboard.Clipboard; | ||||
| import com.sk89q.worldedit.extent.transform.BlockTransformExtent; | ||||
| import com.sk89q.worldedit.internal.helper.MCDirections; | ||||
| @@ -58,11 +60,13 @@ import com.sk89q.worldedit.world.block.BaseBlock; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import javax.annotation.Nullable; | ||||
| import java.io.File; | ||||
| import java.lang.reflect.Field; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
|  | ||||
| public class HybridPlotWorld extends ClassicPlotWorld { | ||||
| @@ -71,6 +75,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|     private static final AffineTransform transform = new AffineTransform().rotateY(90); | ||||
|     public boolean ROAD_SCHEMATIC_ENABLED; | ||||
|     public boolean PLOT_SCHEMATIC = false; | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public int PLOT_SCHEMATIC_HEIGHT = -1; | ||||
|     public short PATH_WIDTH_LOWER; | ||||
|     public short PATH_WIDTH_UPPER; | ||||
| @@ -80,6 +85,11 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|     private Location SIGN_LOCATION; | ||||
|     private File root = null; | ||||
|     private int lastOverlayHeightError = Integer.MIN_VALUE; | ||||
|     private List<Entity> schem3Entities = null; | ||||
|     private BlockVector3 schem3MinPoint = null; | ||||
|     private boolean schem1PopulationNeeded = false; | ||||
|     private boolean schem2PopulationNeeded = false; | ||||
|     private boolean schem3PopulationNeeded = false; | ||||
|  | ||||
|     @Inject | ||||
|     private SchematicHandler schematicHandler; | ||||
| @@ -98,6 +108,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         PlotSquared.platform().injector().injectMembers(this); | ||||
|     } | ||||
|  | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public static byte wrap(byte data, int start) { | ||||
|         if ((data >= start) && (data < (start + 4))) { | ||||
|             data = (byte) ((((data - start) + 2) & 3) + start); | ||||
| @@ -105,6 +116,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         return data; | ||||
|     } | ||||
|  | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public static byte wrap2(byte data, int start) { | ||||
|         if ((data >= start) && (data < (start + 2))) { | ||||
|             data = (byte) ((((data - start) + 1) & 1) + start); | ||||
| @@ -112,8 +124,6 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         return data; | ||||
|     } | ||||
|  | ||||
|     // FIXME depends on block ids | ||||
|     // Possibly make abstract? | ||||
|     public static BaseBlock rotate(BaseBlock id) { | ||||
|  | ||||
|         CompoundTag tag = id.getNbtData(); | ||||
| @@ -251,6 +261,14 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         Schematic schematic1 = this.schematicHandler.getSchematic(schematic1File); | ||||
|         Schematic schematic2 = this.schematicHandler.getSchematic(schematic2File); | ||||
|         Schematic schematic3 = this.schematicHandler.getSchematic(schematic3File); | ||||
|  | ||||
|         // If the plot schematic contains entities, then they need to be populated upon generation. | ||||
|         if (schematic3 != null && !schematic3.getClipboard().getEntities().isEmpty()) { | ||||
|             this.schem3Entities = new ArrayList<>(schematic3.getClipboard().getEntities()); | ||||
|             this.schem3MinPoint = schematic3.getClipboard().getMinimumPoint(); | ||||
|             this.schem3PopulationNeeded = true; | ||||
|         } | ||||
|  | ||||
|         int shift = this.ROAD_WIDTH / 2; | ||||
|         int oddshift = (this.ROAD_WIDTH & 1); | ||||
|  | ||||
| @@ -314,19 +332,28 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|             for (short x = 0; x < w3; x++) { | ||||
|                 for (short z = 0; z < l3; z++) { | ||||
|                     for (short y = 0; y < h3; y++) { | ||||
|                         BaseBlock id = | ||||
|                                 blockArrayClipboard3.getFullBlock(BlockVector3.at( | ||||
|                         BaseBlock id = blockArrayClipboard3.getFullBlock(BlockVector3.at( | ||||
|                                 x + min.getBlockX(), | ||||
|                                 y + min.getBlockY(), | ||||
|                                 z + min.getBlockZ() | ||||
|                         )); | ||||
|                         if (!id.getBlockType().getMaterial().isAir()) { | ||||
|                             addOverlayBlock((short) (x + shift + oddshift + centerShiftX), (short) (y + plotY), | ||||
|                                     (short) (z + shift + oddshift + centerShiftZ), id, false, h3 | ||||
|                             schem3PopulationNeeded |= id.hasNbtData(); | ||||
|                             addOverlayBlock( | ||||
|                                     (short) (x + shift + oddshift + centerShiftX), | ||||
|                                     (short) (y + plotY), | ||||
|                                     (short) (z + shift + oddshift + centerShiftZ), | ||||
|                                     id, | ||||
|                                     false, | ||||
|                                     h3 | ||||
|                             ); | ||||
|                         } | ||||
|                     } | ||||
|                     BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); | ||||
|                     if (blockArrayClipboard3.hasBiomes()) { | ||||
|                         BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at( | ||||
|                                 x + min.getBlockX(), | ||||
|                                 z + min.getBlockZ() | ||||
|                         )); | ||||
|                         addOverlayBiome( | ||||
|                                 (short) (x + shift + oddshift + centerShiftX), | ||||
|                                 (short) (z + shift + oddshift + centerShiftZ), | ||||
| @@ -334,12 +361,13 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (Settings.DEBUG) { | ||||
|                 LOGGER.info("- plot schematic: {}", schematic3File.getPath()); | ||||
|             } | ||||
|         } | ||||
|         if ((schematic1 == null&& schematic2 == null) || this.ROAD_WIDTH == 0) { | ||||
|         if ((schematic1 == null && schematic2 == null) || this.ROAD_WIDTH == 0) { | ||||
|             if (Settings.DEBUG) { | ||||
|                 LOGGER.info("- schematic: false"); | ||||
|             } | ||||
| @@ -370,6 +398,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|                             z + min.getBlockZ() | ||||
|                     )); | ||||
|                     if (!id.getBlockType().getMaterial().isAir()) { | ||||
|                         schem1PopulationNeeded |= id.hasNbtData(); | ||||
|                         addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z + shift + oddshift), id, false, h1); | ||||
|                         addOverlayBlock( | ||||
|                                 (short) (z + shift + oddshift), | ||||
| @@ -381,11 +410,13 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|                 if (blockArrayClipboard1.hasBiomes()) { | ||||
|                     BiomeType biome = blockArrayClipboard1.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); | ||||
|                     addOverlayBiome((short) (x - shift), (short) (z + shift + oddshift), biome); | ||||
|                     addOverlayBiome((short) (z + shift + oddshift), (short) (shift - x + (oddshift - 1)), biome); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Clipboard blockArrayClipboard2 = schematic2.getClipboard(); | ||||
|         BlockVector3 d2 = blockArrayClipboard2.getDimensions(); | ||||
| @@ -406,14 +437,17 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|                             z + min.getBlockZ() | ||||
|                     )); | ||||
|                     if (!id.getBlockType().getMaterial().isAir()) { | ||||
|                         schem2PopulationNeeded |= id.hasNbtData(); | ||||
|                         addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z - shift), id, false, h2); | ||||
|                     } | ||||
|                 } | ||||
|                 if (blockArrayClipboard2.hasBiomes()) { | ||||
|                     BiomeType biome = blockArrayClipboard2.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); | ||||
|                     addOverlayBiome((short) (x - shift), (short) (z - shift), biome); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void addOverlayBlock(short x, short y, short z, BaseBlock id, boolean rotate, int height) { | ||||
|         if (z < 0) { | ||||
| @@ -456,8 +490,52 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         this.G_SCH_B.put(pair, id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the entities contained within the plot schematic for generation. Intended for internal use only. | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
|     public @Nullable List<Entity> getPlotSchematicEntities() { | ||||
|         return schem3Entities; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the minimum point of the plot schematic for generation. Intended for internal use only. | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
|     public @Nullable BlockVector3 getPlotSchematicMinPoint() { | ||||
|         return schem3MinPoint; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get if post-generation population of chunks with tiles/entities is needed for this world. Not for public API use. | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
|     public boolean populationNeeded() { | ||||
|         return schem1PopulationNeeded || schem2PopulationNeeded || schem3PopulationNeeded; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @deprecated in favour of {@link HybridPlotWorld#getSchematicRoot()} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public File getRoot() { | ||||
|         return this.root; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the root folder for this world's generation schematics. May be null if schematics not initialised via | ||||
|      * {@link HybridPlotWorld#setupSchematics()} | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public @Nullable File getSchematicRoot() { | ||||
|         return this.root; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -47,9 +47,7 @@ public abstract class IndependentPlotGenerator { | ||||
|     public abstract String getName(); | ||||
|  | ||||
|     /** | ||||
|      * Use the setBlock or setBiome method of the PlotChunk result parameter to make changes. | ||||
|      * The PlotArea settings is the same one this was initialized with. | ||||
|      * The PseudoRandom random is a fast random object. | ||||
|      * Generate chunk block data | ||||
|      * | ||||
|      * @param result   queue | ||||
|      * @param settings PlotArea (settings) | ||||
| @@ -59,10 +57,15 @@ public abstract class IndependentPlotGenerator { | ||||
|     public abstract void generateChunk(ScopedQueueCoordinator result, PlotArea settings); | ||||
|  | ||||
|     /** | ||||
|      * Populates the queue representing a chunk area with tile entities and entities | ||||
|      * | ||||
|      * @param result   Queue to write to | ||||
|      * @param settings PlotArea (settings) | ||||
|      * @return True if any population occurred | ||||
|      * @deprecated {@link ScopedQueueCoordinator} will be renamed in v7. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     public boolean populateChunk(ScopedQueueCoordinator result, PlotArea setting) { | ||||
|     public boolean populateChunk(ScopedQueueCoordinator result, PlotArea settings) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -41,14 +41,17 @@ import org.khelekore.prtree.SimpleMBR; | ||||
|  * An unmodifiable 6-tuple (world,x,y,z,yaw,pitch) | ||||
|  */ | ||||
| @SuppressWarnings("unused") | ||||
| public final class Location extends BlockLoc implements Comparable<Location> { | ||||
| public sealed class Location extends BlockLoc implements Comparable<Location> permits UncheckedWorldLocation { | ||||
|  | ||||
|     private final float yaw; | ||||
|     private final float pitch; | ||||
|     private final BlockVector3 blockVector3; | ||||
|     private final World<?> world; | ||||
|  | ||||
|     private Location( | ||||
|     /** | ||||
|      * @since TODO | ||||
|      */ | ||||
|     protected Location( | ||||
|             final @NonNull World<?> world, final @NonNull BlockVector3 blockVector3, | ||||
|             final float yaw, final float pitch | ||||
|     ) { | ||||
|   | ||||
| @@ -0,0 +1,77 @@ | ||||
| /* | ||||
|  *       _____  _       _    _____                                _ | ||||
|  *      |  __ \| |     | |  / ____|                              | | | ||||
|  *      | |__) | | ___ | |_| (___   __ _ _   _  __ _ _ __ ___  __| | | ||||
|  *      |  ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | | ||||
|  *      | |    | | (_) | |_ ____) | (_| | |_| | (_| | | |  __/ (_| | | ||||
|  *      |_|    |_|\___/ \__|_____/ \__, |\__,_|\__,_|_|  \___|\__,_| | ||||
|  *                                    | | | ||||
|  *                                    |_| | ||||
|  *            PlotSquared plot management system for Minecraft | ||||
|  *               Copyright (C) 2014 - 2022 IntellectualSites | ||||
|  * | ||||
|  *     This program is free software: you can redistribute it and/or modify | ||||
|  *     it under the terms of the GNU General Public License as published by | ||||
|  *     the Free Software Foundation, either version 3 of the License, or | ||||
|  *     (at your option) any later version. | ||||
|  * | ||||
|  *     This program is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public License | ||||
|  *     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.location; | ||||
|  | ||||
| import com.plotsquared.core.util.AnnotationHelper; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| /** | ||||
|  * Used internally for generation to reference locations in worlds that "don't exist yet". There is no guarantee that the world | ||||
|  * name provided by {@link UncheckedWorldLocation#getWorldName()} exists on the server. | ||||
|  * | ||||
|  * @since TODO | ||||
|  */ | ||||
| @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
| public final class UncheckedWorldLocation extends Location { | ||||
|  | ||||
|     private final String worldName; | ||||
|  | ||||
|     /** | ||||
|      * @since TODO | ||||
|      */ | ||||
|     private UncheckedWorldLocation( | ||||
|             final @NonNull String worldName, final int x, final int y, final int z | ||||
|     ) { | ||||
|         super(World.nullWorld(), BlockVector3.at(x, y, z), 0f, 0f); | ||||
|         this.worldName = worldName; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Construct a new location with yaw and pitch equal to 0 | ||||
|      * | ||||
|      * @param world World | ||||
|      * @param x     X coordinate | ||||
|      * @param y     Y coordinate | ||||
|      * @param z     Z coordinate | ||||
|      * @return New location | ||||
|      * | ||||
|      * @since TODO | ||||
|      */ | ||||
|     @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
|     public static @NonNull UncheckedWorldLocation at( | ||||
|             final @NonNull String world, final int x, final int y, final int z | ||||
|     ) { | ||||
|         return new UncheckedWorldLocation(world, x, y, z); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
|     public @NonNull String getWorldName() { | ||||
|         return this.worldName; | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user