diff --git a/patches/api/0002-Set-BlockData-without-light-updates.patch b/patches/api/0002-Set-BlockData-without-light-updates.patch new file mode 100644 index 000000000..cff1d30a9 --- /dev/null +++ b/patches/api/0002-Set-BlockData-without-light-updates.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:29:11 -0500 +Subject: [PATCH] Set BlockData without light updates + + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 390a2a2611df35a9ea6f1eb996b47e2aa4597ff0..384e5700b6899850d91a34e1d13d1ca0678cfaaa 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -298,6 +298,28 @@ public interface Block extends Metadatable, Translatable, net.kyori.adventure.tr + */ + void setBlockData(@NotNull BlockData data, boolean applyPhysics); + ++ /** ++ * Sets the complete data for this block ++ * ++ *
++ * Note that applyPhysics = false is not in general safe. It should only be ++ * used when you need to avoid triggering a physics update of neighboring ++ * blocks, for example when creating a {@link Bisected} block. If you are ++ * using a custom populator, then this parameter may also be required to ++ * prevent triggering infinite chunk loads on border blocks. This method ++ * should NOT be used to "hack" physics by placing blocks in impossible ++ * locations. Such blocks are liable to be removed on various events such as ++ * world upgrades. Furthermore setting large amounts of such blocks in close ++ * proximity may overload the server physics engine if an update is ++ * triggered at a later point. If this occurs, the resulting behavior is ++ * undefined. ++ * ++ * @param data new block specific data ++ * @param applyPhysics false to cancel physics from the changed block ++ * @param checkLight false to prevent a light-check update ++ */ ++ void setBlockData(@NotNull BlockData data, boolean applyPhysics, boolean checkLight); ++ + /** + * Sets the type of this block + * diff --git a/patches/api/0003-Add-BlockDestroyedByNeighborEvent.patch b/patches/api/0003-Add-BlockDestroyedByNeighborEvent.patch new file mode 100644 index 000000000..a97d57865 --- /dev/null +++ b/patches/api/0003-Add-BlockDestroyedByNeighborEvent.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:30:30 -0500 +Subject: [PATCH] Add BlockDestroyedByNeighborEvent + + +diff --git a/src/main/java/io/papermc/paper/event/block/BlockDestroyedByNeighborEvent.java b/src/main/java/io/papermc/paper/event/block/BlockDestroyedByNeighborEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7db2789d54a609b023ea6deff87b45d717aabbf0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/block/BlockDestroyedByNeighborEvent.java +@@ -0,0 +1,67 @@ ++package io.papermc.paper.event.block; ++ ++import org.bukkit.block.Block; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.block.BlockEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a block is broken another block. This is generally the result of BlockPhysicsEvent propagation ++ */ ++public class BlockDestroyedByNeighborEvent extends BlockEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private final Player player; ++ private final Block sourceBlock; ++ private boolean cancel; ++ ++ public BlockDestroyedByNeighborEvent(@NotNull final Block theBlock, @Nullable Player player, @NotNull final Block sourceBlock) { ++ super(theBlock); ++ ++ this.player = player; ++ this.sourceBlock = sourceBlock; ++ } ++ ++ /** ++ * Gets the Player that caused this ++ * ++ * @return The Player that is breaking the block involved in this event ++ */ ++ @Nullable ++ public Player getPlayer() { ++ return player; ++ } ++ ++ /** ++ * Gets the source block that caused this block break ++ * ++ * @return The Source Block which block is involved in this event ++ */ ++ @NotNull ++ public final Block getSourceBlock() { ++ return sourceBlock; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @Override ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api/0004-Add-provided-Material-to-getDrops.patch b/patches/api/0004-Add-provided-Material-to-getDrops.patch new file mode 100644 index 000000000..30e9021a0 --- /dev/null +++ b/patches/api/0004-Add-provided-Material-to-getDrops.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:31:55 -0500 +Subject: [PATCH] Add provided Material to getDrops + + +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 384e5700b6899850d91a34e1d13d1ca0678cfaaa..9c1aef68b1b6f4fddfa171f7189dda5619e758d6 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -666,6 +666,20 @@ public interface Block extends Metadatable, Translatable, net.kyori.adventure.tr + @NotNull + Collection getDrops(@NotNull ItemStack tool, @Nullable Entity entity); + ++ // Slice start ++ /** ++ * Returns a list of items which would drop by the entity destroying this ++ * block as though it were a given Material with a specific tool ++ * ++ * @param blockType The block type to use as the source loot ++ * @param tool The tool or item in hand used for digging ++ * @param entity the entity destroying the block ++ * @return a list of dropped items for this type of block ++ */ ++ @NotNull ++ Collection getDrops(@NotNull Material blockType, @NotNull ItemStack tool, @Nullable Entity entity); ++ // Slice end ++ + /** + * Returns if the given item is a preferred choice to break this Block. + * diff --git a/patches/api/0005-Add-Player-to-SpongeAbsorbEvent.patch b/patches/api/0005-Add-Player-to-SpongeAbsorbEvent.patch new file mode 100644 index 000000000..60de92b6e --- /dev/null +++ b/patches/api/0005-Add-Player-to-SpongeAbsorbEvent.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:36:22 -0500 +Subject: [PATCH] Add Player to SpongeAbsorbEvent + + +diff --git a/src/main/java/org/bukkit/event/block/SpongeAbsorbEvent.java b/src/main/java/org/bukkit/event/block/SpongeAbsorbEvent.java +index 7029cfcd00ed5d9c7f06898ec2b81238ec775a70..0e2f21e0f1983d2e8b67deebf4d12d25107d1582 100644 +--- a/src/main/java/org/bukkit/event/block/SpongeAbsorbEvent.java ++++ b/src/main/java/org/bukkit/event/block/SpongeAbsorbEvent.java +@@ -7,6 +7,7 @@ import org.bukkit.block.BlockState; + import org.bukkit.event.Cancellable; + import org.bukkit.event.HandlerList; + import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; // Paper + + /** + * Called when a sponge absorbs water from the world. +@@ -21,11 +22,13 @@ public class SpongeAbsorbEvent extends BlockEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; ++ private final org.bukkit.entity.Player player; // Paper + private final List blocks; + +- public SpongeAbsorbEvent(@NotNull Block block, @NotNull List waterblocks) { ++ public SpongeAbsorbEvent(@NotNull Block block, @Nullable org.bukkit.entity.Player player, @NotNull List waterblocks) { // Paper + super(block); + this.blocks = waterblocks; ++ this.player = player; // Paper + } + + /** +@@ -41,6 +44,18 @@ public class SpongeAbsorbEvent extends BlockEvent implements Cancellable { + return blocks; + } + ++ // Paper start ++ /** ++ * Gets the Player that placed the Sponge Block ++ * ++ * @return The Player that placed the sponge block causing the absorb event, or null if no Player was involved ++ */ ++ @Nullable ++ public org.bukkit.entity.Player getPlayer() { ++ return player; ++ } ++ // Paper end ++ + @Override + public boolean isCancelled() { + return cancelled; diff --git a/patches/api/0006-Add-World-Instance-flag.patch b/patches/api/0006-Add-World-Instance-flag.patch new file mode 100644 index 000000000..059680870 --- /dev/null +++ b/patches/api/0006-Add-World-Instance-flag.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:37:06 -0500 +Subject: [PATCH] Add World Instance flag + + +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 0b8776355f724927ada826735d5e73f3fb6897d5..facf3cf587724bf4dcf194a4a873b7f870f2193a 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -2599,6 +2599,11 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + */ + public void setAutoSave(boolean value); + ++ // Slice start ++ public boolean isInstance(); ++ public void setInstance(boolean value); ++ // Slice end ++ + /** + * Sets the Difficulty of the world. + * diff --git a/patches/api/0007-Add-PlayerData-Events.patch b/patches/api/0007-Add-PlayerData-Events.patch new file mode 100644 index 000000000..6f3d20877 --- /dev/null +++ b/patches/api/0007-Add-PlayerData-Events.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Mon, 10 Apr 2023 07:38:40 -0500 +Subject: [PATCH] Add PlayerData Events + + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLoadDataEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLoadDataEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ae0132d9c7ae17b478d1d504961e1fd6b479f6d0 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLoadDataEvent.java +@@ -0,0 +1,63 @@ ++package com.destroystokyo.paper.event.player; ++ ++import com.google.gson.JsonObject; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.UUID; ++ ++/** ++ * Calls an event in which playerdata can be provided. If null, will load from disk, otherwise will use provided data ++ */ ++public class PlayerLoadDataEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ private final UUID playerId; ++ private Object playerData; ++ private JsonObject statistics; ++ ++ public PlayerLoadDataEvent(@NotNull UUID playerId) { ++ super(); ++ this.playerId = playerId; ++ } ++ ++ /** ++ * Gets the player's unique ID. ++ * ++ * @return The unique ID ++ */ ++ @NotNull ++ public UUID getUniqueId() { ++ return playerId; ++ } ++ ++ @Nullable ++ public Object getPlayerData() { ++ return playerData; ++ } ++ ++ public void setPlayerData(@NotNull Object playerData) { ++ this.playerData = playerData; ++ } ++ ++ @Nullable ++ public JsonObject getStatistics() { ++ return statistics; ++ } ++ ++ public void setStatistics(@NotNull JsonObject statistics) { ++ this.statistics = statistics; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api/0008-Add-PlayerGetRespawnLocationEvent.patch b/patches/api/0008-Add-PlayerGetRespawnLocationEvent.patch new file mode 100644 index 000000000..914c58f5d --- /dev/null +++ b/patches/api/0008-Add-PlayerGetRespawnLocationEvent.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:46:19 -0500 +Subject: [PATCH] Add PlayerGetRespawnLocationEvent + + +diff --git a/src/main/java/org/bukkit/event/player/PlayerGetRespawnLocationEvent.java b/src/main/java/org/bukkit/event/player/PlayerGetRespawnLocationEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7eca4d6929fc7a75974d182c1ea692d3823a19c0 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/player/PlayerGetRespawnLocationEvent.java +@@ -0,0 +1,53 @@ ++package org.bukkit.event.player; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when a respawn event tries to determine the location of a respawn ++ */ ++public class PlayerGetRespawnLocationEvent extends PlayerEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ private Location respawnLocation; ++ ++ public PlayerGetRespawnLocationEvent(@NotNull final Player respawnPlayer) { ++ super(respawnPlayer); ++ } ++ ++ /** ++ * Gets the current respawn location ++ * ++ * @return Location current respawn location ++ */ ++ @Nullable ++ public Location getRespawnLocation() { ++ return this.respawnLocation; ++ } ++ ++ /** ++ * Sets the new respawn location ++ * ++ * @param respawnLocation new location for the respawn ++ */ ++ public void setRespawnLocation(@NotNull Location respawnLocation) { ++ Validate.notNull(respawnLocation, "Respawn location can not be null"); ++ Validate.notNull(respawnLocation.getWorld(), "Respawn world can not be null"); ++ ++ this.respawnLocation = respawnLocation; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api/0009-Set-multiple-team-settings-at-once.patch b/patches/api/0009-Set-multiple-team-settings-at-once.patch new file mode 100644 index 000000000..440149b0b --- /dev/null +++ b/patches/api/0009-Set-multiple-team-settings-at-once.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:52:54 -0500 +Subject: [PATCH] Set multiple team settings at once + + +diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java +index 0f1c08092577a7d66fdc1ea8b645ea67e0d9c6cf..f1b3d05901a4fe32366699280f44147a9cda2873 100644 +--- a/src/main/java/org/bukkit/scoreboard/Team.java ++++ b/src/main/java/org/bukkit/scoreboard/Team.java +@@ -532,6 +532,24 @@ public interface Team { + boolean hasEntity(@NotNull org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException; + // Paper end + ++ //Slice start ++ /** ++ * Fully set all team options, combining all 5 options into one packet send, rather than one packet sent ++ * for every single option change. ++ * @param displayName New display name ++ * @param prefix New prefix ++ * @param suffix New suffix ++ * @param color new color ++ * @param options A Paired list of options ++ * @throws IllegalStateException ++ */ ++ void teamOptions(net.kyori.adventure.text.Component displayName, ++ net.kyori.adventure.text.Component prefix, ++ net.kyori.adventure.text.Component suffix, ++ net.kyori.adventure.text.format.NamedTextColor color, ++ java.util.List> options) throws IllegalStateException; ++ //Slice end ++ + /** + * Represents an option which may be applied to this team. + */ diff --git a/patches/api/0010-Smooth-Teleports.patch b/patches/api/0010-Smooth-Teleports.patch new file mode 100644 index 000000000..ef8a92cdb --- /dev/null +++ b/patches/api/0010-Smooth-Teleports.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:55:36 -0500 +Subject: [PATCH] Smooth Teleports + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index ee446bfb3e6c4b1d4428c00d6406bf9455c68ad5..66226b67b8c28522c7673d487ee4a33be9351386 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2917,6 +2917,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + String getClientBrandName(); + // Paper end + ++ /** ++ * This abuses some of how Minecraft works and allows teleporting a player to another world without ++ * triggering typical respawn packets. All of natural state of chunk resends, entity adds/removes, etc still ++ * happen but the visual "refresh" of a world change is hidden. Depending on the destination location/world, ++ * this can act as a "smooth teleport" to a world if the new world is very similar looking to the old one. ++ * ++ * @param location New location to teleport this Player to ++ */ ++ // Slice start ++ @org.jetbrains.annotations.ApiStatus.Experimental ++ void teleportWithoutRespawn(Location location); ++ // Slice end ++ + // Paper start - Teleport API + /** + * Sets the player's rotation. diff --git a/patches/api/0011-AntiXray-Bypass.patch b/patches/api/0011-AntiXray-Bypass.patch new file mode 100644 index 000000000..20a1cd894 --- /dev/null +++ b/patches/api/0011-AntiXray-Bypass.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:46:54 -0500 +Subject: [PATCH] AntiXray Bypass + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 66226b67b8c28522c7673d487ee4a33be9351386..b0d42ffecd0bb759b5c237643dc1d3fa52b53ebf 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2699,6 +2699,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + */ + boolean hasResourcePack(); + ++ // Slice start ++ void toggleAntiXrayBypass(boolean bypass); ++ // Slice end ++ + /** + * Gets a copy of this players profile + * @return The players profile object diff --git a/patches/api/0012-Add-PlayerPreChunkLoadEvent.patch b/patches/api/0012-Add-PlayerPreChunkLoadEvent.patch new file mode 100644 index 000000000..adc66a465 --- /dev/null +++ b/patches/api/0012-Add-PlayerPreChunkLoadEvent.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:47:44 -0500 +Subject: [PATCH] Add PlayerPreChunkLoadEvent + + +diff --git a/src/main/java/io/papermc/paper/event/packet/PlayerPreChunkLoadEvent.java b/src/main/java/io/papermc/paper/event/packet/PlayerPreChunkLoadEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b5cc9538a70c7ce0b494d4878d51b52134c2fd75 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/packet/PlayerPreChunkLoadEvent.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.event.packet; ++ ++import org.bukkit.Chunk; ++import org.bukkit.World; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Is called when a {@link Player} is about to receive a {@link Chunk} ++ *

++ * Can be cancelled, but only use if you really really mean it. ++ */ ++public class PlayerPreChunkLoadEvent extends Event implements Cancellable { ++ ++ private static final HandlerList handlers = new HandlerList(); ++ private final World world; ++ private final int chunkX; ++ private final int chunkZ; ++ private final Player player; ++ private boolean cancel; ++ ++ public PlayerPreChunkLoadEvent(World world, int chunkX, int chunkZ, @NotNull Player player) { ++ this.world = world; ++ this.chunkX = chunkX; ++ this.chunkZ = chunkZ; ++ this.player = player; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public World getWorld() { ++ return world; ++ } ++ ++ public int getChunkX() { ++ return chunkX; ++ } ++ ++ public int getChunkZ() { ++ return chunkZ; ++ } ++ ++ @NotNull ++ public Player getPlayer() { ++ return player; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index facf3cf587724bf4dcf194a4a873b7f870f2193a..5c3b12c626c88b0500ce3a10b1cf71ae99e8271e 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -526,6 +526,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient + //@Deprecated // Paper + public boolean refreshChunk(int x, int z); + ++ it.unimi.dsi.fastutil.longs.LongOpenHashSet getSentChunks(Player p); // Slice ++ + /** + * Gets whether the chunk at the specified chunk coordinates is force + * loaded. diff --git a/patches/server/0001-Build-Changes.patch b/patches/server/0001-Build-Changes.patch index 650c07446..a9e3286c0 100644 --- a/patches/server/0001-Build-Changes.patch +++ b/patches/server/0001-Build-Changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build Changes diff --git a/build.gradle.kts b/build.gradle.kts -index b0e4f11e8af4b909a56bb5576d05ef0537fb25f7..c4dde3980605eff079e9a6b0a97f73eadb2fc89b 100644 +index 9cf389defdaeb887e9cad4f0fed3f3b95667b238..1c7c148feb1785839b9dad0aa8477a52a2e12b3c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,12 @@ plugins { @@ -42,10 +42,10 @@ index b0e4f11e8af4b909a56bb5576d05ef0537fb25f7..c4dde3980605eff079e9a6b0a97f73ea standardInput = System.`in` workingDir = rootProject.layout.projectDirectory diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6dc6c3bccb4ba34268a87b0754c87eb1e0df4135..82a15bfd47552b9af6d761279ae75f820f26675b 100644 +index 9f15d9dbdfa74a0640b1a2b4ff695609d4758a4c..fa14ab3d8117e9d357380d21d3c6a2cd1df7c04c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1654,7 +1654,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Mon, 10 Apr 2023 07:29:11 -0500 +Subject: [PATCH] Set BlockData without light updates + + +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +index 877498729c66de9aa6a27c9148f7494d7895615c..63959d7f15c682c2935f872d50de03fdacf95db4 100644 +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -235,7 +235,7 @@ public class WorldGenRegion implements WorldGenLevel { + Block.dropResources(iblockdata, this.level, pos, tileentity, breakingEntity, ItemStack.EMPTY); + } + +- return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, maxUpdateDepth); ++ return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, maxUpdateDepth, true); // Slice + } + } + +@@ -310,7 +310,7 @@ public class WorldGenRegion implements WorldGenLevel { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { // Slice + if (!this.ensureCanWrite(pos)) { + return false; + } else { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 973ecd50f9cb6b86c353586e84d15dcb118ccb60..8e3db48534fc90bb55d0772084b1543f2239878f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -515,12 +515,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline +- return this.setBlock(pos, state, flags, 512); ++ public final boolean setBlock(BlockPos pos, BlockState state, int flags, boolean checkLight) { // Paper - final for inline ++ return this.setBlock(pos, state, flags, 512, checkLight); + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { + // Paper start +@@ -568,7 +568,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } else { + BlockState iblockdata2 = this.getBlockState(pos); + +- if ((flags & 128) == 0 && iblockdata2 != iblockdata1 && (iblockdata2.getLightBlock(this, pos) != iblockdata1.getLightBlock(this, pos) || iblockdata2.getLightEmission() != iblockdata1.getLightEmission() || iblockdata2.useShapeForLightOcclusion() || iblockdata1.useShapeForLightOcclusion())) { ++ if (checkLight && (flags & 128) == 0 && iblockdata2 != iblockdata1 && (iblockdata2.getLightBlock(this, pos) != iblockdata1.getLightBlock(this, pos) || iblockdata2.getLightEmission() != iblockdata1.getLightEmission() || iblockdata2.useShapeForLightOcclusion() || iblockdata1.useShapeForLightOcclusion())) { + this.getProfiler().push("queueCheckLight"); + this.getChunkSource().getLightEngine().checkBlock(pos); + this.getProfiler().pop(); +@@ -716,7 +716,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY); + } + +- boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth); ++ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth, true); + + if (flag1) { + this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(breakingEntity, iblockdata)); +diff --git a/src/main/java/net/minecraft/world/level/LevelWriter.java b/src/main/java/net/minecraft/world/level/LevelWriter.java +index 134e5ec79bf2dddd4e31930f8a7cb2c02fa29518..fd72d278a2719911a46b6bc9e7da2dc24bbe681e 100644 +--- a/src/main/java/net/minecraft/world/level/LevelWriter.java ++++ b/src/main/java/net/minecraft/world/level/LevelWriter.java +@@ -7,10 +7,14 @@ import net.minecraft.world.level.block.state.BlockState; + + public interface LevelWriter { + +- boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth); ++ boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight); + + default boolean setBlock(BlockPos pos, BlockState state, int flags) { +- return this.setBlock(pos, state, flags, 512); ++ return this.setBlock(pos, state, flags, 512, true); ++ } ++ ++ default boolean setBlock(BlockPos pos, BlockState state, int flags, boolean checkLight) { ++ return this.setBlock(pos, state, flags, 512, checkLight); + } + + boolean removeBlock(BlockPos pos, boolean move); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index 4f91e4832a94c3facbc711fcae4cb5ad540a5ca0..5fe1a2c493c2a47ec3da8293428d45ef650249c1 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -196,7 +196,7 @@ public class Block extends BlockBehaviour implements ItemLike { + world.destroyBlock(pos, (flags & 32) == 0, (Entity) null, maxUpdateDepth); + } + } else { +- world.setBlock(pos, newState, flags & -33, maxUpdateDepth); ++ world.setBlock(pos, newState, flags & -33, maxUpdateDepth, true); // Slice + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java +index ef25a0ae25e1f1f7c5bee64b9e60b17eb998ced6..045b420d561d91acc020743594281e117c406e93 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java +@@ -285,7 +285,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor { + BlockPos pos = new BlockPos(x, y, z); + net.minecraft.world.level.block.state.BlockState old = this.getHandle().getBlockState(pos); + +- CraftBlock.setTypeAndData(world, pos, old, ((CraftBlockData) blockData).getState(), true); ++ CraftBlock.setTypeAndData(world, pos, old, ((CraftBlockData) blockData).getState(), true, true); + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 962c950ca9c7e047a3aec215d4faa73676049d36..7621a8fea46e16bb1aa031ec426721e7d4a4444f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -189,15 +189,20 @@ public class CraftBlock implements Block { + + @Override + public void setBlockData(BlockData data, boolean applyPhysics) { ++ setBlockData(data, applyPhysics, true); ++ } ++ ++ @Override ++ public void setBlockData(BlockData data, boolean applyPhysics, boolean checkLight) { + Preconditions.checkArgument(data != null, "BlockData cannot be null"); +- this.setTypeAndData(((CraftBlockData) data).getState(), applyPhysics); ++ this.setTypeAndData(((CraftBlockData) data).getState(), applyPhysics, checkLight); + } + +- boolean setTypeAndData(final net.minecraft.world.level.block.state.BlockState blockData, final boolean applyPhysics) { +- return CraftBlock.setTypeAndData(this.world, this.position, this.getNMS(), blockData, applyPhysics); ++ boolean setTypeAndData(final net.minecraft.world.level.block.state.BlockState blockData, final boolean applyPhysics, boolean checkLight) { ++ return CraftBlock.setTypeAndData(this.world, this.position, this.getNMS(), blockData, applyPhysics, checkLight); + } + +- public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) { ++ public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics, boolean checkLight) { + // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup + if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes + // SPIGOT-4612: faster - just clear tile +@@ -211,7 +216,7 @@ public class CraftBlock implements Block { + if (applyPhysics) { + return world.setBlock(position, blockData, 3); + } else { +- boolean success = world.setBlock(position, blockData, 2 | 16 | 1024); // NOTIFY | NO_OBSERVER | NO_PLACE (custom) ++ boolean success = world.setBlock(position, blockData, 2 | 16 | 1024, checkLight); // NOTIFY | NO_OBSERVER | NO_PLACE (custom) + if (success && world instanceof net.minecraft.world.level.Level) { + world.getMinecraftWorld().sendBlockUpdated( + position, +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +index a8ab1d3ee81664193be39d2735d6495136e0e310..fd4f00fa38b2d90e13937f114d96ea37bbc6dcdb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +@@ -213,7 +213,7 @@ public class CraftBlockState implements BlockState { + } + + net.minecraft.world.level.block.state.BlockState newBlock = this.data; +- block.setTypeAndData(newBlock, applyPhysics); ++ block.setTypeAndData(newBlock, applyPhysics, true); + if (access instanceof net.minecraft.world.level.Level) { + this.world.getHandle().sendBlockUpdated( + position, +diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +index 0b7d882551bcb8be149754209aad5fe4142f0fac..db3a7b550b1fa0654ba76f522a8163135f222281 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +@@ -245,7 +245,7 @@ public class DummyGeneratorAccess implements WorldGenLevel { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { + return false; + } + diff --git a/patches/server/0004-Add-BlockDestroyedByNeighborEvent.patch b/patches/server/0004-Add-BlockDestroyedByNeighborEvent.patch new file mode 100644 index 000000000..5e38fb356 --- /dev/null +++ b/patches/server/0004-Add-BlockDestroyedByNeighborEvent.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:30:29 -0500 +Subject: [PATCH] Add BlockDestroyedByNeighborEvent + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 1d33c02088c150189d7f4b0aa27f6a1de96b11cf..14f68a88a5dacaacc799787a9f451699bc4bd5cd 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -418,6 +418,7 @@ public class ServerPlayerGameMode { + org.bukkit.block.BlockState state = bblock.getState(); + level.captureDrops = new ArrayList<>(); + // CraftBukkit end ++ level.pendingPlayerBlockEvents.put(pos, new Level.PendingBlockEvent(pos, this.player)); // Paper + block.playerWillDestroy(this.level, pos, iblockdata, this.player); + boolean flag = this.level.removeBlock(pos, false); + +@@ -446,6 +447,7 @@ public class ServerPlayerGameMode { + // CraftBukkit start + java.util.List itemsToDrop = level.captureDrops; // Paper - store current list + level.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff ++ level.pendingPlayerBlockEvents.remove(pos); // Paper + if (event.isDropItems()) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref + } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index a7533d18fe6148d7bfd3106b9cdcb6fa3347cf7c..588a4fdcb294b9b1a92ef9969ef64f999bf529cc 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -356,6 +356,7 @@ public final class ItemStack { + } + } + Item item = this.getItem(); ++ if (entityhuman != null) world.pendingPlayerBlockEvents.put(blockposition, new Level.PendingBlockEvent(blockposition, entityhuman)); // Paper + InteractionResult enuminteractionresult = item.useOn(itemactioncontext); + CompoundTag newData = this.getTagClone(); + int newCount = this.getCount(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 8e3db48534fc90bb55d0772084b1543f2239878f..23630e4ab396158d8f3f77bf9aa05f66c6b27a9d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -185,6 +185,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + ++ // Paper start - Holder class used to track what Player is responsible the last block event ++ public static class PendingBlockEvent { ++ ++ public final BlockPos block; ++ public final Player player; ++ public @Nullable BlockPos sourceBlock; ++ ++ public PendingBlockEvent(BlockPos block, Player player) { ++ this(block, player, null); ++ } ++ ++ public PendingBlockEvent(BlockPos block, Player player, @Nullable BlockPos sourceBlock) { ++ this.block = block; ++ this.player = player; ++ this.sourceBlock = sourceBlock; ++ } ++ ++ } ++ public final Map pendingPlayerBlockEvents = new HashMap<>(); ++ // Paper end ++ + // Paper start - fix and optimise world upgrading + // copied from below + public static ResourceKey getDimensionKey(DimensionType manager) { +@@ -670,6 +691,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (!this.preventPoiUpdated) { + this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); + } ++ pendingPlayerBlockEvents.remove(blockposition); // Paper + // CraftBukkit end + } + } +@@ -691,6 +713,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (iblockdata.isAir()) { + return false; + } else { ++ // Paper start ++ PendingBlockEvent blockEvent = pendingPlayerBlockEvents.get(pos); ++ if (blockEvent != null && blockEvent.sourceBlock != null) { ++ io.papermc.paper.event.block.BlockDestroyedByNeighborEvent event = ++ new io.papermc.paper.event.block.BlockDestroyedByNeighborEvent(org.bukkit.craftbukkit.block.CraftBlock.at(this, pos), ++ (org.bukkit.entity.Player) blockEvent.player.getBukkitEntity(), ++ org.bukkit.craftbukkit.block.CraftBlock.at(this, blockEvent.sourceBlock)); ++ event.callEvent(); ++ } ++ // Paper end ++ + FluidState fluid = this.getFluidState(pos); + // Paper start - while the above setAir method is named same and looks very similar + // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, +diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +index 9db66b393e057d93a8025b803ae0ad2a1bca61f6..4c7cd93daa2d4fcbf444fe7fceca9e779f883603 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -105,6 +105,15 @@ public class DoublePlantBlock extends BushBlock { + BlockPos blockposition1 = pos.below(); + BlockState iblockdata1 = world.getBlockState(blockposition1); + ++ Level.PendingBlockEvent blockEvent = world.pendingPlayerBlockEvents.remove(pos); ++ if (blockEvent != null) { ++ io.papermc.paper.event.block.BlockDestroyedByNeighborEvent event = ++ new io.papermc.paper.event.block.BlockDestroyedByNeighborEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition1), ++ (org.bukkit.entity.Player) blockEvent.player.getBukkitEntity(), ++ org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)); ++ if (!event.callEvent()) return; ++ } ++ + if (iblockdata1.is(state.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER) { + BlockState iblockdata2 = iblockdata1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 505503a3f59d4b747649275c6f6faa504b7c7b64..0578f8e08b8079898be037e56eb093042a2df0cc 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -1036,6 +1036,16 @@ public abstract class BlockBehaviour implements FeatureElement { + Direction enumdirection = aenumdirection[l]; + + blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ // Paper start - Propagate the PendingBlockEvent from the current blockPos to the next block ++ // if it will break (!canSurvive) ++ if (this.getMaterial() == Material.AIR && !world.getBlockState(blockposition_mutableblockposition).canSurvive(world, blockposition_mutableblockposition)) { ++ Level.PendingBlockEvent blockEvent = ((Level) world).pendingPlayerBlockEvents.get(pos); ++ if (blockEvent != null) { ++ BlockPos blockPosCopy = blockposition_mutableblockposition.immutable(); ++ ((Level) world).pendingPlayerBlockEvents.put(blockPosCopy, new Level.PendingBlockEvent(blockPosCopy, blockEvent.player, pos)); ++ } ++ } ++ // Paper end + world.neighborShapeChanged(enumdirection.getOpposite(), this.asState(), blockposition_mutableblockposition, pos, flags, maxUpdateDepth); + } + diff --git a/patches/server/0005-Add-provided-Material-to-getDrops.patch b/patches/server/0005-Add-provided-Material-to-getDrops.patch new file mode 100644 index 000000000..013b60667 --- /dev/null +++ b/patches/server/0005-Add-provided-Material-to-getDrops.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:31:54 -0500 +Subject: [PATCH] Add provided Material to getDrops + + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index 7621a8fea46e16bb1aa031ec426721e7d4a4444f..4455e7d6265ba658c24615ec092cc36643fd4cb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -616,7 +616,18 @@ public class CraftBlock implements Block { + + @Override + public Collection getDrops(ItemStack item, Entity entity) { +- net.minecraft.world.level.block.state.BlockState iblockdata = this.getNMS(); ++ return getDrops(null, item, entity); // Slice start ++ } ++ ++ @Override ++ public Collection getDrops(Material blockType, ItemStack item, Entity entity) { ++ net.minecraft.world.level.block.state.BlockState iblockdata; ++ if (blockType == null) { ++ iblockdata = this.getNMS(); ++ } else { ++ iblockdata = ((CraftBlockData) blockType.createBlockData()).getState(); ++ } ++ + net.minecraft.world.item.ItemStack nms = CraftItemStack.asNMSCopy(item); + + // Modelled off EntityHuman#hasBlock +@@ -627,6 +638,7 @@ public class CraftBlock implements Block { + return Collections.emptyList(); + } + } ++ // Slice end + + @Override + public boolean isPreferredTool(ItemStack item) { diff --git a/patches/server/0006-Add-Player-to-SpongeAbsorbEvent.patch b/patches/server/0006-Add-Player-to-SpongeAbsorbEvent.patch new file mode 100644 index 000000000..93cdd2a9f --- /dev/null +++ b/patches/server/0006-Add-Player-to-SpongeAbsorbEvent.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:36:21 -0500 +Subject: [PATCH] Add Player to SpongeAbsorbEvent + + +diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +index 7304b2659eb45bc4bc9fa7c43e6ca07221d0fc73..63e385993022b6e708e981982c18060273d3e019 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +@@ -109,7 +109,8 @@ public class SpongeBlock extends Block { + if (!blocks.isEmpty()) { + final org.bukkit.block.Block bblock = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + +- SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ Level.PendingBlockEvent blockEvent = world.pendingPlayerBlockEvents.remove(pos); // Paper ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, blockEvent != null ? (org.bukkit.entity.Player) blockEvent.player.getBukkitEntity() : null, (List) (List) blocks); // Paper + world.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { diff --git a/patches/server/0007-Add-World-Instance-flag.patch b/patches/server/0007-Add-World-Instance-flag.patch new file mode 100644 index 000000000..eef6bc273 --- /dev/null +++ b/patches/server/0007-Add-World-Instance-flag.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:37:05 -0500 +Subject: [PATCH] Add World Instance flag + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 3bb63a652aca3c23f5f1bbf9cb70fce6540f2e33..5813349d484cf40c5b75de6e55dff95286285934 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -219,6 +219,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper + public boolean hasEntityMoveEvent = false; // Paper ++ public boolean instance; // Slice + private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) + public static Throwable getAddToWorldStackTrace(Entity entity) { + final Throwable thr = new Throwable(entity + " Added to world at " + new java.util.Date()); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 86ffc869b57410fd4993c0fd0ae000da2e2c070c..7b67bcba6d3dea4da815566d0a24e547cd5a1e87 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1276,6 +1276,18 @@ public class CraftWorld extends CraftRegionAccessor implements World { + world.noSave = !value; + } + ++ // Slice start ++ @Override ++ public boolean isInstance() { ++ return world.instance; ++ } ++ ++ @Override ++ public void setInstance(boolean value) { ++ world.instance = value; ++ } ++ // Slice end ++ + @Override + public void setDifficulty(Difficulty difficulty) { + this.getHandle().getServer().setDifficulty(this.getHandle(), net.minecraft.world.Difficulty.byId(difficulty.getValue()), true); // Paper - don't skip other difficulty-changing logic diff --git a/patches/server/0008-Add-PlayerData-Events.patch b/patches/server/0008-Add-PlayerData-Events.patch new file mode 100644 index 000000000..ad0f2dcd5 --- /dev/null +++ b/patches/server/0008-Add-PlayerData-Events.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tom +Date: Mon, 10 Apr 2023 07:38:40 -0500 +Subject: [PATCH] Add PlayerData Events + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 14f68a88a5dacaacc799787a9f451699bc4bd5cd..a1db0c83d472a87560ca1b3834dd1f1bdbb9fc1a 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -600,6 +600,8 @@ public class ServerPlayerGameMode { + enuminteractionresult1 = stack.useOn(itemactioncontext, hand); + } + ++ world.pendingPlayerBlockEvents.remove(blockposition); // Paper ++ + if (enuminteractionresult1.consumesAction()) { + CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockposition, itemstack1); + } +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index 9501e5f25f5c4d3069e554d4dc82b0e094156682..8afd9b785fb8734255e3ea926b8375bb9cae60be 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -198,7 +198,12 @@ public class ServerStatsCounter extends StatsCounter { + return nbttagcompound; + } + +- protected String toJson() { ++ // Slice start - OBFHELPER ++ public String toJson() { ++ return serialize().toString(); ++ } ++ ++ public JsonObject serialize() { // Slice end + Map, JsonObject> map = Maps.newHashMap(); + ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); + +@@ -224,7 +229,7 @@ public class ServerStatsCounter extends StatsCounter { + + jsonobject1.add("stats", jsonobject); + jsonobject1.addProperty("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- return jsonobject1.toString(); ++ return jsonobject1; // Slice + } + + private static ResourceLocation getKey(Stat stat) { +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 36af81f0957d17e170d229059c66f4eb4539dfeb..e8d324a32838b69255ce48b1c03e47cd9e201da6 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -33,6 +33,7 @@ public class PlayerDataStorage { + + public void save(Player player) { + if (org.spigotmc.SpigotConfig.disablePlayerDataSaving) return; // Spigot ++ if (!new com.destroystokyo.paper.event.player.PlayerSaveDataEvent((org.bukkit.entity.Player) player.getBukkitEntity()).callEvent()) return; // Slice + try { + CompoundTag nbttagcompound = player.saveWithoutId(new CompoundTag()); + File file = File.createTempFile(player.getStringUUID() + "-", ".dat", this.playerDir); +@@ -52,32 +53,40 @@ public class PlayerDataStorage { + public CompoundTag load(Player player) { + CompoundTag nbttagcompound = null; + +- try { +- File file = new File(this.playerDir, player.getStringUUID() + ".dat"); +- // Spigot Start +- boolean usingWrongFile = false; +- if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first +- { +- file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + player.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); +- if ( file.exists() ) ++ // Slice start - If event supplies playerdata, use it. Otherwise just load from disk as usual ++ com.destroystokyo.paper.event.player.PlayerLoadDataEvent event = new com.destroystokyo.paper.event.player.PlayerLoadDataEvent(player.getUUID()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ Object playerData = event.getPlayerData(); ++ if (playerData != null) { ++ nbttagcompound = (CompoundTag) playerData; ++ } else { ++ try { ++ File file = new File(this.playerDir, player.getStringUUID() + ".dat"); ++ // Spigot Start ++ boolean usingWrongFile = false; ++ if (org.bukkit.Bukkit.getOnlineMode() && !file.exists()) // Paper - Check online mode first + { +- usingWrongFile = true; +- org.bukkit.Bukkit.getServer().getLogger().warning( "Using offline mode UUID file for player " + player.getScoreboardName() + " as it is the only copy we can find." ); ++ file = new File(this.playerDir, java.util.UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getScoreboardName()).getBytes("UTF-8")).toString() + ".dat"); ++ if (file.exists()) { ++ usingWrongFile = true; ++ org.bukkit.Bukkit.getServer().getLogger().warning("Using offline mode UUID file for player " + player.getScoreboardName() + " as it is the only copy we can find."); ++ } + } +- } +- // Spigot End ++ // Spigot End + +- if (file.exists() && file.isFile()) { +- nbttagcompound = NbtIo.readCompressed(file); +- } +- // Spigot Start +- if ( usingWrongFile ) +- { +- file.renameTo( new File( file.getPath() + ".offline-read" ) ); ++ if (file.exists() && file.isFile()) { ++ nbttagcompound = NbtIo.readCompressed(file); ++ } ++ // Spigot Start ++ if (usingWrongFile) { ++ file.renameTo(new File(file.getPath() + ".offline-read")); ++ } ++ // Spigot End ++ } catch (Exception exception) { ++ PlayerDataStorage.LOGGER.warn("Failed to load player data for {}", player.getName().getString()); + } +- // Spigot End +- } catch (Exception exception) { +- PlayerDataStorage.LOGGER.warn("Failed to load player data for {}", player.getName().getString()); ++ // Slice end + } + + if (nbttagcompound != null) { diff --git a/patches/server/0009-Add-PlayerGetRespawnLocationEvent.patch b/patches/server/0009-Add-PlayerGetRespawnLocationEvent.patch new file mode 100644 index 000000000..b4aef808b --- /dev/null +++ b/patches/server/0009-Add-PlayerGetRespawnLocationEvent.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:46:18 -0500 +Subject: [PATCH] Add PlayerGetRespawnLocationEvent + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 4d837c1530a3031a4c2a5a39d87bd013d60e14a6..cc1fe063eeeaac4b91d54e692967e20a00a20d16 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -835,49 +835,57 @@ public abstract class PlayerList { + + // CraftBukkit start - fire PlayerRespawnEvent + if (location == null) { +- // boolean isBedSpawn = false; // Paper - moved up +- ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); +- if (worldserver1 != null) { +- Optional optional; ++ // Slice start ++ Player respawnPlayer = entityplayer1.getBukkitEntity(); ++ org.bukkit.event.player.PlayerGetRespawnLocationEvent preRespawnEvent = new org.bukkit.event.player.PlayerGetRespawnLocationEvent(respawnPlayer); ++ preRespawnEvent.callEvent(); ++ location = preRespawnEvent.getRespawnLocation(); + +- if (blockposition != null) { +- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 +- } else { +- optional = Optional.empty(); +- } ++ if (location == null) { ++ // Slice end ++ // boolean isBedSpawn = false; // Paper - moved up ++ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; ++ ++ if (blockposition != null) { ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 ++ } else { ++ optional = Optional.empty(); ++ } + +- if (optional.isPresent()) { +- BlockState iblockdata = worldserver1.getBlockState(blockposition); +- boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); +- isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal +- Vec3 vec3d = (Vec3) optional.get(); +- float f1; ++ if (optional.isPresent()) { ++ BlockState iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal ++ Vec3 vec3d = (Vec3) optional.get(); ++ float f1; + +- if (!iblockdata.is(BlockTags.BEDS) && !flag3) { +- f1 = f; +- } else { +- Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ if (!iblockdata.is(BlockTags.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); + +- f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); +- } ++ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } + +- entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // Paper - PlayerSetSpawnEvent +- flag2 = !flag && flag3; +- isBedSpawn = true; +- location = new Location(worldserver1.getWorld(), vec3d.x, vec3d.y, vec3d.z, f1, 0.0F); +- } else if (blockposition != null) { +- entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); +- entityplayer1.setRespawnPosition(null, null, 0f, false, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - PlayerSetSpawnEvent ++ entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // Paper - PlayerSetSpawnEvent ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = new Location(worldserver1.getWorld(), vec3d.x, vec3d.y, vec3d.z, f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - PlayerSetSpawnEvent ++ } + } +- } + +- if (location == null) { +- worldserver1 = this.server.getLevel(Level.OVERWORLD); +- blockposition = entityplayer1.getSpawnPoint(worldserver1); +- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle ++ if (location == null) { ++ worldserver1 = this.server.getLevel(Level.OVERWORLD); ++ blockposition = entityplayer1.getSpawnPoint(worldserver1); ++ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.levelData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle ++ } + } + +- Player respawnPlayer = entityplayer1.getBukkitEntity(); + PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, reason, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal + this.cserver.getPluginManager().callEvent(respawnEvent); + // Spigot Start diff --git a/patches/server/0010-Set-multiple-team-settings-at-once.patch b/patches/server/0010-Set-multiple-team-settings-at-once.patch new file mode 100644 index 000000000..e357e2e47 --- /dev/null +++ b/patches/server/0010-Set-multiple-team-settings-at-once.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:52:53 -0500 +Subject: [PATCH] Set multiple team settings at once + + +diff --git a/src/main/java/net/minecraft/world/scores/PlayerTeam.java b/src/main/java/net/minecraft/world/scores/PlayerTeam.java +index 9464054912e19fc78dd965b71fce20a18564b351..1624a0f8ea211a4c43fd01612674ca501c10d7e6 100644 +--- a/src/main/java/net/minecraft/world/scores/PlayerTeam.java ++++ b/src/main/java/net/minecraft/world/scores/PlayerTeam.java +@@ -28,6 +28,7 @@ public class PlayerTeam extends Team { + private ChatFormatting color = ChatFormatting.RESET; + private Team.CollisionRule collisionRule = Team.CollisionRule.ALWAYS; + private final Style displayNameStyle; ++ private boolean updateTeamChangeInstantly = true; // Slice + + public PlayerTeam(Scoreboard scoreboard, String name) { + this.scoreboard = scoreboard; +@@ -36,6 +37,12 @@ public class PlayerTeam extends Team { + this.displayNameStyle = Style.EMPTY.withInsertion(name).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal(name))); + } + ++ // Slice start ++ public void setUpdateTeamChangeInstantly(boolean updateTeamChangeInstantly) { ++ this.updateTeamChangeInstantly = updateTeamChangeInstantly; ++ } ++ // Slice end ++ + public Scoreboard getScoreboard() { + return this.scoreboard; + } +@@ -64,13 +71,13 @@ public class PlayerTeam extends Team { + throw new IllegalArgumentException("Name cannot be null"); + } else { + this.displayName = displayName; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + } + + public void setPlayerPrefix(@Nullable Component prefix) { + this.playerPrefix = prefix == null ? CommonComponents.EMPTY : prefix; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + public Component getPlayerPrefix() { +@@ -79,7 +86,7 @@ public class PlayerTeam extends Team { + + public void setPlayerSuffix(@Nullable Component suffix) { + this.playerSuffix = suffix == null ? CommonComponents.EMPTY : suffix; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + public Component getPlayerSuffix() { +@@ -113,7 +120,7 @@ public class PlayerTeam extends Team { + + public void setAllowFriendlyFire(boolean friendlyFire) { + this.allowFriendlyFire = friendlyFire; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + @Override +@@ -123,7 +130,7 @@ public class PlayerTeam extends Team { + + public void setSeeFriendlyInvisibles(boolean showFriendlyInvisible) { + this.seeFriendlyInvisibles = showFriendlyInvisible; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + @Override +@@ -138,12 +145,12 @@ public class PlayerTeam extends Team { + + public void setNameTagVisibility(Team.Visibility nameTagVisibilityRule) { + this.nameTagVisibility = nameTagVisibilityRule; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + public void setDeathMessageVisibility(Team.Visibility deathMessageVisibilityRule) { + this.deathMessageVisibility = deathMessageVisibilityRule; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + @Override +@@ -153,7 +160,7 @@ public class PlayerTeam extends Team { + + public void setCollisionRule(Team.CollisionRule collisionRule) { + this.collisionRule = collisionRule; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + public int packOptions() { +@@ -176,7 +183,7 @@ public class PlayerTeam extends Team { + + public void setColor(ChatFormatting color) { + this.color = color; +- this.scoreboard.onTeamChanged(this); ++ if (updateTeamChangeInstantly) this.scoreboard.onTeamChanged(this); // Slice + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +index 67efb0d38ae369ff5254f7b1ec85d32d4eee8291..e4110e3a60242b958c9983a090b28aae540b2bdf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java ++++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +@@ -347,6 +347,37 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { + } + } + ++ //Slice start ++ @Override ++ public void teamOptions(net.kyori.adventure.text.Component displayName, ++ net.kyori.adventure.text.Component prefix, ++ net.kyori.adventure.text.Component suffix, ++ net.kyori.adventure.text.format.NamedTextColor color, ++ java.util.List> options) throws IllegalStateException { ++ checkState(); ++ team.setUpdateTeamChangeInstantly(false); ++ ++ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); ++ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ ++ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); ++ team.setPlayerPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); ++ ++ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); ++ team.setPlayerSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); ++ ++ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; ++ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); ++ ++ for (org.apache.commons.lang3.tuple.Pair pair : options) { ++ setOption(pair.getLeft(), pair.getRight()); ++ } ++ ++ team.setUpdateTeamChangeInstantly(true); ++ team.getScoreboard().onTeamChanged(team); ++ } ++ //Slice end ++ + // Paper start + @Override + public void addEntity(org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException { diff --git a/patches/server/0011-Smooth-Teleports.patch b/patches/server/0011-Smooth-Teleports.patch new file mode 100644 index 000000000..062fcaed7 --- /dev/null +++ b/patches/server/0011-Smooth-Teleports.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 07:55:35 -0500 +Subject: [PATCH] Smooth Teleports + + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 1d4d02f26391ac55c7631817f09d05e2769b0d29..3e4f97d0a46b4708f30a52b7f02eeb8503e52c87 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -275,6 +275,7 @@ public class ServerPlayer extends Player { + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event ++ public boolean smoothWorldTeleport; // Slice + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index cc1fe063eeeaac4b91d54e692967e20a00a20d16..a5828dd3cc747eb720b7c53f0d59f01a6d1fdd7c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -917,12 +917,12 @@ public abstract class PlayerList { + int i = flag ? 1 : 0; + // CraftBukkit start + LevelData worlddata = worldserver1.getLevelData(); +- entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), (byte) i, entityplayer1.getLastDeathLocation())); ++ if (!entityplayer.smoothWorldTeleport) entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), (byte) i, entityplayer1.getLastDeathLocation())); + entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetSendDistance())); // Spigot // Paper - replace old player chunk management + entityplayer1.connection.send(new ClientboundSetSimulationDistancePacket(worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetTickViewDistance())); // Spigot // Paper - replace old player chunk management + entityplayer1.spawnIn(worldserver1); + entityplayer1.unsetRemoved(); +- entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); ++ if (!entityplayer.smoothWorldTeleport) entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); + entityplayer1.setShiftKeyDown(false); + + // entityplayer1.connection.teleport(entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot()); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index ca22b7de2dd05a0bdcdcd3bffb9ec991d196abde..dd2140fece85748dfa64eea7651835834f0363ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1264,6 +1264,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end + } + ++ // Slice start ++ public void teleportWithoutRespawn(Location location) { ++ ServerPlayer serverPlayer = getHandle(); ++ serverPlayer.smoothWorldTeleport = true; ++ teleport(location); ++ serverPlayer.smoothWorldTeleport = false; ++ } ++ // Slice end ++ + @Override + public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + // Paper start - Teleport API diff --git a/patches/server/0012-Ignore-durability-changes-for-equipment-updates.patch b/patches/server/0012-Ignore-durability-changes-for-equipment-updates.patch new file mode 100644 index 000000000..59fa3f0c2 --- /dev/null +++ b/patches/server/0012-Ignore-durability-changes-for-equipment-updates.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:40:20 -0500 +Subject: [PATCH] Ignore durability changes for equipment updates + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 95a27d28f73039693ca64601954af62028413634..72739d5949314b242869fd5fef3b5f0c076434d0 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3096,7 +3096,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + public boolean equipmentHasChanged(ItemStack stack, ItemStack stack2) { +- return !ItemStack.matches(stack2, stack); ++ return !ItemStack.isSame(stack2, stack); + } + + private void handleHandSwap(Map equipmentChanges) { diff --git a/patches/server/0013-Disable-Azalea-generation.patch b/patches/server/0013-Disable-Azalea-generation.patch new file mode 100644 index 000000000..7efb18d7f --- /dev/null +++ b/patches/server/0013-Disable-Azalea-generation.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:45:12 -0500 +Subject: [PATCH] Disable Azalea generation + + +diff --git a/src/main/java/net/minecraft/data/worldgen/BiomeDefaultFeatures.java b/src/main/java/net/minecraft/data/worldgen/BiomeDefaultFeatures.java +index 8f5178e934b5f9bc48beacd082e479fd9fb80fa6..d580238d733ba2dbbbbaa2659d1a7834c8cf7dac 100644 +--- a/src/main/java/net/minecraft/data/worldgen/BiomeDefaultFeatures.java ++++ b/src/main/java/net/minecraft/data/worldgen/BiomeDefaultFeatures.java +@@ -161,7 +161,7 @@ public class BiomeDefaultFeatures { + builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.CAVE_VINES); + builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.LUSH_CAVES_CLAY); + builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.LUSH_CAVES_VEGETATION); +- builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.ROOTED_AZALEA_TREE); ++// builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.ROOTED_AZALEA_TREE); // Slice + builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.SPORE_BLOSSOM); + builder.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, CavePlacements.CLASSIC_VINES); + } +diff --git a/src/main/java/net/minecraft/data/worldgen/features/CaveFeatures.java b/src/main/java/net/minecraft/data/worldgen/features/CaveFeatures.java +index feabf6db6a5987bec36b611b160b67ca30af2ecf..974c4d03dd36cd30ff0736cdc1605623e21e7c78 100644 +--- a/src/main/java/net/minecraft/data/worldgen/features/CaveFeatures.java ++++ b/src/main/java/net/minecraft/data/worldgen/features/CaveFeatures.java +@@ -110,7 +110,7 @@ public class CaveFeatures { + RandomizedIntStateProvider randomizedIntStateProvider = new RandomizedIntStateProvider(new WeightedStateProvider(SimpleWeightedRandomList.builder().add(Blocks.CAVE_VINES.defaultBlockState(), 4).add(Blocks.CAVE_VINES.defaultBlockState().setValue(CaveVines.BERRIES, Boolean.valueOf(true)), 1)), CaveVinesBlock.AGE, UniformInt.of(23, 25)); + FeatureUtils.register(featureRegisterable, CAVE_VINE, Feature.BLOCK_COLUMN, new BlockColumnConfiguration(List.of(BlockColumnConfiguration.layer(new WeightedListInt(SimpleWeightedRandomList.builder().add(UniformInt.of(0, 19), 2).add(UniformInt.of(0, 2), 3).add(UniformInt.of(0, 6), 10).build()), weightedStateProvider), BlockColumnConfiguration.layer(ConstantInt.of(1), randomizedIntStateProvider)), Direction.DOWN, BlockPredicate.ONLY_IN_AIR_PREDICATE, true)); + FeatureUtils.register(featureRegisterable, CAVE_VINE_IN_MOSS, Feature.BLOCK_COLUMN, new BlockColumnConfiguration(List.of(BlockColumnConfiguration.layer(new WeightedListInt(SimpleWeightedRandomList.builder().add(UniformInt.of(0, 3), 5).add(UniformInt.of(1, 7), 1).build()), weightedStateProvider), BlockColumnConfiguration.layer(ConstantInt.of(1), randomizedIntStateProvider)), Direction.DOWN, BlockPredicate.ONLY_IN_AIR_PREDICATE, true)); +- FeatureUtils.register(featureRegisterable, MOSS_VEGETATION, Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(new WeightedStateProvider(SimpleWeightedRandomList.builder().add(Blocks.FLOWERING_AZALEA.defaultBlockState(), 4).add(Blocks.AZALEA.defaultBlockState(), 7).add(Blocks.MOSS_CARPET.defaultBlockState(), 25).add(Blocks.GRASS.defaultBlockState(), 50).add(Blocks.TALL_GRASS.defaultBlockState(), 10)))); ++ FeatureUtils.register(featureRegisterable, MOSS_VEGETATION, Feature.SIMPLE_BLOCK, new SimpleBlockConfiguration(new WeightedStateProvider(SimpleWeightedRandomList.builder().add(Blocks.MOSS_CARPET.defaultBlockState(), 25).add(Blocks.GRASS.defaultBlockState(), 50).add(Blocks.TALL_GRASS.defaultBlockState(), 10)))); + FeatureUtils.register(featureRegisterable, MOSS_PATCH, Feature.VEGETATION_PATCH, new VegetationPatchConfiguration(BlockTags.MOSS_REPLACEABLE, BlockStateProvider.simple(Blocks.MOSS_BLOCK), PlacementUtils.inlinePlaced(holderGetter.getOrThrow(MOSS_VEGETATION)), CaveSurface.FLOOR, ConstantInt.of(1), 0.0F, 5, 0.8F, UniformInt.of(4, 7), 0.3F)); + FeatureUtils.register(featureRegisterable, MOSS_PATCH_BONEMEAL, Feature.VEGETATION_PATCH, new VegetationPatchConfiguration(BlockTags.MOSS_REPLACEABLE, BlockStateProvider.simple(Blocks.MOSS_BLOCK), PlacementUtils.inlinePlaced(holderGetter.getOrThrow(MOSS_VEGETATION)), CaveSurface.FLOOR, ConstantInt.of(1), 0.0F, 5, 0.6F, UniformInt.of(1, 2), 0.75F)); + FeatureUtils.register(featureRegisterable, DRIPLEAF, Feature.SIMPLE_RANDOM_SELECTOR, new SimpleRandomFeatureConfiguration(HolderSet.direct(makeSmallDripleaf(), makeDripleaf(Direction.EAST), makeDripleaf(Direction.WEST), makeDripleaf(Direction.SOUTH), makeDripleaf(Direction.NORTH)))); diff --git a/patches/server/0014-AntiXray-Bypass.patch b/patches/server/0014-AntiXray-Bypass.patch new file mode 100644 index 000000000..0f6594777 --- /dev/null +++ b/patches/server/0014-AntiXray-Bypass.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:46:54 -0500 +Subject: [PATCH] AntiXray Bypass + + +diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +index cab91880a08c6fdc545804911d295e0f24f4d983..f90f27d9d9a4043198c33d65efa7068b76b58818 100644 +--- a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java ++++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +@@ -163,6 +163,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo + + @Override + public boolean shouldModify(ServerPlayer player, LevelChunk chunk) { ++ if (player.getBukkitEntity().hasAntiXrayBypass()) return false; // Slice + return !usePermission || !player.getBukkitEntity().hasPermission("paper.antixray.bypass"); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index dd2140fece85748dfa64eea7651835834f0363ab..6f95b7c41d050d27cd6e61cc0f6442bd665f1eba 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -181,6 +181,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit + private long lastSaveTime; + // Paper end ++ private boolean antiXrayBypass; // Slice + + public CraftPlayer(CraftServer server, ServerPlayer entity) { + super(server, entity); +@@ -2742,6 +2743,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + // Paper end + ++ // Slice start ++ public boolean hasAntiXrayBypass() { ++ return this.antiXrayBypass; ++ } ++ ++ @Override ++ public void toggleAntiXrayBypass(boolean bypass) { ++ this.antiXrayBypass = bypass; ++ } ++ // Slice end ++ + @Override + public void updateCommands() { + if (this.getHandle().connection == null) return; diff --git a/patches/server/0015-Add-PlayerPreChunkLoadEvent.patch b/patches/server/0015-Add-PlayerPreChunkLoadEvent.patch new file mode 100644 index 000000000..dad5fffe3 --- /dev/null +++ b/patches/server/0015-Add-PlayerPreChunkLoadEvent.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Mon, 10 Apr 2023 08:47:43 -0500 +Subject: [PATCH] Add PlayerPreChunkLoadEvent + + +diff --git a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java +index e77972c4c264100ffdd824bfa2dac58dbbc6d678..5b32567bcf532994a31f184743cf42f4ea0113a4 100644 +--- a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java ++++ b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java +@@ -787,7 +787,7 @@ public final class PlayerChunkLoader { + // warning: modifications of this field must be aware that the loadQueue inside PlayerChunkLoader uses this field + // in a comparator! + protected final ArrayDeque loadQueue = new ArrayDeque<>(); +- protected final LongOpenHashSet sentChunks = new LongOpenHashSet(); ++ public final LongOpenHashSet sentChunks = new LongOpenHashSet(); // Slice - public + protected final LongOpenHashSet chunksToBeSent = new LongOpenHashSet(); + + protected final TreeSet sendQueue = new TreeSet<>((final ChunkPriorityHolder p1, final ChunkPriorityHolder p2) -> { +@@ -871,7 +871,14 @@ public final class PlayerChunkLoader { + } + + public void sendChunk(final int chunkX, final int chunkZ, final Runnable onChunkSend) { +- if (this.sentChunks.add(CoordinateUtils.getChunkKey(chunkX, chunkZ))) { ++ // Slice start ++ if (!new io.papermc.paper.event.packet.PlayerPreChunkLoadEvent(this.player.getBukkitEntity().getWorld(), chunkX, chunkZ, this.player.getBukkitEntity()).callEvent()) { ++ this.player.connection.connection.execute(onChunkSend); ++ return; ++ } ++ // Slice end ++ ++ if (this.sentChunks.add(CoordinateUtils.getChunkKey(chunkX, chunkZ))) { // Slice + this.player.getLevel().getChunkSource().chunkMap.updateChunkTracking(this.player, + new ChunkPos(chunkX, chunkZ), new MutableObject<>(), false, true); // unloaded, loaded + this.player.connection.connection.execute(onChunkSend); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 7b67bcba6d3dea4da815566d0a24e547cd5a1e87..3e45551d8d677ccfb362e3039d7dee10018206d6 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -534,6 +534,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { + return true; + } + ++ @Override ++ public it.unimi.dsi.fastutil.longs.LongOpenHashSet getSentChunks(Player p) { ++ CraftPlayer craftPlayer = (CraftPlayer) p; ++ io.papermc.paper.chunk.PlayerChunkLoader.PlayerLoaderData data = this.world.chunkSource.chunkMap.playerChunkManager.getData(craftPlayer.getHandle()); ++ return data != null ? data.sentChunks : null; ++ } ++ + @Override + public boolean isChunkInUse(int x, int z) { + return this.isChunkLoaded(x, z);