diff --git a/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts index 9a24b8892..bef443803 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_19/build.gradle.kts @@ -12,6 +12,6 @@ repositories { } dependencies { - paperDevBundle("1.19.2-R0.1-20220805.230830-1") + paperDevBundle("1.19.2-R0.1-20221029.172539-134") compileOnly("io.papermc:paperlib") } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java index f05648b0d..2b39f4211 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightFaweAdapter.java @@ -55,6 +55,7 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.BlockMaterial; +import io.papermc.lib.PaperLib; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.WritableRegistry; @@ -97,6 +98,8 @@ import org.bukkit.entity.Player; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -114,6 +117,14 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter { private static final Logger LOGGER = LogManagerCompat.getLogger(); + private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE; + + static { + try { + CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave"); + } catch (NoSuchMethodException ignored) { // may not be present in newer paper versions + } + } private final PaperweightAdapter parent; // ------------------------------------------------------------------------ @@ -490,7 +501,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) { ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ()); - if (map != null && map.wasAccessibleSinceLastSave()) { + if (map != null && wasAccessibleSinceLastSave(map)) { boolean flag = false; // PlayerChunk.d players = map.players; Stream stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag) @@ -674,4 +685,16 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements return new PaperweightPostProcessor(); } + private boolean wasAccessibleSinceLastSave(ChunkHolder holder) { + if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) { + try { + return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder); + } catch (IllegalAccessException | InvocationTargetException ignored) { + // fall-through + } + } + // Papers new chunk system has no related replacement - therefor we assume true. + return true; + } + } diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks.java index 9ee467201..7a0b00f1f 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightGetBlocks.java @@ -14,7 +14,6 @@ import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; -import com.google.common.collect.Iterables; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; @@ -82,7 +81,6 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPlatformAdapter.java index 307a52d77..9b4d5cb7e 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightPlatformAdapter.java @@ -1,5 +1,6 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1; +import com.destroystokyo.paper.util.maplist.EntityList; import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter; import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore; import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; @@ -18,18 +19,18 @@ import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import io.papermc.paper.world.ChunkEntitySlices; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; -import net.minecraft.core.SectionPos; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.BitStorage; +import net.minecraft.util.ExceptionCollector; import net.minecraft.util.SimpleBitStorage; import net.minecraft.util.ThreadingDetector; import net.minecraft.util.ZeroBitStorage; @@ -49,6 +50,7 @@ import net.minecraft.world.level.chunk.LinearPalette; import net.minecraft.world.level.chunk.Palette; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.SingleValuePalette; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.gameevent.GameEventDispatcher; import net.minecraft.world.level.gameevent.GameEventListener; import org.bukkit.craftbukkit.v1_19_R1.CraftChunk; @@ -106,6 +108,11 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static final Field fieldRemove; + static final boolean POST_CHUNK_REWRITE; + private static Method PAPER_CHUNK_GEN_ALL_ENTITIES; + private static Field LEVEL_CHUNK_ENTITIES; + private static Field SERVER_LEVEL_ENTITY_MANAGER; + static { try { fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d")); @@ -176,6 +183,27 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { throw new Error("data type scale not a power of two"); } CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); + boolean chunkRewrite; + try { + ServerLevel.class.getDeclaredMethod("getEntityLookup"); + chunkRewrite = true; + PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities"); + } catch (NoSuchMethodException ignored) { + chunkRewrite = false; + } + try { + // Paper - Pre-Chunk-Update + LEVEL_CHUNK_ENTITIES = LevelChunk.class.getDeclaredField("entities"); + LEVEL_CHUNK_ENTITIES.setAccessible(true); + } catch (NoSuchFieldException ignored) { + } + try { + // Non-Paper + SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager"); + LEVEL_CHUNK_ENTITIES.setAccessible(true); + } catch (NoSuchFieldException ignored) { + } + POST_CHUNK_REWRITE = chunkRewrite; } catch (RuntimeException e) { throw e; } catch (Throwable rethrow) { @@ -590,10 +618,32 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static List getEntities(LevelChunk chunk) { + ExceptionCollector collector = new ExceptionCollector<>(); if (PaperLib.isPaper()) { - return Arrays.asList(chunk.entities.getRawData()); + if (POST_CHUNK_REWRITE) { + try { + //noinspection unchecked + return (List) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e); + } + } + try { + EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk); + return List.of(entityList.getRawData()); + } catch (IllegalAccessException e) { + collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e)); + // fall through + } } - return chunk.level.entityManager.getEntities(chunk.getPos()); + try { + //noinspection unchecked + return ((PersistentEntitySectionManager) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos()); + } catch (IllegalAccessException e) { + collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e)); + } + collector.throwIfPresent(); + return List.of(); } record FakeIdMapBlock(int size) implements IdMap { diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java index 8591aab4c..5e29656ef 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/PaperweightStarlightRelighter.java @@ -12,7 +12,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.LongArraySet; import it.unimi.dsi.fastutil.longs.LongIterator; import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.server.MCUtil; +import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.TicketType; @@ -41,7 +41,7 @@ public class PaperweightStarlightRelighter implements Relighter { private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting private static final TicketType FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0); - private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT); + private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT); static { MethodHandle tmp = null; diff --git a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java index e97f78247..2e904d9b0 100644 --- a/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_19/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R1/regen/PaperweightRegen.java @@ -364,7 +364,7 @@ public class PaperweightRegen extends Regenerator { try { freshChunkProvider.close(false); - } catch (IOException e) { + } catch (Exception e) { throw new RuntimeException(e); } });