Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-26 02:50:06 +01:00
Address incompatibilities after CraftChunk changes in spigot (#2179)
Dieser Commit ist enthalten in:
Ursprung
86acb1c4d4
Commit
05afaf00a9
@ -9,6 +9,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
paperDevBundle("1.19.4-R0.1-20230331.112431-38")
|
paperDevBundle("1.19.4-R0.1-20230412.010331-64")
|
||||||
compileOnly("io.papermc:paperlib")
|
compileOnly("io.papermc:paperlib")
|
||||||
}
|
}
|
||||||
|
@ -306,54 +306,6 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
|
|||||||
return SideEffectSet.defaults().getSideEffectsToApply();
|
return SideEffectSet.defaults().getSideEffectsToApply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
|
|
||||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
|
||||||
LevelChunk levelChunk = craftChunk.getHandle();
|
|
||||||
Level level = levelChunk.getLevel();
|
|
||||||
|
|
||||||
BlockPos blockPos = new BlockPos(x, y, z);
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
|
|
||||||
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
|
|
||||||
int y4 = y >> 4;
|
|
||||||
LevelChunkSection section = levelChunkSections[y4];
|
|
||||||
|
|
||||||
net.minecraft.world.level.block.state.BlockState existing;
|
|
||||||
if (section == null) {
|
|
||||||
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
|
|
||||||
} else {
|
|
||||||
existing = section.getBlockState(x & 15, y & 15, z & 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
|
|
||||||
|
|
||||||
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
|
|
||||||
if (compoundTag != null || existing instanceof TileEntityBlock) {
|
|
||||||
level.setBlock(blockPos, blockState, 0);
|
|
||||||
// remove tile
|
|
||||||
if (compoundTag != null) {
|
|
||||||
// We will assume that the tile entity was created for us,
|
|
||||||
// though we do not do this on the Forge version
|
|
||||||
BlockEntity blockEntity = level.getBlockEntity(blockPos);
|
|
||||||
if (blockEntity != null) {
|
|
||||||
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
|
|
||||||
tag.put("x", IntTag.valueOf(x));
|
|
||||||
tag.put("y", IntTag.valueOf(y));
|
|
||||||
tag.put("z", IntTag.valueOf(z));
|
|
||||||
blockEntity.load(tag); // readTagIntoTileEntity - load data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (existing == blockState) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
levelChunk.setBlockState(blockPos, blockState, false);
|
|
||||||
}
|
|
||||||
if (update) {
|
|
||||||
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
|
||||||
return new PaperweightFaweWorldNativeAccess(
|
return new PaperweightFaweWorldNativeAccess(
|
||||||
|
@ -102,7 +102,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
|||||||
}
|
}
|
||||||
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
|
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
|
||||||
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
|
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
|
||||||
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
|
cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ));
|
||||||
boolean nextTick = lastTick.get() > currentTick;
|
boolean nextTick = lastTick.get() > currentTick;
|
||||||
if (nextTick || cachedChanges.size() >= 1024) {
|
if (nextTick || cachedChanges.size() >= 1024) {
|
||||||
if (nextTick) {
|
if (nextTick) {
|
||||||
|
@ -41,6 +41,8 @@ import net.minecraft.world.level.biome.Biome;
|
|||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
import net.minecraft.world.level.chunk.GlobalPalette;
|
import net.minecraft.world.level.chunk.GlobalPalette;
|
||||||
import net.minecraft.world.level.chunk.HashMapPalette;
|
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
@ -57,6 +59,7 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -74,6 +77,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static java.lang.invoke.MethodType.methodType;
|
||||||
import static net.minecraft.core.registries.Registries.BIOME;
|
import static net.minecraft.core.registries.Registries.BIOME;
|
||||||
|
|
||||||
public final class PaperweightPlatformAdapter extends NMSAdapter {
|
public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||||
@ -103,6 +107,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
private static final MethodHandle methodRemoveGameEventListener;
|
private static final MethodHandle methodRemoveGameEventListener;
|
||||||
private static final MethodHandle methodremoveTickingBlockEntity;
|
private static final MethodHandle methodremoveTickingBlockEntity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a workaround for the changes from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1fddefce1cdce44010927b888432bf70c0e88cde#src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||||
|
* and is only needed to support 1.19.4 versions before *and* after this change.
|
||||||
|
*/
|
||||||
|
private static final MethodHandle CRAFT_CHUNK_GET_HANDLE;
|
||||||
|
|
||||||
private static final Field fieldRemove;
|
private static final Field fieldRemove;
|
||||||
|
|
||||||
static final boolean POST_CHUNK_REWRITE;
|
static final boolean POST_CHUNK_REWRITE;
|
||||||
@ -111,6 +121,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
private static Field SERVER_LEVEL_ENTITY_MANAGER;
|
private static Field SERVER_LEVEL_ENTITY_MANAGER;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||||
try {
|
try {
|
||||||
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
|
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
|
||||||
fieldData.setAccessible(true);
|
fieldData.setAccessible(true);
|
||||||
@ -136,7 +147,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
"b"
|
"b"
|
||||||
), long.class);
|
), long.class);
|
||||||
getVisibleChunkIfPresent.setAccessible(true);
|
getVisibleChunkIfPresent.setAccessible(true);
|
||||||
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
|
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);
|
||||||
|
|
||||||
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
Unsafe unsafe = ReflectionUtils.getUnsafe();
|
||||||
if (!PaperLib.isPaper()) {
|
if (!PaperLib.isPaper()) {
|
||||||
@ -160,7 +171,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
ServerLevel.class
|
ServerLevel.class
|
||||||
);
|
);
|
||||||
removeGameEventListener.setAccessible(true);
|
removeGameEventListener.setAccessible(true);
|
||||||
methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener);
|
methodRemoveGameEventListener = lookup.unreflect(removeGameEventListener);
|
||||||
|
|
||||||
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
|
||||||
Refraction.pickName(
|
Refraction.pickName(
|
||||||
@ -169,7 +180,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
), BlockPos.class
|
), BlockPos.class
|
||||||
);
|
);
|
||||||
removeBlockEntityTicker.setAccessible(true);
|
removeBlockEntityTicker.setAccessible(true);
|
||||||
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
|
methodremoveTickingBlockEntity = lookup.unreflect(removeBlockEntityTicker);
|
||||||
|
|
||||||
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
|
||||||
fieldRemove.setAccessible(true);
|
fieldRemove.setAccessible(true);
|
||||||
@ -208,6 +219,20 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
rethrow.printStackTrace();
|
rethrow.printStackTrace();
|
||||||
throw new RuntimeException(rethrow);
|
throw new RuntimeException(rethrow);
|
||||||
}
|
}
|
||||||
|
MethodHandle craftChunkGetHandle;
|
||||||
|
final MethodType type = methodType(ChunkAccess.class);
|
||||||
|
try {
|
||||||
|
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", type);
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||||
|
try {
|
||||||
|
final MethodType newType = methodType(ChunkAccess.class, ChunkStatus.class);
|
||||||
|
craftChunkGetHandle = lookup.findVirtual(CraftChunk.class, "getHandle", newType);
|
||||||
|
craftChunkGetHandle = MethodHandles.insertArguments(craftChunkGetHandle, 1, ChunkStatus.FULL);
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CRAFT_CHUNK_GET_HANDLE = craftChunkGetHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean setSectionAtomic(
|
static boolean setSectionAtomic(
|
||||||
@ -280,7 +305,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
|
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
|
||||||
try {
|
try {
|
||||||
CraftChunk chunk = (CraftChunk) future.get();
|
CraftChunk chunk = (CraftChunk) future.get();
|
||||||
return chunk.getHandle();
|
return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ import net.minecraft.world.level.storage.LevelStorageSource;
|
|||||||
import net.minecraft.world.level.storage.PrimaryLevelData;
|
import net.minecraft.world.level.storage.PrimaryLevelData;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_19_R3.generator.CustomChunkGenerator;
|
import org.bukkit.craftbukkit.v1_19_R3.generator.CustomChunkGenerator;
|
||||||
@ -440,7 +441,11 @@ public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, Level
|
|||||||
@Override
|
@Override
|
||||||
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
|
||||||
// BlockPopulator#populate has to be called synchronously for TileEntity access
|
// BlockPopulator#populate has to be called synchronously for TileEntity access
|
||||||
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
|
TaskManager.taskManager().task(() -> {
|
||||||
|
final CraftWorld world = freshWorld.getWorld();
|
||||||
|
final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ);
|
||||||
|
blockPopulator.populate(world, random, chunk);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren