PlotSquared/src/main/java/com/plotsquared/bukkit/util/SendChunk.java

194 lines
7.9 KiB
Java
Raw Normal View History

2015-07-30 19:24:01 +02:00
package com.plotsquared.bukkit.util;
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.HashMap;
import java.util.HashSet;
2015-07-30 16:25:16 +02:00
import java.util.List;
import org.bukkit.Chunk;
import com.intellectualcrafters.plot.PS;
2015-02-20 06:53:00 +01:00
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
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;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.bukkit.object.BukkitPlayer;
2015-08-21 06:53:53 +02:00
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.Bukkit;
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
*/
public class SendChunk {
2015-04-02 02:56:34 +02:00
// // Ref Class
2015-08-03 20:20:04 +02:00
private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
2015-08-21 06:53:53 +02:00
private final RefClass classPacket = getRefClass("{nms}.Packet");
private final RefClass classConnection = getRefClass("{nms}.PlayerConnection");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer");
2015-08-23 14:04:17 +02:00
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
private RefMethod methodGetHandlePlayer;
2015-08-23 14:04:17 +02:00
private RefMethod methodGetHandleChunk;
private RefConstructor MapChunk;
private RefField connection;
private RefMethod send;
2015-02-23 02:32:27 +01:00
2014-11-21 23:45:46 +01:00
/**
* Constructor
*
* @throws NoSuchMethodException
*/
public SendChunk() throws NoSuchMethodException {
methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle");
2015-08-23 14:04:17 +02:00
methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
2015-08-21 06:53:53 +02:00
MapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), boolean.class, int.class);
connection = classEntityPlayer.getField("playerConnection");
send = classConnection.getMethod("sendPacket", classPacket.getRealClass());
}
2015-02-23 02:32:27 +01:00
public void sendChunk(final Collection<Chunk> input) {
HashSet<Chunk> chunks = new HashSet<Chunk>(input);
HashMap<String, ArrayList<Chunk>> map = new HashMap<>();
int view = Bukkit.getServer().getViewDistance();
for (Chunk chunk : chunks) {
String world = chunk.getWorld().getName();
ArrayList<Chunk> list = map.get(world);
if (list == null) {
list = new ArrayList<>();
map.put(world, list);
}
list.add(chunk);
}
for (PlotPlayer pp : UUIDHandler.getPlayers().values() ) {
Plot plot = pp.getCurrentPlot();
Location loc = null;
String world;
if (plot != null) {
world = plot.world;
}
else {
loc = pp.getLocation();
world = loc.getWorld();
}
ArrayList<Chunk> list = map.get(world);
if (list == null) {
continue;
}
if (loc == null) {
loc = pp.getLocation();
}
int cx = loc.getX() >> 4;
int cz = loc.getZ() >> 4;
Player player = ((BukkitPlayer) pp).player;
Object entity = methodGetHandlePlayer.of(player).call();
for (Chunk chunk : list) {
int dx = Math.abs(cx - chunk.getX());
int dz = Math.abs(cz - chunk.getZ());
if (dx > view || dz > view) {
continue;
}
net.minecraft.server.v1_8_R2.Chunk c = (net.minecraft.server.v1_8_R2.Chunk) methodGetHandleChunk.of(chunk).call();
c.initLighting();
chunks.remove(chunk);
Object con = connection.of(entity).get();
// if (dx != 0 || dz != 0) {
// Object packet = MapChunk.create(c, true, 0);
// send.of(con).call(packet);
// }
Object packet = MapChunk.create(c, true, 65535);
send.of(con).call(packet);
}
}
for (final Chunk chunk : chunks) {
TaskManager.runTask(new Runnable() {
@Override
public void run() {
try {
chunk.unload(true, true);
}
catch (Exception e) {
String worldname = chunk.getWorld().getName();
PS.debug("$4Could not save chunk: " + worldname + ";" + chunk.getX() + ";" + chunk.getZ());
PS.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
PS.debug("$3 - $4" + worldname + "/level.dat or " + worldname + "level_old.dat may be corrupt (try repairing or removing these)");
}
}
});
}
//
//
// int diffx, diffz;
// << 4;
// for (final Chunk chunk : chunks) {
// if (!chunk.isLoaded()) {
// continue;
// }
// boolean unload = true;
// final Object c = methodGetHandle.of(chunk).call();
// final Object w = world.of(c).get();
// final Object p = players.of(w).get();
// 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();
// diffx = Math.abs(x - (chunk.getX() << 4));
// diffz = Math.abs(z - (chunk.getZ() << 4));
// if ((diffx <= view) && (diffz <= view)) {
// 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);
// }
// }
// }
// if (unload) {
// TaskManager.runTask(new Runnable() {
// @Override
// public void run() {
// try {
// chunk.unload(true, true);
// }
// catch (Exception e) {
// String worldname = chunk.getWorld().getName();
// PS.debug("$4Could not save chunk: " + worldname + ";" + chunk.getX() + ";" + chunk.getZ());
// PS.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
// PS.debug("$3 - $4" + worldname + "/level.dat or " + worldname + "level_old.dat may be corrupt (try repairing or removing these)");
// }
// }
// });
// }
//
// }
}
2015-02-23 02:32:27 +01:00
2015-08-03 20:20:04 +02:00
public void sendChunk(final String worldname, final List<ChunkLoc> locs) {
2015-02-20 07:34:19 +01:00
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);
}
}