PlotSquared/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java

347 lines
13 KiB
Java
Raw Normal View History

/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* 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.util;
2020-07-10 22:12:37 +02:00
import com.google.inject.Inject;
import com.google.inject.Singleton;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.generator.AugmentedUtils;
2020-10-09 17:34:59 +02:00
import com.plotsquared.core.inject.factory.ProgressSubscriberFactory;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.PlotLoc;
2020-09-11 13:59:40 +02:00
import com.plotsquared.core.player.PlotPlayer;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
2020-07-01 22:36:46 +02:00
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
2015-07-30 16:25:16 +02:00
2019-11-04 18:44:23 +01:00
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
2016-07-25 07:19:29 +02:00
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 BukkitRegionManager extends RegionManager {
2020-07-10 22:12:37 +02:00
private final GlobalBlockQueue blockQueue;
@Inject
public BukkitRegionManager(
@NonNull WorldUtil worldUtil, @NonNull GlobalBlockQueue blockQueue, @NonNull
ProgressSubscriberFactory subscriberFactory
) {
2020-10-09 17:34:59 +02:00
super(worldUtil, blockQueue, subscriberFactory);
this.blockQueue = blockQueue;
}
2016-03-29 09:43:57 +02:00
2020-09-11 13:59:40 +02:00
@Override
public boolean handleClear(
@NonNull Plot plot,
@Nullable Runnable whenDone,
@NonNull PlotManager manager,
@Nullable PlotPlayer<?> player
) {
2020-07-01 22:36:46 +02:00
return false;
}
@Override
public int[] countEntities(@NonNull Plot plot) {
int[] existing = (int[]) plot.getMeta("EntityCount");
2020-09-11 13:59:40 +02:00
if (existing != null && (System.currentTimeMillis() - (long) plot.getMeta("EntityCountTime") < 1000)) {
return existing;
}
PlotArea area = plot.getArea();
World world = BukkitUtil.getWorld(area.getWorldName());
Location bot = plot.getBottomAbs();
Location top = plot.getTopAbs();
int bx = bot.getX() >> 4;
int bz = bot.getZ() >> 4;
int tx = top.getX() >> 4;
int tz = top.getZ() >> 4;
int size = tx - bx << 4;
Set<Chunk> chunks = new HashSet<>();
for (int X = bx; X <= tx; X++) {
for (int Z = bz; Z <= tz; Z++) {
if (world.isChunkLoaded(X, Z)) {
chunks.add(world.getChunkAt(X, Z));
}
}
}
boolean doWhole = false;
List<Entity> entities = null;
if (size > 200 && chunks.size() > 200) {
entities = world.getEntities();
if (entities.size() < 16 + size / 8) {
doWhole = true;
}
}
int[] count = new int[6];
if (doWhole) {
for (Entity entity : entities) {
org.bukkit.Location location = entity.getLocation();
2020-04-30 12:01:52 +02:00
PaperLib.getChunkAtAsync(location).thenAccept(chunk -> {
if (chunks.contains(chunk)) {
int X = chunk.getX();
int Z = chunk.getZ();
if (X > bx && X < tx && Z > bz && Z < tz) {
count(count, entity);
} else {
Plot other = area.getPlot(BukkitUtil.adapt(location));
if (plot.equals(other)) {
count(count, entity);
}
}
}
});
}
} else {
for (Chunk chunk : chunks) {
int X = chunk.getX();
int Z = chunk.getZ();
Entity[] entities1 = chunk.getEntities();
for (Entity entity : entities1) {
if (X == bx || X == tx || Z == bz || Z == tz) {
Plot other = area.getPlot(BukkitUtil.adapt(entity.getLocation()));
if (plot.equals(other)) {
count(count, entity);
}
} else {
count(count, entity);
}
}
}
}
return count;
}
@Override
public boolean regenerateRegion(
final @NonNull Location pos1,
final @NonNull Location pos2,
final boolean ignoreAugment,
final @Nullable Runnable whenDone
) {
2021-09-15 14:19:25 +02:00
final BukkitWorld world = (BukkitWorld) worldUtil.getWeWorld(pos1.getWorldName());
final int p1x = pos1.getX();
final int p1z = pos1.getZ();
final int p2x = pos2.getX();
final int p2z = pos2.getZ();
final int bcx = p1x >> 4;
final int bcz = p1z >> 4;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
final QueueCoordinator queue = blockQueue.getNewQueue(world);
final QueueCoordinator regenQueue = blockQueue.getNewQueue(world);
2020-09-11 13:59:40 +02:00
queue.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
queue.setChunkConsumer(chunk -> {
int x = chunk.getX();
int z = chunk.getZ();
int xxb = x << 4;
int zzb = z << 4;
int xxt = xxb + 15;
int zzt = zzb + 15;
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
2020-09-11 13:59:40 +02:00
AugmentedUtils.bypass(ignoreAugment, () -> regenQueue.regenChunk(chunk.getX(), chunk.getZ()));
return;
2015-02-23 06:29:45 +01:00
}
boolean checkX1 = false;
int xxb2;
if (x == bcx) {
xxb2 = p1x - 1;
checkX1 = true;
} else {
xxb2 = xxb;
}
boolean checkX2 = false;
int xxt2;
if (x == tcx) {
xxt2 = p2x + 1;
checkX2 = true;
} else {
xxt2 = xxt;
}
boolean checkZ1 = false;
int zzb2;
if (z == bcz) {
zzb2 = p1z - 1;
checkZ1 = true;
} else {
zzb2 = zzb;
}
boolean checkZ2 = false;
int zzt2;
if (z == tcz) {
zzt2 = p2z + 1;
checkZ2 = true;
} else {
zzt2 = zzt;
}
final ContentMap map = new ContentMap();
if (checkX1) {
map.saveRegion(world, xxb, xxb2, zzb2, zzt2); //
}
if (checkX2) {
map.saveRegion(world, xxt2, xxt, zzb2, zzt2); //
}
if (checkZ1) {
map.saveRegion(world, xxb2, xxt2, zzb, zzb2); //
}
if (checkZ2) {
map.saveRegion(world, xxb2, xxt2, zzt2, zzt); //
}
if (checkX1 && checkZ1) {
map.saveRegion(world, xxb, xxb2, zzb, zzb2); //
}
if (checkX2 && checkZ1) {
map.saveRegion(world, xxt2, xxt, zzb, zzb2); // ?
}
if (checkX1 && checkZ2) {
map.saveRegion(world, xxb, xxb2, zzt2, zzt); // ?
}
if (checkX2 && checkZ2) {
map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
}
Implement extended world heights from Y-64 to Y319 #3473 (#3473) * Begin to implement extended world heights: - Implemented in Bukkit module (and where required in Core module) * Implement extended world heights into core module * Add min gen height to setup, * Default gen/build heights based on minecraft version * Few fixes * Fix up queues * Address comments * Make road schematic stuff slightly more efficient by sharing queues * Minor fixes, don't overlay error many times for the same y * Fix incorrect schematic paste height, undo changes to HybridUtils * Overhall regenallroads method to make it work, make sure BukkitChunkCoordinator can/will finish * Process chunks in order when regenerating all roads * Address comments * Address comments * Ground level//bedrock is at min gen height - Add comment on == rather than <= being used - It's because it's only checking for the bedrock layer being broken if that's disabled * Fix offset for min build height in SchematicHandler * Better javadoc Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com> * Address inclusivity issues for max world height * Javadocs/comments/deprecation * Use world min/max heights if present in QueueCoordinator * Address some deprecations for regions and biome setting * Add a count for chunks we're currently trying to load to not skip chunks at the end of a queue's edit * Use minGenHeight + 1 rather than build height in AugmentedUtils * Create utility method for layer index in GenChunk * Correct height in HybridUtils, also use minGenHeight + 1 * Don't magically split to 128 height in regeneration * Add utility methods for world height in QueueCoordinator * Clean up ClassicPlotManager road creation/removal * Start generation at min gen height if bedrock is disabled * min gen height is set in PlotArea * Add note on schem y normalisation * Improve plot getVolume method readability * Don't overly extend height when regenerating road region * y index utility method in ChunknQueueCoordinator * Layer index utility method in LocalChunk * Use version min/max heights if world not present in QueueCoordinator * Fix min -> max * Don't allow players to modify outside build height when using plot set / schematics. - Also fixes schematic height issues * Remove debug * Address comments * Switch loadingChunks to AtomicInteger to be safe (in case of multi-threaded) * Fix "security" issue that was already present * Ensure sign isn't physicsed Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2022-03-05 19:03:39 +01:00
CuboidRegion currentPlotClear = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3());
2020-09-11 13:59:40 +02:00
map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), currentPlotClear);
AugmentedUtils.bypass(
ignoreAugment,
() -> ChunkManager.setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
@Override
public void run(ScopedQueueCoordinator value) {
Location min = value.getMin();
int bx = min.getX();
int bz = min.getZ();
for (int x1 = 0; x1 < 16; x1++) {
for (int z1 = 0; z1 < 16; z1++) {
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
BaseBlock[] ids = map.allBlocks.get(plotLoc);
if (ids != null) {
Implement extended world heights from Y-64 to Y319 #3473 (#3473) * Begin to implement extended world heights: - Implemented in Bukkit module (and where required in Core module) * Implement extended world heights into core module * Add min gen height to setup, * Default gen/build heights based on minecraft version * Few fixes * Fix up queues * Address comments * Make road schematic stuff slightly more efficient by sharing queues * Minor fixes, don't overlay error many times for the same y * Fix incorrect schematic paste height, undo changes to HybridUtils * Overhall regenallroads method to make it work, make sure BukkitChunkCoordinator can/will finish * Process chunks in order when regenerating all roads * Address comments * Address comments * Ground level//bedrock is at min gen height - Add comment on == rather than <= being used - It's because it's only checking for the bedrock layer being broken if that's disabled * Fix offset for min build height in SchematicHandler * Better javadoc Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com> * Address inclusivity issues for max world height * Javadocs/comments/deprecation * Use world min/max heights if present in QueueCoordinator * Address some deprecations for regions and biome setting * Add a count for chunks we're currently trying to load to not skip chunks at the end of a queue's edit * Use minGenHeight + 1 rather than build height in AugmentedUtils * Create utility method for layer index in GenChunk * Correct height in HybridUtils, also use minGenHeight + 1 * Don't magically split to 128 height in regeneration * Add utility methods for world height in QueueCoordinator * Clean up ClassicPlotManager road creation/removal * Start generation at min gen height if bedrock is disabled * min gen height is set in PlotArea * Add note on schem y normalisation * Improve plot getVolume method readability * Don't overly extend height when regenerating road region * y index utility method in ChunknQueueCoordinator * Layer index utility method in LocalChunk * Use version min/max heights if world not present in QueueCoordinator * Fix min -> max * Don't allow players to modify outside build height when using plot set / schematics. - Also fixes schematic height issues * Remove debug * Address comments * Switch loadingChunks to AtomicInteger to be safe (in case of multi-threaded) * Fix "security" issue that was already present * Ensure sign isn't physicsed Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2022-03-05 19:03:39 +01:00
int minY = value.getMin().getY();
for (int yIndex = 0; yIndex < ids.length; yIndex++) {
int y = yIndex + minY;
BaseBlock id = ids[yIndex];
if (id != null) {
value.setBlock(x1, y, z1, id);
} else {
value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState());
}
}
}
}
}
}
}, world.getName(), chunk)
);
//map.restoreBlocks(worldObj, 0, 0);
Implement extended world heights from Y-64 to Y319 #3473 (#3473) * Begin to implement extended world heights: - Implemented in Bukkit module (and where required in Core module) * Implement extended world heights into core module * Add min gen height to setup, * Default gen/build heights based on minecraft version * Few fixes * Fix up queues * Address comments * Make road schematic stuff slightly more efficient by sharing queues * Minor fixes, don't overlay error many times for the same y * Fix incorrect schematic paste height, undo changes to HybridUtils * Overhall regenallroads method to make it work, make sure BukkitChunkCoordinator can/will finish * Process chunks in order when regenerating all roads * Address comments * Address comments * Ground level//bedrock is at min gen height - Add comment on == rather than <= being used - It's because it's only checking for the bedrock layer being broken if that's disabled * Fix offset for min build height in SchematicHandler * Better javadoc Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com> * Address inclusivity issues for max world height * Javadocs/comments/deprecation * Use world min/max heights if present in QueueCoordinator * Address some deprecations for regions and biome setting * Add a count for chunks we're currently trying to load to not skip chunks at the end of a queue's edit * Use minGenHeight + 1 rather than build height in AugmentedUtils * Create utility method for layer index in GenChunk * Correct height in HybridUtils, also use minGenHeight + 1 * Don't magically split to 128 height in regeneration * Add utility methods for world height in QueueCoordinator * Clean up ClassicPlotManager road creation/removal * Start generation at min gen height if bedrock is disabled * min gen height is set in PlotArea * Add note on schem y normalisation * Improve plot getVolume method readability * Don't overly extend height when regenerating road region * y index utility method in ChunknQueueCoordinator * Layer index utility method in LocalChunk * Use version min/max heights if world not present in QueueCoordinator * Fix min -> max * Don't allow players to modify outside build height when using plot set / schematics. - Also fixes schematic height issues * Remove debug * Address comments * Switch loadingChunks to AtomicInteger to be safe (in case of multi-threaded) * Fix "security" issue that was already present * Ensure sign isn't physicsed Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2022-03-05 19:03:39 +01:00
map.restoreEntities(Bukkit.getWorld(world.getName()));
});
regenQueue.setCompleteTask(whenDone);
queue.setCompleteTask(regenQueue::enqueue);
queue.enqueue();
return true;
}
@Override
public void clearAllEntities(@NonNull Location pos1, @NonNull Location pos2) {
String world = pos1.getWorldName();
final World bukkitWorld = BukkitUtil.getWorld(world);
final List<Entity> entities;
if (bukkitWorld != null) {
entities = new ArrayList<>(bukkitWorld.getEntities());
} else {
entities = new ArrayList<>();
}
int bx = pos1.getX();
int bz = pos1.getZ();
int tx = pos2.getX();
int tz = pos2.getZ();
for (Entity entity : entities) {
if (!(entity instanceof Player)) {
2016-06-02 17:38:47 +02:00
org.bukkit.Location location = entity.getLocation();
2020-09-11 13:59:40 +02:00
if (location.getX() >= bx && location.getX() <= tx && location.getZ() >= bz && location.getZ() <= tz) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
entity.remove();
2015-02-23 06:29:45 +01:00
}
}
}
}
private void count(int[] count, @NonNull Entity entity) {
2020-09-11 13:59:40 +02:00
final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(entity.getType());
if (EntityCategories.PLAYER.contains(entityType)) {
return;
2020-09-11 13:59:40 +02:00
} else if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER.contains(entityType) || EntityCategories.HANGING
.contains(entityType)) {
count[CAP_MISC]++;
2020-09-11 13:59:40 +02:00
} 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]++;
}
2015-02-23 06:29:45 +01:00
}