mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-06-29 04:04:43 +02:00
Move all files! Hahah
This commit is contained in:
@ -0,0 +1,287 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.BlockWrapper;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.PlotCluster;
|
||||
import com.intellectualcrafters.plot.object.PlotGenerator;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.bukkit.BukkitChunkManager;
|
||||
import com.intellectualcrafters.plot.util.bukkit.BukkitSetBlockManager;
|
||||
|
||||
public class AugmentedPopulator extends BlockPopulator {
|
||||
public static short[][] x_loc;
|
||||
public static short[][] y_loc;
|
||||
public static short[][] z_loc;
|
||||
public final PlotWorld plotworld;
|
||||
public final PlotManager manager;
|
||||
public final PlotGenerator generator;
|
||||
public final PlotCluster cluster;
|
||||
public final Random r = new Random();
|
||||
public final boolean p;
|
||||
public final boolean b;
|
||||
public final boolean o;
|
||||
private final int bx;
|
||||
private final int bz;
|
||||
private final int tx;
|
||||
private final int tz;
|
||||
|
||||
public AugmentedPopulator(final String world, final PlotGenerator generator, final PlotCluster cluster, final boolean p, final boolean b) {
|
||||
initCache();
|
||||
this.cluster = cluster;
|
||||
this.generator = generator;
|
||||
this.plotworld = PS.get().getPlotWorld(world);
|
||||
this.manager = generator.getPlotManager();
|
||||
this.p = p;
|
||||
this.b = b;
|
||||
this.o = (this.plotworld.TERRAIN == 1) || (this.plotworld.TERRAIN == 2);
|
||||
final World bukkitWorld = Bukkit.getWorld(world);
|
||||
if (cluster != null) {
|
||||
final Location bl = this.manager.getPlotBottomLocAbs(this.plotworld, cluster.getP1());
|
||||
final Location tl = this.manager.getPlotTopLocAbs(this.plotworld, cluster.getP2()).add(1, 0, 1);
|
||||
this.bx = bl.getX();
|
||||
this.bz = bl.getZ();
|
||||
this.tx = tl.getX();
|
||||
this.tz = tl.getZ();
|
||||
} else {
|
||||
this.bx = Integer.MIN_VALUE;
|
||||
this.bz = Integer.MIN_VALUE;
|
||||
this.tx = Integer.MAX_VALUE;
|
||||
this.tz = Integer.MAX_VALUE;
|
||||
}
|
||||
// Add the populator
|
||||
if (this.o) {
|
||||
bukkitWorld.getPopulators().add(0, this);
|
||||
} else {
|
||||
bukkitWorld.getPopulators().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removePopulator(final String worldname, final PlotCluster cluster) {
|
||||
final World world = Bukkit.getWorld(worldname);
|
||||
for (final Iterator<BlockPopulator> iterator = world.getPopulators().iterator(); iterator.hasNext();) {
|
||||
final BlockPopulator populator = iterator.next();
|
||||
if (populator instanceof AugmentedPopulator) {
|
||||
if (((AugmentedPopulator) populator).cluster.equals(cluster)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void initCache() {
|
||||
if (x_loc == null) {
|
||||
x_loc = new short[16][4096];
|
||||
y_loc = new short[16][4096];
|
||||
z_loc = new short[16][4096];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int i4 = i << 4;
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
final int y = (i4) + (j >> 8);
|
||||
final int a = (j - ((y & 0xF) << 8));
|
||||
final int z1 = (a >> 4);
|
||||
final int x1 = a - (z1 << 4);
|
||||
x_loc[i][j] = (short) x1;
|
||||
y_loc[i][j] = (short) y;
|
||||
z_loc[i][j] = (short) z1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockWrapper get(final int x, final int z, final int i, final int j, final short[][] r, final boolean c) {
|
||||
final int y = (i << 4) + (j >> 8);
|
||||
final int a = (j - ((y & 0xF) << 8));
|
||||
final int z1 = (a >> 4);
|
||||
final int x1 = a - (z1 << 4);
|
||||
if (r[i] == null) {
|
||||
return (c && (((z + z1) < this.bz) || ((z + z1) > this.tz) || ((x + x1) < this.bx) || ((x + x1) > this.tx))) ? null : new BlockWrapper(x1, y, z1, (short) 0, (byte) 0);
|
||||
} else {
|
||||
return (c && (((z + z1) < this.bz) || ((z + z1) > this.tz) || ((x + x1) < this.bx) || ((x + x1) > this.tx))) ? null : new BlockWrapper(x1, y, z1, r[i][j], (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(final World world, final Random rand, final Chunk chunk) {
|
||||
if (this.plotworld.TERRAIN == 3) {
|
||||
int X = chunk.getX() << 4;
|
||||
int Z = chunk.getZ() << 4;
|
||||
if (ChunkManager.FORCE_PASTE) {
|
||||
for (short x = 0; x < 16; x++) {
|
||||
for (short z = 0; z < 16; z++) {
|
||||
final PlotLoc loc = new PlotLoc((short) (X + x), (short) (Z + z));
|
||||
final HashMap<Short, Short> blocks = ChunkManager.GENERATE_BLOCKS.get(loc);
|
||||
HashMap<Short, Byte> datas = ChunkManager.GENERATE_DATA.get(loc);
|
||||
for (final Entry<Short, Short> entry : blocks.entrySet()) {
|
||||
int y = entry.getKey();
|
||||
byte data;
|
||||
if (datas != null) {
|
||||
data = datas.get(y);
|
||||
}
|
||||
else {
|
||||
data = 0;
|
||||
}
|
||||
BukkitSetBlockManager.setBlockManager.set(world, x, y, z, blocks.get(y), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ChunkManager.CURRENT_PLOT_CLEAR != null) {
|
||||
PlotLoc loc;
|
||||
for (Entry<PlotLoc, HashMap<Short, Byte>> entry : ChunkManager.GENERATE_DATA.entrySet()) {
|
||||
HashMap<Short, Byte> datas = ChunkManager.GENERATE_DATA.get(entry.getKey());
|
||||
for (Entry<Short, Byte> entry2 : entry.getValue().entrySet()) {
|
||||
Short y = entry2.getKey();
|
||||
byte data;
|
||||
if (datas != null) {
|
||||
data = datas.get(y);
|
||||
}
|
||||
else {
|
||||
data = 0;
|
||||
}
|
||||
loc = entry.getKey();
|
||||
int xx = loc.x - X;
|
||||
int zz = loc.z - Z;
|
||||
if (xx >= 0 && xx < 16) {
|
||||
if (zz >= 0 && zz < 16) {
|
||||
BukkitSetBlockManager.setBlockManager.set(world, xx, y, zz, entry2.getValue(), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
final int X = chunk.getX();
|
||||
final int Z = chunk.getZ();
|
||||
final int x = X << 4;
|
||||
final int z = Z << 4;
|
||||
final int x2 = x + 15;
|
||||
final int z2 = z + 15;
|
||||
final boolean inX1 = ((x >= this.bx) && (x <= this.tx));
|
||||
final boolean inX2 = ((x2 >= this.bx) && (x2 <= this.tx));
|
||||
final boolean inZ1 = ((z >= this.bz) && (z <= this.tz));
|
||||
final boolean inZ2 = ((z2 >= this.bz) && (z2 <= this.tz));
|
||||
final boolean inX = inX1 || inX2;
|
||||
final boolean inZ = inZ1 || inZ2;
|
||||
if (!inX || !inZ) {
|
||||
return;
|
||||
}
|
||||
final boolean check;
|
||||
check = !inX1 || !inX2 || !inZ1 || !inZ2;
|
||||
if (this.plotworld.TERRAIN > 1) {
|
||||
final PlotId plot1 = this.manager.getPlotIdAbs(this.plotworld, x, 0, z);
|
||||
final PlotId plot2 = this.manager.getPlotIdAbs(this.plotworld, x2, 0, z2);
|
||||
if ((plot1 != null) && (plot2 != null) && plot1.equals(plot2)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.o) {
|
||||
populateBlocks(world, rand, X, Z, x, z, check);
|
||||
} else {
|
||||
TaskManager.runTaskLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
populateBiome(world, x, z);
|
||||
}
|
||||
}, 20 + rand.nextInt(10));
|
||||
TaskManager.runTaskLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chunk.load(true);
|
||||
populateBlocks(world, rand, X, Z, x, z, check);
|
||||
}
|
||||
}, 40 + rand.nextInt(40));
|
||||
}
|
||||
}
|
||||
|
||||
private void populateBiome(final World world, final int x, final int z) {
|
||||
final Biome biome = Biome.valueOf(this.plotworld.PLOT_BIOME);
|
||||
if (this.b) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
world.setBiome(x + i, z + j, biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateBlocks(final World world, final Random rand, final int X, final int Z, final int x, final int z, final boolean check) {
|
||||
final short[][] result = this.generator.generateExtBlockSections(world, rand, X, Z, null);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
if (result[i] != null) {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x1 = x_loc[i][j];
|
||||
int y = y_loc[i][j];
|
||||
int z1 = z_loc[i][j];
|
||||
short id = result[i][j];
|
||||
final int xx = x + x1;
|
||||
final int zz = z + z1;
|
||||
if (check && (((zz) < this.bz) || ((zz) > this.tz) || ((xx) < this.bx) || ((xx) > this.tx))) {
|
||||
continue;
|
||||
}
|
||||
if (this.p) {
|
||||
if (ChunkManager.CURRENT_PLOT_CLEAR != null) {
|
||||
if (BukkitChunkManager.isIn(ChunkManager.CURRENT_PLOT_CLEAR, xx, zz)) {
|
||||
continue;
|
||||
}
|
||||
} else if (this.manager.getPlotIdAbs(this.plotworld, xx, 0, zz) != null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BukkitSetBlockManager.setBlockManager.set(world, xx, y, zz, id, (byte) 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
short y_min = y_loc[i][0];
|
||||
if (y_min < 128) {
|
||||
for (int x1 = x; x1 < x + 16; x1++) {
|
||||
for (int z1 = z; z1 < z + 16; z1++) {
|
||||
if (check && (((z1) < this.bz) || ((z1) > this.tz) || ((x1) < this.bx) || ((x1) > this.tx))) {
|
||||
continue;
|
||||
}
|
||||
if (this.p) {
|
||||
if (ChunkManager.CURRENT_PLOT_CLEAR != null) {
|
||||
if (BukkitChunkManager.isIn(ChunkManager.CURRENT_PLOT_CLEAR, x1, z1)) {
|
||||
continue;
|
||||
}
|
||||
} else if (this.manager.getPlotIdAbs(this.plotworld, x1, 0, z1) != null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (int y = y_min; y < y_min + 16; y++) {
|
||||
BukkitSetBlockManager.setBlockManager.set(world, x1, y, z1, 0, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final BlockPopulator populator : this.generator.getPopulators(world.getName())) {
|
||||
Chunk chunk = world.getChunkAt(X, Z);
|
||||
populator.populate(world, this.r, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIn(final RegionWrapper plot, final int x, final int z) {
|
||||
return ((x >= plot.minX) && (x <= plot.maxX) && (z >= plot.minZ) && (z <= plot.maxZ));
|
||||
}
|
||||
}
|
@ -0,0 +1,508 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableInt;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
import org.bukkit.material.Directional;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.intellectualcrafters.plot.BukkitMain;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotAnalysis;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.bukkit.BukkitUtil;
|
||||
|
||||
public class BukkitHybridUtils extends HybridUtils {
|
||||
|
||||
public static List<ChunkLoc> regions;
|
||||
public static List<ChunkLoc> chunks = new ArrayList<>();
|
||||
public static String world;
|
||||
private static boolean UPDATE = false;
|
||||
public int task;
|
||||
private long last;
|
||||
|
||||
public double getMean(int[] array) {
|
||||
double count = 0;
|
||||
for (int i : array) {
|
||||
count += i;
|
||||
}
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public double getMean(double[] array) {
|
||||
double count = 0;
|
||||
for (double i : array) {
|
||||
count += i;
|
||||
}
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public double getSD(double[] array, double av) {
|
||||
double sd = 0;
|
||||
for (int i=0; i<array.length;i++)
|
||||
{
|
||||
sd += Math.pow(Math.abs(array[i] - av), 2);
|
||||
}
|
||||
return Math.sqrt(sd/array.length);
|
||||
}
|
||||
|
||||
public double getSD(int[] array, double av) {
|
||||
double sd = 0;
|
||||
for (int i=0; i<array.length;i++)
|
||||
{
|
||||
sd += Math.pow(Math.abs(array[i] - av), 2);
|
||||
}
|
||||
return Math.sqrt(sd/array.length);
|
||||
}
|
||||
|
||||
public int mod(int x) {
|
||||
if (x < 0) {
|
||||
return (x % 16) + 16;
|
||||
}
|
||||
return x % 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzePlot(Plot plot, final RunnableVal<PlotAnalysis> whenDone) {
|
||||
// TODO Auto-generated method stub
|
||||
// int diff, int variety, int verticies, int rotation, int height_sd
|
||||
|
||||
/*
|
||||
* diff: compare to base by looping through all blocks
|
||||
* variety: add to hashset for each plotblock
|
||||
* height_sd: loop over all blocks and get top block
|
||||
*
|
||||
* verticies: store air map and compare with neighbours
|
||||
* for each block check the adjacent
|
||||
* - Store all blocks then go through in second loop
|
||||
* - recheck each block
|
||||
*
|
||||
*/
|
||||
final World world = Bukkit.getWorld(plot.world);
|
||||
final ChunkGenerator gen = world.getGenerator();
|
||||
if (gen == null) {
|
||||
return;
|
||||
}
|
||||
final BiomeGrid base = new BiomeGrid() { @Override public void setBiome(int a, int b, Biome c) {} @Override public Biome getBiome(int a, int b) {return null;}};
|
||||
Location bot = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1, 0, 1);
|
||||
Location top = MainUtil.getPlotTopLoc(plot.world, plot.id);
|
||||
final int bx = bot.getX();
|
||||
final int bz = bot.getZ();
|
||||
final int tx = top.getX();
|
||||
final int tz = top.getZ();
|
||||
final int cbx = bx >> 4;
|
||||
final int cbz = bz >> 4;
|
||||
final int ctx = tx >> 4;
|
||||
final int ctz = tz >> 4;
|
||||
final Random r = new Random();
|
||||
AugmentedPopulator.initCache();
|
||||
|
||||
final int width = tx - bx + 1;
|
||||
final int length = tz - bz + 1;
|
||||
|
||||
final short[][][] oldblocks = new short[256][width][length];
|
||||
final short[][][] newblocks = new short[256][width][length];
|
||||
|
||||
final List<Chunk> chunks = new ArrayList<>();
|
||||
final List<Chunk> processed_chunks = new ArrayList<>();
|
||||
|
||||
for (int X = cbx; X <= ctx; X++) {
|
||||
for (int Z = cbz; Z <= ctz; Z++) {
|
||||
Chunk chunk = world.getChunkAt(X, Z);
|
||||
chunks.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
final Runnable run = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int t = 0;
|
||||
for (Chunk chunk : processed_chunks) {
|
||||
short[][] result = gen.generateExtBlockSections(world, r, chunk.getX(), chunk.getZ(), base);
|
||||
int X = chunk.getX();
|
||||
int Z = chunk.getZ();
|
||||
int xb = ((X - cbx) << 4) - bx;
|
||||
int zb = ((Z - cbz) << 4) - bz;
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
if (result[i] == null) {
|
||||
for (int j = 0; j < 4096; j++) {
|
||||
int x = AugmentedPopulator.x_loc[i][j] + xb;
|
||||
if (x < 0 || x >= width) continue;
|
||||
int z = AugmentedPopulator.z_loc[i][j] + zb;
|
||||
if (z < 0 || z >= length) continue;
|
||||
int y = AugmentedPopulator.y_loc[i][j];
|
||||
oldblocks[y][x][z] = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < result[i].length; j++) {
|
||||
int x = AugmentedPopulator.x_loc[i][j] + xb;
|
||||
if (x < 0 || x >= width) continue;
|
||||
int z = AugmentedPopulator.z_loc[i][j] + zb;
|
||||
if (z < 0 || z >= length) continue;
|
||||
int y = AugmentedPopulator.y_loc[i][j];
|
||||
oldblocks[y][x][z] = result[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = width * length;
|
||||
int[] changes = new int[size];
|
||||
int[] faces = new int[size];
|
||||
int[] data = new int[size];
|
||||
int[] air = new int[size];
|
||||
int[] variety = new int[size];
|
||||
|
||||
int i = 0;
|
||||
for (int x = 0; x < width;x++) {
|
||||
for (int z = 0; z < length;z++) {
|
||||
HashSet<Short> 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) {
|
||||
t++;
|
||||
changes[i]++;
|
||||
}
|
||||
if (now == 0) {
|
||||
air[i]++;
|
||||
}
|
||||
else {
|
||||
// check verticies
|
||||
// modifications_adjacent
|
||||
|
||||
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1 && y < 255) {
|
||||
if (oldblocks[y - 1][x][z] == 0) faces[i]++;
|
||||
if (oldblocks[y][x - 1][z] == 0) faces[i]++;
|
||||
if (oldblocks[y][x][z - 1] == 0) faces[i]++;
|
||||
if (oldblocks[y + 1][x][z] == 0) faces[i]++;
|
||||
if (oldblocks[y][x + 1][z] == 0) faces[i]++;
|
||||
if (oldblocks[y][x][z + 1] == 0) faces[i]++;
|
||||
}
|
||||
|
||||
Material material = Material.getMaterial(now);
|
||||
Class<? extends MaterialData> md = material.getData();
|
||||
if (md.equals(Directional.class)) {
|
||||
data[i] += 8;
|
||||
}
|
||||
else if (!md.equals(MaterialData.class)) {
|
||||
data[i]++;
|
||||
}
|
||||
types.add(now);
|
||||
}
|
||||
}
|
||||
variety[i] = types.size();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// analyze plot
|
||||
// put in analysis obj
|
||||
|
||||
// run whenDone
|
||||
PlotAnalysis analysis = new PlotAnalysis();
|
||||
analysis.changes = getMean(changes);
|
||||
analysis.faces = getMean(faces);
|
||||
analysis.data = getMean(data);
|
||||
analysis.air = getMean(air);
|
||||
analysis.variety = getMean(variety);
|
||||
analysis.complexity = getSD(changes, analysis.changes) + getSD(faces, analysis.faces) + getSD(data, analysis.data) + getSD(air, analysis.air) + getSD(variety, analysis.variety);
|
||||
whenDone.value = analysis;
|
||||
whenDone.run();
|
||||
}
|
||||
};
|
||||
|
||||
System.gc();
|
||||
AugmentedPopulator.initCache();
|
||||
|
||||
TaskManager.index.increment();
|
||||
final Integer currentIndex = TaskManager.index.toInteger();
|
||||
final Integer task = TaskManager.runTaskRepeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int index = chunks.size() - 1;
|
||||
if (index == -1) {
|
||||
PS.get().TASK.cancelTask(TaskManager.tasks.get(currentIndex));
|
||||
TaskManager.runTaskAsync(run);
|
||||
return;
|
||||
}
|
||||
Chunk chunk = chunks.remove(0);
|
||||
processed_chunks.add(chunk);
|
||||
int X = chunk.getX();
|
||||
int Z = chunk.getZ();
|
||||
short[][] current = new short[16][];
|
||||
int minX;
|
||||
int minZ;
|
||||
int maxX;
|
||||
int maxZ;
|
||||
if (X == cbx) minX = mod(bx);
|
||||
else minX = 0;
|
||||
if (Z == cbz) minZ = mod(bz);
|
||||
else minZ = 0;
|
||||
if (X == ctx) maxX = mod(tx);
|
||||
else maxX = 16;
|
||||
if (Z == ctz) maxZ = mod(tz);
|
||||
else maxZ = 16;
|
||||
|
||||
int xb = ((X - cbx) << 4) - bx;
|
||||
int zb = ((Z - cbz) << 4) - bz;
|
||||
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
Block block = chunk.getBlock(x, y, z);
|
||||
int xx = xb + x;
|
||||
int zz = zb + z;
|
||||
newblocks[y][xx][zz] = (short) block.getTypeId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
TaskManager.tasks.put(currentIndex, task);
|
||||
}
|
||||
|
||||
public void checkModified(final Plot plot, final RunnableVal<Integer> whenDone) {
|
||||
TaskManager.index.increment();
|
||||
final Location bot = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1, 0, 1);
|
||||
final Location top = MainUtil.getPlotTopLoc(plot.world, plot.id);
|
||||
int bx = bot.getX() >> 4;
|
||||
int bz = bot.getZ() >> 4;
|
||||
int tx = top.getX() >> 4;
|
||||
int tz = top.getZ() >> 4;
|
||||
World world = BukkitUtil.getWorld(plot.world);
|
||||
final HashSet<Chunk> chunks = new HashSet<>();
|
||||
for (int X = bx; X <= tx; X++) {
|
||||
for (int Z = bz; Z <= tz; Z++) {
|
||||
chunks.add(world.getChunkAt(X,Z));
|
||||
}
|
||||
}
|
||||
PlotWorld plotworld = PS.get().getPlotWorld(plot.world);
|
||||
if (!(plotworld instanceof ClassicPlotWorld)) {
|
||||
whenDone.value = -1;
|
||||
TaskManager.runTaskLater(whenDone, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
final ClassicPlotWorld cpw = (ClassicPlotWorld) plotworld;
|
||||
|
||||
final MutableInt count = new MutableInt(0);
|
||||
|
||||
final Integer currentIndex = TaskManager.index.toInteger();
|
||||
final Integer task = TaskManager.runTaskRepeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (chunks.size() == 0) {
|
||||
whenDone.value = count.intValue();
|
||||
TaskManager.runTaskLater(whenDone, 1);
|
||||
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
|
||||
TaskManager.tasks.remove(currentIndex);
|
||||
return;
|
||||
}
|
||||
Iterator<Chunk> iter = chunks.iterator();
|
||||
final Chunk chunk = iter.next();
|
||||
iter.remove();
|
||||
int bx = Math.max(chunk.getX() << 4, bot.getX());
|
||||
int bz = Math.max(chunk.getZ() << 4, bot.getZ());
|
||||
int ex = Math.min((chunk.getX() << 4) + 15, top.getX());
|
||||
int ez = Math.min((chunk.getZ() << 4) + 15, top.getZ());
|
||||
// count changes
|
||||
count.add(checkModified(plot.world, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK));
|
||||
count.add(checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK));
|
||||
count.add(checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, new PlotBlock[] { new PlotBlock((short) 0, (byte) 0) }));
|
||||
}
|
||||
}, 1);
|
||||
TaskManager.tasks.put(currentIndex, task);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkModified(final String worldname, final int x1, final int x2, final int y1, final int y2, final int z1, final int z2, final PlotBlock[] blocks) {
|
||||
final World world = BukkitUtil.getWorld(worldname);
|
||||
int count = 0;
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
for (int z = z1; z <= z2; z++) {
|
||||
final Block block = world.getBlockAt(x, y, z);
|
||||
final int id = block.getTypeId();
|
||||
boolean same = false;
|
||||
for (final PlotBlock p : blocks) {
|
||||
if (id == p.id) {
|
||||
same = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!same) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_ey(final String worldname, final int sx, final int ex, final int sz, final int ez, final int sy) {
|
||||
final World world = BukkitUtil.getWorld(worldname);
|
||||
final int maxY = world.getMaxHeight();
|
||||
int ey = sy;
|
||||
for (int x = sx; x <= ex; x++) {
|
||||
for (int z = sz; z <= ez; z++) {
|
||||
for (int y = sy; y < maxY; y++) {
|
||||
if (y > ey) {
|
||||
final Block block = world.getBlockAt(x, y, z);
|
||||
if (block.getTypeId() != 0) {
|
||||
ey = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ey;
|
||||
}
|
||||
|
||||
public void regenerateChunkChunk(final String worldname, final ChunkLoc loc) {
|
||||
final World world = BukkitUtil.getWorld(worldname);
|
||||
final int sx = loc.x << 5;
|
||||
final int sz = loc.z << 5;
|
||||
for (int x = sx; x < (sx + 32); x++) {
|
||||
for (int z = sz; z < (sz + 32); z++) {
|
||||
final Chunk chunk = world.getChunkAt(x, z);
|
||||
chunk.load(false);
|
||||
}
|
||||
}
|
||||
final ArrayList<Chunk> chunks2 = new ArrayList<>();
|
||||
for (int x = sx; x < (sx + 32); x++) {
|
||||
for (int z = sz; z < (sz + 32); z++) {
|
||||
final Chunk chunk = world.getChunkAt(x, z);
|
||||
chunks2.add(chunk);
|
||||
regenerateRoad(worldname, new ChunkLoc(x, z), 0);
|
||||
MainUtil.update(world.getName(), new ChunkLoc(chunk.getX(), chunk.getZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final ArrayList<ChunkLoc> getChunks(ChunkLoc region) {
|
||||
ArrayList<ChunkLoc> chunks = new ArrayList<ChunkLoc>();
|
||||
final int sx = region.x << 5;
|
||||
final int sz = region.z << 5;
|
||||
for (int x = sx; x < (sx + 32); x++) {
|
||||
for (int z = sz; z < (sz + 32); z++) {
|
||||
chunks.add(new ChunkLoc(x, z));
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scheduleRoadUpdate(final String world, int extend) {
|
||||
if (BukkitHybridUtils.UPDATE) {
|
||||
return false;
|
||||
}
|
||||
BukkitHybridUtils.UPDATE = true;
|
||||
final List<ChunkLoc> regions = ChunkManager.manager.getChunkChunks(world);
|
||||
return scheduleRoadUpdate(world, regions, extend);
|
||||
}
|
||||
|
||||
public boolean scheduleRoadUpdate(final String world, final List<ChunkLoc> rgs, final int extend) {
|
||||
BukkitHybridUtils.regions = rgs;
|
||||
BukkitHybridUtils.world = world;
|
||||
chunks = new ArrayList<ChunkLoc>();
|
||||
final Plugin plugin = BukkitMain.THIS;
|
||||
final MutableInt count = new MutableInt(0);
|
||||
this.task = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
count.increment();
|
||||
if (count.intValue() % 20 == 0) {
|
||||
PS.log("PROGRESS: " + ((100 * (2048 - chunks.size())) / 2048) + "%");
|
||||
}
|
||||
if (regions.size() == 0 && chunks.size() == 0) {
|
||||
BukkitHybridUtils.UPDATE = false;
|
||||
PS.log(C.PREFIX.s() + "Finished road conversion");
|
||||
Bukkit.getScheduler().cancelTask(BukkitHybridUtils.this.task);
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
if (chunks.size() < 1024) {
|
||||
if (regions.size() > 0) {
|
||||
final ChunkLoc loc = regions.get(0);
|
||||
PS.log("&3Updating .mcr: " + loc.x + ", " + loc.z + " (aprrox 1024 chunks)");
|
||||
PS.log(" - Remaining: " + regions.size());
|
||||
chunks.addAll(getChunks(loc));
|
||||
regions.remove(0);
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
if (chunks.size() > 0) {
|
||||
long diff = System.currentTimeMillis() + 25;
|
||||
if (System.currentTimeMillis() - last > 1200 && last != 0) {
|
||||
last = 0;
|
||||
PS.log(C.PREFIX.s() + "Detected low TPS. Rescheduling in 30s");
|
||||
while (chunks.size() > 0) {
|
||||
ChunkLoc chunk = chunks.get(0);
|
||||
chunks.remove(0);
|
||||
regenerateRoad(world, chunk, extend);
|
||||
ChunkManager.manager.unloadChunk(world, chunk);
|
||||
}
|
||||
Bukkit.getScheduler().cancelTask(BukkitHybridUtils.this.task);
|
||||
TaskManager.runTaskLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scheduleRoadUpdate(world, regions, extend);
|
||||
}
|
||||
}, 600);
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() - last < 1000) {
|
||||
while (System.currentTimeMillis() < diff && chunks.size() > 0) {
|
||||
ChunkLoc chunk = chunks.get(0);
|
||||
chunks.remove(0);
|
||||
regenerateRoad(world, chunk, extend);
|
||||
ChunkManager.manager.unloadChunk(world, chunk);
|
||||
}
|
||||
}
|
||||
last = System.currentTimeMillis();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
final ChunkLoc loc = regions.get(0);
|
||||
PS.log("&c[ERROR]&7 Could not update '" + world + "/region/r." + loc.x + "." + loc.z + ".mca' (Corrupt chunk?)");
|
||||
final int sx = loc.x << 5;
|
||||
final int sz = loc.z << 5;
|
||||
for (int x = sx; x < (sx + 32); x++) {
|
||||
for (int z = sz; z < (sz + 32); z++) {
|
||||
ChunkManager.manager.unloadChunk(world, new ChunkLoc(x, z));
|
||||
}
|
||||
}
|
||||
PS.log("&d - Potentially skipping 1024 chunks");
|
||||
PS.log("&d - TODO: recommend chunkster if corrupt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 20, 20);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SetBlockQueue;
|
||||
|
||||
/**
|
||||
* A plot manager with square plots which tesselate on a square grid with the following sections: ROAD, WALL, BORDER (wall), PLOT, FLOOR (plot)
|
||||
*/
|
||||
public abstract class ClassicPlotManager extends SquarePlotManager {
|
||||
@Override
|
||||
public boolean setComponent(final PlotWorld plotworld, final PlotId plotid, final String component, final PlotBlock[] blocks) {
|
||||
switch (component) {
|
||||
case "floor": {
|
||||
setFloor(plotworld, plotid, blocks);
|
||||
return true;
|
||||
}
|
||||
case "wall": {
|
||||
setWallFilling(plotworld, plotid, blocks);
|
||||
return true;
|
||||
}
|
||||
case "border": {
|
||||
setWall(plotworld, plotid, blocks);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setFloor(final PlotWorld plotworld, final PlotId plotid, final PlotBlock[] blocks) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos1 = MainUtil.getPlotBottomLoc(plotworld.worldname, plotid).add(1, 0, 1);
|
||||
final Location pos2 = MainUtil.getPlotTopLoc(plotworld.worldname, plotid).add(1, 0, 1);
|
||||
pos1.setY(dpw.PLOT_HEIGHT);
|
||||
pos2.setY(dpw.PLOT_HEIGHT + 1);
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, pos1, pos2, blocks);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setWallFilling(final PlotWorld plotworld, final PlotId plotid, final PlotBlock[] blocks) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
if (dpw.ROAD_WIDTH == 0) {
|
||||
return false;
|
||||
}
|
||||
final Location bottom = MainUtil.getPlotBottomLoc(plotworld.worldname, plotid);
|
||||
final Location top = MainUtil.getPlotTopLoc(plotworld.worldname, plotid).add(1, 0, 1);
|
||||
int x, z;
|
||||
z = bottom.getZ();
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
for (x = bottom.getX(); x <= (top.getX() - 1); x++) {
|
||||
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
}
|
||||
x = top.getX();
|
||||
for (z = bottom.getZ(); z <= (top.getZ() - 1); z++) {
|
||||
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
}
|
||||
z = top.getZ();
|
||||
for (x = top.getX(); x >= (bottom.getX() + 1); x--) {
|
||||
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
}
|
||||
x = bottom.getX();
|
||||
for (z = top.getZ(); z >= (bottom.getZ() + 1); z--) {
|
||||
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setWall(final PlotWorld plotworld, final PlotId plotid, final PlotBlock[] blocks) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
if (dpw.ROAD_WIDTH == 0) {
|
||||
return false;
|
||||
}
|
||||
final Location bottom = MainUtil.getPlotBottomLoc(plotworld.worldname, plotid);
|
||||
final Location top = MainUtil.getPlotTopLoc(plotworld.worldname, plotid).add(1, 0, 1);
|
||||
int x, z;
|
||||
z = bottom.getZ();
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
final int y = dpw.WALL_HEIGHT + 1;
|
||||
for (x = bottom.getX(); x <= (top.getX() - 1); x++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
x = top.getX();
|
||||
for (z = bottom.getZ(); z <= (top.getZ() - 1); z++) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
z = top.getZ();
|
||||
for (x = top.getX(); x >= (bottom.getX() + 1); x--) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
x = bottom.getX();
|
||||
for (z = top.getZ(); z >= (bottom.getZ() + 1); z--) {
|
||||
SetBlockQueue.setBlock(plotworld.worldname, x, y, z, blocks[random.random(blocks.length)]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* PLOT MERGING
|
||||
*/
|
||||
@Override
|
||||
public boolean createRoadEast(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos1 = getPlotBottomLocAbs(plotworld, plot.id);
|
||||
final Location pos2 = getPlotTopLocAbs(plotworld, plot.id);
|
||||
final int sx = pos2.getX() + 1;
|
||||
final int ex = (sx + dpw.ROAD_WIDTH) - 1;
|
||||
final int sz = pos1.getZ() - 1;
|
||||
final int ez = pos2.getZ() + 2;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz + 1), new Location(plotworld.worldname, ex + 1, 257, ez), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, 1, sz + 1), new Location(plotworld.worldname, ex + 1, dpw.PLOT_HEIGHT, ez), new PlotBlock((short) 7, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, 1, sz + 1), new Location(plotworld.worldname, sx + 1, dpw.WALL_HEIGHT + 1, ez), dpw.WALL_FILLING);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, dpw.WALL_HEIGHT + 1, sz + 1), new Location(plotworld.worldname, sx + 1, dpw.WALL_HEIGHT + 2, ez), dpw.WALL_BLOCK);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, ex, 1, sz + 1), new Location(plotworld.worldname, ex + 1, dpw.WALL_HEIGHT + 1, ez), dpw.WALL_FILLING);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, ex, dpw.WALL_HEIGHT + 1, sz + 1), new Location(plotworld.worldname, ex + 1, dpw.WALL_HEIGHT + 2, ez), dpw.WALL_BLOCK);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, sz + 1), new Location(plotworld.worldname, ex, dpw.ROAD_HEIGHT + 1, ez), dpw.ROAD_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createRoadSouth(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos1 = getPlotBottomLocAbs(plotworld, plot.id);
|
||||
final Location pos2 = getPlotTopLocAbs(plotworld, plot.id);
|
||||
final int sz = pos2.getZ() + 1;
|
||||
final int ez = (sz + dpw.ROAD_WIDTH) - 1;
|
||||
final int sx = pos1.getX() - 1;
|
||||
final int ex = pos2.getX() + 2;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), new Location(plotworld.worldname, ex, 257, ez + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 0, sz), new Location(plotworld.worldname, ex, 1, ez + 1), new PlotBlock((short) 7, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, sz), new Location(plotworld.worldname, ex, dpw.WALL_HEIGHT + 1, sz + 1), dpw.WALL_FILLING);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, dpw.WALL_HEIGHT + 1, sz), new Location(plotworld.worldname, ex, dpw.WALL_HEIGHT + 2, sz + 1), dpw.WALL_BLOCK);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, ez), new Location(plotworld.worldname, ex, dpw.WALL_HEIGHT + 1, ez + 1), dpw.WALL_FILLING);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, dpw.WALL_HEIGHT + 1, ez), new Location(plotworld.worldname, ex, dpw.WALL_HEIGHT + 2, ez + 1), dpw.WALL_BLOCK);
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, sz + 1), new Location(plotworld.worldname, ex, dpw.ROAD_HEIGHT + 1, ez), dpw.ROAD_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createRoadSouthEast(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos2 = getPlotTopLocAbs(plotworld, plot.id);
|
||||
final int sx = pos2.getX() + 1;
|
||||
final int ex = (sx + dpw.ROAD_WIDTH) - 1;
|
||||
final int sz = pos2.getZ() + 1;
|
||||
final int ez = (sz + dpw.ROAD_WIDTH) - 1;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, dpw.ROAD_HEIGHT + 1, sz + 1), new Location(plotworld.worldname, ex, 257, ez), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 0, sz + 1), new Location(plotworld.worldname, ex, 1, ez), new PlotBlock((short) 7, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, sz + 1), new Location(plotworld.worldname, ex, dpw.ROAD_HEIGHT + 1, ez), dpw.ROAD_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRoadEast(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos1 = getPlotBottomLocAbs(plotworld, plot.id);
|
||||
final Location pos2 = getPlotTopLocAbs(plotworld, plot.id);
|
||||
final int sx = pos2.getX() + 1;
|
||||
final int ex = (sx + dpw.ROAD_WIDTH) - 1;
|
||||
final int sz = pos1.getZ();
|
||||
final int ez = pos2.getZ() + 1;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), new Location(plotworld.worldname, ex + 1, 257, ez + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, 1, sz + 1), new Location(plotworld.worldname, ex + 1, dpw.PLOT_HEIGHT, ez), dpw.MAIN_BLOCK);
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, dpw.PLOT_HEIGHT, sz + 1), new Location(plotworld.worldname, ex + 1, dpw.PLOT_HEIGHT + 1, ez), dpw.TOP_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRoadSouth(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location pos1 = getPlotBottomLocAbs(plotworld, plot.id);
|
||||
final Location pos2 = getPlotTopLocAbs(plotworld, plot.id);
|
||||
final int sz = pos2.getZ() + 1;
|
||||
final int ez = (sz + dpw.ROAD_WIDTH) - 1;
|
||||
final int sx = pos1.getX();
|
||||
final int ex = pos2.getX() + 1;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), new Location(plotworld.worldname, ex + 1, 257, ez + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, 1, sz), new Location(plotworld.worldname, ex, dpw.PLOT_HEIGHT, ez + 1), dpw.MAIN_BLOCK);
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx + 1, dpw.PLOT_HEIGHT, sz), new Location(plotworld.worldname, ex, dpw.PLOT_HEIGHT + 1, ez + 1), dpw.TOP_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRoadSouthEast(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location loc = getPlotTopLocAbs(dpw, plot.id);
|
||||
final int sx = loc.getX() + 1;
|
||||
final int ex = (sx + dpw.ROAD_WIDTH) - 1;
|
||||
final int sz = loc.getZ() + 1;
|
||||
final int ez = (sz + dpw.ROAD_WIDTH) - 1;
|
||||
MainUtil.setSimpleCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, dpw.ROAD_HEIGHT + 1, sz), new Location(plotworld.worldname, ex + 1, 257, ez + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, 1, sz), new Location(plotworld.worldname, ex + 1, dpw.ROAD_HEIGHT, ez + 1), dpw.MAIN_BLOCK);
|
||||
MainUtil.setCuboidAsync(plotworld.worldname, new Location(plotworld.worldname, sx, dpw.ROAD_HEIGHT, sz), new Location(plotworld.worldname, ex + 1, dpw.ROAD_HEIGHT + 1, ez + 1), dpw.TOP_BLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishing off plot merging by adding in the walls surrounding the plot (OPTIONAL)(UNFINISHED)
|
||||
*/
|
||||
@Override
|
||||
public boolean finishPlotMerge(final PlotWorld plotworld, final ArrayList<PlotId> plotIds) {
|
||||
final PlotId pos1 = plotIds.get(0);
|
||||
final PlotBlock block = ((ClassicPlotWorld) plotworld).CLAIMED_WALL_BLOCK;
|
||||
final PlotBlock unclaim = ((ClassicPlotWorld) plotworld).WALL_BLOCK;
|
||||
if (!block.equals(unclaim)) {
|
||||
setWall(plotworld, pos1, new PlotBlock[] { block });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishPlotUnlink(final PlotWorld plotworld, final ArrayList<PlotId> plotIds) {
|
||||
final PlotBlock block = ((ClassicPlotWorld) plotworld).CLAIMED_WALL_BLOCK;
|
||||
final PlotBlock unclaim = ((ClassicPlotWorld) plotworld).WALL_BLOCK;
|
||||
for (final PlotId id : plotIds) {
|
||||
if (block.id != 0 || !block.equals(unclaim)) {
|
||||
setWall(plotworld, id, new PlotBlock[] { block });
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startPlotMerge(final PlotWorld plotworld, final ArrayList<PlotId> plotIds) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startPlotUnlink(final PlotWorld plotworld, final ArrayList<PlotId> plotIds) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean claimPlot(final PlotWorld plotworld, final Plot plot) {
|
||||
final PlotBlock unclaim = ((ClassicPlotWorld) plotworld).WALL_BLOCK;
|
||||
final PlotBlock claim = ((ClassicPlotWorld) plotworld).CLAIMED_WALL_BLOCK;
|
||||
if (claim.id != 0 || !claim.equals(unclaim)) {
|
||||
setWall(plotworld, plot.id, new PlotBlock[] { claim });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unclaimPlot(final PlotWorld plotworld, final Plot plot) {
|
||||
final PlotBlock unclaim = ((ClassicPlotWorld) plotworld).WALL_BLOCK;
|
||||
final PlotBlock claim = ((ClassicPlotWorld) plotworld).CLAIMED_WALL_BLOCK;
|
||||
if (unclaim.id != 0 || !claim.equals(unclaim)) {
|
||||
setWall(plotworld, plot.id, new PlotBlock[] { unclaim });
|
||||
}
|
||||
MainUtil.removeSign(plot);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlotComponents(final PlotWorld plotworld, final PlotId plotid) {
|
||||
return new String[] { "floor", "wall", "border" };
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove sign for a plot
|
||||
*/
|
||||
@Override
|
||||
public Location getSignLoc(final PlotWorld plotworld, final Plot plot) {
|
||||
final ClassicPlotWorld dpw = (ClassicPlotWorld) plotworld;
|
||||
final Location bot = MainUtil.getPlotBottomLoc(plotworld.worldname, plot.id);
|
||||
return new com.intellectualcrafters.plot.object.Location(plotworld.worldname, bot.getX(), dpw.ROAD_HEIGHT + 1, bot.getZ() - 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.intellectualcrafters.configuration.ConfigurationSection;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Configuration;
|
||||
import com.intellectualcrafters.plot.config.ConfigurationNode;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
|
||||
public abstract class ClassicPlotWorld extends SquarePlotWorld {
|
||||
public static int ROAD_HEIGHT_DEFAULT = 64;
|
||||
public static int PLOT_HEIGHT_DEFAULT = 64;
|
||||
public static int WALL_HEIGHT_DEFAULT = 64;
|
||||
public static PlotBlock[] MAIN_BLOCK_DEFAULT = new PlotBlock[] { new PlotBlock((short) 1, (byte) 0) };
|
||||
public static PlotBlock[] TOP_BLOCK_DEFAULT = new PlotBlock[] { new PlotBlock((short) 2, (byte) 0) };
|
||||
public static PlotBlock WALL_BLOCK_DEFAULT = new PlotBlock((short) 44, (byte) 0);
|
||||
public final static PlotBlock CLAIMED_WALL_BLOCK_DEFAULT = new PlotBlock((short) 44, (byte) 1);
|
||||
public static PlotBlock WALL_FILLING_DEFAULT = new PlotBlock((short) 1, (byte) 0);
|
||||
public final static PlotBlock ROAD_BLOCK_DEFAULT = new PlotBlock((short) 155, (byte) 0);
|
||||
public int ROAD_HEIGHT;
|
||||
public int PLOT_HEIGHT;
|
||||
public int WALL_HEIGHT;
|
||||
public PlotBlock[] MAIN_BLOCK;
|
||||
public PlotBlock[] TOP_BLOCK;
|
||||
public PlotBlock WALL_BLOCK;
|
||||
public PlotBlock CLAIMED_WALL_BLOCK;
|
||||
public PlotBlock WALL_FILLING;
|
||||
public PlotBlock ROAD_BLOCK;
|
||||
public boolean PLOT_BEDROCK;
|
||||
|
||||
/**
|
||||
* CONFIG NODE | DEFAULT VALUE | DESCRIPTION | CONFIGURATION TYPE | REQUIRED FOR INITIAL SETUP
|
||||
*
|
||||
* Set the last boolean to false if you do not require a specific config node to be set while using the setup
|
||||
* command - this may be useful if a config value can be changed at a later date, and has no impact on the actual
|
||||
* world generation
|
||||
*/
|
||||
@Override
|
||||
public ConfigurationNode[] getSettingNodes() {
|
||||
return new ConfigurationNode[] { new ConfigurationNode("plot.height", ClassicPlotWorld.PLOT_HEIGHT_DEFAULT, "Plot height", Configuration.INTEGER, true), new ConfigurationNode("plot.size", SquarePlotWorld.PLOT_WIDTH_DEFAULT, "Plot width", Configuration.INTEGER, true), new ConfigurationNode("plot.filling", ClassicPlotWorld.MAIN_BLOCK_DEFAULT, "Plot block", Configuration.BLOCKLIST, true), new ConfigurationNode("plot.floor", ClassicPlotWorld.TOP_BLOCK_DEFAULT, "Plot floor block", Configuration.BLOCKLIST, true), new ConfigurationNode("wall.block", ClassicPlotWorld.WALL_BLOCK_DEFAULT, "Top wall block", Configuration.BLOCK, true), new ConfigurationNode("wall.block_claimed", ClassicPlotWorld.CLAIMED_WALL_BLOCK_DEFAULT, "Wall block (claimed)", Configuration.BLOCK, true), new ConfigurationNode("road.width", SquarePlotWorld.ROAD_WIDTH_DEFAULT, "Road width", Configuration.INTEGER, true),
|
||||
new ConfigurationNode("road.height", ClassicPlotWorld.ROAD_HEIGHT_DEFAULT, "Road height", Configuration.INTEGER, true), new ConfigurationNode("road.block", ClassicPlotWorld.ROAD_BLOCK_DEFAULT, "Road block", Configuration.BLOCK, true), new ConfigurationNode("wall.filling", ClassicPlotWorld.WALL_FILLING_DEFAULT, "Wall filling block", Configuration.BLOCK, true), new ConfigurationNode("wall.height", ClassicPlotWorld.WALL_HEIGHT_DEFAULT, "Wall height", Configuration.INTEGER, true), new ConfigurationNode("plot.bedrock", true, "Plot bedrock generation", Configuration.BOOLEAN, true) };
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a world loads. Make sure you set all your constants here. You are provided with the
|
||||
* configuration section for that specific world.
|
||||
*/
|
||||
@Override
|
||||
public void loadConfiguration(final ConfigurationSection config) {
|
||||
super.loadConfiguration(config);
|
||||
this.PLOT_BEDROCK = config.getBoolean("plot.bedrock");
|
||||
this.PLOT_HEIGHT = Math.min(255, config.getInt("plot.height"));
|
||||
this.MAIN_BLOCK = (PlotBlock[]) Configuration.BLOCKLIST.parseString(StringUtils.join(config.getStringList("plot.filling"), ','));
|
||||
this.TOP_BLOCK = (PlotBlock[]) Configuration.BLOCKLIST.parseString(StringUtils.join(config.getStringList("plot.floor"), ','));
|
||||
this.WALL_BLOCK = (PlotBlock) Configuration.BLOCK.parseString(config.getString("wall.block"));
|
||||
this.ROAD_HEIGHT = Math.min(255, config.getInt("road.height"));
|
||||
this.ROAD_BLOCK = (PlotBlock) Configuration.BLOCK.parseString(config.getString("road.block"));
|
||||
this.WALL_FILLING = (PlotBlock) Configuration.BLOCK.parseString(config.getString("wall.filling"));
|
||||
this.WALL_HEIGHT = Math.min(254, config.getInt("wall.height"));
|
||||
this.CLAIMED_WALL_BLOCK = (PlotBlock) Configuration.BLOCK.parseString(config.getString("wall.block_claimed"));
|
||||
}
|
||||
|
||||
public ClassicPlotWorld(final String worldname) {
|
||||
super(worldname);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
|
||||
/**
|
||||
* A plot manager where plots tessellate in a grid formation symmetrical about x=z
|
||||
*/
|
||||
public abstract class GridPlotManager extends PlotManager {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
|
||||
public abstract class GridPlotWorld extends PlotWorld {
|
||||
public short SIZE;
|
||||
|
||||
public GridPlotWorld(final String worldname) {
|
||||
super(worldname);
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlotSquared - A plot manager and world generator for the Bukkit API /
|
||||
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
|
||||
// /
|
||||
// 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, write to the Free Software Foundation, /
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
|
||||
// /
|
||||
// You can contact us via: support@intellectualsites.com /
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotGenerator;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PlotPopulator;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
|
||||
/**
|
||||
* The default generator is very messy, as we have decided to try externalize all calculations from within the loop. -
|
||||
* You will see a lot of slower implementations have a single for loop. - This is perfectly fine to do, it will just
|
||||
* mean world generation may take somewhat longer
|
||||
*
|
||||
* @author Citymonstret
|
||||
* @author Empire92
|
||||
*/
|
||||
public class HybridGen extends PlotGenerator {
|
||||
|
||||
public HybridGen(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to static to re-use the same managet for all Default World Generators
|
||||
*/
|
||||
private static PlotManager manager = null;
|
||||
/**
|
||||
* plotworld object
|
||||
*/
|
||||
public HybridPlotWorld plotworld = null;
|
||||
/**
|
||||
* Some generator specific variables (implementation dependent)
|
||||
*/
|
||||
int plotsize;
|
||||
int pathsize;
|
||||
short wall;
|
||||
short wallfilling;
|
||||
short roadblock;
|
||||
int size;
|
||||
Biome biome;
|
||||
int roadheight;
|
||||
int wallheight;
|
||||
int plotheight;
|
||||
short[] plotfloors;
|
||||
short[] filling;
|
||||
short pathWidthLower;
|
||||
short pathWidthUpper;
|
||||
boolean doState = false;
|
||||
int maxY = 0;
|
||||
|
||||
/**
|
||||
* Initialize variables, and create plotworld object used in calculations
|
||||
*/
|
||||
public void init(PlotWorld plotworld) {
|
||||
if (plotworld != null) {
|
||||
this.plotworld = (HybridPlotWorld) plotworld;
|
||||
}
|
||||
this.plotsize = this.plotworld.PLOT_WIDTH;
|
||||
this.pathsize = this.plotworld.ROAD_WIDTH;
|
||||
this.roadblock = this.plotworld.ROAD_BLOCK.id;
|
||||
this.wallfilling = this.plotworld.WALL_FILLING.id;
|
||||
this.size = this.pathsize + this.plotsize;
|
||||
this.wall = this.plotworld.WALL_BLOCK.id;
|
||||
this.plotfloors = new short[this.plotworld.TOP_BLOCK.length];
|
||||
for (int i = 0; i < this.plotworld.TOP_BLOCK.length; i++) {
|
||||
this.plotfloors[i] = this.plotworld.TOP_BLOCK[i].id;
|
||||
}
|
||||
this.filling = new short[this.plotworld.MAIN_BLOCK.length];
|
||||
for (int i = 0; i < this.plotworld.MAIN_BLOCK.length; i++) {
|
||||
this.filling[i] = this.plotworld.MAIN_BLOCK[i].id;
|
||||
}
|
||||
if ((this.filling.length > 1) || (this.plotfloors.length > 1)) {
|
||||
this.doState = true;
|
||||
}
|
||||
this.wallheight = this.plotworld.WALL_HEIGHT;
|
||||
this.roadheight = this.plotworld.ROAD_HEIGHT;
|
||||
this.plotheight = this.plotworld.PLOT_HEIGHT;
|
||||
if (this.pathsize == 0) {
|
||||
this.pathWidthLower = (short) -1;
|
||||
this.pathWidthUpper = (short) (this.plotsize + 1);
|
||||
}
|
||||
else {
|
||||
if ((this.pathsize % 2) == 0) {
|
||||
this.pathWidthLower = (short) (Math.floor(this.pathsize / 2) - 1);
|
||||
} else {
|
||||
this.pathWidthLower = (short) (Math.floor(this.pathsize / 2));
|
||||
}
|
||||
this.pathWidthUpper = (short) (this.pathWidthLower + this.plotsize + 1);
|
||||
}
|
||||
this.biome = Biome.valueOf(this.plotworld.PLOT_BIOME);
|
||||
try {
|
||||
this.maxY = Bukkit.getWorld(plotworld.worldname).getMaxHeight();
|
||||
} catch (final NullPointerException e) {}
|
||||
if (this.maxY == 0) {
|
||||
this.maxY = 256;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the plot manager for this type of generator, or create one For square plots you may as well use the
|
||||
* default plot manager which comes with PlotSquared
|
||||
*/
|
||||
public PlotManager getPlotManager() {
|
||||
if (HybridGen.manager == null) {
|
||||
HybridGen.manager = new HybridPlotManager();
|
||||
}
|
||||
return HybridGen.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new plotworld class For square plots you can use the DefaultPlotWorld class which comes with PlotSquared
|
||||
*/
|
||||
public PlotWorld getNewPlotWorld(final String world) {
|
||||
if (this.plotworld == null) {
|
||||
this.plotworld = new HybridPlotWorld(world);
|
||||
}
|
||||
return this.plotworld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the block populator
|
||||
*/
|
||||
public List<PlotPopulator> getPopulators(final String world) {
|
||||
// You can have as many populators as you would like, e.g. tree
|
||||
// populator, ore populator
|
||||
return Arrays.asList((PlotPopulator) new HybridPop(this.plotworld));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This part is a fucking mess. - Refer to a proper tutorial if you would like to learn how to make a world
|
||||
* generator
|
||||
*/
|
||||
public void generateChunk(final World world, RegionWrapper region, final PseudoRandom random, final int cx, final int cz, final BiomeGrid biomes) {
|
||||
if (this.plotworld.PLOT_BEDROCK) {
|
||||
for (short x = 0; x < 16; x++) {
|
||||
for (short z = 0; z < 16; z++) {
|
||||
setBlock(x, 0, z, (short) 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sx = (short) ((this.X - this.plotworld.ROAD_OFFSET_X) % this.size);
|
||||
int sz = (short) ((this.Z - this.plotworld.ROAD_OFFSET_Z) % this.size);
|
||||
if (sx < 0) {
|
||||
sx += this.size;
|
||||
}
|
||||
if (sz < 0) {
|
||||
sz += this.size;
|
||||
}
|
||||
|
||||
if (region != null) {
|
||||
for (short x = 0; x < 16; x++) {
|
||||
final int absX = ((sx + x) % this.size);
|
||||
for (short z = 0; z < 16; z++) {
|
||||
if (biomes != null) {
|
||||
biomes.setBiome(x, z, this.biome);
|
||||
}
|
||||
if (contains(region, x, z)) {
|
||||
for (short y = 1; y < this.plotheight; y++) {
|
||||
setBlock(x, y, z, this.filling);
|
||||
}
|
||||
setBlock(x, this.plotheight, z, this.plotfloors);
|
||||
final int absZ = ((sz + z) % this.size);
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Short> blocks = plotworld.G_SCH.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final Entry<Short, Short> entry : blocks.entrySet()) {
|
||||
setBlock(x, this.plotheight + entry.getKey(), z, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (short x = 0; x < 16; x++) {
|
||||
final int absX = ((sx + x) % this.size);
|
||||
final boolean gx = absX > this.pathWidthLower;
|
||||
final boolean lx = absX < this.pathWidthUpper;
|
||||
for (short z = 0; z < 16; z++) {
|
||||
if (biomes != null) {
|
||||
biomes.setBiome(x, z, this.biome);
|
||||
}
|
||||
final int absZ = ((sz + z) % this.size);
|
||||
final boolean gz = absZ > this.pathWidthLower;
|
||||
final boolean lz = absZ < this.pathWidthUpper;
|
||||
// inside plot
|
||||
if (gx && gz && lx && lz) {
|
||||
for (short y = 1; y < this.plotheight; y++) {
|
||||
setBlock(x, y, z, this.filling);
|
||||
}
|
||||
setBlock(x, this.plotheight, z, this.plotfloors);
|
||||
if (this.plotworld.PLOT_SCHEMATIC) {
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Short> blocks = this.plotworld.G_SCH.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final Entry<Short, Short> entry : blocks.entrySet()) {
|
||||
setBlock(x, this.plotheight + entry.getKey(), z, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pathsize != 0) {
|
||||
// wall
|
||||
if (((absX >= this.pathWidthLower) && (absX <= this.pathWidthUpper) && (absZ >= this.pathWidthLower) && (absZ <= this.pathWidthUpper))) {
|
||||
for (short y = 1; y <= this.wallheight; y++) {
|
||||
setBlock(x, y, z, this.wallfilling);
|
||||
}
|
||||
if (!this.plotworld.ROAD_SCHEMATIC_ENABLED) {
|
||||
setBlock(x, this.wallheight + 1, z, this.wall);
|
||||
}
|
||||
}
|
||||
// road
|
||||
else {
|
||||
for (short y = 1; y <= this.roadheight; y++) {
|
||||
setBlock(x, y, z, this.roadblock);
|
||||
}
|
||||
}
|
||||
if (this.plotworld.ROAD_SCHEMATIC_ENABLED) {
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Short> blocks = this.plotworld.G_SCH.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final Entry<Short, Short> entry : blocks.entrySet()) {
|
||||
setBlock(x, this.roadheight + entry.getKey(), z, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
@ -0,0 +1,309 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlotSquared - A plot manager and world generator for the Bukkit API /
|
||||
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
|
||||
// /
|
||||
// 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, write to the Free Software Foundation, /
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
|
||||
// /
|
||||
// You can contact us via: support@intellectualsites.com /
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.commands.Template;
|
||||
import com.intellectualcrafters.plot.object.FileBytes;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SetBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.bukkit.BukkitUtil;
|
||||
|
||||
public class HybridPlotManager extends ClassicPlotManager {
|
||||
|
||||
@Override
|
||||
public void exportTemplate(final PlotWorld plotworld) throws IOException {
|
||||
final HashSet<FileBytes> files = new HashSet<>(Arrays.asList(new FileBytes("templates/" + "tmp-data.yml", Template.getBytes(plotworld))));
|
||||
final String psRoot = PS.get().IMP.getDirectory() + File.separator;
|
||||
final String dir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plotworld.worldname + File.separator;
|
||||
final String newDir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + "__TEMP_DIR__" + File.separator;
|
||||
try {
|
||||
final File sideroad = new File(psRoot + dir + "sideroad.schematic");
|
||||
if (sideroad.exists()) {
|
||||
files.add(new FileBytes(newDir + "sideroad.schematic", Files.readAllBytes(sideroad.toPath())));
|
||||
}
|
||||
final File intersection = new File(psRoot + dir + "intersection.schematic");
|
||||
if (intersection.exists()) {
|
||||
files.add(new FileBytes(newDir + "intersection.schematic", Files.readAllBytes(intersection.toPath())));
|
||||
}
|
||||
final File plot = new File(psRoot + dir + "plot.schematic");
|
||||
if (plot.exists()) {
|
||||
files.add(new FileBytes(newDir + "plot.schematic", Files.readAllBytes(plot.toPath())));
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Template.zipAll(plotworld.worldname, files);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createRoadEast(PlotWorld plotworld, Plot plot) {
|
||||
super.createRoadEast(plotworld, plot);
|
||||
HybridPlotWorld hpw = (HybridPlotWorld) plotworld;
|
||||
if (!hpw.ROAD_SCHEMATIC_ENABLED) {
|
||||
return true;
|
||||
}
|
||||
PlotId id = plot.id;
|
||||
PlotId id2 = new PlotId(id.x + 1, id.y);
|
||||
Location bot = getPlotBottomLocAbs(hpw, id2);
|
||||
Location top = getPlotTopLocAbs(hpw, id);
|
||||
Location pos1 = new Location(plot.world, top.getX() + 1, 0, bot.getZ());
|
||||
Location pos2 = new Location(plot.world, bot.getX(), 256, top.getZ() + 1);
|
||||
createSchemAbs(hpw, pos1, pos2, hpw.ROAD_HEIGHT, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void createSchemAbs(HybridPlotWorld hpw, Location pos1, Location pos2, int height, boolean clear) {
|
||||
final int size = hpw.SIZE;
|
||||
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
|
||||
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
|
||||
short absX = (short) (x % size);
|
||||
short absZ = (short) (z % size);
|
||||
if (absX < 0) {
|
||||
absX += size;
|
||||
}
|
||||
if (absZ < 0) {
|
||||
absZ += size;
|
||||
}
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Short> blocks = hpw.G_SCH.get(loc);
|
||||
if (clear) {
|
||||
for (short y = (short) (height); y <= (height + hpw.SCHEMATIC_HEIGHT); y++) {
|
||||
SetBlockQueue.setBlock(hpw.worldname, x, y + y, z, 0);
|
||||
}
|
||||
}
|
||||
if (blocks != null) {
|
||||
final HashMap<Short, Byte> datas = hpw.G_SCH_DATA.get(loc);
|
||||
if (datas == null) {
|
||||
for (final Short y : blocks.keySet()) {
|
||||
SetBlockQueue.setBlock(hpw.worldname, x, height + y, z, blocks.get(y));
|
||||
}
|
||||
} else {
|
||||
for (final Short y : blocks.keySet()) {
|
||||
Byte data = datas.get(y);
|
||||
if (data == null) {
|
||||
data = 0;
|
||||
}
|
||||
SetBlockQueue.setBlock(hpw.worldname, x, height + y, z, new PlotBlock(blocks.get(y), data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createRoadSouth(PlotWorld plotworld, Plot plot) {
|
||||
super.createRoadSouth(plotworld, plot);
|
||||
HybridPlotWorld hpw = (HybridPlotWorld) plotworld;
|
||||
if (!hpw.ROAD_SCHEMATIC_ENABLED) {
|
||||
return true;
|
||||
}
|
||||
PlotId id = plot.id;
|
||||
PlotId id2 = new PlotId(id.x, id.y + 1);
|
||||
Location bot = getPlotBottomLocAbs(hpw, id2);
|
||||
Location top = getPlotTopLocAbs(hpw, id);
|
||||
Location pos1 = new Location(plot.world, bot.getX(), 0, top.getZ() + 1);
|
||||
Location pos2 = new Location(plot.world, top.getX() + 1, 256, bot.getZ());
|
||||
createSchemAbs(hpw, pos1, pos2, hpw.ROAD_HEIGHT, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createRoadSouthEast(PlotWorld plotworld, Plot plot) {
|
||||
super.createRoadSouthEast(plotworld, plot);
|
||||
HybridPlotWorld hpw = (HybridPlotWorld) plotworld;
|
||||
if (!hpw.ROAD_SCHEMATIC_ENABLED) {
|
||||
return true;
|
||||
}
|
||||
PlotId id = plot.id;
|
||||
PlotId id2 = new PlotId(id.x + 1, id.y + 1);
|
||||
Location pos1 = getPlotTopLocAbs(hpw, id).add(1, 0, 1);
|
||||
Location pos2 = getPlotBottomLocAbs(hpw, id2);
|
||||
pos1.setY(0);
|
||||
pos2.setY(256);
|
||||
createSchemAbs(hpw, pos1, pos2, hpw.ROAD_HEIGHT, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearing the plot needs to only consider removing the blocks - This implementation has used the setCuboidAsync
|
||||
* function, as it is fast, and uses NMS code - It also makes use of the fact that deleting chunks is a lot faster
|
||||
* than block updates This code is very messy, but you don't need to do something quite as complex unless you happen
|
||||
* to have 512x512 sized plots
|
||||
*/
|
||||
@Override
|
||||
public boolean clearPlot(final PlotWorld plotworld, final Plot plot, final boolean isDelete, final Runnable whenDone) {
|
||||
final String world = plotworld.worldname;
|
||||
final HybridPlotWorld dpw = ((HybridPlotWorld) plotworld);
|
||||
final Location pos1 = MainUtil.getPlotBottomLocAbs(world, plot.id).add(1, 0, 1);
|
||||
final Location pos2 = MainUtil.getPlotTopLocAbs(world, plot.id);
|
||||
final PlotBlock[] plotfloor = dpw.TOP_BLOCK;
|
||||
final PlotBlock[] filling = dpw.MAIN_BLOCK;
|
||||
final PlotBlock wall;
|
||||
if (isDelete) {
|
||||
wall = dpw.WALL_BLOCK;
|
||||
} else {
|
||||
wall = dpw.CLAIMED_WALL_BLOCK;
|
||||
}
|
||||
final PlotBlock wall_filling = dpw.WALL_FILLING;
|
||||
setWallFilling(dpw, plot.id, new PlotBlock[] { wall_filling });
|
||||
final int maxy = BukkitUtil.getMaxHeight(world);
|
||||
final short bedrock = (short) (dpw.PLOT_BEDROCK ? 7 : 0);
|
||||
final int startX = (pos1.getX() / 16) * 16;
|
||||
final int startZ = (pos1.getZ() / 16) * 16;
|
||||
final int chunkX = 16 + pos2.getX();
|
||||
final int chunkZ = 16 + pos2.getZ();
|
||||
final Location l1 = MainUtil.getPlotBottomLoc(world, plot.id);
|
||||
final Location l2 = MainUtil.getPlotTopLoc(world, plot.id);
|
||||
final int plotMinX = l1.getX() + 1;
|
||||
final int plotMinZ = l1.getZ() + 1;
|
||||
final int plotMaxX = l2.getX();
|
||||
final int plotMaxZ = l2.getZ();
|
||||
Location mn = null;
|
||||
Location mx = null;
|
||||
if (plotworld.TYPE == 0 && plotworld.TERRAIN == 0) {
|
||||
for (int i = startX; i < chunkX; i += 16) {
|
||||
for (int j = startZ; j < chunkZ; j += 16) {
|
||||
final Plot plot1 = MainUtil.getPlot(new Location(world, i, 0, j));
|
||||
if ((plot1 != null) && (!plot1.getId().equals(plot.getId()))) {
|
||||
break;
|
||||
}
|
||||
final Plot plot2 = MainUtil.getPlot(new Location(world, i + 15, 0, j));
|
||||
if ((plot2 != null) && (!plot2.getId().equals(plot.getId()))) {
|
||||
break;
|
||||
}
|
||||
final Plot plot3 = MainUtil.getPlot(new Location(world, i + 15, 0, j + 15));
|
||||
if ((plot3 != null) && (!plot3.getId().equals(plot.getId()))) {
|
||||
break;
|
||||
}
|
||||
final Plot plot4 = MainUtil.getPlot(new Location(world, i, 0, j + 15));
|
||||
if ((plot4 != null) && (!plot4.getId().equals(plot.getId()))) {
|
||||
break;
|
||||
}
|
||||
final Plot plot5 = MainUtil.getPlot(new Location(world, i + 15, 0, j + 15));
|
||||
if ((plot5 != null) && (!plot5.getId().equals(plot.getId()))) {
|
||||
break;
|
||||
}
|
||||
if (mn == null) {
|
||||
mn = new Location(world, Math.max(i - 1, plotMinX), 0, Math.max(j - 1, plotMinZ));
|
||||
mx = new Location(world, Math.min(i + 16, plotMaxX), 0, Math.min(j + 16, plotMaxZ));
|
||||
} else if ((mx.getZ() < (j + 15)) || (mx.getX() < (i + 15))) {
|
||||
mx = new Location(world, Math.min(i + 16, plotMaxX), 0, Math.min(j + 16, plotMaxZ));
|
||||
}
|
||||
final int I = i;
|
||||
final int J = j;
|
||||
BukkitUtil.regenerateChunk(world, I / 16, J / 16);
|
||||
if (!MainUtil.canSendChunk) {
|
||||
BukkitUtil.refreshChunk(world, I / 16, J / 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setWall(dpw, plot.id, new PlotBlock[] { wall });
|
||||
final Location max = mx;
|
||||
final Location min = mn;
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (min == null) {
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, pos1.getX(), 0, pos1.getZ()), new Location(world, pos2.getX() + 1, 1, pos2.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, pos1.getX(), dpw.PLOT_HEIGHT + 1, pos1.getZ()), new Location(world, pos2.getX() + 1, maxy + 1, pos2.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, pos1.getX(), 1, pos1.getZ()), new Location(world, pos2.getX() + 1, dpw.PLOT_HEIGHT, pos2.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, pos1.getX(), dpw.PLOT_HEIGHT, pos1.getZ()), new Location(world, pos2.getX() + 1, dpw.PLOT_HEIGHT + 1, pos2.getZ() + 1), plotfloor);
|
||||
pastePlotSchematic(dpw, l1, l2);
|
||||
SetBlockQueue.addNotify(whenDone);
|
||||
return;
|
||||
}
|
||||
if (min.getX() < plotMinX) {
|
||||
min.setX(plotMinX);
|
||||
}
|
||||
if (min.getZ() < plotMinZ) {
|
||||
min.setZ(plotMinZ);
|
||||
}
|
||||
if (max.getX() > plotMaxX) {
|
||||
max.setX(plotMaxX);
|
||||
}
|
||||
if (max.getZ() > plotMaxZ) {
|
||||
max.setZ(plotMaxZ);
|
||||
}
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, 0, plotMinZ), new Location(world, min.getX() + 1, 1, min.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT + 1, plotMinZ), new Location(world, min.getX() + 1, maxy + 1, min.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, 1, plotMinZ), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT + 1, min.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT, plotMinZ), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT + 1, min.getZ() + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, min.getX(), 0, plotMinZ), new Location(world, max.getX() + 1, 1, min.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, min.getX(), dpw.PLOT_HEIGHT + 1, plotMinZ), new Location(world, max.getX() + 1, maxy + 1, min.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, min.getX(), 1, plotMinZ), new Location(world, max.getX() + 1, dpw.PLOT_HEIGHT, min.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, min.getX(), dpw.PLOT_HEIGHT, plotMinZ), new Location(world, max.getX() + 1, dpw.PLOT_HEIGHT + 1, min.getZ() + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), 0, plotMinZ), new Location(world, plotMaxX + 1, 1, min.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT + 1, plotMinZ), new Location(world, plotMaxX + 1, maxy + 1, min.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), 1, plotMinZ), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT, min.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT, plotMinZ), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT + 1, min.getZ() + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, 0, min.getZ()), new Location(world, min.getX() + 1, 1, max.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT + 1, min.getZ()), new Location(world, min.getX() + 1, maxy + 1, max.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, 1, min.getZ()), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT, max.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT, min.getZ()), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT + 1, max.getZ() + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, 0, max.getZ()), new Location(world, min.getX() + 1, 1, plotMaxZ + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT + 1, max.getZ()), new Location(world, min.getX() + 1, maxy + 1, plotMaxZ + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, 1, max.getZ()), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT, plotMaxZ + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, plotMinX, dpw.PLOT_HEIGHT, max.getZ()), new Location(world, min.getX() + 1, dpw.PLOT_HEIGHT + 1, plotMaxZ + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, min.getX(), 0, max.getZ()), new Location(world, max.getX() + 1, 1, plotMaxZ + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, min.getX(), dpw.PLOT_HEIGHT + 1, max.getZ()), new Location(world, max.getX() + 1, maxy + 1, plotMaxZ + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, min.getX(), 1, max.getZ()), new Location(world, max.getX() + 1, dpw.PLOT_HEIGHT, plotMaxZ + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, min.getX(), dpw.PLOT_HEIGHT, max.getZ()), new Location(world, max.getX() + 1, dpw.PLOT_HEIGHT + 1, plotMaxZ + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), 0, min.getZ()), new Location(world, plotMaxX + 1, 1, max.getZ() + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT + 1, min.getZ()), new Location(world, plotMaxX + 1, maxy + 1, max.getZ() + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), 1, min.getZ()), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT, max.getZ() + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT, min.getZ()), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT + 1, max.getZ() + 1), plotfloor);
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), 0, max.getZ()), new Location(world, plotMaxX + 1, 1, plotMaxZ + 1), new PlotBlock(bedrock, (byte) 0));
|
||||
MainUtil.setSimpleCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT + 1, max.getZ()), new Location(world, plotMaxX + 1, maxy + 1, plotMaxZ + 1), new PlotBlock((short) 0, (byte) 0));
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), 1, max.getZ()), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT, plotMaxZ + 1), filling);
|
||||
MainUtil.setCuboidAsync(world, new Location(world, max.getX(), dpw.PLOT_HEIGHT, max.getZ()), new Location(world, plotMaxX + 1, dpw.PLOT_HEIGHT + 1, plotMaxZ + 1), plotfloor);
|
||||
pastePlotSchematic(dpw, l1, l2);
|
||||
SetBlockQueue.addNotify(whenDone);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public void pastePlotSchematic(HybridPlotWorld plotworld, Location l1, Location l2) {
|
||||
if (!plotworld.PLOT_SCHEMATIC) {
|
||||
return;
|
||||
}
|
||||
createSchemAbs(plotworld, l1.add(1,0,1), l2, plotworld.PLOT_HEIGHT, false);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,323 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlotSquared - A plot manager and world generator for the Bukkit API /
|
||||
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
|
||||
// /
|
||||
// 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, write to the Free Software Foundation, /
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
|
||||
// /
|
||||
// You can contact us via: support@intellectualsites.com /
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.intellectualcrafters.configuration.ConfigurationSection;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Configuration;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.schematic.PlotItem;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler.DataCollection;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler.Dimension;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler.Schematic;
|
||||
|
||||
public class HybridPlotWorld extends ClassicPlotWorld {
|
||||
public boolean ROAD_SCHEMATIC_ENABLED;
|
||||
public short SCHEMATIC_HEIGHT;
|
||||
public boolean PLOT_SCHEMATIC = false;
|
||||
public short REQUIRED_CHANGES = 0;
|
||||
public short PATH_WIDTH_LOWER;
|
||||
public short PATH_WIDTH_UPPER;
|
||||
|
||||
/*
|
||||
* Here we are just calling the super method, nothing special
|
||||
*/
|
||||
public HybridPlotWorld(final String worldname) {
|
||||
super(worldname);
|
||||
}
|
||||
|
||||
public HashMap<PlotLoc, HashMap<Short, Short>> G_SCH;
|
||||
public HashMap<PlotLoc, HashMap<Short, Byte>> G_SCH_DATA;
|
||||
public HashMap<PlotLoc, HashSet<PlotItem>> G_SCH_STATE;
|
||||
|
||||
/**
|
||||
* This method is called when a world loads. Make sure you set all your constants here. You are provided with the
|
||||
* configuration section for that specific world.
|
||||
*/
|
||||
@Override
|
||||
public void loadConfiguration(final ConfigurationSection config) {
|
||||
super.loadConfiguration(config);
|
||||
if ((this.ROAD_WIDTH % 2) == 0) {
|
||||
this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2) - 1);
|
||||
} else {
|
||||
this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2));
|
||||
}
|
||||
this.PATH_WIDTH_UPPER = (short) (this.PATH_WIDTH_LOWER + this.PLOT_WIDTH + 1);
|
||||
try {
|
||||
setupSchematics();
|
||||
} catch (final Exception e) {
|
||||
PS.log("&c - road schematics are disabled for this world.");
|
||||
}
|
||||
}
|
||||
|
||||
public void setupSchematics() {
|
||||
this.G_SCH_DATA = new HashMap<>();
|
||||
this.G_SCH = new HashMap<>();
|
||||
final String schem1Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/sideroad";
|
||||
final String schem2Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/intersection";
|
||||
final String schem3Str = "GEN_ROAD_SCHEMATIC/" + this.worldname + "/plot";
|
||||
final Schematic schem1 = SchematicHandler.manager.getSchematic(schem1Str);
|
||||
final Schematic schem2 = SchematicHandler.manager.getSchematic(schem2Str);
|
||||
final Schematic schem3 = SchematicHandler.manager.getSchematic(schem3Str);
|
||||
final int shift = (int) this.ROAD_WIDTH / 2;
|
||||
int oddshift = 0;
|
||||
if ((this.ROAD_WIDTH % 2) != 0) {
|
||||
oddshift = 1;
|
||||
}
|
||||
if (schem3 != null) {
|
||||
this.PLOT_SCHEMATIC = true;
|
||||
final DataCollection[] blocks3 = schem3.getBlockCollection();
|
||||
final Dimension d3 = schem3.getSchematicDimension();
|
||||
final short w3 = (short) d3.getX();
|
||||
final short l3 = (short) d3.getZ();
|
||||
final short h3 = (short) d3.getY();
|
||||
int center_shift_x = 0;
|
||||
int center_shift_z = 0;
|
||||
if (l3 < this.PLOT_WIDTH) {
|
||||
center_shift_z = (this.PLOT_WIDTH - l3) / 2;
|
||||
}
|
||||
if (w3 < this.PLOT_WIDTH) {
|
||||
center_shift_x = (this.PLOT_WIDTH - w3) / 2;
|
||||
}
|
||||
for (short x = 0; x < w3; x++) {
|
||||
for (short z = 0; z < l3; z++) {
|
||||
for (short y = 0; y < h3; y++) {
|
||||
final int index = (y * w3 * l3) + (z * w3) + x;
|
||||
final short id = blocks3[index].getBlock();
|
||||
final byte data = blocks3[index].getData();
|
||||
if (id != 0) {
|
||||
addOverlayBlock((short) (x + shift + oddshift + center_shift_x), (y), (short) (z + shift + oddshift + center_shift_z), id, data, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<PlotItem> items = schem3.getItems();
|
||||
if (items != null) {
|
||||
G_SCH_STATE = new HashMap<>();
|
||||
for (PlotItem item : items) {
|
||||
item.x += shift + oddshift + center_shift_x;
|
||||
item.z += shift + oddshift + center_shift_z;
|
||||
item.y += this.PLOT_HEIGHT;
|
||||
int x = item.x;
|
||||
int y = item.y;
|
||||
int z = item.z;
|
||||
PlotLoc loc = new PlotLoc(x, z);
|
||||
if (!G_SCH_STATE.containsKey(loc)) {
|
||||
G_SCH_STATE.put(loc, new HashSet<PlotItem>());
|
||||
}
|
||||
G_SCH_STATE.get(loc).add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((schem1 == null) || (schem2 == null) || (this.ROAD_WIDTH == 0)) {
|
||||
PS.log(C.PREFIX.s() + "&3 - schematic: &7false");
|
||||
return;
|
||||
}
|
||||
this.ROAD_SCHEMATIC_ENABLED = true;
|
||||
// Do not populate road if using schematic population
|
||||
this.ROAD_BLOCK = new PlotBlock(this.ROAD_BLOCK.id, (byte) 0);
|
||||
final DataCollection[] blocks1 = schem1.getBlockCollection();
|
||||
final DataCollection[] blocks2 = schem2.getBlockCollection();
|
||||
final Dimension d1 = schem1.getSchematicDimension();
|
||||
final short w1 = (short) d1.getX();
|
||||
final short l1 = (short) d1.getZ();
|
||||
final short h1 = (short) d1.getY();
|
||||
final Dimension d2 = schem2.getSchematicDimension();
|
||||
final short w2 = (short) d2.getX();
|
||||
final short l2 = (short) d2.getZ();
|
||||
final short h2 = (short) d2.getY();
|
||||
this.SCHEMATIC_HEIGHT = (short) Math.max(h2, h1);
|
||||
for (short x = 0; x < w1; x++) {
|
||||
for (short z = 0; z < l1; z++) {
|
||||
for (short y = 0; y < h1; y++) {
|
||||
final int index = (y * w1 * l1) + (z * w1) + x;
|
||||
final short id = blocks1[index].getBlock();
|
||||
final byte data = blocks1[index].getData();
|
||||
if (id != 0) {
|
||||
addOverlayBlock((short) (x - (shift)), (y), (short) (z + shift + oddshift), id, data, false);
|
||||
addOverlayBlock((short) (z + shift + oddshift), (y), (short) (x - shift), id, data, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (short x = 0; x < w2; x++) {
|
||||
for (short z = 0; z < l2; z++) {
|
||||
for (short y = 0; y < h2; y++) {
|
||||
final int index = (y * w2 * l2) + (z * w2) + x;
|
||||
final short id = blocks2[index].getBlock();
|
||||
final byte data = blocks2[index].getData();
|
||||
if (id != 0) {
|
||||
addOverlayBlock((short) (x - shift), (y), (short) (z - shift), id, data, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte wrap(byte data, int start) {
|
||||
if (data >= start && data < start + 4) {
|
||||
data = (byte) ((((data - start) + 2) % 4) + start);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static byte wrap2(byte data, int start) {
|
||||
if (data >= start && data < start + 2) {
|
||||
data = (byte) ((((data - start) + 1) % 2) + start);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static byte rotate(final short id, byte data) {
|
||||
switch (id) {
|
||||
case 162:
|
||||
case 17: {
|
||||
if (data >= 4 && data < 12) {
|
||||
if (data >= 8) {
|
||||
return (byte) (data - 4);
|
||||
}
|
||||
return (byte) (data + 4);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
case 183:
|
||||
case 184:
|
||||
case 185:
|
||||
case 186:
|
||||
case 187:
|
||||
case 107:
|
||||
case 53:
|
||||
case 67:
|
||||
case 108:
|
||||
case 109:
|
||||
case 114:
|
||||
case 128:
|
||||
case 134:
|
||||
case 135:
|
||||
case 136:
|
||||
case 156:
|
||||
case 163:
|
||||
case 164:
|
||||
case 180: {
|
||||
data = wrap(data, 0);
|
||||
data = wrap(data, 4);
|
||||
return data;
|
||||
}
|
||||
|
||||
case 26:
|
||||
case 86: {
|
||||
data = wrap(data, 0);
|
||||
return data;
|
||||
}
|
||||
case 64:
|
||||
case 71:
|
||||
case 193:
|
||||
case 194:
|
||||
case 195:
|
||||
case 196:
|
||||
case 197:
|
||||
case 93:
|
||||
case 94:
|
||||
case 131:
|
||||
case 145:
|
||||
case 149:
|
||||
case 150:
|
||||
case 96:
|
||||
case 167: {
|
||||
data = wrap(data, 0);
|
||||
data = wrap(data, 4);
|
||||
data = wrap(data, 8);
|
||||
data = wrap(data, 12);
|
||||
return data;
|
||||
}
|
||||
case 28:
|
||||
case 66:
|
||||
case 157:
|
||||
case 27: {
|
||||
data = wrap2(data, 0);
|
||||
data = wrap2(data, 3);
|
||||
if (data == 2) {
|
||||
data = 5;
|
||||
}
|
||||
else if (data == 5) {
|
||||
data = 2;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
case 23:
|
||||
case 29:
|
||||
case 33:
|
||||
case 158:
|
||||
case 54:
|
||||
case 130:
|
||||
case 146:
|
||||
case 61:
|
||||
case 62:
|
||||
case 65:
|
||||
case 68:
|
||||
case 144: {
|
||||
data = wrap(data, 2);
|
||||
return data;
|
||||
}
|
||||
case 143:
|
||||
case 77: {
|
||||
data = wrap(data, 1);
|
||||
return data;
|
||||
}
|
||||
default:
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public void addOverlayBlock(short x, final short y, short z, final short id, byte data, final boolean rotate) {
|
||||
if (z < 0) {
|
||||
z += this.SIZE;
|
||||
}
|
||||
if (x < 0) {
|
||||
x += this.SIZE;
|
||||
}
|
||||
final PlotLoc loc = new PlotLoc(x, z);
|
||||
if (!this.G_SCH.containsKey(loc)) {
|
||||
this.G_SCH.put(loc, new HashMap<Short, Short>());
|
||||
}
|
||||
this.G_SCH.get(loc).put(y, id);
|
||||
if (rotate) {
|
||||
byte newdata = rotate(id, data);
|
||||
if (data == 0 && newdata == 0) {
|
||||
return;
|
||||
}
|
||||
data = newdata;
|
||||
}
|
||||
if (!this.G_SCH_DATA.containsKey(loc)) {
|
||||
this.G_SCH_DATA.put(loc, new HashMap<Short, Byte>());
|
||||
}
|
||||
this.G_SCH_DATA.get(loc).put(y, data);
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotPopulator;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.schematic.PlotItem;
|
||||
import com.intellectualcrafters.plot.util.BlockManager;
|
||||
|
||||
/**
|
||||
* @author Citymonstret
|
||||
*/
|
||||
public class HybridPop extends PlotPopulator {
|
||||
/*
|
||||
* Sorry, this isn't well documented at the moment.
|
||||
* We advise you to take a look at a world generation tutorial for
|
||||
* information about how a BlockPopulator works.
|
||||
*/
|
||||
final short plotsize;
|
||||
final short pathsize;
|
||||
final byte wall;
|
||||
final byte wallfilling;
|
||||
final byte roadblock;
|
||||
final int size;
|
||||
final int roadheight;
|
||||
final int wallheight;
|
||||
final int plotheight;
|
||||
final byte[] plotfloors;
|
||||
final byte[] filling;
|
||||
final short pathWidthLower;
|
||||
final short pathWidthUpper;
|
||||
private final HybridPlotWorld plotworld;
|
||||
Biome biome;
|
||||
private long state;
|
||||
private boolean doFilling = false;
|
||||
private boolean doFloor = false;
|
||||
private boolean doState = false;
|
||||
|
||||
public HybridPop(final PlotWorld pw) {
|
||||
this.plotworld = (HybridPlotWorld) pw;
|
||||
// save configuration
|
||||
this.plotsize = (short) this.plotworld.PLOT_WIDTH;
|
||||
this.pathsize = (short) this.plotworld.ROAD_WIDTH;
|
||||
this.roadblock = this.plotworld.ROAD_BLOCK.data;
|
||||
this.wallfilling = this.plotworld.WALL_FILLING.data;
|
||||
this.size = this.pathsize + this.plotsize;
|
||||
this.wall = this.plotworld.WALL_BLOCK.data;
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
this.plotfloors = new byte[this.plotworld.TOP_BLOCK.length];
|
||||
for (int i = 0; i < this.plotworld.TOP_BLOCK.length; i++) {
|
||||
count1++;
|
||||
this.plotfloors[i] = this.plotworld.TOP_BLOCK[i].data;
|
||||
if (this.plotworld.TOP_BLOCK[i].data != 0) {
|
||||
this.doFloor = true;
|
||||
}
|
||||
}
|
||||
this.filling = new byte[this.plotworld.MAIN_BLOCK.length];
|
||||
for (int i = 0; i < this.plotworld.MAIN_BLOCK.length; i++) {
|
||||
count2++;
|
||||
this.filling[i] = this.plotworld.MAIN_BLOCK[i].data;
|
||||
if (this.plotworld.MAIN_BLOCK[i].data != 0) {
|
||||
this.doFilling = true;
|
||||
}
|
||||
}
|
||||
if (((count1 > 0) && this.doFloor) || ((count2 > 0) && this.doFilling)) {
|
||||
this.doState = true;
|
||||
}
|
||||
this.wallheight = this.plotworld.WALL_HEIGHT;
|
||||
this.roadheight = this.plotworld.ROAD_HEIGHT;
|
||||
this.plotheight = this.plotworld.PLOT_HEIGHT;
|
||||
if (this.pathsize == 0) {
|
||||
this.pathWidthLower = (short) -1;
|
||||
this.pathWidthUpper = (short) (this.plotsize + 1);
|
||||
}
|
||||
else {
|
||||
if ((this.pathsize % 2) == 0) {
|
||||
this.pathWidthLower = (short) (Math.floor(this.pathsize / 2) - 1);
|
||||
} else {
|
||||
this.pathWidthLower = (short) (Math.floor(this.pathsize / 2));
|
||||
}
|
||||
this.pathWidthUpper = (short) (this.pathWidthLower + this.plotsize + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public final long nextLong() {
|
||||
final long a = this.state;
|
||||
this.state = xorShift64(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
public final long xorShift64(long a) {
|
||||
a ^= (a << 21);
|
||||
a ^= (a >>> 35);
|
||||
a ^= (a << 4);
|
||||
return a;
|
||||
}
|
||||
|
||||
public final int random(final int n) {
|
||||
final long result = ((nextLong() >>> 32) * n) >> 32;
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(World world, RegionWrapper requiredRegion, PseudoRandom random, int cx, int cz) {
|
||||
PS.get().getPlotManager(world.getName());
|
||||
|
||||
int sx = (short) ((this.X - this.plotworld.ROAD_OFFSET_X) % this.size);
|
||||
int sz = (short) ((this.Z - this.plotworld.ROAD_OFFSET_Z) % this.size);
|
||||
if (sx < 0) {
|
||||
sx += this.size;
|
||||
}
|
||||
if (sz < 0) {
|
||||
sz += this.size;
|
||||
}
|
||||
|
||||
if (requiredRegion != null) {
|
||||
for (short x = 0; x < 16; x++) {
|
||||
for (short z = 0; z < 16; z++) {
|
||||
if (contains(requiredRegion, x, z)) {
|
||||
if (this.doFilling) {
|
||||
for (short y = 1; y < this.plotheight; y++) {
|
||||
setBlock(x, y, z, this.filling);
|
||||
}
|
||||
}
|
||||
if (this.doFloor) {
|
||||
setBlock(x, (short) this.plotheight, z, this.plotfloors);
|
||||
}
|
||||
if (this.plotworld.PLOT_SCHEMATIC) {
|
||||
final int absX = ((sx + x) % this.size);
|
||||
final int absZ = ((sz + z) % this.size);
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Byte> blocks = this.plotworld.G_SCH_DATA.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final short y : blocks.keySet()) {
|
||||
setBlockAbs(x, (short) (this.plotheight + y), z, blocks.get(y));
|
||||
}
|
||||
}
|
||||
if (this.plotworld.G_SCH_STATE != null) {
|
||||
HashSet<PlotItem> states = this.plotworld.G_SCH_STATE.get(loc);
|
||||
if (states != null) {
|
||||
for (PlotItem items : states) {
|
||||
BlockManager.manager.addItems(this.plotworld.worldname, items);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (short x = 0; x < 16; x++) {
|
||||
for (short z = 0; z < 16; z++) {
|
||||
final int absX = ((sx + x) % this.size);
|
||||
final int absZ = ((sz + z) % this.size);
|
||||
final boolean gx = absX > this.pathWidthLower;
|
||||
final boolean gz = absZ > this.pathWidthLower;
|
||||
final boolean lx = absX < this.pathWidthUpper;
|
||||
final boolean lz = absZ < this.pathWidthUpper;
|
||||
// inside plot
|
||||
if (gx && gz && lx && lz) {
|
||||
for (short y = 1; y < this.plotheight; y++) {
|
||||
setBlock(x, y, z, this.filling);
|
||||
}
|
||||
setBlock(x, (short) this.plotheight, z, this.plotfloors);
|
||||
if (this.plotworld.PLOT_SCHEMATIC) {
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Byte> blocks = this.plotworld.G_SCH_DATA.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final short y : blocks.keySet()) {
|
||||
setBlockAbs(x, (short) (this.plotheight + y), z, blocks.get(y));
|
||||
}
|
||||
}
|
||||
if (this.plotworld.G_SCH_STATE != null) {
|
||||
HashSet<PlotItem> states = this.plotworld.G_SCH_STATE.get(loc);
|
||||
if (states != null) {
|
||||
for (PlotItem items : states) {
|
||||
items.x = this.X + x;
|
||||
items.z = this.Z + z;
|
||||
BlockManager.manager.addItems(this.plotworld.worldname, items);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pathsize != 0) {
|
||||
// wall
|
||||
if (((absX >= this.pathWidthLower) && (absX <= this.pathWidthUpper) && (absZ >= this.pathWidthLower) && (absZ <= this.pathWidthUpper))) {
|
||||
for (short y = 1; y <= this.wallheight; y++) {
|
||||
setBlock(x, y, z, this.wallfilling);
|
||||
}
|
||||
if (!this.plotworld.ROAD_SCHEMATIC_ENABLED) {
|
||||
setBlock(x, this.wallheight + 1, z, this.wall);
|
||||
}
|
||||
}
|
||||
// road
|
||||
else {
|
||||
for (short y = 1; y <= this.roadheight; y++) {
|
||||
setBlock(x, y, z, this.roadblock);
|
||||
}
|
||||
}
|
||||
if (this.plotworld.ROAD_SCHEMATIC_ENABLED) {
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Byte> blocks = this.plotworld.G_SCH_DATA.get(loc);
|
||||
if (blocks != null) {
|
||||
for (final short y : blocks.keySet()) {
|
||||
setBlockAbs(x, (short) (this.roadheight + y), z, blocks.get(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBlock(final short x, final short y, final short z, final byte[] blkids) {
|
||||
if (blkids.length == 1) {
|
||||
setBlock(x, y, z, blkids[0]);
|
||||
} else {
|
||||
final int i = random(blkids.length);
|
||||
setBlock(x, y, z, blkids[i]);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.intellectualcrafters.jnbt.CompoundTag;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotAnalysis;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.util.BlockManager;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
|
||||
public abstract class HybridUtils {
|
||||
|
||||
public static HybridUtils manager;
|
||||
|
||||
public abstract void checkModified(final Plot plot, final RunnableVal<Integer> whenDone);
|
||||
|
||||
public abstract void analyzePlot(final Plot plot, final RunnableVal<PlotAnalysis> whenDone);
|
||||
|
||||
public abstract int checkModified(final String world, final int x1, final int x2, final int y1, final int y2, final int z1, final int z2, final PlotBlock[] blocks);
|
||||
|
||||
public boolean setupRoadSchematic(final Plot plot) {
|
||||
final String world = plot.world;
|
||||
final Location bot = MainUtil.getPlotBottomLoc(world, plot.id);
|
||||
final Location top = MainUtil.getPlotTopLoc(world, plot.id);
|
||||
final HybridPlotWorld plotworld = (HybridPlotWorld) PS.get().getPlotWorld(world);
|
||||
final int sx = (bot.getX() - plotworld.ROAD_WIDTH) + 1;
|
||||
final int sz = bot.getZ() + 1;
|
||||
final int sy = plotworld.ROAD_HEIGHT;
|
||||
final int ex = bot.getX();
|
||||
final int ez = top.getZ();
|
||||
final int ey = get_ey(world, sx, ex, sz, ez, sy);
|
||||
final Location pos1 = new Location(world, sx, sy, sz);
|
||||
final Location pos2 = new Location(world, ex, ey, ez);
|
||||
final int bx = sx;
|
||||
final int bz = sz - plotworld.ROAD_WIDTH;
|
||||
final int by = sy;
|
||||
final int tx = ex;
|
||||
final int tz = sz - 1;
|
||||
final int ty = get_ey(world, bx, tx, bz, tz, by);
|
||||
final Location pos3 = new Location(world, bx, by, bz);
|
||||
final Location pos4 = new Location(world, tx, ty, tz);
|
||||
final CompoundTag sideroad = SchematicHandler.manager.getCompoundTag(world, pos1, pos2);
|
||||
final CompoundTag intersection = SchematicHandler.manager.getCompoundTag(world, pos3, pos4);
|
||||
final String dir = PS.get().IMP.getDirectory() + File.separator + "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plot.world + File.separator;
|
||||
SchematicHandler.manager.save(sideroad, dir + "sideroad.schematic");
|
||||
SchematicHandler.manager.save(intersection, dir + "intersection.schematic");
|
||||
plotworld.ROAD_SCHEMATIC_ENABLED = true;
|
||||
plotworld.setupSchematics();
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract int get_ey(final String world, final int sx, final int ex, final int sz, final int ez, final int sy);
|
||||
|
||||
public abstract boolean scheduleRoadUpdate(final String world, int extend);
|
||||
|
||||
public boolean regenerateRoad(final String world, final ChunkLoc chunk, int extend) {
|
||||
final int x = chunk.x << 4;
|
||||
final int z = chunk.z << 4;
|
||||
final int ex = x + 15;
|
||||
final int ez = z + 15;
|
||||
final HybridPlotWorld plotworld = (HybridPlotWorld) PS.get().getPlotWorld(world);
|
||||
extend = Math.min(extend, 255 - plotworld.ROAD_HEIGHT - plotworld.SCHEMATIC_HEIGHT);
|
||||
if (!plotworld.ROAD_SCHEMATIC_ENABLED) {
|
||||
return false;
|
||||
}
|
||||
boolean toCheck = false;
|
||||
if (plotworld.TYPE == 2) {
|
||||
boolean c1 = MainUtil.isPlotArea(new Location(plotworld.worldname, x, 1, z));
|
||||
boolean c2 = MainUtil.isPlotArea(new Location(plotworld.worldname, ex, 1, ez));
|
||||
if (!c1 && !c2) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
toCheck = c1 ^ c2;
|
||||
}
|
||||
}
|
||||
final PlotManager manager = PS.get().getPlotManager(world);
|
||||
final PlotId id1 = manager.getPlotId(plotworld, x, 0, z);
|
||||
final PlotId id2 = manager.getPlotId(plotworld, ex, 0, ez);
|
||||
if ((id1 == null) || (id2 == null) || (id1 != id2)) {
|
||||
final boolean result = ChunkManager.manager.loadChunk(world, chunk);
|
||||
if (result) {
|
||||
if (id1 != null) {
|
||||
final Plot p1 = MainUtil.getPlot(world, id1);
|
||||
if ((p1 != null) && p1.hasOwner() && p1.settings.isMerged()) {
|
||||
toCheck = true;
|
||||
}
|
||||
}
|
||||
if ((id2 != null) && !toCheck) {
|
||||
final Plot p2 = MainUtil.getPlot(world, id2);
|
||||
if ((p2 != null) && p2.hasOwner() && p2.settings.isMerged()) {
|
||||
toCheck = true;
|
||||
}
|
||||
}
|
||||
final int size = plotworld.SIZE;
|
||||
for (int X = 0; X < 16; X++) {
|
||||
for (int Z = 0; Z < 16; Z++) {
|
||||
short absX = (short) ((x + X) % size);
|
||||
short absZ = (short) ((z + Z) % size);
|
||||
if (absX < 0) {
|
||||
absX += size;
|
||||
}
|
||||
if (absZ < 0) {
|
||||
absZ += size;
|
||||
}
|
||||
boolean condition;
|
||||
if (toCheck) {
|
||||
condition = manager.getPlotId(plotworld, x + X, 1, z + Z) == null;
|
||||
// condition = MainUtil.isPlotRoad(new Location(plotworld.worldname, x + X, 1, z + Z));
|
||||
} else {
|
||||
final boolean gx = absX > plotworld.PATH_WIDTH_LOWER;
|
||||
final boolean gz = absZ > plotworld.PATH_WIDTH_LOWER;
|
||||
final boolean lx = absX < plotworld.PATH_WIDTH_UPPER;
|
||||
final boolean lz = absZ < plotworld.PATH_WIDTH_UPPER;
|
||||
condition = (!gx || !gz || !lx || !lz);
|
||||
}
|
||||
if (condition) {
|
||||
final int sy = plotworld.ROAD_HEIGHT;
|
||||
final PlotLoc loc = new PlotLoc(absX, absZ);
|
||||
final HashMap<Short, Short> blocks = plotworld.G_SCH.get(loc);
|
||||
for (short y = (short) (plotworld.ROAD_HEIGHT); y <= (plotworld.ROAD_HEIGHT + plotworld.SCHEMATIC_HEIGHT + extend); y++) {
|
||||
BlockManager.manager.functionSetBlock(world, x + X, y, z + Z, 0, (byte) 0);
|
||||
}
|
||||
if (blocks != null) {
|
||||
final HashMap<Short, Byte> datas = plotworld.G_SCH_DATA.get(loc);
|
||||
if (datas == null) {
|
||||
for (final Short y : blocks.keySet()) {
|
||||
BlockManager.manager.functionSetBlock(world, x + X, sy + y, z + Z, blocks.get(y), (byte) 0);
|
||||
}
|
||||
} else {
|
||||
for (final Short y : blocks.keySet()) {
|
||||
Byte data = datas.get(y);
|
||||
if (data == null) {
|
||||
data = 0;
|
||||
}
|
||||
BlockManager.manager.functionSetBlock(world, x + X, sy + y, z + Z, blocks.get(y), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,210 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotWorld;
|
||||
import com.intellectualcrafters.plot.util.BlockManager;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
|
||||
/**
|
||||
* A plot manager with a square grid layout, with square shaped plots
|
||||
*/
|
||||
public abstract class SquarePlotManager extends GridPlotManager {
|
||||
@Override
|
||||
public boolean clearPlot(final PlotWorld plotworld, final Plot plot, final boolean isDelete, final Runnable whenDone) {
|
||||
final Location pos1 = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1, 0, 1);
|
||||
final Location pos2 = MainUtil.getPlotTopLoc(plot.world, plot.id);
|
||||
ChunkManager.manager.regenerateRegion(pos1, pos2, whenDone);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getPlotTopLocAbs(final PlotWorld plotworld, final PlotId plotid) {
|
||||
final SquarePlotWorld dpw = ((SquarePlotWorld) plotworld);
|
||||
final int px = plotid.x;
|
||||
final int pz = plotid.y;
|
||||
final int x = dpw.ROAD_OFFSET_X + (px * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1;
|
||||
final int z = dpw.ROAD_OFFSET_Z + (pz * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1;
|
||||
return new Location(plotworld.worldname, x, 256, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotId getPlotIdAbs(final PlotWorld plotworld, int x, final int y, int z) {
|
||||
final SquarePlotWorld dpw = ((SquarePlotWorld) plotworld);
|
||||
x -= dpw.ROAD_OFFSET_X;
|
||||
z -= dpw.ROAD_OFFSET_Z;
|
||||
int pathWidthLower;
|
||||
int end;
|
||||
if (dpw.ROAD_WIDTH == 0) {
|
||||
pathWidthLower = -1;
|
||||
end = dpw.PLOT_WIDTH;
|
||||
}
|
||||
else {
|
||||
if ((dpw.ROAD_WIDTH % 2) == 0) {
|
||||
pathWidthLower = (dpw.ROAD_WIDTH / 2) - 1;
|
||||
} else {
|
||||
pathWidthLower = dpw.ROAD_WIDTH / 2;
|
||||
}
|
||||
end = pathWidthLower + dpw.PLOT_WIDTH;
|
||||
}
|
||||
final int size = dpw.PLOT_WIDTH + dpw.ROAD_WIDTH;
|
||||
int idx;
|
||||
int idz;
|
||||
if (x < 0) {
|
||||
idx = (x/size);
|
||||
x = size + (x % size);
|
||||
}
|
||||
else {
|
||||
idx = (x/size) + 1;
|
||||
x = (x % size);
|
||||
}
|
||||
if (z < 0) {
|
||||
idz = (z/size);
|
||||
z = size + (z % size);
|
||||
}
|
||||
else {
|
||||
idz = (z/size) + 1;
|
||||
z = (z % size);
|
||||
}
|
||||
final boolean northSouth = (z <= pathWidthLower) || (z > end);
|
||||
final boolean eastWest = (x <= pathWidthLower) || (x > end);
|
||||
if (northSouth || eastWest) {
|
||||
return null;
|
||||
}
|
||||
return new PlotId(idx, idz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotId getPlotId(final PlotWorld plotworld, int x, final int y, int z) {
|
||||
final SquarePlotWorld dpw = ((SquarePlotWorld) plotworld);
|
||||
if (plotworld == null) {
|
||||
return null;
|
||||
}
|
||||
x -= dpw.ROAD_OFFSET_X;
|
||||
z -= dpw.ROAD_OFFSET_Z;
|
||||
final int size = dpw.PLOT_WIDTH + dpw.ROAD_WIDTH;
|
||||
int pathWidthLower;
|
||||
final int end;
|
||||
if (dpw.ROAD_WIDTH == 0) {
|
||||
pathWidthLower = -1;
|
||||
end = dpw.PLOT_WIDTH;
|
||||
}
|
||||
else {
|
||||
if ((dpw.ROAD_WIDTH % 2) == 0) {
|
||||
pathWidthLower = (dpw.ROAD_WIDTH / 2) - 1;
|
||||
} else {
|
||||
pathWidthLower = dpw.ROAD_WIDTH / 2;
|
||||
}
|
||||
end = pathWidthLower + dpw.PLOT_WIDTH;
|
||||
}
|
||||
int dx;
|
||||
int dz;
|
||||
int rx;
|
||||
int rz;
|
||||
if (x < 0) {
|
||||
dx = (x/size);
|
||||
rx = size + (x % size);
|
||||
}
|
||||
else {
|
||||
dx = (x/size) + 1;
|
||||
rx = (x % size);
|
||||
}
|
||||
if (z < 0) {
|
||||
dz = (z/size);
|
||||
rz = size + (z % size);
|
||||
}
|
||||
else {
|
||||
dz = (z/size) + 1;
|
||||
rz = (z % size);
|
||||
}
|
||||
final boolean northSouth = (rz <= pathWidthLower) || (rz > end);
|
||||
final boolean eastWest = (rx <= pathWidthLower) || (rx > end);
|
||||
if (northSouth && eastWest) {
|
||||
// This means you are in the intersection
|
||||
final Location loc = new Location(plotworld.worldname, x + dpw.ROAD_WIDTH, 0, z + dpw.ROAD_WIDTH);
|
||||
final PlotId id = MainUtil.getPlotAbs(loc);
|
||||
final Plot plot = PS.get().getPlots(plotworld.worldname).get(id);
|
||||
if (plot == null) {
|
||||
return null;
|
||||
}
|
||||
if ((plot.settings.getMerged(0) && plot.settings.getMerged(3))) {
|
||||
return MainUtil.getBottomPlot(plot).id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (northSouth) {
|
||||
// You are on a road running West to East (yeah, I named the var poorly)
|
||||
final Location loc = new Location(plotworld.worldname, x, 0, z + dpw.ROAD_WIDTH);
|
||||
final PlotId id = MainUtil.getPlotAbs(loc);
|
||||
final Plot plot = PS.get().getPlots(plotworld.worldname).get(id);
|
||||
if (plot == null) {
|
||||
return null;
|
||||
}
|
||||
if (plot.settings.getMerged(0)) {
|
||||
return MainUtil.getBottomPlot(plot).id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (eastWest) {
|
||||
// This is the road separating an Eastern and Western plot
|
||||
final Location loc = new Location(plotworld.worldname, x + dpw.ROAD_WIDTH, 0, z);
|
||||
final PlotId id = MainUtil.getPlotAbs(loc);
|
||||
final Plot plot = PS.get().getPlots(plotworld.worldname).get(id);
|
||||
if (plot == null) {
|
||||
return null;
|
||||
}
|
||||
if (plot.settings.getMerged(3)) {
|
||||
return MainUtil.getBottomPlot(plot).id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final PlotId id = new PlotId(dx, dz);
|
||||
final Plot plot = PS.get().getPlots(plotworld.worldname).get(id);
|
||||
if (plot == null) {
|
||||
return id;
|
||||
}
|
||||
return MainUtil.getBottomPlot(plot).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom plot loc (some basic math)
|
||||
*/
|
||||
@Override
|
||||
public Location getPlotBottomLocAbs(final PlotWorld plotworld, final PlotId plotid) {
|
||||
final SquarePlotWorld dpw = ((SquarePlotWorld) plotworld);
|
||||
final int px = plotid.x;
|
||||
final int pz = plotid.y;
|
||||
final int x = dpw.ROAD_OFFSET_X + (px * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - dpw.PLOT_WIDTH - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1;
|
||||
final int z = dpw.ROAD_OFFSET_Z + (pz * (dpw.ROAD_WIDTH + dpw.PLOT_WIDTH)) - dpw.PLOT_WIDTH - ((int) Math.floor(dpw.ROAD_WIDTH / 2)) - 1;
|
||||
return new Location(plotworld.worldname, x, 1, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a plot biome
|
||||
*/
|
||||
@Override
|
||||
public boolean setBiome(final Plot plot, final int biome) {
|
||||
final int bottomX = MainUtil.getPlotBottomLoc(plot.world, plot.id).getX() - 1;
|
||||
final int topX = MainUtil.getPlotTopLoc(plot.world, plot.id).getX() + 1;
|
||||
final int bottomZ = MainUtil.getPlotBottomLoc(plot.world, plot.id).getZ() - 1;
|
||||
final int topZ = MainUtil.getPlotTopLoc(plot.world, plot.id).getZ() + 1;
|
||||
final int size = ((topX - bottomX) + 1) * ((topZ - bottomZ) + 1);
|
||||
final int[] xb = new int[size];
|
||||
final int[] zb = new int[size];
|
||||
final int[] biomes = new int[size];
|
||||
int index = 0;
|
||||
for (int x = bottomX; x <= topX; x++) {
|
||||
for (int z = bottomZ; z <= topZ; z++) {
|
||||
xb[index] = x;
|
||||
zb[index] = z;
|
||||
biomes[index] = biome;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
BlockManager.setBiomes(plot.world, xb, zb, biomes);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import com.intellectualcrafters.configuration.ConfigurationSection;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
|
||||
public abstract class SquarePlotWorld extends GridPlotWorld {
|
||||
public static int PLOT_WIDTH_DEFAULT = 42;
|
||||
public static int ROAD_WIDTH_DEFAULT = 7;
|
||||
public static int ROAD_OFFSET_X_DEFAULT = 0;
|
||||
public static int ROAD_OFFSET__Z_DEFAULT = 0;
|
||||
public int PLOT_WIDTH;
|
||||
public int ROAD_WIDTH;
|
||||
public int ROAD_OFFSET_X;
|
||||
public int ROAD_OFFSET_Z;
|
||||
|
||||
@Override
|
||||
public void loadConfiguration(final ConfigurationSection config) {
|
||||
if (!config.contains("plot.height")) {
|
||||
PS.log(" - &cConfiguration is null? (" + config.getCurrentPath() + ")");
|
||||
}
|
||||
this.PLOT_WIDTH = config.getInt("plot.size");
|
||||
this.ROAD_WIDTH = config.getInt("road.width");
|
||||
this.ROAD_OFFSET_X = config.getInt("road.offset.x");
|
||||
this.ROAD_OFFSET_Z = config.getInt("road.offset.z");
|
||||
this.SIZE = (short) (this.PLOT_WIDTH + this.ROAD_WIDTH);
|
||||
}
|
||||
|
||||
public SquarePlotWorld(final String worldname) {
|
||||
super(worldname);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user