下面列出了怎么用org.bukkit.ChunkSnapshot的API类实例代码及写法,或者点击链接到github查看源代码。
public MaterialData getOriginalMaterial(int x, int y, int z) {
if (y < 0 || y >= 256) return new MaterialData(Material.AIR);
ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z);
ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector);
if (chunkSnapshot != null) {
BlockVector chunkPos = chunkVector.worldToChunk(x, y, z);
return new MaterialData(
chunkSnapshot.getBlockTypeId(
chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()),
(byte)
chunkSnapshot.getBlockData(
chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()));
} else {
return match.getWorld().getBlockAt(x, y, z).getState().getMaterialData();
}
}
public BlockState getOriginalBlock(int x, int y, int z) {
BlockState state = match.getWorld().getBlockAt(x, y, z).getState();
if (y < 0 || y >= 256) return state;
ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z);
ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector);
if (chunkSnapshot != null) {
BlockVector chunkPos = chunkVector.worldToChunk(x, y, z);
state.setMaterialData(
new MaterialData(
chunkSnapshot.getBlockTypeId(
chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()),
(byte)
chunkSnapshot.getBlockData(
chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ())));
}
return state;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockChange(BlockTransformEvent event) {
Match match = PGM.get().getMatchManager().getMatch(event.getWorld());
// Dont carry over old chunks into a new match
if (match == null || match.isFinished()) return;
Chunk chunk = event.getOldState().getChunk();
ChunkVector chunkVector = ChunkVector.of(chunk);
if (!chunkSnapshots.containsKey(chunkVector)) {
match.getLogger().fine("Copying chunk at " + chunkVector);
ChunkSnapshot chunkSnapshot = chunk.getChunkSnapshot();
chunkSnapshot.updateBlock(
event
.getOldState()); // ChunkSnapshot is very likely to have the post-event state already,
// so we have to correct it
chunkSnapshots.put(chunkVector, chunkSnapshot);
}
}
@Override
public boolean queueChunkLoad(int cx, int cz, RunnableVal<ChunkSnapshot> operation) {
if (PAPER) {
try {
new PaperChunkCallback(getImpWorld(), cx, cz) {
@Override
public void onLoad(Chunk chunk) {
try {
ChunkSnapshot snapshot = chunk.getChunkSnapshot();
operation.run(snapshot);
} catch (Throwable e) {
PAPER = false;
}
}
};
return true;
} catch (Throwable ignore) {
PAPER = false;
}
}
return super.queueChunkLoad(cx, cz);
}
@Override
public ChunkSnapshot getCachedChunk(World world, int cx, int cz) {
long pair = MathMan.pairInt(cx, cz);
ChunkSnapshot cached = chunkCache.get(pair);
if (cached != null) return cached;
if (world.isChunkLoaded(cx, cz)) {
Long originalKeep = keepLoaded.get(pair);
keepLoaded.put(pair, Long.MAX_VALUE);
if (world.isChunkLoaded(cx, cz)) {
Chunk chunk = world.getChunkAt(cx, cz);
ChunkSnapshot snapshot = getAndCacheChunk(chunk);
if (originalKeep != null) {
keepLoaded.put(pair, originalKeep);
} else {
keepLoaded.remove(pair);
}
return snapshot;
} else {
keepLoaded.remove(pair);
return null;
}
} else {
return null;
}
}
public static int getBlockIDFromSnapshotMap(HashMap<ChunkCoord, ChunkSnapshot> snapshots, int absX, int absY, int absZ, String worldName) throws CivException {
int chunkX = ChunkCoord.castToChunkX(absX);
int chunkZ = ChunkCoord.castToChunkZ(absZ);
int blockChunkX = absX % 16;
int blockChunkZ = absZ % 16;
if (blockChunkX < 0) {
blockChunkX += 16;
}
if (blockChunkZ < 0) {
blockChunkZ += 16;
}
ChunkCoord coord = new ChunkCoord(worldName, chunkX, chunkZ);
ChunkSnapshot snapshot = snapshots.get(coord);
if (snapshot == null) {
throw new CivException("Snapshot for chunk "+chunkX+", "+chunkZ+" in "+worldName+" not found for abs:"+absX+","+absZ);
}
return ItemManager.getBlockTypeId(snapshot, blockChunkX, absY, blockChunkZ);
}
public void setFromSnapshotLocation(int x, int y, int z, ChunkSnapshot snapshot) {
/* Modulo in Java doesn't handle negative numbers the way we want it to, compensate here. */
if (x < 0) {
x += 16;
}
if (z < 0) {
z += 16;
}
this.setX(x);
this.setY(y);
this.setZ(z);
this.setSnapshot(snapshot);
this.setTypeId(ItemManager.getBlockTypeId(snapshot, this.x, this.y, this.z));
this.setData(ItemManager.getBlockData(snapshot, this.x, this.y, this.z));
}
@SuppressWarnings("deprecation")
private void scanChunk(ChunkSnapshot chunk) {
for (int x = 0; x< 16; x++) {
// Check if the block coord is inside the protection zone and if not, don't count it
if (chunk.getX() * 16 + x < island.getMinProtectedX() || chunk.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionSize()) {
continue;
}
for (int z = 0; z < 16; z++) {
// Check if the block coord is inside the protection zone and if not, don't count it
if (chunk.getZ() * 16 + z < island.getMinProtectedZ() || chunk.getZ() * 16 + z >= island.getMinProtectedZ() + island.getProtectionSize()) {
continue;
}
for (int y = 0; y < island.getCenter().getWorld().getMaxHeight(); y++) {
Material blockType = Material.getMaterial(chunk.getBlockTypeId(x, y, z));
boolean belowSeaLevel = Settings.seaHeight > 0 && y <= Settings.seaHeight;
// Air is free
if (!blockType.equals(Material.AIR)) {
checkBlock(blockType, chunk.getBlockData(x, y, z), belowSeaLevel);
}
}
}
}
}
/**
* Loops through the chunks and if a safe spot is found, fires off the teleportation
* @param chunkSnapshot
*/
private void checkChunks(final List<ChunkSnapshot> chunkSnapshot) {
// Run async task to scan chunks
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
for (ChunkSnapshot chunk: chunkSnapshot) {
if (scanChunk(chunk)) {
task.cancel();
return;
}
}
// Nothing happened, change state
checking = true;
}
});
}
/**
* @param chunk
* @return true if a safe spot was found
*/
private boolean scanChunk(ChunkSnapshot chunk) {
// Max height
int maxHeight = location.getWorld().getMaxHeight() - 20;
// Run through the chunk
for (int x = 0; x< 16; x++) {
for (int z = 0; z < 16; z++) {
// Work down from the entry point up
for (int y = Math.min(chunk.getHighestBlockYAt(x, z), maxHeight); y >= 0; y--) {
if (checkBlock(chunk, x,y,z, maxHeight)) {
return true;
}
} // end y
} //end z
} // end x
return false;
}
public MaterialData getOriginalMaterial(int x, int y, int z) {
if(y < 0 || y >= 256) return new MaterialData(Material.AIR);
ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z);
ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector);
if(chunkSnapshot != null) {
BlockVector chunkPos = chunkVector.worldToChunk(x, y, z);
return new MaterialData(chunkSnapshot.getBlockTypeId(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()),
(byte) chunkSnapshot.getBlockData(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()));
} else {
return getMatch().getWorld().getBlockAt(x, y, z).getState().getMaterialData();
}
}
public BlockState getOriginalBlock(int x, int y, int z) {
BlockState state = getMatch().getWorld().getBlockAt(x, y, z).getState();
if(y < 0 || y >= 256) return state;
ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z);
ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector);
if(chunkSnapshot != null) {
BlockVector chunkPos = chunkVector.worldToChunk(x, y, z);
state.setMaterialData(new MaterialData(chunkSnapshot.getBlockTypeId(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()),
(byte) chunkSnapshot.getBlockData(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ())));
}
return state;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockChange(BlockTransformEvent event) {
Chunk chunk = event.getOldState().getChunk();
ChunkVector chunkVector = ChunkVector.of(chunk);
if(!chunkSnapshots.containsKey(chunkVector)) {
logger.fine("Copying chunk at " + chunkVector);
ChunkSnapshot chunkSnapshot = chunk.getChunkSnapshot();
chunkSnapshot.updateBlock(event.getOldState()); // ChunkSnapshot is very likely to have the post-event state already, so we have to correct it
chunkSnapshots.put(chunkVector, chunkSnapshot);
}
}
@Override
public ChunkSnapshot getChunkSnapshot(boolean includeMaxblocky, boolean includeBiome, boolean includeBiomeTempRain) {
if (Fawe.isMainThread()) {
return world.getChunkAt(x, z).getChunkSnapshot(includeMaxblocky, includeBiome, includeBiomeTempRain);
}
return whenLoaded(new RunnableVal<ChunkSnapshot>() {
@Override
public void run(ChunkSnapshot value) {
this.value = world.getBukkitWorld().getChunkAt(x, z).getChunkSnapshot(includeBiome, includeBiome, includeBiomeTempRain);
}
});
}
@Override
public ChunkSnapshot getEmptyChunkSnapshot(final int x, final int z, final boolean includeBiome, final boolean includeBiomeTempRain) {
return TaskManager.IMP.sync(new RunnableVal<ChunkSnapshot>() {
@Override
public void run(ChunkSnapshot value) {
this.value = parent.getEmptyChunkSnapshot(x, z, includeBiome, includeBiomeTempRain);
}
});
}
@Override
public int getCombinedId4Data(ChunkSnapshot chunk, int x, int y, int z) {
if (chunk.isSectionEmpty(y >> 4)) {
return 0;
}
int id = chunk.getBlockTypeId(x & 15, y, z & 15);
if (FaweCache.hasData(id)) {
int data = chunk.getBlockData(x & 15, y, z & 15);
return (id << 4) + data;
} else {
return id << 4;
}
}
@Override
public CompoundTag getTileEntity(ChunkSnapshot chunk, int x, int y, int z) {
if (getAdapter() == null) {
return null;
}
Location loc = new Location(getWorld(), x, y, z);
BaseBlock block = getAdapter().getBlock(loc);
return block != null ? block.getNbtData() : null;
}
@Override
public void calculateScoreAsync(final Location l, final Callback<IslandScore> callback) {
// TODO: 10/05/2015 - R4zorax: Ensure no overlapping calls to this one happen...
log.entering(CN, "calculateScoreAsync");
// is further threading needed here?
final ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(l);
if (region == null) {
return;
}
new ChunkSnapShotTask(plugin, l, region, new Callback<List<ChunkSnapshot>>() {
@Override
public void run() {
final List<ChunkSnapshot> snapshotsOverworld = getState();
Location netherLoc = getNetherLocation(l);
final ProtectedRegion netherRegion = WorldGuardHandler.getNetherRegionAt(netherLoc);
new ChunkSnapShotTask(plugin, netherLoc, netherRegion, new Callback<List<ChunkSnapshot>>() {
@Override
public void run() {
final List<ChunkSnapshot> snapshotsNether = getState();
new BukkitRunnable() {
@Override
public void run() {
calculateScoreAndCallback(region, snapshotsOverworld, netherRegion, snapshotsNether, callback);
}
}.runTaskAsynchronously(plugin);
}
}).runTask(plugin);
}
}).runTask(plugin);
}
private static ChunkSnapshot getChunkSnapshot(int x, int z, List<ChunkSnapshot> snapshots) {
for (ChunkSnapshot chunk : snapshots) {
if (chunk.getX() == x && chunk.getZ() == z) {
return chunk;
}
}
return null;
}
public ChunkSnapShotTask(uSkyBlock plugin, Location location, ProtectedRegion region, final Callback<List<ChunkSnapshot>> callback) {
super(plugin, callback);
this.location = location;
if (region != null) {
chunks = new ArrayList<>(WorldEditHandler.getChunks(new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint())));
} else {
chunks = new ArrayList<>();
}
callback.setState(snapshots);
}
public Material getBlockTypeAt(int x, int y, int z) {
ChunkSnapshot chunkAt = getChunkAt(x >> 4, z >> 4);
if (chunkAt != null) {
int cx = x & 0xF;
int cz = z & 0xF;
return chunkAt.getBlockType(cx, y, cz);
}
return null;
}
@Override
public void run() {
/* Find adjacent farms, get their chunk snapshots and continue processing in our thread. */
ChunkCoord cc = new ChunkCoord(windmill.getCorner());
ArrayList<ChunkSnapshot> snapshots = new ArrayList<ChunkSnapshot>();
int[][] offset = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 1 }, {-1,-1 }, {-1, 1}, {1, -1} };
for (int i = 0; i < 8; i++) {
cc.setX(cc.getX() + offset[i][0]);
cc.setZ(cc.getZ() + offset[i][1]);
FarmChunk farmChunk = CivGlobal.getFarmChunk(cc);
if (farmChunk != null) {
snapshots.add(farmChunk.getChunk().getChunkSnapshot());
}
cc.setFromLocation(windmill.getCorner().getLocation());
}
if (snapshots.size() == 0) {
return;
}
/* Fire off an async task to do some post processing. */
TaskMaster.asyncTask("", new WindmillPreProcessTask(windmill, snapshots), 0);
}
private void checkChunksAsync(final Set<ChunkSnapshot> chunkSnapshot) {
// Run async task to scan chunks
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
for (ChunkSnapshot chunk: chunkSnapshot) {
scanChunk(chunk);
}
// Nothing happened, change state
checking = true;
});
}
private boolean safe(ChunkSnapshot chunk, int x, int y, int z, World world) {
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
if (portal) {
if (bestSpot == null) {
// Stash the best spot
bestSpot = newSpot.toLocation(world);
}
return false;
} else {
teleportEntity(newSpot.toLocation(world));
return true;
}
}
public ChunkSnapshot getChunkSnapshot() {
return getChunkSnapshot(true, false, false);
}
public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world, boolean includeBiome, boolean includeBiomeTempRain) {
Biome[] biome = null;
double[] biomeTemp = null;
double[] biomeRain = null;
if (includeBiome || includeBiomeTempRain) {
BiomeProvider wcm = world.getHandle().getBiomeProvider();
if (includeBiome) {
biome = new Biome[256];
for (int i = 0; i < 256; i++) {
biome[i] = world.getHandle().getBiome(new BlockPos((x << 4) + (i & 0xF), 0, (z << 4) + (i >> 4)));
}
}
if (includeBiomeTempRain) {
biomeTemp = new double[256];
biomeRain = new double[256];
float[] dat = getTemperatures(wcm, x << 4, z << 4);
for (int i = 0; i < 256; i++) {
biomeTemp[i] = dat[i];
}
/* Removed 15w46a
dat = wcm.getWetness(null, x << 4, z << 4, 16, 16);
for (int i = 0; i < 256; i++) {
biomeRain[i] = dat[i];
}
*/
}
}
/* Fill with empty data */
int hSection = world.getMaxHeight() >> 4;
short[][] blockIDs = new short[hSection][];
byte[][] skyLight = new byte[hSection][];
byte[][] emitLight = new byte[hSection][];
byte[][] blockData = new byte[hSection][];
boolean[] empty = new boolean[hSection];
for (int i = 0; i < hSection; i++) {
blockIDs[i] = emptyBlockIDs;
skyLight[i] = emptySkyLight;
emitLight[i] = emptyData;
blockData[i] = emptyData;
empty[i] = true;
}
return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, blockData, skyLight, emitLight, empty, new int[256], biome, biomeTemp, biomeRain);
}
public GChunk(ChunkSnapshot chunkSnapshot) {
this.world = chunkSnapshot.getWorldName();
this.x = chunkSnapshot.getX();
this.z = chunkSnapshot.getZ();
}
public static ChunkPos of(ChunkSnapshot snapshot) {
return new ChunkPos(snapshot.getWorldName(), snapshot.getX(), snapshot.getZ());
}
public void queue(ChunkSnapshot snapshot) {
queue.add(snapshot);
}
@Override
public void run() {
while (!isInterrupted()) {
ChunkSnapshot snapshot;
try {
snapshot = queue.take();
} catch (InterruptedException e) {
interrupt();
break;
}
ChunkPos pos = ChunkPos.of(snapshot);
double worth = 0;
double blockPrice;
Map<Material, Integer> materials = new EnumMap<>(Material.class);
for (int y = 0; y < 256; y++) {
// ChunkSnapshot#getHighestBlockYAt(x, y) for whatever reason
// provides us with a half complete chunk in Spigot v1.10.x. So
// we're testing if the chunk section is empty instead.
if (snapshot.isSectionEmpty(y >> 4)) {
y += 15;
continue;
}
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
Material material = Material.getMaterial(snapshot.getBlockTypeId(x, y, z));
if (material == null) {
continue;
}
blockPrice = plugin.getSettings().getBlockPrice(material);
worth += blockPrice;
if (blockPrice != 0) {
int count = materials.getOrDefault(material, 0);
materials.put(material, count + 1);
}
}
}
}
final double worthFinal = worth;
plugin.getServer().getScheduler().runTask(plugin, () -> {
plugin.getWorthManager().set(pos, WorthType.BLOCK, worthFinal);
plugin.getWorthManager().setMaterials(pos, materials);
});
}
}