PlotSquared/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java

366 lines
14 KiB
Java
Raw Normal View History

2015-07-26 18:14:34 +02:00
package com.plotsquared.bukkit.generator;
2015-07-30 16:25:16 +02:00
import com.intellectualcrafters.plot.PS;
2016-02-10 19:59:51 +01:00
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
2016-04-05 02:08:10 +02:00
import com.intellectualcrafters.plot.object.ChunkLoc;
2016-06-13 06:47:50 +02:00
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.Location;
2016-03-14 07:18:04 +01:00
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.SetupObject;
2015-07-30 16:25:16 +02:00
import com.intellectualcrafters.plot.util.ChunkManager;
2016-02-10 19:59:51 +01:00
import com.intellectualcrafters.plot.util.MainUtil;
2016-06-13 06:47:50 +02:00
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
2016-02-10 19:59:51 +01:00
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.block.GenChunk;
2016-06-13 06:47:50 +02:00
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Set;
2016-02-10 19:59:51 +01:00
public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
2015-09-13 06:04:31 +02:00
2016-06-13 06:47:50 +02:00
private final GenChunk chunkSetter;
2016-02-10 19:59:51 +01:00
private final PseudoRandom random = new PseudoRandom();
private final IndependentPlotGenerator plotGenerator;
private List<BlockPopulator> populators;
2016-03-14 07:18:04 +01:00
private final ChunkGenerator platformGenerator;
private final boolean full;
private final HashMap<ChunkLoc, byte[][]> dataMap = new HashMap<>();
private boolean loaded = false;
2016-02-10 19:59:51 +01:00
public BukkitPlotGenerator(IndependentPlotGenerator generator) {
2016-04-26 01:32:16 +02:00
if (generator == null) {
throw new IllegalArgumentException("Generator may not be null!");
}
2016-02-10 19:59:51 +01:00
this.plotGenerator = generator;
this.platformGenerator = this;
populators = new ArrayList<>();
2016-03-23 02:41:37 +01:00
this.populators.add(new BlockPopulator() {
2016-06-13 06:47:50 +02:00
private LocalBlockQueue queue;
2016-02-10 19:59:51 +01:00
@Override
public void populate(World world, Random r, Chunk c) {
2016-06-13 06:47:50 +02:00
if (queue == null) {
queue = GlobalBlockQueue.IMP.getNewQueue(world.getName(), false);
}
2016-04-05 02:08:10 +02:00
ChunkLoc loc = new ChunkLoc(c.getX(), c.getZ());
byte[][] resultData;
if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) {
2016-06-13 06:47:50 +02:00
GenChunk result = BukkitPlotGenerator.this.chunkSetter;
2016-04-05 02:08:10 +02:00
// Set the chunk location
2016-06-13 06:47:50 +02:00
result.setChunk(c);
2016-04-05 02:08:10 +02:00
// Set the result data
result.result = new short[16][];
result.result_data = new byte[16][];
result.grid = null;
result.cd = null;
// Catch any exceptions (as exceptions usually thrown)
generate(world, loc.x, loc.z, result);
resultData = result.result_data;
} else {
resultData = BukkitPlotGenerator.this.dataMap.remove(loc);
2016-04-05 02:08:10 +02:00
}
if (resultData != null) {
for (int i = 0; i < resultData.length; i++) {
byte[] section = resultData[i];
2016-02-10 19:59:51 +01:00
if (section == null) {
continue;
}
for (int j = 0; j < section.length; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
c.getBlock(x, y, z).setData(section[j]);
}
}
}
BukkitPlotGenerator.this.random.state = c.getX() << 16 | c.getZ() & 0xFFFF;
PlotArea area = PS.get().getPlotArea(world.getName(), null);
2016-06-13 06:47:50 +02:00
ChunkWrapper wrap = new ChunkWrapper(area.worldname, c.getX(), c.getZ());
ScopedLocalBlockQueue chunk = queue.getForChunk(wrap.x, wrap.z);
if (BukkitPlotGenerator.this.plotGenerator.populateChunk(chunk, area, BukkitPlotGenerator.this.random)) {
2016-06-13 06:47:50 +02:00
queue.flush();
}
2016-02-10 19:59:51 +01:00
}
});
2016-03-23 02:41:37 +01:00
this.chunkSetter = new GenChunk(null, null);
2016-02-10 19:59:51 +01:00
this.full = true;
MainUtil.initCache();
}
2015-09-13 06:04:31 +02:00
2016-02-10 19:59:51 +01:00
public BukkitPlotGenerator(final String world, final ChunkGenerator cg) {
if (cg instanceof BukkitPlotGenerator) {
throw new IllegalArgumentException("ChunkGenerator: " + cg.getClass().getName() + " is already a BukkitPlotGenerator!");
}
this.full = false;
2016-03-14 07:18:04 +01:00
PS.debug("BukkitPlotGenerator does not fully support: " + cg);
2016-03-23 02:41:37 +01:00
this.platformGenerator = cg;
this.plotGenerator = new IndependentPlotGenerator() {
2016-02-10 19:59:51 +01:00
@Override
public void processSetup(SetupObject setup) {}
@Override
public void initialize(PlotArea area) {}
@Override
public PlotManager getNewPlotManager() {
return PS.get().IMP.getDefaultGenerator().getNewPlotManager();
2016-02-10 19:59:51 +01:00
}
@Override
public String getName() {
return cg.getClass().getName();
}
@Override
public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) {
return PS.get().IMP.getDefaultGenerator().getNewPlotArea(world, id, min, max);
2016-02-10 19:59:51 +01:00
}
@Override
2016-06-13 06:47:50 +02:00
public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
2016-02-10 19:59:51 +01:00
World w = BukkitUtil.getWorld(world);
2016-06-13 06:47:50 +02:00
Location min = result.getMin();
int cx = min.getX() >> 4;
int cz = min.getZ() >> 4;
Random r = new Random(MathMan.pair((short) cx, (short) cz));
2016-02-10 19:59:51 +01:00
BiomeGrid grid = new BiomeGrid() {
@Override
public void setBiome(int x, int z, Biome biome) {
2016-06-13 06:47:50 +02:00
result.setBiome(x, z, biome.name());
2016-02-10 19:59:51 +01:00
}
@Override
public Biome getBiome(int arg0, int arg1) {
return Biome.FOREST;
}
};
try {
// ChunkData will spill a bit
2016-06-13 06:47:50 +02:00
ChunkData data = cg.generateChunkData(w, r, cx, cz, grid);
2016-02-10 19:59:51 +01:00
if (data != null) {
return;
}
2016-05-12 23:09:35 +02:00
} catch (Throwable ignored) {}
2016-02-10 19:59:51 +01:00
// Populator spillage
2016-06-13 06:47:50 +02:00
short[][] tmp = cg.generateExtBlockSections(w, r, cx, cz, grid);
2016-02-10 19:59:51 +01:00
if (tmp != null) {
for (int i = 0; i < tmp.length; i++) {
short[] section = tmp[i];
if (section == null) {
if (i < 7) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = i << 4; y < (i << 4) + 16; y++) {
result.setBlock(x, y, z, (short) 0, (byte) 0);
}
}
}
}
continue;
}
for (int j = 0; j < section.length; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
result.setBlock(x, y, z, section[j], (byte) 0);
}
}
}
2016-02-10 19:59:51 +01:00
for (BlockPopulator populator : cg.getDefaultPopulators(w)) {
2016-06-13 06:47:50 +02:00
populator.populate(w, r, w.getChunkAt(cx, cz));
2016-02-10 19:59:51 +01:00
}
}
2016-02-10 19:59:51 +01:00
};
2016-06-13 06:47:50 +02:00
this.chunkSetter = new GenChunk(null, new ChunkWrapper(world, 0, 0));
2016-02-10 19:59:51 +01:00
MainUtil.initCache();
}
2015-09-13 06:04:31 +02:00
2016-02-10 19:59:51 +01:00
@Override
public void augment(PlotArea area) {
BukkitAugmentedGenerator.get(BukkitUtil.getWorld(area.worldname));
}
@Override
public boolean isFull() {
2016-03-23 02:41:37 +01:00
return this.full;
2016-02-10 19:59:51 +01:00
}
@Override
public IndependentPlotGenerator getPlotGenerator() {
2016-03-23 02:41:37 +01:00
return this.plotGenerator;
2016-02-10 19:59:51 +01:00
}
@Override
public ChunkGenerator getPlatformGenerator() {
2016-03-23 02:41:37 +01:00
return this.platformGenerator;
2016-02-10 19:59:51 +01:00
}
2015-02-24 12:27:30 +01:00
@Override
2016-03-23 02:41:37 +01:00
public List<BlockPopulator> getDefaultPopulators(World world) {
2015-09-13 06:04:31 +02:00
try {
2016-03-23 02:41:37 +01:00
if (!this.loaded) {
String name = world.getName();
2016-02-10 19:59:51 +01:00
PS.get().loadWorld(name, this);
Set<PlotArea> areas = PS.get().getPlotAreas(name);
if (!areas.isEmpty()) {
2016-02-10 19:59:51 +01:00
PlotArea area = areas.iterator().next();
if (!area.MOB_SPAWNING) {
if (!area.SPAWN_EGGS) {
world.setSpawnFlags(false, false);
}
world.setAmbientSpawnLimit(0);
world.setAnimalSpawnLimit(0);
world.setMonsterSpawnLimit(0);
world.setWaterAnimalSpawnLimit(0);
} else {
world.setSpawnFlags(true, true);
world.setAmbientSpawnLimit(-1);
world.setAnimalSpawnLimit(-1);
world.setMonsterSpawnLimit(-1);
world.setWaterAnimalSpawnLimit(-1);
2015-05-10 05:17:10 +02:00
}
}
2016-03-23 02:41:37 +01:00
this.loaded = true;
}
2016-03-23 02:41:37 +01:00
} catch (Exception e) {
2015-05-10 05:17:10 +02:00
e.printStackTrace();
}
2016-04-30 00:14:12 +02:00
ArrayList<BlockPopulator> toAdd = new ArrayList<>();
List<BlockPopulator> existing = world.getPopulators();
if (populators == null && platformGenerator != null) {
populators = new ArrayList<>();
this.populators.addAll(platformGenerator.getDefaultPopulators(world));
}
for (BlockPopulator populator : this.populators) {
if (!existing.contains(populator)) {
toAdd.add(populator);
}
}
return toAdd;
}
@Override
2016-02-10 19:59:51 +01:00
public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) {
GenChunk result = this.chunkSetter;
2016-02-10 19:59:51 +01:00
// Set the chunk location
2016-06-13 06:47:50 +02:00
result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
2016-02-10 19:59:51 +01:00
// Set the result data
result.cd = createChunkData(world);
result.grid = grid;
result.result = null;
result.result_data = null;
// Catch any exceptions (as exceptions usually thrown)
2015-09-13 06:04:31 +02:00
try {
2016-02-10 19:59:51 +01:00
// Fill the result data if necessary
2016-03-23 02:41:37 +01:00
if (this.platformGenerator != this) {
return this.platformGenerator.generateChunkData(world, random, cx, cz, grid);
2016-02-10 19:59:51 +01:00
} else {
generate(world, cx, cz, result);
2015-05-10 05:17:10 +02:00
}
2016-02-10 19:59:51 +01:00
} catch (Throwable e) {
2015-05-10 05:17:10 +02:00
e.printStackTrace();
}
2016-02-10 19:59:51 +01:00
// Return the result data
return result.cd;
}
2016-06-13 06:47:50 +02:00
public void generate(World world, int cx, int cz, ScopedLocalBlockQueue result) {
2016-02-10 19:59:51 +01:00
// Load if improperly loaded
2016-03-23 02:41:37 +01:00
if (!this.loaded) {
String name = world.getName();
2016-02-10 19:59:51 +01:00
PS.get().loadWorld(name, this);
2016-03-23 02:41:37 +01:00
this.loaded = true;
2016-02-10 19:59:51 +01:00
}
// Set random seed
2016-03-21 03:52:16 +01:00
this.random.state = cx << 16 | cz & 0xFFFF;
2016-02-10 19:59:51 +01:00
// Process the chunk
if (ChunkManager.preProcessChunk(result)) {
2016-02-10 19:59:51 +01:00
return;
}
2016-02-10 19:59:51 +01:00
PlotArea area = PS.get().getPlotArea(world.getName(), null);
2016-04-26 01:32:16 +02:00
try {
this.plotGenerator.generateChunk(this.chunkSetter, area, this.random);
} catch (Throwable e) {
// Recover from generator error
e.printStackTrace();
}
2016-02-10 19:59:51 +01:00
ChunkManager.postProcessChunk(result);
}
2015-09-13 06:04:31 +02:00
2016-02-10 19:59:51 +01:00
@Override
2016-03-23 02:41:37 +01:00
public short[][] generateExtBlockSections(World world, Random r, int cx, int cz, BiomeGrid grid) {
GenChunk result = this.chunkSetter;
2016-02-10 19:59:51 +01:00
// Set the chunk location
2016-06-13 06:47:50 +02:00
result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
2016-02-10 19:59:51 +01:00
// Set the result data
result.result = new short[16][];
result.result_data = new byte[16][];
result.grid = grid;
result.cd = null;
// Catch any exceptions (as exceptions usually thrown)
2016-02-10 19:59:51 +01:00
try {
// Fill the result data
2016-03-23 02:41:37 +01:00
if (this.platformGenerator != this) {
return this.platformGenerator.generateExtBlockSections(world, r, cx, cz, grid);
2016-02-10 19:59:51 +01:00
} else {
generate(world, cx, cz, result);
this.dataMap.put(new ChunkLoc(cx, cz), result.result_data);
2016-04-05 02:08:10 +02:00
2016-02-10 19:59:51 +01:00
}
} catch (Throwable e) {
e.printStackTrace();
2015-03-27 09:20:19 +01:00
}
2016-02-10 19:59:51 +01:00
// Return the result data
return result.result;
}
2015-09-13 06:04:31 +02:00
2015-03-27 09:20:19 +01:00
/**
2016-03-23 02:41:37 +01:00
* Allow spawning everywhere.
* @param world Ignored
* @param x Ignored
* @param z Ignored
* @return always true
2015-03-27 09:20:19 +01:00
*/
@Override
2016-03-23 02:41:37 +01:00
public boolean canSpawn(World world, int x, int z) {
2015-03-27 09:20:19 +01:00
return true;
}
2015-09-13 06:04:31 +02:00
2016-02-10 19:59:51 +01:00
@Override
public String toString() {
2016-03-23 02:41:37 +01:00
if (this.platformGenerator == this) {
return this.plotGenerator.getName();
2016-03-23 02:41:37 +01:00
}
if (this.platformGenerator == null) {
return "null";
} else {
return this.platformGenerator.getClass().getName();
2016-02-10 19:59:51 +01:00
}
}
2015-09-13 06:04:31 +02:00
2016-02-10 19:59:51 +01:00
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
2016-03-21 03:52:16 +01:00
return toString().equals(obj.toString()) || toString().equals(obj.getClass().getName());
2016-02-10 19:59:51 +01:00
}
}