More work

This commit is contained in:
Cryptite
2024-11-17 09:34:13 -06:00
parent 33b007c39f
commit edd4afb8af
7 changed files with 487 additions and 2 deletions

View File

@@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sat, 9 Nov 2024 09:48:21 -0600
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;
+ }
+}

View File

@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sun, 17 Nov 2024 08:24:22 -0600
Subject: [PATCH] Expose getBlockPosBelowThatAffectsMyMovement
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 6324e8f11a382288fc0a6c30f47760ea50e231d5..8188b3a27fddac18cf49db5a8049149e784f4cbc 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -1187,4 +1187,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
void setVanished(boolean vanished);
// Slice end
+
+ // Slice start
+ /**
+ * Returns the Block that is currently supporting the player, particularly in the case of
+ * crouching over the edge of a block.
+ */
+ org.bukkit.block.Block getBlockStandingOn();
+ // Slice end
}

View File

@@ -0,0 +1,140 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sun, 17 Nov 2024 09:19:41 -0600
Subject: [PATCH] Add DimensionDataStorageEvents
diff --git a/src/main/java/io/papermc/paper/event/server/DimensionDataStorageLoadEvent.java b/src/main/java/io/papermc/paper/event/server/DimensionDataStorageLoadEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f85074ae3bb7eb558fc07a4e1877f130aec33d39
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/server/DimensionDataStorageLoadEvent.java
@@ -0,0 +1,61 @@
+package io.papermc.paper.event.server;
+
+import com.google.gson.JsonElement;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.server.ServerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+import java.nio.file.Path;
+
+/**
+ * Called when resources such as datapacks are reloaded (e.g. /minecraft:reload)
+ * <p>
+ * Intended for use to re-register custom recipes, advancements that may be lost during a reload like this.
+ */
+@NullMarked
+public class DimensionDataStorageLoadEvent extends ServerEvent implements Cancellable {
+ public static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final Path path;
+ private final JsonElement json;
+ private boolean cancelled;
+ @ApiStatus.Internal
+ public DimensionDataStorageLoadEvent(final Path path, final JsonElement json) {
+ this.path = path;
+ this.json = json;
+ }
+
+ public Path getPath() {
+ return path;
+ }
+
+ public JsonElement getJson() {
+ return json;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public enum Cause {
+ COMMAND,
+ PLUGIN,
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/server/DimensionDataStorageSaveEvent.java b/src/main/java/io/papermc/paper/event/server/DimensionDataStorageSaveEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b29981621c959dd6027a072dab06339ebf315bf
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/server/DimensionDataStorageSaveEvent.java
@@ -0,0 +1,61 @@
+package io.papermc.paper.event.server;
+
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.server.ServerEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.file.Path;
+
+/**
+ * Called when resources such as datapacks are reloaded (e.g. /minecraft:reload)
+ * <p>
+ * Intended for use to re-register custom recipes, advancements that may be lost during a reload like this.
+ */
+@NullMarked
+public class DimensionDataStorageSaveEvent extends ServerEvent implements Cancellable {
+ public static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final String id;
+ private final ByteArrayOutputStream output;
+ private boolean cancelled;
+ @ApiStatus.Internal
+ public DimensionDataStorageSaveEvent(final String id, final ByteArrayOutputStream output) {
+ this.id = id;
+ this.output = output;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public ByteArrayOutputStream getOutput() {
+ return output;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public enum Cause {
+ COMMAND,
+ PLUGIN,
+ }
+}

View File

@@ -0,0 +1,144 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sat, 9 Nov 2024 09:48:21 -0600
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 a96f859a5d0c6ec692d4627a69f3c9ee49199dbc..7fe358dac8740ac6338a942f4189bca300d1f1be 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -425,6 +425,7 @@ public class ServerPlayerGameMode {
this.level.captureDrops = new ArrayList<>();
// CraftBukkit end
BlockState iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player);
+ level.pendingPlayerBlockEvents.put(pos, new Level.PendingBlockEvent(pos, this.player)); // Paper
boolean flag = this.level.removeBlock(pos, false);
if (flag) {
@@ -452,6 +453,7 @@ public class ServerPlayerGameMode {
// CraftBukkit start
java.util.List<net.minecraft.world.entity.item.ItemEntity> itemsToDrop = this.level.captureDrops; // Paper - capture all item additions to the world
this.level.captureDrops = null; // Paper - capture all item additions to the world; 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 - capture all item additions to the world
}
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 33e7d2884195677c4d6340d8b84c1dd85c636ec1..04f8269abe339610795237652edcd54ba31bc5fc 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -424,6 +424,7 @@ public final class ItemStack implements DataComponentHolder {
DataComponentPatch oldData = this.components.asPatch();
int oldCount = this.getCount();
ServerLevel world = (ServerLevel) context.getLevel();
+ if (entityhuman != null) world.pendingPlayerBlockEvents.put(blockposition, new Level.PendingBlockEvent(blockposition, entityhuman)); // Paper
if (!(item instanceof BucketItem/* || item instanceof SolidBucketItem*/)) { // if not bucket // Paper - Fix cancelled powdered snow bucket placement
world.captureBlockStates = true;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 022de445bbbb869c38be4972c98dcf1c665539ec..abdbfb6bc3989bdc9332712be3c71b2afbf43c48 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -181,6 +181,28 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public final Map<ServerExplosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; 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<BlockPos, PendingBlockEvent> pendingPlayerBlockEvents = new HashMap<>();
+ // Paper end
+
+
public CraftWorld getWorld() {
return this.world;
}
@@ -1225,6 +1247,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
if (!this.preventPoiUpdated) {
this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
}
+ pendingPlayerBlockEvents.remove(blockposition); // Paper
// CraftBukkit end
}
}
@@ -1246,6 +1269,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
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 - BlockDestroyEvent; 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 4fe83bd0f355549847b66afb7e61f6f2a6d97016..be6e6247d1a94271926544b128a52f501bc2cad5 100644
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -114,6 +114,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 99fd67a78539133adf78d65e2c520ff3dd260301..12d9c6769c8cb705d232bc01b50b04df503e4c3a 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
@@ -1237,11 +1237,22 @@ public abstract class BlockBehaviour implements FeatureElement {
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
Direction[] aenumdirection = BlockBehaviour.UPDATE_SHAPE_ORDER;
int k = aenumdirection.length;
+ BlockState blockState = world.getBlockState(pos); // Slice
for (int l = 0; l < k; ++l) {
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 (blockState.getBukkitMaterial() == org.bukkit.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(), blockposition_mutableblockposition, pos, this.asState(), flags, maxUpdateDepth);
}

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Packet obfuscation and reduction
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
index 0f99733660f91280e4c6262cf75b3c9cae86f65a..fd28ad10df3cfcfdb44cafc4182ead53a4200027 100644
index 0f99733660f91280e4c6262cf75b3c9cae86f65a..8845497071ca3be0e439b454f1f2d14f0f74e842 100644
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
@@ -63,15 +63,29 @@ public class SynchedEntityData {
@@ -48,7 +48,7 @@ index 0f99733660f91280e4c6262cf75b3c9cae86f65a..fd28ad10df3cfcfdb44cafc4182ead53
+ public List<SynchedEntityData.DataValue<?>> packForeignDirty() {
+ List<SynchedEntityData.DataValue<?>> list = null;
+
+ for (DataItem<?> dataItem : this.itemsById.values()) {
+ for (DataItem<?> dataItem : this.itemsById) {
+ if (dataItem.isDirty(true)) {
+ dataItem.setForeignDirty(false);
+ if (list == null) {

View File

@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sun, 17 Nov 2024 08:24:22 -0600
Subject: [PATCH] Expose getBlockPosBelowThatAffectsMyMovement
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index aefa94ffd630e2dd6aefd547664ae25d2a81420c..0a34c8fb259ac9d3bfba518521d9137495509b96 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -28,6 +28,7 @@ import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.Sound;
import org.bukkit.World;
+import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.PistonMoveReaction;
import org.bukkit.craftbukkit.CraftServer;
@@ -1318,4 +1319,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
this.entity.vanished = vanished;
}
// Slice end
+
+ // Slice start
+ @Override
+ public Block getBlockStandingOn() {
+ net.minecraft.core.BlockPos pos = this.entity.getBlockPosBelowThatAffectsMyMovement();
+ return this.entity.level().getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ }
+ // Slice end
}

View File

@@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Sun, 17 Nov 2024 09:19:41 -0600
Subject: [PATCH] Add DimensionDataStorageEvents
diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
index d16f124e0371ce943298c8d7d9bfac21e98cf885..74de7e040ebccb000aa258238ed0bc41dec3754f 100644
--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
@@ -1,12 +1,12 @@
package net.minecraft.world.level.storage;
+import ca.spottedleaf.dataconverter.minecraft.converters.custom.V3818_Commands;
import com.mojang.datafixers.DataFixer;
import com.mojang.logging.LogUtils;
+import io.papermc.paper.event.server.DimensionDataStorageSaveEvent;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
+
+import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
@@ -128,29 +128,34 @@ public class DimensionDataStorage implements AutoCloseable {
}
public CompletableFuture<?> scheduleSave() {
- Map<Path, CompoundTag> map = this.collectDirtyTagsToSave();
+ Map<String, CompoundTag> map = this.collectDirtyTagsToSave();
if (map.isEmpty()) {
return CompletableFuture.completedFuture(null);
} else {
this.pendingWriteFuture = this.pendingWriteFuture
.thenCompose(
v -> CompletableFuture.allOf(
- map.entrySet().stream().map(entry -> tryWriteAsync(entry.getKey(), entry.getValue())).toArray(CompletableFuture[]::new)
+ map.entrySet().stream().map(entry -> tryWriteAsync(entry.getKey(), this.getDataFile(entry.getKey()), entry.getValue())).toArray(CompletableFuture[]::new)
)
);
return this.pendingWriteFuture;
}
}
- private Map<Path, CompoundTag> collectDirtyTagsToSave() {
- Map<Path, CompoundTag> map = new Object2ObjectArrayMap<>();
- this.cache.forEach((id, state) -> state.filter(SavedData::isDirty).ifPresent(state2 -> map.put(this.getDataFile(id), state2.save(this.registries))));
+ private Map<String, CompoundTag> collectDirtyTagsToSave() {
+ Map<String, CompoundTag> map = new Object2ObjectArrayMap<>();
+ this.cache.forEach((id, state) -> state.filter(SavedData::isDirty).ifPresent(state2 -> map.put(id, state2.save(this.registries))));
return map;
}
- private static CompletableFuture<Void> tryWriteAsync(Path path, CompoundTag nbt) {
+ private static CompletableFuture<Void> tryWriteAsync(String id, Path path, CompoundTag nbt) {
return CompletableFuture.runAsync(() -> {
try {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ NbtIo.writeCompressed(nbt, buf);
+ DimensionDataStorageSaveEvent event = new DimensionDataStorageSaveEvent(id, buf);
+ if (!event.callEvent()) return;
+
NbtIo.writeCompressed(nbt, path);
} catch (IOException var3) {
LOGGER.error("Could not save data to {}", path.getFileName(), var3);