Skip to content

Commit 4005df8

Browse files
committed
fix: spigot compatibility for 26.2
- Refraction is not required anymore. - Conversion between NMS and CB BlockStates requires reflection / MH invocations on Spigot (Paper method does not exist on Spigot, and Spigot method is not available in Paper and can't be called directly therefor)
1 parent 1d28df9 commit 4005df8

5 files changed

Lines changed: 87 additions & 39 deletions

File tree

worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweAdapter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,12 @@ private synchronized boolean init() {
251251
@Override
252252
public Collection<String> getRegisteredDefaultBlockStates() {
253253
ArrayList<String> states = new ArrayList<>();
254-
for (final Block block : BuiltInRegistries.BLOCK) {
255-
states.add(block.defaultBlockState().asBlockData().getAsString());
254+
try {
255+
for (final Block block : BuiltInRegistries.BLOCK) {
256+
states.add(PlatformCompat.fromData(block.defaultBlockState()).getAsString());
257+
}
258+
} catch (Throwable e) {
259+
LOGGER.error("Failed to initialize block state", e);
256260
}
257261
return states;
258262
}

worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightFaweWorldNativeAccess.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fastasyncworldedit.core.util.task.RunnableVal;
77
import com.sk89q.worldedit.bukkit.BukkitAdapter;
88
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
9+
import com.sk89q.worldedit.internal.util.LogManagerCompat;
910
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
1011
import com.sk89q.worldedit.util.SideEffect;
1112
import com.sk89q.worldedit.util.SideEffectSet;
@@ -21,6 +22,7 @@
2122
import net.minecraft.world.level.chunk.LevelChunk;
2223
import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils;
2324
import net.minecraft.world.level.storage.ValueInput;
25+
import org.apache.logging.log4j.Logger;
2426
import org.bukkit.craftbukkit.CraftWorld;
2527
import org.bukkit.craftbukkit.block.data.CraftBlockData;
2628
import org.bukkit.event.block.BlockPhysicsEvent;
@@ -39,6 +41,8 @@
3941
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
4042
net.minecraft.world.level.block.state.BlockState, BlockPos> {
4143

44+
private static final Logger LOGGER = LogManagerCompat.getLogger();
45+
4246
private static final int UPDATE = 1;
4347
private static final int NOTIFY = 2;
4448
private static final Direction[] NEIGHBOUR_ORDER = {
@@ -207,9 +211,15 @@ public void updateNeighbors(
207211
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
208212
CraftWorld craftWorld = level.getWorld();
209213
if (craftWorld != null) {
214+
CraftBlockData cbd;
215+
try {
216+
cbd = PlatformCompat.fromData(newState);
217+
} catch (Throwable e) {
218+
LOGGER.error("Failed to update neighbors: Failed to convert BlockState to CraftBlockData", e);
219+
return;
220+
}
210221
BlockPhysicsEvent event = new BlockPhysicsEvent(
211-
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
212-
newState.asBlockData()
222+
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()), cbd
213223
);
214224
level.getCraftServer().getPluginManager().callEvent(event);
215225
if (event.isCancelled()) {

worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v26_2/PaperweightPlatformAdapter.java

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import com.mojang.serialization.DataResult;
1616
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
1717
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
18-
import com.sk89q.worldedit.bukkit.adapter.Refraction;
1918
import com.sk89q.worldedit.bukkit.adapter.impl.v26_2.PaperweightBlockMaterial;
2019
import com.sk89q.worldedit.internal.util.LogManagerCompat;
2120
import com.sk89q.worldedit.world.biome.BiomeType;
@@ -112,31 +111,28 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
112111
static {
113112
final MethodHandles.Lookup lookup = MethodHandles.lookup();
114113
try {
115-
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "b"));
114+
fieldData = PalettedContainer.class.getDeclaredField("data");
116115
fieldData.setAccessible(true);
117116

118117
Class<?> dataClazz = fieldData.getType();
119118
dataConstructor = dataClazz.getDeclaredConstructors()[0];
120119
dataConstructor.setAccessible(true);
121120

122-
fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b"));
121+
fieldStorage = dataClazz.getDeclaredField("storage");
123122
fieldStorage.setAccessible(true);
124-
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
123+
fieldPalette = dataClazz.getDeclaredField("palette");
125124
fieldPalette.setAccessible(true);
126125

127-
//noinspection JavaLangInvokeHandleSignature - method is obfuscated
126+
//noinspection JavaLangInvokeHandleSignature - signature differs between Paper and Spigot
128127
palettedContainerUnpackSpigot = PaperSupport.isPaper() ? null : lookup.findStatic(
129-
PalettedContainer.class,
130-
"a", // unpack
131-
MethodType.methodType(DataResult.class, Strategy.class, PalettedContainerRO.PackedData.class)
128+
PalettedContainer.class,
129+
"unpack",
130+
MethodType.methodType(DataResult.class, Strategy.class, PalettedContainerRO.PackedData.class)
132131
);
133132

134-
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName(
135-
"tickingFluidCount",
136-
"g"
137-
));
133+
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField("tickingFluidCount");
138134
fieldTickingFluidCount.setAccessible(true);
139-
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "f"));
135+
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField("tickingBlockCount");
140136
fieldTickingBlockCount.setAccessible(true);
141137
Field tmpFieldBiomes;
142138
try {
@@ -148,21 +144,16 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
148144
fieldBiomes = tmpFieldBiomes;
149145
fieldBiomes.setAccessible(true);
150146

151-
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(
152-
Refraction.pickName(
153-
"getVisibleChunkIfPresent",
154-
"b"
155-
), long.class
156-
);
147+
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod("getVisibleChunkIfPresent", long.class);
157148
getVisibleChunkIfPresent.setAccessible(true);
158149
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
159150

160151
if (!PaperSupport.isPaper()) {
161-
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "d"));
152+
fieldThreadingDetector = PalettedContainer.class.getDeclaredField("threadingDetector");
162153
fieldThreadingDetector.setAccessible(true);
163-
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
154+
fieldLock = ThreadingDetector.class.getDeclaredField("lock");
164155
fieldLock.setAccessible(true);
165-
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M"));
156+
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager");
166157
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
167158
} else {
168159
// in paper, the used methods are synchronized properly
@@ -171,29 +162,21 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
171162
}
172163

173164
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
174-
Refraction.pickName("removeGameEventListener", "a"),
165+
"removeGameEventListener",
175166
BlockEntity.class,
176167
ServerLevel.class
177168
);
178169
removeGameEventListener.setAccessible(true);
179170
methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener);
180171

181-
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
182-
Refraction.pickName(
183-
"removeBlockEntityTicker",
184-
"k"
185-
), BlockPos.class
186-
);
172+
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod("removeBlockEntityTicker", BlockPos.class);
187173
removeBlockEntityTicker.setAccessible(true);
188174
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
189175

