/* * _____ _ _ _____ _ * | __ \| | | | / ____| | | * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| * | | * |_| * PlotSquared plot management system for Minecraft * Copyright (C) 2020 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 . */ package com.plotsquared.bukkit.util; import com.google.inject.Singleton; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.listener.WEExtent; import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.block.BaseBlock; import io.papermc.lib.PaperLib; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import java.util.concurrent.CompletableFuture; import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL; import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY; import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC; import static com.plotsquared.core.util.entity.EntityCategories.CAP_MOB; import static com.plotsquared.core.util.entity.EntityCategories.CAP_MONSTER; import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; @Singleton public class BukkitChunkManager extends ChunkManager { public static boolean isIn(CuboidRegion region, int x, int z) { return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX() && z >= region.getMinimumPoint().getZ() && z <= region.getMaximumPoint().getZ(); } public static ContentMap swapChunk(World world1, World world2, Chunk pos1, Chunk pos2, CuboidRegion r1, CuboidRegion r2) { ContentMap map = new ContentMap(); int relX = r2.getMinimumPoint().getX() - r1.getMinimumPoint().getX(); int relZ = r2.getMinimumPoint().getZ() - r1.getMinimumPoint().getZ(); map.saveEntitiesIn(pos1, r1, relX, relZ, true); map.saveEntitiesIn(pos2, r2, -relX, -relZ, true); int sx = pos1.getX() << 4; int sz = pos1.getZ() << 4; String worldName1 = world1.getName(); String worldName2 = world2.getName(); BukkitWorld bukkitWorld1 = new BukkitWorld(world1); BukkitWorld bukkitWorld2 = new BukkitWorld(world2); LocalBlockQueue queue1 = GlobalBlockQueue.IMP.getNewQueue(worldName1, false); LocalBlockQueue queue2 = GlobalBlockQueue.IMP.getNewQueue(worldName2, false); for (int x = Math.max(r1.getMinimumPoint().getX(), sx); x <= Math.min(r1.getMaximumPoint().getX(), sx + 15); x++) { for (int z = Math.max(r1.getMinimumPoint().getZ(), sz); z <= Math.min(r1.getMaximumPoint().getZ(), sz + 15); z++) { for (int y = 0; y < 256; y++) { Block block1 = world1.getBlockAt(x, y, z); BaseBlock baseBlock1 = bukkitWorld1.getFullBlock(BlockVector3.at(x, y, z)); BlockData data1 = block1.getBlockData(); int xx = x + relX; int zz = z + relZ; Block block2 = world2.getBlockAt(xx, y, zz); BaseBlock baseBlock2 = bukkitWorld2.getFullBlock(BlockVector3.at(xx, y, zz)); BlockData data2 = block2.getBlockData(); if (block1.isEmpty()) { if (!block2.isEmpty()) { queue1.setBlock(x, y, z, baseBlock2); queue2.setBlock(xx, y, zz, WEExtent.AIRBASE); } } else if (block2.isEmpty()) { queue1.setBlock(x, y, z, WEExtent.AIRBASE); queue2.setBlock(xx, y, zz, baseBlock1); } else if (block1.equals(block2)) { if (!data1.matches(data2)) { block1.setBlockData(data2); block2.setBlockData(data1); } } else { queue1.setBlock(x, y, z, baseBlock2); queue2.setBlock(xx, y, zz, baseBlock1); } } } } queue1.enqueue(); queue2.enqueue(); return map; } @Override public CompletableFuture loadChunk(String world, BlockVector2 chunkLoc, boolean force) { return PaperLib .getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force); } @Override public void unloadChunk(final String world, final BlockVector2 chunkLoc, final boolean save) { if (!PlotSquared.get().isMainThread(Thread.currentThread())) { TaskManager.runTask(() -> BukkitUtil.getWorld(world) .unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save)); } else { BukkitUtil.getWorld(world).unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save); } } private void count(int[] count, Entity entity) { final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(entity.getType()); if (EntityCategories.PLAYER.contains(entityType)) { return; } else if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER .contains(entityType) || EntityCategories.HANGING.contains(entityType)) { count[CAP_MISC]++; } else if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER .contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) { count[CAP_MOB]++; count[CAP_ANIMAL]++; } else if (EntityCategories.VEHICLE.contains(entityType)) { count[CAP_VEHICLE]++; } else if (EntityCategories.HOSTILE.contains(entityType)) { count[CAP_MOB]++; count[CAP_MONSTER]++; } count[CAP_ENTITY]++; } }