2015-07-30 19:24:01 +02:00
|
|
|
package com.plotsquared.bukkit.util;
|
2014-11-21 04:11:41 +01:00
|
|
|
|
2015-07-30 16:25:16 +02:00
|
|
|
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.Chunk;
|
|
|
|
import org.bukkit.World;
|
|
|
|
|
2015-07-03 14:15:20 +02:00
|
|
|
import com.intellectualcrafters.plot.PS;
|
2015-02-20 06:53:00 +01:00
|
|
|
import com.intellectualcrafters.plot.object.ChunkLoc;
|
2015-01-13 17:38:15 +01:00
|
|
|
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
|
|
|
|
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
|
|
|
|
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
|
|
|
|
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
|
2014-11-21 23:45:46 +01:00
|
|
|
|
|
|
|
/**
|
2014-12-18 03:15:11 +01:00
|
|
|
* An utility that can be used to send chunks, rather than using bukkit code to do so (uses heavy NMS)
|
2014-11-21 23:45:46 +01:00
|
|
|
*
|
|
|
|
* @author Empire92
|
|
|
|
*/
|
2014-11-21 04:11:41 +01:00
|
|
|
public class SendChunk {
|
2015-04-02 02:56:34 +02:00
|
|
|
|
2014-11-21 23:45:46 +01:00
|
|
|
// Ref Class
|
2014-12-18 03:15:11 +01:00
|
|
|
private static final RefClass classWorld = getRefClass("{nms}.World");
|
|
|
|
private static final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
|
2014-11-21 04:11:41 +01:00
|
|
|
private static final RefClass classChunkCoordIntPair = getRefClass("{nms}.ChunkCoordIntPair");
|
2014-12-18 03:15:11 +01:00
|
|
|
private static final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
|
|
|
private static final RefClass classChunk = getRefClass("{nms}.Chunk");
|
2015-07-26 18:14:34 +02:00
|
|
|
private static boolean v1_7_10 = PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 7, 10) && !PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 8, 0);
|
2014-11-21 23:45:46 +01:00
|
|
|
// Ref Method
|
2014-12-18 03:15:11 +01:00
|
|
|
private static RefMethod methodGetHandle;
|
2014-11-21 23:45:46 +01:00
|
|
|
// Ref Field
|
2014-12-18 03:15:11 +01:00
|
|
|
private static RefField chunkCoordIntPairQueue;
|
|
|
|
private static RefField players;
|
|
|
|
private static RefField locX;
|
|
|
|
private static RefField locZ;
|
|
|
|
private static RefField world;
|
2014-11-21 23:45:46 +01:00
|
|
|
// Ref Constructor
|
2014-11-21 04:11:41 +01:00
|
|
|
private static RefConstructor ChunkCoordIntPairCon;
|
2015-02-23 02:32:27 +01:00
|
|
|
|
2014-11-21 23:45:46 +01:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @throws NoSuchMethodException
|
|
|
|
*/
|
2014-11-21 04:11:41 +01:00
|
|
|
public SendChunk() throws NoSuchMethodException {
|
|
|
|
methodGetHandle = classCraftChunk.getMethod("getHandle");
|
|
|
|
chunkCoordIntPairQueue = classEntityPlayer.getField("chunkCoordIntPairQueue");
|
|
|
|
players = classWorld.getField("players");
|
|
|
|
locX = classEntityPlayer.getField("locX");
|
|
|
|
locZ = classEntityPlayer.getField("locZ");
|
|
|
|
world = classChunk.getField("world");
|
|
|
|
ChunkCoordIntPairCon = classChunkCoordIntPair.getConstructor(int.class, int.class);
|
|
|
|
}
|
2015-02-23 02:32:27 +01:00
|
|
|
|
2015-03-27 12:25:24 +01:00
|
|
|
public static void sendChunk(final Collection<Chunk> chunks) {
|
2014-11-21 04:11:41 +01:00
|
|
|
int diffx, diffz;
|
2014-12-16 06:03:20 +01:00
|
|
|
final int view = Bukkit.getServer().getViewDistance() << 4;
|
|
|
|
for (final Chunk chunk : chunks) {
|
2015-06-23 23:44:44 +02:00
|
|
|
if (!chunk.isLoaded()) {
|
|
|
|
continue;
|
|
|
|
}
|
2015-04-02 02:56:34 +02:00
|
|
|
boolean unload = true;
|
2014-11-21 04:11:41 +01:00
|
|
|
final Object c = methodGetHandle.of(chunk).call();
|
|
|
|
final Object w = world.of(c).get();
|
|
|
|
final Object p = players.of(w).get();
|
2014-12-16 06:03:20 +01:00
|
|
|
for (final Object ep : (List<Object>) p) {
|
|
|
|
final int x = ((Double) locX.of(ep).get()).intValue();
|
|
|
|
final int z = ((Double) locZ.of(ep).get()).intValue();
|
2014-11-21 04:11:41 +01:00
|
|
|
diffx = Math.abs(x - (chunk.getX() << 4));
|
|
|
|
diffz = Math.abs(z - (chunk.getZ() << 4));
|
2014-12-16 06:03:20 +01:00
|
|
|
if ((diffx <= view) && (diffz <= view)) {
|
2015-04-02 02:56:34 +02:00
|
|
|
unload = false;
|
|
|
|
if (v1_7_10) {
|
|
|
|
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
|
|
|
|
chunk.load(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
final Object pair = ChunkCoordIntPairCon.create(chunk.getX(), chunk.getZ());
|
|
|
|
final Object pq = chunkCoordIntPairQueue.of(ep).get();
|
|
|
|
((List) pq).add(pair);
|
|
|
|
}
|
2014-11-21 04:11:41 +01:00
|
|
|
}
|
|
|
|
}
|
2015-04-02 02:56:34 +02:00
|
|
|
if (unload) {
|
|
|
|
chunk.unload(true, true);
|
|
|
|
}
|
2014-11-21 04:11:41 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-23 02:32:27 +01:00
|
|
|
|
2015-02-20 07:34:19 +01:00
|
|
|
public static void sendChunk(final String worldname, final List<ChunkLoc> locs) {
|
|
|
|
final World myworld = Bukkit.getWorld(worldname);
|
|
|
|
final ArrayList<Chunk> chunks = new ArrayList<>();
|
|
|
|
for (final ChunkLoc loc : locs) {
|
2015-02-20 07:28:21 +01:00
|
|
|
chunks.add(myworld.getChunkAt(loc.x, loc.z));
|
|
|
|
}
|
|
|
|
sendChunk(chunks);
|
|
|
|
}
|
2014-11-21 04:11:41 +01:00
|
|
|
}
|