190-
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
176+
fieldRemove = BlockEntity.class.getDeclaredField("remove");
191177
fieldRemove.setAccessible(true);
192178

193-
Method palettedContainerGet = PalettedContainer.class.getDeclaredMethod(
194-
Refraction.pickName("get", "a"),
195-
int.class
196-
);
179+
Method palettedContainerGet = PalettedContainer.class.getDeclaredMethod("get", int.class);
197180
palettedContainerGet.setAccessible(true);
198181
PALETTED_CONTAINER_GET = lookup.unreflect(palettedContainerGet);
199182
} catch (RuntimeException | Error e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2;
2+
3+
import com.fastasyncworldedit.bukkit.util.PaperSupport;
4+
import com.sk89q.worldedit.internal.util.LogManagerCompat;
5+
import net.minecraft.world.level.block.state.BlockState;
6+
import org.apache.logging.log4j.Logger;
7+
import org.bukkit.craftbukkit.block.data.CraftBlockData;
8+
9+
import java.lang.invoke.MethodHandle;
10+
import java.lang.invoke.MethodHandles;
11+
import java.lang.invoke.MethodType;
12+
13+
public final class PlatformCompat {
14+
15+
private static final Logger LOGGER = LogManagerCompat.getLogger();
16+
17+
private static MethodHandle SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA;
18+
19+
static {
20+
if (!PaperSupport.isPaper()) {
21+
try {
22+
//noinspection JavaLangInvokeHandleSignature (not available on Paper)
23+
SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA = MethodHandles.lookup().findStatic(
24+
CraftBlockData.class,
25+
"fromData",
26+
MethodType.methodType(CraftBlockData.class, net.minecraft.world.level.block.state.BlockState.class)
27+
);
28+
} catch (NoSuchMethodException | IllegalAccessException e) {
29+
LOGGER.error("Failed to lookup CraftBlockData#fromData(BlockState)", e);
30+
}
31+
}
32+
}
33+
34+
public static CraftBlockData fromData(BlockState state) throws Throwable {
35+
if (SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA == null) {
36+
return state.asBlockData();
37+
}
38+
return (CraftBlockData) SPIGOT__CRAFT_BLOCK_DATA__FROM_DATA.invokeExact(state);
39+
}
40+
41+
public static CraftBlockData fromDataUnsafe(BlockState state) {
42+
try {
43+
return fromData(state);
44+
} catch (Throwable e) {
45+
LOGGER.error("Unsafe call to #fromData", e);
46+
}
47+
return null; // this will most likely fail somewhere along the call (NPE)
48+
}
49+
50+
}

worldedit-bukkit/adapters/adapter-26.2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v26_2/PaperweightBlockMaterial.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.fastasyncworldedit.bukkit.adapter.BukkitBlockMaterial;
2323
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
2424
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2.PaperweightGetBlocks;
25+
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v26_2.PlatformCompat;
2526
import net.minecraft.core.BlockPos;
2627
import net.minecraft.world.level.EmptyBlockGetter;
2728
import net.minecraft.world.level.block.Block;
@@ -38,7 +39,7 @@ public PaperweightBlockMaterial(Block block) {
3839
}
3940

4041
public PaperweightBlockMaterial(Block block, BlockState blockState) {
41-
super(block, blockState, blockState.asBlockData());
42+
super(block, blockState, PlatformCompat.fromDataUnsafe(blockState));
4243
}
4344

4445
@Override

0 commit comments

Comments
 (0)