Plot analysis (#2239)

* Start to fix (and may have fixed) plot analysis with block buxkets and 1.13

* Standard deviation ought also be multiplied by 100, and only obtain the BlockBucket array once

* Add schematics to Plot Analysis
Add generateBlockBucketChunk method to SingleWorldGenerator
This commit is contained in:
dordsor21 2019-01-17 01:04:00 +00:00 committed by GitHub
parent 0817d7de5a
commit 223064567f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 377 additions and 251 deletions

View File

@ -4,6 +4,7 @@ import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.bukkit.util.block.GenChunk;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotWorld;
import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator;
@ -28,7 +29,6 @@ public class BukkitPlotGenerator extends ChunkGenerator
private final IndependentPlotGenerator plotGenerator;
private final ChunkGenerator platformGenerator;
private final boolean full;
private final HashMap<ChunkLoc, byte[][]> dataMap = new HashMap<>();
private List<BlockPopulator> populators;
private boolean loaded = false;
@ -89,6 +89,30 @@ public class BukkitPlotGenerator extends ChunkGenerator
.getNewPlotArea(world, id, min, max);
}
@Override public BlockBucket[][] generateBlockBucketChunk(PlotArea settings) {
BlockBucket[][] blockBuckets = new BlockBucket[16][];
HybridPlotWorld hpw = (HybridPlotWorld) settings;
// Bedrock
if (hpw.PLOT_BEDROCK) {
for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) {
blockBuckets[0][(z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get("bedrock"));
}
}
}
for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) {
for (int y = 1; y < hpw.PLOT_HEIGHT; y++) {
blockBuckets[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = hpw.MAIN_BLOCK;
}
blockBuckets[hpw.PLOT_HEIGHT >> 4][((hpw.PLOT_HEIGHT & 0xF) << 8) | (z << 4)
| x] = hpw.MAIN_BLOCK;
}
}
return blockBuckets;
}
@Override
public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings) {
World w = BukkitUtil.getWorld(world);

View File

@ -1,9 +1,26 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotWorld;
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
import com.github.intellectualsites.plotsquared.plot.object.RegionWrapper;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.MathMan;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.expiry.PlotAnalysis;
import com.sk89q.worldedit.world.block.BaseBlock;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.generator.ChunkGenerator;
import java.util.HashSet;
public class BukkitHybridUtils extends HybridUtils {
@ -21,23 +38,13 @@ public class BukkitHybridUtils extends HybridUtils {
* - recheck each block
*
*/
/* TODO: Redo
TaskManager.runTaskAsync(new Runnable() {
@Override public void run() {
TaskManager.runTaskAsync(() -> {
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
final World worldObj = Bukkit.getWorld(world);
final ChunkGenerator gen = worldObj.getGenerator();
if (gen == null) {
final ChunkGenerator chunkGenerator = worldObj.getGenerator();
if (!(chunkGenerator instanceof BukkitPlotGenerator)) {
return;
}
final BiomeGrid nullBiomeGrid = new BiomeGrid() {
@Override public void setBiome(int a, int b, Biome c) {
}
@Override public Biome getBiome(int a, int b) {
return null;
}
};
final Location bot = new Location(world, region.minX, region.minY, region.minZ);
final Location top = new Location(world, region.maxX, region.maxY, region.maxZ);
@ -50,25 +57,71 @@ public class BukkitHybridUtils extends HybridUtils {
final int cbz = bz >> 4;
final int ctx = tx >> 4;
final int ctz = tz >> 4;
final Random r = new Random();
MainUtil.initCache();
final int width = tx - bx + 1;
final int length = tz - bz + 1;
System.gc();
System.gc();
final short[][][] oldBlocks = new short[256][width][length];
final short[][][] newBlocks = new short[256][width][length];
final BlockBucket[][][] oldBlocks = new BlockBucket[256][width][length];
final PlotBlock[][][] newBlocks = new PlotBlock[256][width][length];
final Runnable run = new Runnable() {
@Override public void run() {
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
PlotArea area = PlotSquared.get().getPlotArea(world, null);
if (!(area instanceof HybridPlotWorld))
return;
HybridPlotWorld hpw = (HybridPlotWorld) area;
final BlockBucket[][] result = hpw.getBlockBucketChunk();
if (hpw.PLOT_SCHEMATIC) {
short[] rx = new short[16];
short[] rz = new short[16];
short rbx;
short rbz;
if (bx < 0) {
rbx = (short) (hpw.SIZE + (bx % hpw.SIZE));
} else {
rbx = (short) (bx % hpw.SIZE);
}
if (bz < 0) {
rbz = (short) (hpw.SIZE + (bz % hpw.SIZE));
} else {
rbz = (short) (bz % hpw.SIZE);
}
for (short i = 0; i < 16; i++) {
short v = (short) (rbx + i);
if (v >= hpw.SIZE) {
v -= hpw.SIZE;
}
rx[i] = v;
}
for (short i = 0; i < 16; i++) {
short v = (short) (rbz + i);
if (v >= hpw.SIZE) {
v -= hpw.SIZE;
}
rz[i] = v;
}
int minY = Math.min(hpw.PLOT_HEIGHT, hpw.ROAD_HEIGHT);
for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) {
BaseBlock[] blocks = hpw.G_SCH.get(MathMan.pair(rx[x], rz[z]));
for (int y = 0; y < blocks.length; y++) {
if (blocks[y] != null) {
result[(minY + y) >> 4][(((minY + y) & 0xF) << 8) | (z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get(blocks[y]));
}
}
}
}
}
final Runnable run = () -> ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
// [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
int X = value[0];
int Z = value[1];
short[][] result =
gen.generateExtBlockSections(worldObj, r, X, Z, nullBiomeGrid);
int xb = (X << 4) - bx;
int zb = (Z << 4) - bz;
for (int i = 0; i < result.length; i++) {
@ -83,7 +136,8 @@ public class BukkitHybridUtils extends HybridUtils {
continue;
}
int y = MainUtil.y_loc[i][j];
oldBlocks[y][x][z] = 0;
oldBlocks[y][x][z] =
BlockBucket.withSingle(StringPlotBlock.EVERYTHING);
}
continue;
}
@ -102,10 +156,7 @@ public class BukkitHybridUtils extends HybridUtils {
}
}
}, new Runnable() {
@Override public void run() {
TaskManager.runTaskAsync(new Runnable() {
@Override public void run() {
}, () -> TaskManager.runTaskAsync(() -> {
int size = width * length;
int[] changes = new int[size];
int[] faces = new int[size];
@ -115,49 +166,46 @@ public class BukkitHybridUtils extends HybridUtils {
int i = 0;
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {
HashSet<Short> types = new HashSet<>();
HashSet<PlotBlock> types = new HashSet<>();
for (int y = 0; y < 256; y++) {
short old = oldBlocks[y][x][z];
short now = newBlocks[y][x][z];
if (old != now) {
BlockBucket old = oldBlocks[y][x][z];
PlotBlock now = newBlocks[y][x][z];
if (!old.getBlocks().contains(now)) {
changes[i]++;
}
if (now == 0) {
if (now.isAir()) {
air[i]++;
} else {
// check vertices
// modifications_adjacent
if (x > 0 && z > 0 && y > 0 && x < width - 1
&& z < length - 1 && y < 255) {
if (newBlocks[y - 1][x][z] == 0) {
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1
&& y < 255) {
if (newBlocks[y - 1][x][z].isAir()) {
faces[i]++;
}
if (newBlocks[y][x - 1][z] == 0) {
if (newBlocks[y][x - 1][z].isAir()) {
faces[i]++;
}
if (newBlocks[y][x][z - 1] == 0) {
if (newBlocks[y][x][z - 1].isAir()) {
faces[i]++;
}
if (newBlocks[y + 1][x][z] == 0) {
if (newBlocks[y + 1][x][z].isAir()) {
faces[i]++;
}
if (newBlocks[y][x + 1][z] == 0) {
if (newBlocks[y][x + 1][z].isAir()) {
faces[i]++;
}
if (newBlocks[y][x][z + 1] == 0) {
if (newBlocks[y][x][z + 1].isAir()) {
faces[i]++;
}
}
Material material =
Material.getMaterial(now);
Material material = now.to(Material.class);
if (material != null) {
Class<? extends MaterialData> md =
material.getData();
if (md.equals(Directional.class)) {
BlockData blockData = material.createBlockData();
if (blockData instanceof Directional) {
data[i] += 8;
} else if (!md
.equals(MaterialData.class)) {
} else if (!blockData.getClass().equals(BlockData.class)) {
data[i]++;
}
}
@ -179,29 +227,19 @@ public class BukkitHybridUtils extends HybridUtils {
analysis.air = (int) (MathMan.getMean(air) * 100);
analysis.variety = (int) (MathMan.getMean(variety) * 100);
analysis.changes_sd =
(int) MathMan.getSD(changes, analysis.changes);
analysis.faces_sd =
(int) MathMan.getSD(faces, analysis.faces);
analysis.data_sd = (int) MathMan.getSD(data, analysis.data);
analysis.air_sd = (int) MathMan.getSD(air, analysis.air);
analysis.variety_sd =
(int) MathMan.getSD(variety, analysis.variety);
analysis.changes_sd = (int) (MathMan.getSD(changes, analysis.changes) * 100);
analysis.faces_sd = (int) (MathMan.getSD(faces, analysis.faces) * 100);
analysis.data_sd = (int) (MathMan.getSD(data, analysis.data) * 100);
analysis.air_sd = (int) (MathMan.getSD(air, analysis.air) * 100);
analysis.variety_sd = (int) (MathMan.getSD(variety, analysis.variety) * 100);
System.gc();
System.gc();
whenDone.value = analysis;
whenDone.run();
}
});
}
}, 5);
}
};
}), 5);
System.gc();
MainUtil.initCache();
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
int X = value[0];
int Z = value[1];
@ -244,19 +282,13 @@ public class BukkitHybridUtils extends HybridUtils {
PlotBlock block = queue.getBlock(xx, y, zz);
int xr = xb + x;
int zr = zb + z;
newBlocks[y][xr][zr] = block.id;
newBlocks[y][xr][zr] = block;
}
}
}
worldObj.unloadChunkRequest(X, Z, true);
}
}, new Runnable() {
@Override public void run() {
TaskManager.runTaskAsync(run);
}
}, 5);
}
}, () -> TaskManager.runTaskAsync(run), 5);
});
*/
}
}

View File

@ -27,6 +27,30 @@ public class HybridGen extends IndependentPlotGenerator {
}
}
@Override public BlockBucket[][] generateBlockBucketChunk(PlotArea settings) {
BlockBucket[][] blockBuckets = new BlockBucket[16][];
HybridPlotWorld hpw = (HybridPlotWorld) settings;
// Bedrock
if (hpw.PLOT_BEDROCK) {
for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) {
blockBuckets[0][(z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get("bedrock"));
}
}
}
for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) {
for (int y = 1; y < hpw.PLOT_HEIGHT; y++) {
blockBuckets[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = hpw.MAIN_BLOCK;
}
blockBuckets[hpw.PLOT_HEIGHT >> 4][((hpw.PLOT_HEIGHT & 0xF) << 8) | (z << 4) | x] =
hpw.MAIN_BLOCK;
}
}
return blockBuckets;
}
@Override public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings) {
HybridPlotWorld hpw = (HybridPlotWorld) settings;
// Biome
@ -41,8 +65,6 @@ public class HybridGen extends IndependentPlotGenerator {
}
// Coords
Location min = result.getMin();
int cx = min.getX() >> 4;
int cz = min.getZ() >> 4;
int bx = (min.getX()) - hpw.ROAD_OFFSET_X;
int bz = (min.getZ()) - hpw.ROAD_OFFSET_Z;
short rbx;

View File

@ -1,10 +1,7 @@
package com.github.intellectualsites.plotsquared.plot.generator;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.object.PlotManager;
import com.github.intellectualsites.plotsquared.plot.object.SetupObject;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue;
/**
@ -19,6 +16,14 @@ public abstract class IndependentPlotGenerator {
*/
public abstract String getName();
/**
* Generates a 16x4096 array of BlockBuckets corresponding to the area settings to allow for plot analysis
*
* @param settings
* @return
*/
public abstract BlockBucket[][] generateBlockBucketChunk(PlotArea settings);
/**
* 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.

View File

@ -14,6 +14,7 @@ import com.github.intellectualsites.plotsquared.plot.util.*;
import com.github.intellectualsites.plotsquared.plot.util.area.QuadMap;
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import lombok.Getter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -34,6 +35,7 @@ public abstract class PlotArea {
private final PlotId min;
private final PlotId max;
private final IndependentPlotGenerator generator;
@Getter private final BlockBucket[][] blockBucketChunk;
public int MAX_PLOT_MEMBERS = 128;
public boolean AUTO_MERGE = false;
public boolean ALLOW_SIGNS = true;
@ -66,8 +68,9 @@ public abstract class PlotArea {
private ConcurrentHashMap<String, Object> meta;
private QuadMap<PlotCluster> clusters;
public PlotArea(@Nonnull final String worldName, @Nullable final String id, @Nullable IndependentPlotGenerator generator,
@Nullable final PlotId min, @Nullable final PlotId max) {
public PlotArea(@Nonnull final String worldName, @Nullable final String id,
@Nullable IndependentPlotGenerator generator, @Nullable final PlotId min,
@Nullable final PlotId max) {
this.worldname = worldName;
this.id = id;
this.manager = generator != null ? generator.getNewPlotManager() : null;
@ -84,6 +87,11 @@ public abstract class PlotArea {
this.max = max;
}
this.worldhash = worldName.hashCode();
if (Settings.Enabled_Components.PLOT_EXPIRY) {
blockBucketChunk = generator.generateBlockBucketChunk(this);
} else {
blockBucketChunk = null;
}
}
/**
@ -591,7 +599,8 @@ public abstract class PlotArea {
return this.clusters != null ? this.clusters.get(plot.getId().x, plot.getId().y) : null;
}
@Nullable public PlotCluster getFirstIntersectingCluster(@Nonnull final PlotId pos1, @Nonnull final PlotId pos2) {
@Nullable public PlotCluster getFirstIntersectingCluster(@Nonnull final PlotId pos1,
@Nonnull final PlotId pos2) {
if (this.clusters == null) {
return null;
}
@ -615,6 +624,7 @@ public abstract class PlotArea {
* Session only plot metadata (session is until the server stops).
* <br>
* For persistent metadata use the flag system
*
* @see FlagManager
*/
public void setMeta(@Nonnull final String key, @Nullable final Object value) {

View File

@ -17,6 +17,39 @@ public class SingleWorldGenerator extends IndependentPlotGenerator {
return "PlotSquared:single";
}
@Override public BlockBucket[][] generateBlockBucketChunk(PlotArea settings) {
BlockBucket[][] blockBuckets = new BlockBucket[16][];
SinglePlotArea area = (SinglePlotArea) settings;
if (area.VOID) {
return blockBuckets;
}
for (int x = bedrock1.getX(); x <= bedrock2.getX(); x++) {
for (int z = bedrock1.getZ(); z <= bedrock2.getZ(); z++) {
for (int y = bedrock1.getY(); y <= bedrock2.getY(); y++) {
blockBuckets[y >> 4][((y & 0xF) << 8) | (z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get("bedrock"));
}
}
}
for (int x = dirt1.getX(); x <= dirt2.getX(); x++) {
for (int z = dirt1.getZ(); z <= dirt2.getZ(); z++) {
for (int y = dirt1.getY(); y <= dirt2.getY(); y++) {
blockBuckets[y >> 4][((y & 0xF) << 8) | (z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get("dirt"));
}
}
}
for (int x = grass1.getX(); x <= grass2.getX(); x++) {
for (int z = grass1.getZ(); z <= grass2.getZ(); z++) {
for (int y = grass1.getY(); y <= grass2.getY(); y++) {
blockBuckets[y >> 4][((y & 0xF) << 8) | (z << 4) | x] =
BlockBucket.withSingle(PlotBlock.get("grass_block"));
}
}
}
return blockBuckets;
}
@Override public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings) {
SinglePlotArea area = (SinglePlotArea) settings;
if (area.VOID) {
@ -25,9 +58,9 @@ public class SingleWorldGenerator extends IndependentPlotGenerator {
result.setBlock(0, 0, 0, PlotBlock.get("bedrock"));
}
} else {
result.setCuboid(bedrock1, bedrock2, PlotBlock.get(7, 0));
result.setCuboid(dirt1, dirt2, PlotBlock.get(3, 0));
result.setCuboid(grass1, grass2, PlotBlock.get(2, 0));
result.setCuboid(bedrock1, bedrock2, PlotBlock.get("bedrock"));
result.setCuboid(dirt1, dirt2, PlotBlock.get("dirt"));
result.setCuboid(grass1, grass2, PlotBlock.get("grass_block"));
}
result.fillBiome("PLAINS");
}