Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-26 02:50:06 +01:00
Avoid Unsafe usage where possible (#2403)
Dieser Commit ist enthalten in:
Ursprung
60a3994d62
Commit
f36c5d42c7
@ -85,11 +85,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
private static final int CHUNKSECTION_BASE;
|
|
||||||
private static final int CHUNKSECTION_SHIFT;
|
|
||||||
|
|
||||||
private static final Field fieldLock;
|
private static final Field fieldLock;
|
||||||
private static final long fieldLockOffset;
|
|
||||||
|
|
||||||
private static final Field fieldGameEventDispatcherSections;
|
private static final Field fieldGameEventDispatcherSections;
|
||||||
private static final MethodHandle methodremoveBlockEntityTicker;
|
private static final MethodHandle methodremoveBlockEntityTicker;
|
||||||
@ -127,15 +123,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
getVisibleChunkIfPresent.setAccessible(true);
|
getVisibleChunkIfPresent.setAccessible(true);
|
||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
|
|
||||||
fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
|
fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLock.setAccessible(true);
|
||||||
} else {
|
} else {
|
||||||
// in paper, the used methods are synchronized properly
|
// in paper, the used methods are synchronized properly
|
||||||
fieldLock = null;
|
fieldLock = null;
|
||||||
fieldLockOffset = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
|
||||||
@ -152,13 +145,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
|
|
||||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
|
|
||||||
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
|
|
||||||
if ((scale & (scale - 1)) != 0) {
|
|
||||||
throw new Error("data type scale not a power of two");
|
|
||||||
}
|
|
||||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable rethrow) {
|
} catch (Throwable rethrow) {
|
||||||
@ -173,9 +159,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
LevelChunkSection value,
|
LevelChunkSection value,
|
||||||
int layer
|
int layer
|
||||||
) {
|
) {
|
||||||
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
|
|
||||||
if (layer >= 0 && layer < sections.length) {
|
if (layer >= 0 && layer < sections.length) {
|
||||||
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
|
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -190,14 +175,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
||||||
Semaphore currentLock = (Semaphore) unsafe.getObject(blocks, fieldLockOffset);
|
Semaphore currentLock = (Semaphore) fieldLock.get(blocks);
|
||||||
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
||||||
return delegateSemaphore;
|
return delegateSemaphore;
|
||||||
}
|
}
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
||||||
unsafe.putObject(blocks, fieldLockOffset, newLock);
|
fieldLock.set(blocks, newLock);
|
||||||
return newLock;
|
return newLock;
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -329,7 +329,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
|
chunkSourceField.set(freshWorld, freshChunkProvider);
|
||||||
//let's start then
|
//let's start then
|
||||||
structureManager = server.getStructureManager();
|
structureManager = server.getStructureManager();
|
||||||
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
||||||
|
@ -92,14 +92,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
private static final int CHUNKSECTION_BASE;
|
|
||||||
private static final int CHUNKSECTION_SHIFT;
|
|
||||||
|
|
||||||
private static final Field fieldThreadingDetector;
|
private static final Field fieldThreadingDetector;
|
||||||
private static final long fieldThreadingDetectorOffset;
|
|
||||||
|
|
||||||
private static final Field fieldLock;
|
private static final Field fieldLock;
|
||||||
private static final long fieldLockOffset;
|
|
||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
@ -136,20 +130,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
getVisibleChunkIfPresent.setAccessible(true);
|
getVisibleChunkIfPresent.setAccessible(true);
|
||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||||
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
fieldThreadingDetector.setAccessible(true);
|
||||||
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLock.setAccessible(true);
|
||||||
} else {
|
} else {
|
||||||
// in paper, the used methods are synchronized properly
|
// in paper, the used methods are synchronized properly
|
||||||
fieldThreadingDetector = null;
|
fieldThreadingDetector = null;
|
||||||
fieldThreadingDetectorOffset = -1;
|
|
||||||
|
|
||||||
fieldLock = null;
|
fieldLock = null;
|
||||||
fieldLockOffset = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
||||||
@ -169,13 +158,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
|
|
||||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
|
|
||||||
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
|
|
||||||
if ((scale & (scale - 1)) != 0) {
|
|
||||||
throw new Error("data type scale not a power of two");
|
|
||||||
}
|
|
||||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable rethrow) {
|
} catch (Throwable rethrow) {
|
||||||
@ -190,9 +172,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
LevelChunkSection value,
|
LevelChunkSection value,
|
||||||
int layer
|
int layer
|
||||||
) {
|
) {
|
||||||
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
|
|
||||||
if (layer >= 0 && layer < sections.length) {
|
if (layer >= 0 && layer < sections.length) {
|
||||||
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
|
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -207,19 +188,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
||||||
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
|
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
|
||||||
blocks,
|
|
||||||
fieldThreadingDetectorOffset
|
|
||||||
);
|
|
||||||
synchronized (currentThreadingDetector) {
|
synchronized (currentThreadingDetector) {
|
||||||
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
|
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
|
||||||
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
||||||
return delegateSemaphore;
|
return delegateSemaphore;
|
||||||
}
|
}
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
||||||
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
|
fieldLock.set(currentThreadingDetector, newLock);
|
||||||
return newLock;
|
return newLock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
|
chunkSourceField.set(freshWorld, freshChunkProvider);
|
||||||
//let's start then
|
//let's start then
|
||||||
structureManager = server.getStructureManager();
|
structureManager = server.getStructureManager();
|
||||||
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
|
||||||
|
@ -99,14 +99,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
private static final int CHUNKSECTION_BASE;
|
|
||||||
private static final int CHUNKSECTION_SHIFT;
|
|
||||||
|
|
||||||
private static final Field fieldThreadingDetector;
|
private static final Field fieldThreadingDetector;
|
||||||
private static final long fieldThreadingDetectorOffset;
|
|
||||||
|
|
||||||
private static final Field fieldLock;
|
private static final Field fieldLock;
|
||||||
private static final long fieldLockOffset;
|
|
||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
@ -149,20 +143,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
getVisibleChunkIfPresent.setAccessible(true);
|
getVisibleChunkIfPresent.setAccessible(true);
|
||||||
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||||
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
fieldThreadingDetector.setAccessible(true);
|
||||||
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLock.setAccessible(true);
|
||||||
} else {
|
} else {
|
||||||
// in paper, the used methods are synchronized properly
|
// in paper, the used methods are synchronized properly
|
||||||
fieldThreadingDetector = null;
|
fieldThreadingDetector = null;
|
||||||
fieldThreadingDetectorOffset = -1;
|
|
||||||
|
|
||||||
fieldLock = null;
|
fieldLock = null;
|
||||||
fieldLockOffset = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
||||||
@ -185,12 +174,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
|
|
||||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
|
|
||||||
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
|
|
||||||
if ((scale & (scale - 1)) != 0) {
|
|
||||||
throw new Error("data type scale not a power of two");
|
|
||||||
}
|
|
||||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
|
||||||
boolean chunkRewrite;
|
boolean chunkRewrite;
|
||||||
try {
|
try {
|
||||||
ServerLevel.class.getDeclaredMethod("getEntityLookup");
|
ServerLevel.class.getDeclaredMethod("getEntityLookup");
|
||||||
@ -226,9 +209,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
LevelChunkSection value,
|
LevelChunkSection value,
|
||||||
int layer
|
int layer
|
||||||
) {
|
) {
|
||||||
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
|
|
||||||
if (layer >= 0 && layer < sections.length) {
|
if (layer >= 0 && layer < sections.length) {
|
||||||
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
|
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -243,19 +225,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
||||||
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
|
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
|
||||||
blocks,
|
|
||||||
fieldThreadingDetectorOffset
|
|
||||||
);
|
|
||||||
synchronized (currentThreadingDetector) {
|
synchronized (currentThreadingDetector) {
|
||||||
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
|
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
|
||||||
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
||||||
return delegateSemaphore;
|
return delegateSemaphore;
|
||||||
}
|
}
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
||||||
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
|
fieldLock.set(currentThreadingDetector, newLock);
|
||||||
return newLock;
|
return newLock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
|
chunkSourceField.set(freshWorld, freshChunkProvider);
|
||||||
//let's start then
|
//let's start then
|
||||||
structureTemplateManager = server.getStructureManager();
|
structureTemplateManager = server.getStructureManager();
|
||||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
||||||
|
@ -102,14 +102,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
|
|
||||||
private static final MethodHandle methodGetVisibleChunk;
|
private static final MethodHandle methodGetVisibleChunk;
|
||||||
|
|
||||||
private static final int CHUNKSECTION_BASE;
|
|
||||||
private static final int CHUNKSECTION_SHIFT;
|
|
||||||
|
|
||||||
private static final Field fieldThreadingDetector;
|
private static final Field fieldThreadingDetector;
|
||||||
private static final long fieldThreadingDetectorOffset;
|
|
||||||
|
|
||||||
private static final Field fieldLock;
|
private static final Field fieldLock;
|
||||||
private static final long fieldLockOffset;
|
|
||||||
|
|
||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
@ -158,20 +152,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
getVisibleChunkIfPresent.setAccessible(true);
|
getVisibleChunkIfPresent.setAccessible(true);
|
||||||
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
|
||||||
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
|
fieldThreadingDetector.setAccessible(true);
|
||||||
|
|
||||||
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
|
||||||
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
|
fieldLock.setAccessible(true);
|
||||||
} else {
|
} else {
|
||||||
// in paper, the used methods are synchronized properly
|
// in paper, the used methods are synchronized properly
|
||||||
fieldThreadingDetector = null;
|
fieldThreadingDetector = null;
|
||||||
fieldThreadingDetectorOffset = -1;
|
|
||||||
|
|
||||||
fieldLock = null;
|
fieldLock = null;
|
||||||
fieldLockOffset = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
|
||||||
@ -194,12 +183,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
|
|
||||||
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
|
|
||||||
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
|
|
||||||
if ((scale & (scale - 1)) != 0) {
|
|
||||||
throw new Error("data type scale not a power of two");
|
|
||||||
}
|
|
||||||
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
|
|
||||||
boolean chunkRewrite;
|
boolean chunkRewrite;
|
||||||
try {
|
try {
|
||||||
ServerLevel.class.getDeclaredMethod("getEntityLookup");
|
ServerLevel.class.getDeclaredMethod("getEntityLookup");
|
||||||
@ -249,9 +232,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
LevelChunkSection value,
|
LevelChunkSection value,
|
||||||
int layer
|
int layer
|
||||||
) {
|
) {
|
||||||
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
|
|
||||||
if (layer >= 0 && layer < sections.length) {
|
if (layer >= 0 && layer < sections.length) {
|
||||||
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
|
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -266,19 +248,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (section) {
|
synchronized (section) {
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
|
||||||
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
|
||||||
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
|
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
|
||||||
blocks,
|
|
||||||
fieldThreadingDetectorOffset
|
|
||||||
);
|
|
||||||
synchronized (currentThreadingDetector) {
|
synchronized (currentThreadingDetector) {
|
||||||
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
|
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
|
||||||
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
|
||||||
return delegateSemaphore;
|
return delegateSemaphore;
|
||||||
}
|
}
|
||||||
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
|
||||||
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
|
fieldLock.set(currentThreadingDetector, newLock);
|
||||||
return newLock;
|
return newLock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
|
chunkSourceField.set(freshWorld, freshChunkProvider);
|
||||||
//let's start then
|
//let's start then
|
||||||
structureTemplateManager = server.getStructureManager();
|
structureTemplateManager = server.getStructureManager();
|
||||||
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
|
||||||
|
@ -4,19 +4,19 @@ import sun.misc.Unsafe;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
import java.lang.reflect.AccessibleObject;
|
import java.lang.reflect.AccessibleObject;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an internal class not meant to be used outside the FAWE internals.
|
* This is an internal class not meant to be used outside the FAWE internals.
|
||||||
*/
|
*/
|
||||||
public class ReflectionUtils {
|
public class ReflectionUtils {
|
||||||
|
|
||||||
|
private static final VarHandle REFERENCE_ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(Object[].class);
|
||||||
private static Unsafe UNSAFE;
|
private static Unsafe UNSAFE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -33,6 +33,21 @@ public class ReflectionUtils {
|
|||||||
return t.isInstance(o) ? t.cast(o) : null;
|
return t.isInstance(o) ? t.cast(o) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs CAS on the array element at the given index.
|
||||||
|
*
|
||||||
|
* @param array the array in which to compare and set the value
|
||||||
|
* @param expectedValue the value expected to be at the index
|
||||||
|
* @param newValue the new value to be set at the index if the expected value matches
|
||||||
|
* @param index the index at which to compare and set the value
|
||||||
|
* @param <T> the type of elements in the array
|
||||||
|
* @return true if the value at the index was successfully updated to the new value, false otherwise
|
||||||
|
* @see VarHandle#compareAndSet(Object...)
|
||||||
|
*/
|
||||||
|
public static <T> boolean compareAndSet(T[] array, T expectedValue, T newValue, int index) {
|
||||||
|
return REFERENCE_ARRAY_HANDLE.compareAndSet(array, index, expectedValue, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setAccessibleNonFinal(Field field) {
|
public static void setAccessibleNonFinal(Field field) {
|
||||||
// let's make the field accessible
|
// let's make the field accessible
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren