diff --git a/patches/server/Fix-inventory-desync.patch b/patches/server/Fix-inventory-desync.patch index ca22ca9811..ee846d6e4c 100644 --- a/patches/server/Fix-inventory-desync.patch +++ b/patches/server/Fix-inventory-desync.patch @@ -16,6 +16,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void resendItemInHands() { this.containerMenu.findSlot(this.getInventory(), this.getInventory().selected).ifPresent(s -> { this.containerSynchronizer.sendSlotChange(this.containerMenu, s, this.getMainHandItem()); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (!this.level().isClientSide()) { + // CraftBukkit start - fire PlayerLeashEntityEvent + if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) { +- ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item ++ // ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item // Paper - Fix inventory desync + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, leashable.getLeashHolder())); ++ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync + return InteractionResult.PASS; + } + // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cow.java diff --git a/patches/server/MC-Dev-fixes.patch b/patches/server/MC-Dev-fixes.patch index 85b9daf2b6..998a10d73f 100644 --- a/patches/server/MC-Dev-fixes.patch +++ b/patches/server/MC-Dev-fixes.patch @@ -109,3 +109,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.goalSelector.addGoal(3, new RangedCrossbowAttackGoal<>(this, 1.0D, 8.0F)); this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 15.0F, 1.0F)); +diff --git a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java ++++ b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java +@@ -0,0 +0,0 @@ public class ChunkStatusTasks { + if (protochunk instanceof ImposterProtoChunk) { + chunk1 = ((ImposterProtoChunk) protochunk).getWrapped(); + } else { +- chunk1 = new LevelChunk(worldserver, protochunk, (chunk1) -> { ++ chunk1 = new LevelChunk(worldserver, protochunk, ($) -> { // Paper - decompile fix + ChunkStatusTasks.postLoadProtoChunk(worldserver, protochunk.getEntities()); + }); + generationchunkholder.replaceProtoChunk(new ImposterProtoChunk(chunk1, false)); diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch index e763bc3082..e4147f1444 100644 --- a/patches/server/MC-Utils.patch +++ b/patches/server/MC-Utils.patch @@ -2671,11 +2671,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; +import com.destroystokyo.paper.util.SneakyThrow; -+import com.mojang.datafixers.util.Either; +import com.mojang.logging.LogUtils; +import io.papermc.paper.util.CoordinateUtils; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ChunkResult; +import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; @@ -2683,8 +2683,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.status.ChunkPyramid; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.status.ChunkStep; +import org.bukkit.Bukkit; +import org.slf4j.Logger; +import java.util.ArrayList; @@ -2695,6 +2697,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +public final class ChunkSystem { + + private static final Logger LOGGER = LogUtils.getLogger(); ++ private static final ChunkStep FULL_CHUNK_STEP = ChunkPyramid.GENERATION_PYRAMID.getStepTo(ChunkStatus.FULL); ++ ++ public static int getDistance(final ChunkStatus status) { ++ return FULL_CHUNK_STEP.getAccumulatedRadiusOf(status); ++ } + + public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) { + scheduleChunkTask(level, chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL); @@ -2715,7 +2722,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (chunk == null) { + onComplete.accept(null); + } else { -+ if (chunk.getStatus().isOrAfter(toStatus)) { ++ if (chunk.getPersistedStatus().isOrAfter(toStatus)) { + scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete); + } else { + onComplete.accept(null); @@ -2736,7 +2743,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ final int minLevel = 33 + ChunkStatus.getDistance(toStatus); ++ final int minLevel = 33 + ChunkSystem.getDistance(toStatus); + final Long chunkReference = addTicket ? Long.valueOf(++chunkLoadCounter) : null; + final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ); + @@ -2770,19 +2777,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ final CompletableFuture> loadFuture = holder.getOrScheduleFuture(toStatus, level.chunkSource.chunkMap); ++ final CompletableFuture> loadFuture = holder.scheduleChunkGenerationTask(toStatus, level.chunkSource.chunkMap); + + if (loadFuture.isDone()) { -+ loadCallback.accept(loadFuture.join().left().orElse(null)); ++ loadCallback.accept(loadFuture.join().orElse(null)); + return; + } + -+ loadFuture.whenCompleteAsync((final Either either, final Throwable thr) -> { ++ loadFuture.whenCompleteAsync((final ChunkResult result, final Throwable thr) -> { + if (thr != null) { + loadCallback.accept(null); + return; + } -+ loadCallback.accept(either.left().orElse(null)); ++ loadCallback.accept(result.orElse(null)); + }, (final Runnable r) -> { + scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST); + }); @@ -2838,7 +2845,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ final CompletableFuture> tickingState; ++ final CompletableFuture> tickingState; + switch (toStatus) { + case FULL: { + tickingState = holder.getFullChunkFuture(); @@ -2858,16 +2865,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (tickingState.isDone()) { -+ loadCallback.accept(tickingState.join().left().orElse(null)); ++ loadCallback.accept(tickingState.join().orElse(null)); + return; + } + -+ tickingState.whenCompleteAsync((final Either either, final Throwable thr) -> { ++ tickingState.whenCompleteAsync((final ChunkResult result, final Throwable thr) -> { + if (thr != null) { + loadCallback.accept(null); + return; + } -+ loadCallback.accept(either.left().orElse(null)); ++ loadCallback.accept(result.orElse(null)); + }, (final Runnable r) -> { + scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST); + }); @@ -4014,7 +4021,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public static int getTicketLevelFor(net.minecraft.world.level.chunk.status.ChunkStatus status) { -+ return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.status.ChunkStatus.getDistance(status); ++ return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + io.papermc.paper.chunk.system.ChunkSystem.getDistance(status); + } + + @NotNull @@ -6171,12 +6178,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public @Nullable ChunkAccess getAvailableChunkNow() { + // TODO can we just getStatusFuture(EMPTY)? + for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) { -+ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); -+ ChunkResult either = future.getNow(null); -+ if (either == null || either.isSuccess()) { ++ ChunkAccess chunkAccess = this.getChunkIfPresentUnchecked(curr); ++ if (chunkAccess == null) { + continue; + } -+ return either.orElseThrow(IllegalStateException::new); ++ return chunkAccess; + } + return null; + } @@ -6216,9 +6222,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + public @Nullable ChunkStatus getChunkHolderStatus() { + for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) { -+ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); -+ ChunkResult either = future.getNow(null); -+ if (either == null || !either.isSuccess()) { ++ ChunkAccess chunkAccess = this.getChunkIfPresentUnchecked(curr); ++ if (chunkAccess == null) { + continue; + } + return curr; @@ -6745,7 +6750,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + -+ return holder.getLastAvailable(); ++ return holder.getLatestChunk(); + } + + public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { diff --git a/patches/server/stubs.patch b/patches/server/stubs.patch new file mode 100644 index 0000000000..83ed687cab --- /dev/null +++ b/patches/server/stubs.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Fri, 14 Jun 2024 17:19:59 +0200 +Subject: [PATCH] stubs + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import org.bukkit.BanEntry; + import org.bukkit.BanList; + import org.bukkit.Bukkit; ++import org.bukkit.Chunk; + import org.bukkit.DyeColor; + import org.bukkit.Effect; + import org.bukkit.GameMode; +@@ -0,0 +0,0 @@ import org.bukkit.scoreboard.Scoreboard; + import org.jetbrains.annotations.NotNull; + + import net.md_5.bungee.api.chat.BaseComponent; // Spigot ++import org.jetbrains.annotations.Unmodifiable; + + @DelegateDeserialization(CraftOfflinePlayer.class) + public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void resetIdleDuration() { + this.getHandle().resetLastActionTime(); + } ++ ++ @Override ++ public @NotNull @Unmodifiable Set getSentChunkKeys() { ++ throw new UnsupportedOperationException("Not implemented yet"); ++ } ++ ++ @Override ++ public @NotNull @Unmodifiable Set getSentChunks() { ++ throw new UnsupportedOperationException("Not implemented yet"); ++ } ++ ++ @Override ++ public boolean isChunkSent(final long chunkKey) { ++ throw new UnsupportedOperationException("Not implemented yet"); ++ } + // Paper end + + public Player.Spigot spigot()