mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-06-12 04:23:54 +00:00
Feature/unsafe over reflections (#1082)
* Use Unsafe to replace Lock * Start cleaning up everything that has to do with CleanableThreadLocal * Make cancellation work Co-authored-by: NotMyFault <mc.cache@web.de>
This commit is contained in:
@ -9,8 +9,6 @@ import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitQueueHandler;
|
||||
import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
||||
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
|
||||
import com.boydti.fawe.bukkit.listener.CFIPacketListener;
|
||||
import com.boydti.fawe.bukkit.listener.ChunkListener9;
|
||||
import com.boydti.fawe.bukkit.listener.RenderListener;
|
||||
import com.boydti.fawe.bukkit.regions.GriefPreventionFeature;
|
||||
@ -57,8 +55,6 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
private ItemUtil itemUtil;
|
||||
|
||||
private boolean listeningImages;
|
||||
private BukkitImageListener imageListener;
|
||||
private CFIPacketListener packetListener;
|
||||
private final boolean chunksStretched;
|
||||
private final FAWEPlatformAdapterImpl platformAdapter;
|
||||
|
||||
@ -102,26 +98,14 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@Override // Please don't delete this again, it's WIP
|
||||
public void registerPacketListener() {
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
if (packetListener == null && manager.getPlugin("ProtocolLib") != null) {
|
||||
packetListener = new CFIPacketListener(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public QueueHandler getQueueHandler() {
|
||||
return new BukkitQueueHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ImageViewer getImageViewer(com.sk89q.worldedit.entity.Player player) {
|
||||
if (listeningImages && imageListener == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
listeningImages = true;
|
||||
registerPacketListener();
|
||||
PluginManager manager = Bukkit.getPluginManager();
|
||||
|
||||
if (manager.getPlugin("PacketListenerApi") == null) {
|
||||
@ -140,11 +124,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
fos.write(jarData);
|
||||
}
|
||||
}
|
||||
BukkitImageViewer viewer = new BukkitImageViewer(BukkitAdapter.adapt(player));
|
||||
if (imageListener == null) {
|
||||
this.imageListener = new BukkitImageListener(plugin);
|
||||
}
|
||||
return viewer;
|
||||
return new BukkitImageViewer(BukkitAdapter.adapt(player));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return null;
|
||||
|
@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BitArray;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -63,9 +62,6 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
public static final Field fieldTickingBlockCount;
|
||||
public static final Field fieldNonEmptyBlockCount;
|
||||
|
||||
private static final Field fieldDirtyCount;
|
||||
private static final Field fieldDirtyBits;
|
||||
|
||||
private static final Field fieldBiomeArray;
|
||||
|
||||
private final static MethodHandle methodGetVisibleChunk;
|
||||
@ -76,6 +72,7 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
private static final int CHUNKSECTION_SHIFT;
|
||||
|
||||
private static final Field fieldLock;
|
||||
private static final long fieldLockOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -93,11 +90,6 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
|
||||
fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount");
|
||||
fieldDirtyCount.setAccessible(true);
|
||||
fieldDirtyBits = PlayerChunk.class.getDeclaredField("r");
|
||||
fieldDirtyBits.setAccessible(true);
|
||||
|
||||
fieldBiomeArray = BiomeStorage.class.getDeclaredField("g");
|
||||
fieldBiomeArray.setAccessible(true);
|
||||
|
||||
@ -109,12 +101,10 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
declaredSetLightNibbleArray.setAccessible(true);
|
||||
methodSetLightNibbleArray = MethodHandles.lookup().unreflect(declaredSetLightNibbleArray);
|
||||
|
||||
Field tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
ReflectionUtils.setAccessibleNonFinal(tmp);
|
||||
fieldLock = tmp;
|
||||
fieldLock.setAccessible(true);
|
||||
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
fieldLock = DataPaletteBlock.class.getDeclaredField("j");
|
||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||
|
||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class);
|
||||
int scale = unsafe.arrayIndexScale(ChunkSection[].class);
|
||||
if ((scale & (scale - 1)) != 0) {
|
||||
@ -141,16 +131,17 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
//todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS?
|
||||
try {
|
||||
synchronized (section) {
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
|
||||
ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset);
|
||||
if (currentLock instanceof DelegateLock) {
|
||||
return (DelegateLock) currentLock;
|
||||
}
|
||||
DelegateLock newLock = new DelegateLock(currentLock);
|
||||
fieldLock.set(blocks, newLock);
|
||||
unsafe.putObject(blocks, fieldLockOffset, newLock);
|
||||
return newLock;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BitArrayUnstretched;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
public static final Field fieldTickingBlockCount;
|
||||
public static final Field fieldNonEmptyBlockCount;
|
||||
|
||||
private static final Field fieldDirtyCount;
|
||||
private static final Field fieldDirtyBits;
|
||||
|
||||
private static final Field fieldBiomeArray;
|
||||
|
||||
private final static MethodHandle methodGetVisibleChunk;
|
||||
@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
private static final int CHUNKSECTION_SHIFT;
|
||||
|
||||
private static final Field fieldLock;
|
||||
private static final long fieldLockOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
|
||||
fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount");
|
||||
fieldDirtyCount.setAccessible(true);
|
||||
fieldDirtyBits = PlayerChunk.class.getDeclaredField("r");
|
||||
fieldDirtyBits.setAccessible(true);
|
||||
|
||||
fieldBiomeArray = BiomeStorage.class.getDeclaredField("g");
|
||||
fieldBiomeArray.setAccessible(true);
|
||||
|
||||
@ -106,12 +98,10 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
declaredGetVisibleChunk.setAccessible(true);
|
||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk);
|
||||
|
||||
Field tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
ReflectionUtils.setAccessibleNonFinal(tmp);
|
||||
fieldLock = tmp;
|
||||
fieldLock.setAccessible(true);
|
||||
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
fieldLock = DataPaletteBlock.class.getDeclaredField("j");
|
||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||
|
||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class);
|
||||
int scale = unsafe.arrayIndexScale(ChunkSection[].class);
|
||||
if ((scale & (scale - 1)) != 0) {
|
||||
@ -138,16 +128,17 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
//todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS?
|
||||
try {
|
||||
synchronized (section) {
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
|
||||
ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset);
|
||||
if (currentLock instanceof DelegateLock) {
|
||||
return (DelegateLock) currentLock;
|
||||
}
|
||||
DelegateLock newLock = new DelegateLock(currentLock);
|
||||
fieldLock.set(blocks, newLock);
|
||||
unsafe.putObject(blocks, fieldLockOffset, newLock);
|
||||
return newLock;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BitArrayUnstretched;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
public static final Field fieldTickingBlockCount;
|
||||
public static final Field fieldNonEmptyBlockCount;
|
||||
|
||||
private static final Field fieldDirty;
|
||||
private static final Field fieldDirtyBlocks;
|
||||
|
||||
private static final Field fieldBiomeArray;
|
||||
|
||||
private static final MethodHandle methodGetVisibleChunk;
|
||||
@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
private static final int CHUNKSECTION_SHIFT;
|
||||
|
||||
private static final Field fieldLock;
|
||||
private static final long fieldLockOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
|
||||
fieldDirty = PlayerChunk.class.getDeclaredField("p");
|
||||
fieldDirty.setAccessible(true);
|
||||
fieldDirtyBlocks = PlayerChunk.class.getDeclaredField("dirtyBlocks");
|
||||
fieldDirtyBlocks.setAccessible(true);
|
||||
|
||||
fieldBiomeArray = BiomeStorage.class.getDeclaredField("h");
|
||||
fieldBiomeArray.setAccessible(true);
|
||||
|
||||
@ -106,25 +98,16 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
declaredGetVisibleChunk.setAccessible(true);
|
||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk);
|
||||
|
||||
Field tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
ReflectionUtils.setAccessibleNonFinal(tmp);
|
||||
fieldLock = tmp;
|
||||
fieldLock.setAccessible(true);
|
||||
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
fieldLock = DataPaletteBlock.class.getDeclaredField("j");
|
||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||
|
||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class);
|
||||
int scale = unsafe.arrayIndexScale(ChunkSection[].class);
|
||||
if ((scale & (scale - 1)) != 0) {
|
||||
throw new Error("data type scale not a power of two");
|
||||
}
|
||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
||||
|
||||
Class<?> clsShortArraySet;
|
||||
try { //paper
|
||||
clsShortArraySet = Class.forName(new String(new char[]{'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'}));
|
||||
} catch (Throwable t) { // still using spigot boo
|
||||
clsShortArraySet = Class.forName(new String(new char[]{'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't', '.', 'l', 'i', 'b', 's', '.', 'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'}));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable rethrow) {
|
||||
@ -145,16 +128,17 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
//todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS?
|
||||
try {
|
||||
synchronized (section) {
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
|
||||
ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset);
|
||||
if (currentLock instanceof DelegateLock) {
|
||||
return (DelegateLock) currentLock;
|
||||
}
|
||||
DelegateLock newLock = new DelegateLock(currentLock);
|
||||
fieldLock.set(blocks, newLock);
|
||||
unsafe.putObject(blocks, fieldLockOffset, newLock);
|
||||
return newLock;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BitArrayUnstretched;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
public static final Field fieldTickingBlockCount;
|
||||
public static final Field fieldNonEmptyBlockCount;
|
||||
|
||||
private static final Field fieldDirty;
|
||||
private static final Field fieldDirtyBlocks;
|
||||
|
||||
private static final Field fieldBiomeArray;
|
||||
|
||||
private static final MethodHandle methodGetVisibleChunk;
|
||||
@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
private static final int CHUNKSECTION_SHIFT;
|
||||
|
||||
private static final Field fieldLock;
|
||||
private static final long fieldLockOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
|
||||
fieldDirty = PlayerChunk.class.getDeclaredField("p");
|
||||
fieldDirty.setAccessible(true);
|
||||
fieldDirtyBlocks = PlayerChunk.class.getDeclaredField("dirtyBlocks");
|
||||
fieldDirtyBlocks.setAccessible(true);
|
||||
|
||||
fieldBiomeArray = BiomeStorage.class.getDeclaredField("h");
|
||||
fieldBiomeArray.setAccessible(true);
|
||||
|
||||
@ -106,25 +98,16 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
declaredGetVisibleChunk.setAccessible(true);
|
||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk);
|
||||
|
||||
Field tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
ReflectionUtils.setAccessibleNonFinal(tmp);
|
||||
fieldLock = tmp;
|
||||
fieldLock.setAccessible(true);
|
||||
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
fieldLock = DataPaletteBlock.class.getDeclaredField("j");
|
||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
||||
|
||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class);
|
||||
int scale = unsafe.arrayIndexScale(ChunkSection[].class);
|
||||
if ((scale & (scale - 1)) != 0) {
|
||||
throw new Error("data type scale not a power of two");
|
||||
}
|
||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
||||
|
||||
Class<?> clsShortArraySet;
|
||||
try { //paper
|
||||
clsShortArraySet = Class.forName(new String(new char[]{'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'}));
|
||||
} catch (Throwable t) { // still using spigot boo
|
||||
clsShortArraySet = Class.forName(new String(new char[]{'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't', '.', 'l', 'i', 'b', 's', '.', 'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'}));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable rethrow) {
|
||||
@ -145,16 +128,17 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
//todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS?
|
||||
try {
|
||||
synchronized (section) {
|
||||
Unsafe unsafe = UnsafeUtils.getUNSAFE();
|
||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||
ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks);
|
||||
ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset);
|
||||
if (currentLock instanceof DelegateLock) {
|
||||
return (DelegateLock) currentLock;
|
||||
}
|
||||
DelegateLock newLock = new DelegateLock(currentLock);
|
||||
fieldLock.set(blocks, newLock);
|
||||
unsafe.putObject(blocks, fieldLockOffset, newLock);
|
||||
return newLock;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -191,7 +175,7 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendChunk(WorldServer nmsWorld, int chunkX, int chunkZ, int mask, boolean lighting) {
|
||||
public static void sendChunk(WorldServer nmsWorld, int chunkX, int chunkZ, boolean lighting) {
|
||||
PlayerChunk playerChunk = getPlayerChunk(nmsWorld, chunkX, chunkZ);
|
||||
if (playerChunk == null) {
|
||||
return;
|
||||
|
@ -689,7 +689,7 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
||||
|
||||
@Override
|
||||
public synchronized void send(int mask, boolean lighting) {
|
||||
BukkitAdapter_1_16_5.sendChunk(world, chunkX, chunkZ, mask, lighting);
|
||||
BukkitAdapter_1_16_5.sendChunk(world, chunkX, chunkZ, lighting);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -214,7 +214,7 @@ public class FAWEWorldNativeAccess_1_16_R3 implements WorldNativeAccess<Chunk, I
|
||||
return;
|
||||
}
|
||||
for (IntPair chunk : toSend) {
|
||||
BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, 0, false);
|
||||
BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -229,7 +229,7 @@ public class FAWEWorldNativeAccess_1_16_R3 implements WorldNativeAccess<Chunk, I
|
||||
cachedChanges.forEach(cc -> cc.chunk.setType(cc.position, cc.blockData,
|
||||
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)));
|
||||
for (IntPair chunk : cachedChunksToSend) {
|
||||
BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, 0, false);
|
||||
BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -180,7 +180,7 @@ public class TuinityRelighter_1_16_5 implements Relighter {
|
||||
int x = pos.x;
|
||||
int z = pos.z;
|
||||
if (delay) { // we still need to send the block changes of that chunk
|
||||
BukkitAdapter_1_16_5.sendChunk(world, x, z, -1, false);
|
||||
BukkitAdapter_1_16_5.sendChunk(world, x, z, false);
|
||||
}
|
||||
world.getChunkProvider().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
|
||||
}
|
||||
|
@ -1,292 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.listener;
|
||||
|
||||
import com.boydti.fawe.bukkit.util.image.BukkitImageViewer;
|
||||
import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator;
|
||||
import com.boydti.fawe.util.image.ImageViewer;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class BukkitImageListener implements Listener {
|
||||
|
||||
private Location mutable = new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
|
||||
|
||||
public BukkitImageListener(Plugin plugin) {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
//TODO Fix along with CFI code 2020-02-04
|
||||
/*
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onPlayerInteractEntity(AsyncPlayerChatEvent event) {
|
||||
Set<Player> recipients = event.getRecipients();
|
||||
Iterator<Player> iter = recipients.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Player player = iter.next();
|
||||
BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player);
|
||||
CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings");
|
||||
if (player.equals(event.getPlayer()) || !bukkitPlayer.hasMeta() || settings == null || !settings.hasGenerator()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (!event.getMessage().toLowerCase(Locale.ROOT).contains(name)) {
|
||||
ArrayDeque<String> buffered = bukkitPlayer.getMeta("CFIBufferedMessages");
|
||||
if (buffered == null) {
|
||||
bukkitPlayer.setMeta("CFIBufferedMessaged", buffered = new ArrayDeque<>());
|
||||
}
|
||||
String full = String.format(event.getFormat(), event.getPlayer().getDisplayName(),
|
||||
event.getMessage());
|
||||
buffered.add(full);
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onHangingBreakByEntity(HangingBreakByEntityEvent event) {
|
||||
if (!(event.getRemover() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
handleInteract(event, (Player) event.getRemover(), event.getEntity(), false);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
handleInteract(event, (Player) event.getDamager(), event.getEntity(), false);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (event.useItemInHand() == Event.Result.DENY) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player);
|
||||
if (bukkitPlayer.getMeta("CFISettings") == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
return;
|
||||
}
|
||||
} catch (NoSuchFieldError | NoSuchMethodError ignored) {
|
||||
}
|
||||
|
||||
List<Block> target = player.getLastTwoTargetBlocks(null, 100);
|
||||
if (target.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block targetBlock = target.get(0);
|
||||
World world = player.getWorld();
|
||||
mutable.setWorld(world);
|
||||
mutable.setX(targetBlock.getX() + 0.5);
|
||||
mutable.setY(targetBlock.getY() + 0.5);
|
||||
mutable.setZ(targetBlock.getZ() + 0.5);
|
||||
Collection<Entity> entities = world.getNearbyEntities(mutable, 0.46875, 0, 0.46875);
|
||||
|
||||
if (!entities.isEmpty()) {
|
||||
Action action = event.getAction();
|
||||
boolean primary =
|
||||
action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK;
|
||||
|
||||
double minDist = Integer.MAX_VALUE;
|
||||
ItemFrame minItemFrame = null;
|
||||
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemFrame) {
|
||||
ItemFrame itemFrame = (ItemFrame) entity;
|
||||
Location loc = itemFrame.getLocation();
|
||||
double dx = loc.getX() - mutable.getX();
|
||||
double dy = loc.getY() - mutable.getY();
|
||||
double dz = loc.getZ() - mutable.getZ();
|
||||
double dist = dx * dx + dy * dy + dz * dz;
|
||||
if (dist < minDist) {
|
||||
minItemFrame = itemFrame;
|
||||
minDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (minItemFrame != null) {
|
||||
handleInteract(event, minItemFrame, primary);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
handleInteract(event, event.getRightClicked(), true);
|
||||
}
|
||||
|
||||
private BukkitImageViewer get(HeightMapMCAGenerator generator) {
|
||||
if (generator == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageViewer viewer = generator.getImageViewer();
|
||||
if (!(viewer instanceof BukkitImageViewer)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (BukkitImageViewer) viewer;
|
||||
}
|
||||
|
||||
private void handleInteract(PlayerEvent event, Entity entity, boolean primary) {
|
||||
handleInteract(event, event.getPlayer(), entity, primary);
|
||||
}
|
||||
|
||||
private void handleInteract(Event event, Player player, Entity entity, boolean primary) {
|
||||
//todo fix with cfi code 2020-02-04
|
||||
/*
|
||||
if (!(entity instanceof ItemFrame)) {
|
||||
return;
|
||||
}
|
||||
ItemFrame itemFrame = (ItemFrame) entity;
|
||||
|
||||
BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player);
|
||||
CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings");
|
||||
HeightMapMCAGenerator generator = settings == null ? null : settings.getGenerator();
|
||||
BukkitImageViewer viewer = get(generator);
|
||||
if (viewer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemFrame.getRotation() != Rotation.NONE) {
|
||||
itemFrame.setRotation(Rotation.NONE);
|
||||
}
|
||||
|
||||
LocalSession session = bukkitPlayer.getSession();
|
||||
BrushTool tool;
|
||||
try {
|
||||
tool = session.getBrushTool(bukkitPlayer, false);
|
||||
} catch (InvalidToolBindException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemFrame[][] frames = viewer.getItemFrames();
|
||||
if (frames == null || tool == null) {
|
||||
viewer.selectFrame(itemFrame);
|
||||
player.updateInventory();
|
||||
TaskManager.IMP.laterAsync(() -> viewer.view(generator), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
BrushSettings context = primary ? tool.getPrimary() : tool.getSecondary();
|
||||
Brush brush = context.getBrush();
|
||||
if (brush == null) {
|
||||
return;
|
||||
}
|
||||
tool.setContext(context);
|
||||
|
||||
if (event instanceof Cancellable) {
|
||||
((Cancellable) event).setCancelled(true);
|
||||
}
|
||||
|
||||
Location target = itemFrame.getLocation();
|
||||
Location source = player.getLocation();
|
||||
|
||||
double yawRad = Math.toRadians(source.getYaw() + 90d);
|
||||
double pitchRad = Math.toRadians(-source.getPitch());
|
||||
|
||||
double a = Math.cos(pitchRad);
|
||||
double xRat = Math.cos(yawRad) * a;
|
||||
double zRat = Math.sin(yawRad) * a;
|
||||
|
||||
BlockFace facing = itemFrame.getFacing();
|
||||
double thickness = 1 / 32D + 1 / 128D;
|
||||
double modX = facing.getModX();
|
||||
double modZ = facing.getModZ();
|
||||
double dx = source.getX() - target.getX() - modX * thickness;
|
||||
double dy = source.getY() + player.getEyeHeight() - target.getY();
|
||||
double dz = source.getZ() - target.getZ() - modZ * thickness;
|
||||
|
||||
double offset;
|
||||
double localX;
|
||||
if (modX != 0) {
|
||||
offset = dx / xRat;
|
||||
localX = (-modX) * (dz - offset * zRat);
|
||||
} else {
|
||||
offset = dz / zRat;
|
||||
localX = (modZ) * (dx - offset * xRat);
|
||||
}
|
||||
double localY = dy - offset * Math.sin(pitchRad);
|
||||
int localPixelX = (int) ((localX + 0.5) * 128);
|
||||
int localPixelY = (int) ((localY + 0.5) * 128);
|
||||
|
||||
UUID uuid = itemFrame.getUniqueId();
|
||||
for (int blockX = 0; blockX < frames.length; blockX++) {
|
||||
for (int blockY = 0; blockY < frames[0].length; blockY++) {
|
||||
if (uuid.equals(frames[blockX][blockY].getUniqueId())) {
|
||||
int pixelX = localPixelX + blockX * 128;
|
||||
int pixelY = (128 * frames[0].length) - (localPixelY + blockY * 128 + 1);
|
||||
|
||||
int width = generator.getWidth();
|
||||
int length = generator.getLength();
|
||||
int worldX = (int) (pixelX * width / (frames.length * 128d));
|
||||
int worldZ = (int) (pixelY * length / (frames[0].length * 128d));
|
||||
|
||||
if (worldX < 0 || worldX > width || worldZ < 0 || worldZ > length) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitPlayer.runAction(() -> {
|
||||
BlockVector3 wPos = BlockVector3.at(worldX, 0, worldZ);
|
||||
viewer.refresh();
|
||||
int topY = generator
|
||||
.getNearestSurfaceTerrainBlock(wPos.getBlockX(), wPos.getBlockZ(), 255,
|
||||
0, 255);
|
||||
wPos = wPos.withY(topY);
|
||||
|
||||
EditSession es = new EditSessionBuilder(bukkitPlayer.getWorld()).player(bukkitPlayer)
|
||||
.combineStages(false).autoQueue(false).blockBag(null).limitUnlimited()
|
||||
.build();
|
||||
ExtentTraverser last = new ExtentTraverser(es.getExtent()).last();
|
||||
Extent extent = last.get();
|
||||
if (extent instanceof IQueueExtent) {
|
||||
last = last.previous();
|
||||
}
|
||||
last.setNext(generator);
|
||||
try {
|
||||
brush.build(es, wPos, context.getMaterial(), context.getSize());
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
es.flushQueue();
|
||||
viewer.view(generator);
|
||||
}, true, true);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
@ -1,338 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.listener;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.RunnableVal3;
|
||||
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.wrappers.BlockPosition;
|
||||
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
||||
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
|
||||
import com.sk89q.worldedit.event.platform.Interaction;
|
||||
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The CFIPacketListener handles packets for editing the {@link VirtualWorld}.
|
||||
*
|
||||
* <p>
|
||||
* The virtual world will be displayed inside the current world. Block/Chunk/Movement packets
|
||||
* need to be handled properly.
|
||||
* </p>
|
||||
*/
|
||||
public class CFIPacketListener implements Listener {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final ProtocolManager protocolmanager;
|
||||
|
||||
public CFIPacketListener(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.protocolmanager = ProtocolLibrary.getProtocolManager();
|
||||
|
||||
// Direct digging to the virtual world
|
||||
registerBlockEvent(PacketType.Play.Client.BLOCK_DIG, false, new RunnableVal3<PacketEvent, VirtualWorld, BlockVector3>() {
|
||||
@Override
|
||||
public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) {
|
||||
try {
|
||||
Player plr = event.getPlayer();
|
||||
BlockVector3 realPos = pt.add(gen.getOrigin().toBlockPoint());
|
||||
if (!sendBlockChange(plr, gen, pt, Interaction.HIT)) {
|
||||
gen.setBlock(pt, BlockTypes.AIR.getDefaultState());
|
||||
}
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Direct placing to the virtual world
|
||||
RunnableVal3<PacketEvent, VirtualWorld, BlockVector3> placeTask = new RunnableVal3<PacketEvent, VirtualWorld, BlockVector3>() {
|
||||
@Override
|
||||
public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) {
|
||||
try {
|
||||
Player plr = event.getPlayer();
|
||||
List<EnumWrappers.Hand> hands = event.getPacket().getHands().getValues();
|
||||
|
||||
EnumWrappers.Hand enumHand = hands.isEmpty() ? EnumWrappers.Hand.MAIN_HAND : hands.get(0);
|
||||
PlayerInventory inv = plr.getInventory();
|
||||
ItemStack hand = enumHand == EnumWrappers.Hand.MAIN_HAND ? inv.getItemInMainHand() : inv.getItemInOffHand();
|
||||
if (hand.getType().isBlock()) {
|
||||
Material type = hand.getType();
|
||||
switch (type) {
|
||||
case AIR:
|
||||
case CAVE_AIR:
|
||||
case VOID_AIR:
|
||||
break;
|
||||
default: {
|
||||
BlockState block = BukkitAdapter.asBlockState(hand);
|
||||
if (block != null) {
|
||||
gen.setBlock(pt, block);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pt = getRelPos(event, gen);
|
||||
sendBlockChange(plr, gen, pt, Interaction.OPEN);
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
registerBlockEvent(PacketType.Play.Client.BLOCK_PLACE, true, placeTask);
|
||||
registerBlockEvent(PacketType.Play.Client.USE_ITEM, true, placeTask);
|
||||
|
||||
// Cancel block change packets where the real world overlaps with the virtual one
|
||||
registerBlockEvent(PacketType.Play.Server.BLOCK_CHANGE, false, new RunnableVal3<PacketEvent, VirtualWorld, BlockVector3>() {
|
||||
@Override
|
||||
public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
|
||||
// Modify chunk packets where the real world overlaps with the virtual one
|
||||
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (!event.isServerPacket() || FaweCache.IMP.CHUNK_FLAG.get().get()) {
|
||||
return;
|
||||
}
|
||||
VirtualWorld gen = getGenerator(event);
|
||||
if (gen != null) {
|
||||
BlockVector3 origin = gen.getOrigin().toBlockPoint();
|
||||
PacketContainer packet = event.getPacket();
|
||||
StructureModifier<Integer> ints = packet.getIntegers();
|
||||
int cx = ints.read(0);
|
||||
int cz = ints.read(1);
|
||||
|
||||
int ocx = origin.getBlockX() >> 4;
|
||||
int ocz = origin.getBlockZ() >> 4;
|
||||
|
||||
if (gen.contains(BlockVector3.at((cx - ocx) << 4, 0, (cz - ocz) << 4))) {
|
||||
event.setCancelled(true);
|
||||
gen.refreshChunk(cx - ocx, cz - ocz);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// The following few listeners are to ignore block collisions where the virtual and real world overlap
|
||||
|
||||
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_VELOCITY) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (!event.isServerPacket()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
Location pos = player.getLocation();
|
||||
VirtualWorld gen = getGenerator(event);
|
||||
if (gen != null) {
|
||||
BlockVector3 origin = gen.getOrigin().toBlockPoint();
|
||||
BlockVector3 pt = BlockVector3.at(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
|
||||
|
||||
StructureModifier<Integer> ints = event.getPacket().getIntegers();
|
||||
int id = ints.read(0);
|
||||
int mx = ints.read(1);
|
||||
int my = ints.read(2);
|
||||
int mz = ints.read(3);
|
||||
|
||||
if (gen.contains(pt.subtract(origin)) && mx == 0 && my == 0 && mz == 0) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.POSITION) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (!event.isServerPacket()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
Location pos = player.getLocation();
|
||||
VirtualWorld gen = getGenerator(event);
|
||||
if (gen != null) {
|
||||
BlockVector3 origin = gen.getOrigin().toBlockPoint();
|
||||
BlockVector3 from = BlockVector3.at(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
|
||||
|
||||
PacketContainer packet = event.getPacket();
|
||||
StructureModifier<Double> doubles = packet.getDoubles();
|
||||
BlockVector3 to = BlockVector3.at(doubles.read(0), doubles.read(1), doubles.read(2));
|
||||
if (gen.contains(to.subtract(origin)) && from.distanceSq(to) < 8) {
|
||||
int id = packet.getIntegers().read(0);
|
||||
PacketContainer reply = new PacketContainer(PacketType.Play.Client.TELEPORT_ACCEPT);
|
||||
reply.getIntegers().write(0, id);
|
||||
try {
|
||||
protocolmanager.recieveClientPacket(player, reply);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MULTI_BLOCK_CHANGE) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (!event.isServerPacket()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VirtualWorld gen = getGenerator(event);
|
||||
if (gen != null) {
|
||||
PacketContainer packet = event.getPacket();
|
||||
ChunkCoordIntPair chunk = packet.getChunkCoordIntPairs().read(0);
|
||||
BlockVector3 origin = gen.getOrigin().toBlockPoint();
|
||||
int cx = chunk.getChunkX() - (origin.getBlockX() >> 4);
|
||||
int cz = chunk.getChunkZ() - (origin.getBlockX() >> 4);
|
||||
if (gen.contains(BlockVector3.at(cx << 4, 0, cz << 4))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTeleport(PlayerTeleportEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
VirtualWorld gen = getGenerator(player);
|
||||
if (gen != null) {
|
||||
Location from = event.getFrom();
|
||||
Location to = event.getTo();
|
||||
if (to.getWorld().equals(from.getWorld()) && to.distanceSquared(from) < 8) {
|
||||
event.setTo(player.getLocation());
|
||||
event.setCancelled(true);
|
||||
player.setVelocity(player.getVelocity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendBlockChange(Player plr, VirtualWorld gen, BlockVector3 pt, Interaction action) {
|
||||
PlatformManager platform = WorldEdit.getInstance().getPlatformManager();
|
||||
com.sk89q.worldedit.entity.Player actor = BukkitAdapter.adapt(plr);
|
||||
com.sk89q.worldedit.util.Location location = new com.sk89q.worldedit.util.Location(actor.getWorld(), pt.toVector3());
|
||||
BlockInteractEvent toCall = new BlockInteractEvent(actor, location, action);
|
||||
platform.handleBlockInteract(toCall);
|
||||
if (toCall.isCancelled() || action == Interaction.OPEN) {
|
||||
BlockVector3 realPos = pt.add(gen.getOrigin().toBlockPoint());
|
||||
BlockState block = gen.getBlock(pt);
|
||||
sendBlockChange(plr, realPos, block);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sendBlockChange(Player plr, BlockVector3 pt, BlockState block) {
|
||||
plr.sendBlockChange(new Location(plr.getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()), BukkitAdapter.adapt(block));
|
||||
}
|
||||
|
||||
private VirtualWorld getGenerator(PacketEvent event) {
|
||||
return getGenerator(event.getPlayer());
|
||||
}
|
||||
|
||||
private VirtualWorld getGenerator(Player player) {
|
||||
BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player);
|
||||
VirtualWorld vw = bukkitPlayer.getSession().getVirtualWorld();
|
||||
if (vw != null) {
|
||||
return vw;
|
||||
}
|
||||
// CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings");
|
||||
// if (settings != null && settings.hasGenerator() && settings.getGenerator().hasPacketViewer()) {
|
||||
// return settings.getGenerator();
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
private BlockVector3 getRelPos(PacketEvent event, VirtualWorld generator) {
|
||||
PacketContainer packet = event.getPacket();
|
||||
StructureModifier<BlockPosition> position = packet.getBlockPositionModifier();
|
||||
BlockPosition loc = position.readSafely(0);
|
||||
if (loc == null) {
|
||||
return null;
|
||||
}
|
||||
BlockVector3 origin = generator.getOrigin().toBlockPoint();
|
||||
return BlockVector3.at(loc.getX() - origin.getBlockX(), loc.getY() - origin.getBlockY(), loc.getZ() - origin.getBlockZ());
|
||||
}
|
||||
|
||||
private void handleBlockEvent(PacketEvent event, boolean relative, RunnableVal3<PacketEvent, VirtualWorld, BlockVector3> task) {
|
||||
VirtualWorld gen = getGenerator(event);
|
||||
if (gen != null) {
|
||||
BlockVector3 pt = getRelPos(event, gen);
|
||||
if (pt != null) {
|
||||
if (relative) {
|
||||
pt = getRelative(event, pt);
|
||||
}
|
||||
if (gen.contains(pt)) {
|
||||
event.setCancelled(true);
|
||||
task.run(event, gen, pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBlockEvent(PacketType type, boolean relative, RunnableVal3<PacketEvent, VirtualWorld, BlockVector3> task) {
|
||||
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, type) {
|
||||
@Override
|
||||
public void onPacketReceiving(final PacketEvent event) {
|
||||
if (type.isClient() || event.isServerPacket()) {
|
||||
handleBlockEvent(event, relative, task);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
onPacketReceiving(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BlockVector3 getRelative(PacketEvent container, BlockVector3 pt) {
|
||||
PacketContainer packet = container.getPacket();
|
||||
StructureModifier<EnumWrappers.Direction> dirs = packet.getDirections();
|
||||
EnumWrappers.Direction dir = dirs.readSafely(0);
|
||||
if (dir == null) {
|
||||
return pt;
|
||||
}
|
||||
switch (dir.ordinal()) {
|
||||
case 0: return pt.add(0, -1, 0);
|
||||
case 1: return pt.add(0, 1, 0);
|
||||
case 2: return pt.add(0, 0, -1);
|
||||
case 3: return pt.add(0, 0, 1);
|
||||
case 4: return pt.add(-1, 0, 0);
|
||||
case 5: return pt.add(1, 0, 0);
|
||||
default: return pt;
|
||||
}
|
||||
}
|
||||
}
|
@ -41,33 +41,6 @@ public class BukkitReflectionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get class for name. Replace {nms} to net.minecraft.server.V*. Replace {cb} to org.bukkit.craftbukkit.V*. Replace
|
||||
* {nm} to net.minecraft
|
||||
*
|
||||
* @param classes possible class paths
|
||||
* @return RefClass object
|
||||
* @throws RuntimeException if no class found
|
||||
*/
|
||||
public static ReflectionUtils.RefClass getRefClass(final String... classes)
|
||||
throws RuntimeException {
|
||||
if (preClassM == null) {
|
||||
init();
|
||||
}
|
||||
for (String className : classes) {
|
||||
try {
|
||||
className = className.replace("{cb}", preClassB).replace("{nms}", preClassM)
|
||||
.replace("{nm}", "net.minecraft");
|
||||
return ReflectionUtils.getRefClass(Class.forName(className));
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(
|
||||
"no class found: " + classes[0].replace("{cb}", preClassB).replace("{nms}", preClassM)
|
||||
.replace("{nm}", "net.minecraft"));
|
||||
}
|
||||
|
||||
public static Class<?> getNmsClass(final String name) {
|
||||
final String className = "net.minecraft.server." + getVersion() + "." + name;
|
||||
return ReflectionUtils.getClass(className);
|
||||
|
Reference in New Issue
Block a user