Merge remote-tracking branch 'upstream/main' into update

This commit is contained in:
2024-12-31 17:12:20 +01:00
172 changed files with 2994 additions and 1313 deletions

View File

@@ -239,7 +239,7 @@ index 0f346faa82b988e86834c38837f6f11bea7f31c6..771d6ed6a7c889c09efd4ff6e20298c8
if (blockState == null) {
// CraftBukkit start - remove blockstate if failed (or the same)
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index 809b3c37d3749c76c3c243cd91c593d03693e9b3..860d1c9729c4ee97ec6f40f7aa969829070b27c0 100644
index c82780db7fe5b1557a7802d3111f38099be55ac1..d63d745a0220963a297cfedf1e8983aeb471a045 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@@ -261,7 +261,7 @@ index 809b3c37d3749c76c3c243cd91c593d03693e9b3..860d1c9729c4ee97ec6f40f7aa969829
}
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 51a136cf015de730ca0d1b48cf618a2ed69ea89f..96b0342ab7b922aa16d07b6c00542e6cb66c974a 100644
index ce781ba2c8b3f9f051201d3809a9cb041036f93a..cad71ac79fc52225a192aa5c5d07b13c831fc2c1 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -109,7 +109,7 @@ public class LevelChunk extends ChunkAccess {
@@ -270,11 +270,11 @@ index 51a136cf015de730ca0d1b48cf618a2ed69ea89f..96b0342ab7b922aa16d07b6c00542e6c
) {
- super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
+ super(pos, data, level, net.minecraft.server.MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); // Paper - Anti-Xray - The world isn't ready yet, use server singleton for registry
this.level = (net.minecraft.server.level.ServerLevel) level; // CraftBukkit - type
this.level = (ServerLevel) level; // CraftBukkit - type
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
index baa9f3e2e6e45c250930658e82bad70a3a292b05..fc21c3268c4b4fda2933d71f0913db28e3796653 100644
index b3d600b0d6deaf44f232dfc86e1456c867e1c07f..a7fabde0f32f09d7f7bed65576ce469f069a21fa 100644
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -38,9 +38,15 @@ public class LevelChunkSection {
@@ -550,7 +550,7 @@ index bfbb1a2bb4abbb369a24f2f01439e9ea3e16794b..8d6ed8be4d93f7d4e6ea80c351020d88
int getSerializedSize();
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 37437a86d74291fab1de9495008aafb15dfadce0..cf6e2053d81f7b0f8c8e58b9c0fad3285ebc047d 100644
index c7c87bc8df86ceeef3e15a8f23fc252d4cee1984..3b55e7fb27d680204b8621666ae9200870def3eb 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -94,7 +94,7 @@ public record SerializableChunkData(
@@ -607,9 +607,9 @@ index 37437a86d74291fab1de9495008aafb15dfadce0..cf6e2053d81f7b0f8c8e58b9c0fad328
@@ -414,7 +418,7 @@ public record SerializableChunkData(
// CraftBukkit start - read/write
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> iregistry) {
- return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
+ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> biomeRegistry) {
- return PalettedContainer.codecRW(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
+ return PalettedContainer.codecRW(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
}
// CraftBukkit end

View File

@@ -30633,10 +30633,10 @@ index 0d65bf24f515b80701150fdc430f324a533cb478..b92a3da5c325e69f5601416d4205fb33
Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> atomicReference.get().runServer(), "Server thread");
thread.setUncaughtExceptionHandler((thread1, exception) -> LOGGER.error("Uncaught exception in server thread", exception));
diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d5946cf2501 100644
index 1a0455936cbca2d3812866b332e00a3aaacae8bd..5ba7f724687401c9ea1756a6491498e03548a257 100644
--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -85,7 +85,7 @@ public class ChunkStorage implements AutoCloseable {
@@ -54,7 +54,7 @@ public class ChunkStorage implements AutoCloseable {
} else {
try {
// CraftBukkit start
@@ -30644,8 +30644,8 @@ index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d59
+ if (false && version < 1466) { // Paper - no longer needed, data converter system / DFU handles it now
CompoundTag level = chunkData.getCompound("Level");
if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
net.minecraft.server.level.ServerChunkCache cps = (generatoraccess == null) ? null : ((net.minecraft.server.level.ServerLevel) generatoraccess).getChunkSource();
@@ -96,7 +96,7 @@ public class ChunkStorage implements AutoCloseable {
// Light is purged updating to 1.14+. We need to set light populated to true so the converter recognizes the chunk as being "full"
@@ -63,7 +63,7 @@ public class ChunkStorage implements AutoCloseable {
}
// CraftBukkit end
if (version < 1493) {
@@ -30654,7 +30654,7 @@ index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d59
if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) {
LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage);
chunkData = legacyStructureHandler.updateFromLegacy(chunkData);
@@ -113,7 +113,7 @@ public class ChunkStorage implements AutoCloseable {
@@ -80,7 +80,7 @@ public class ChunkStorage implements AutoCloseable {
// Spigot end
injectDatafixingContext(chunkData, levelKey, chunkGeneratorKey);
@@ -30741,7 +30741,7 @@ index feb4cd21e26598509dc140028496a6f4254c0680..de43e54698125ce9f319d4889dd49f70
}
diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java
index 6c9640f5432e9110e7811b6db246d268c6243feb..45f2800c4862a726490048576fca8e1f24252676 100644
index d68c6c978ac0f154ffe541fd204bec03f033ae96..c44110b123ba5912af18faf0065e9ded780da9b7 100644
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
@@ -115,7 +115,7 @@ public class PlayerDataStorage {

View File

@@ -23508,10 +23508,10 @@ index 3d3eec1db91cb47395f40c4f47aa77164ad42175..216f97207dac88cc1dc3df59c6ee8a62
+ // Paper end - optimise collisions
}
diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java
index 47b1fafd91b39e73c4e9134b0b8048000fba108a..76994c1491221c06cca5405ba239e6ff642b19ed 100644
index 452c358c2cfa0c39e0b09853cd4a9a12c6ced65d..5f752603aa5611ce9d3dd44cc5b70c27ac46a86e 100644
--- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java
@@ -50,6 +50,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
@@ -51,6 +51,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
return this.getTags();
}
@@ -23531,10 +23531,10 @@ index 47b1fafd91b39e73c4e9134b0b8048000fba108a..76994c1491221c06cca5405ba239e6ff
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle registryLifecycle) {
this(key, registryLifecycle, false);
}
@@ -114,6 +127,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
this.toId.put(value, size);
@@ -116,6 +129,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
this.temporaryUnfrozenMap.put(key.location(), value); // Paper - support pre-filling in registry mod API
+ this.injectFluidRegister(key, value); // Paper - fluid method optimisations
return reference;
}
@@ -26719,7 +26719,7 @@ index 2f49dbc919f7f5eea9abce6106723c72f5ae45fb..87d4291a3944f706a694536da6de0f28
}
}
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 70f6d068b3f3665b282d9750310c883839120ab2..870b9efd445ddadb3725e88351555ad986ce7c72 100644
index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7dfda69f28 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -91,6 +91,11 @@ public class ServerEntity {
@@ -27496,7 +27496,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index ff5889f8fed0707a6654d9d21862e32e2ebc866d..e61fe83479f095e8addbd3e8f1d5179c998ae1eb 100644
index 097ec55166b9e9269142be58992c29687122fe28..aeabb79512aabd7a9e8af1be72e1745f0e7eefe4 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team;
@@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab6814aef9ee 100644
index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640c88fc282 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -28725,7 +28725,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
}
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2664,23 +2812,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -2662,23 +2810,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean isInWall() {
@@ -28849,7 +28849,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
}
public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4104,15 +4339,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4102,15 +4337,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public Iterable<Entity> getIndirectPassengers() {
@@ -28875,7 +28875,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
}
public int countPlayerPassengers() {
@@ -4250,77 +4487,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4248,77 +4485,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(partialTick, this.yRotO, this.yRot);
}
@@ -29066,7 +29066,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4473,6 +4769,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4471,6 +4767,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPosRaw(x, y, z, false);
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -29082,7 +29082,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
if (!checkPosition(this, x, y, z)) {
return;
}
@@ -4603,6 +4908,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4601,6 +4906,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override
public final void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) {
@@ -29095,7 +29095,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause);
// CraftBukkit end
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
@@ -4614,7 +4925,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4612,7 +4923,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding();
}
@@ -29104,7 +29104,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason);
// Paper start - Folia schedulers
@@ -4648,7 +4959,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4646,7 +4957,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean shouldBeSaved() {
return (this.removalReason == null || this.removalReason.shouldSave())
&& !this.isPassenger()
@@ -30907,7 +30907,7 @@ index 8d98cba3830dc5dfb5cae9a6f5fedfffee0d2cd8..73962e79a0f3d892e3155443a1b84508
public interface NoiseBiomeSource {
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
index 91d7d250f7c3de8a71aef26e23c12764b06b322b..0d36b1ac7d54283af71f2494accded11c059dba5 100644
index a4eb9a10b6c1351c7341bc031bb9f819e17ff1e5..976de81d65b6494cdad20f4ec5125fceec86f951 100644
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -259,7 +259,7 @@ public class Block extends BlockBehaviour implements ItemLike {
@@ -30920,7 +30920,7 @@ index 91d7d250f7c3de8a71aef26e23c12764b06b322b..0d36b1ac7d54283af71f2494accded11
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 25e49a24cedfa8ad04245d59fcac3231bcd62103..061d94a35d957ca72a01bae959d38aab59b1a64d 100644
index fa816de449a6077c05fee76835a1625f5b2008ac..5473b4006f7e0266ea11a7b05cef78a113c30d97 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -416,7 +416,7 @@ public abstract class BlockBehaviour implements FeatureElement {
@@ -31399,7 +31399,7 @@ index 92350434746f06bbf4a161c6bc42602de7b45220..1c24f38d21da1be9740512981f219924
public Property.Value<T> value(T value) {
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf0a5998c6 100644
index d63d745a0220963a297cfedf1e8983aeb471a045..6d565b52552534ce9cacfc35ad1bf4adcb69eac3 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -57,7 +57,7 @@ import net.minecraft.world.ticks.SavedTick;
@@ -31537,8 +31537,8 @@ index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf
+ // Paper end - get block chunk optimisation
}
// CraftBukkit start
public void setBiome(int i, int j, int k, Holder<Biome> biome) {
@@ -507,12 +572,12 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
public void setBiome(int x, int y, int z, Holder<Biome> biome) {
@@ -503,12 +568,12 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
}
public void initializeLightSources() {
@@ -31554,7 +31554,7 @@ index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf
public record PackedTicks(List<SavedTick<Block>> blocks, List<SavedTick<Fluid>> fluids) {
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
index 65117a9cb9d1b8684cae8d36ea3b8e2050fb928c..a9d65e28b849c9660a14ef7c16ed17bd5182bd7e 100644
index b320519578f7e2c52b2116afb247e071b322696e..6ed51cf42b5864194d671b5b56f5b9bdf0291dc0 100644
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -116,7 +116,7 @@ public abstract class ChunkGenerator {
@@ -31717,7 +31717,7 @@ index e7c0f4da8508fbca467326f475668d66454d7b77..41856c98d97e7eb0782f8e441b9a269a
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 96b0342ab7b922aa16d07b6c00542e6cb66c974a..c1ae7755e8d6fa8501d2210dab7605d993c55722 100644
index cad71ac79fc52225a192aa5c5d07b13c831fc2c1..761fdcd4a4e18f45547afd8edff44f61c6eeacb4 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -52,7 +52,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
@@ -31896,7 +31896,7 @@ index 96b0342ab7b922aa16d07b6c00542e6cb66c974a..c1ae7755e8d6fa8501d2210dab7605d9
@Nullable
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
index fc21c3268c4b4fda2933d71f0913db28e3796653..2ff691bcd32f587e8add2d8eda7e7339ccbde6e8 100644
index a7fabde0f32f09d7f7bed65576ce469f069a21fa..412e7b1cf8c24f0ddf6d174967bedad576f10aba 100644
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -13,7 +13,7 @@ import net.minecraft.world.level.block.Blocks;
@@ -32627,7 +32627,7 @@ index 7a4d299d2ce36982204e30de9278ddfd5b37c3df..b8348976e80578d9eff64eea68c04c60
private final ChunkStatus status;
@Nullable
diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1c3b75ba6 100644
index 5ba7f724687401c9ea1756a6491498e03548a257..64343a3f6e6009eed5b392482ec053be8e00ee63 100644
--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -22,20 +22,30 @@ import net.minecraft.world.level.chunk.ChunkGenerator;
@@ -32665,7 +32665,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
}
// CraftBukkit start
@@ -99,7 +109,9 @@ public class ChunkStorage implements AutoCloseable {
@@ -66,7 +76,9 @@ public class ChunkStorage implements AutoCloseable {
chunkData = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, chunkData, version, 1493); // Paper - replace chunk converter
if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) {
LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage);
@@ -32675,7 +32675,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
}
}
@@ -163,7 +175,13 @@ public class ChunkStorage implements AutoCloseable {
@@ -130,7 +142,13 @@ public class ChunkStorage implements AutoCloseable {
}
public CompletableFuture<Optional<CompoundTag>> read(ChunkPos chunkPos) {
@@ -32690,7 +32690,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
}
public CompletableFuture<Void> write(ChunkPos pos, Supplier<CompoundTag> tagSupplier) {
@@ -179,29 +197,54 @@ public class ChunkStorage implements AutoCloseable {
@@ -146,29 +164,54 @@ public class ChunkStorage implements AutoCloseable {
};
// Paper end - guard against possible chunk pos desync
this.handleLegacyStructureIndex(pos);
@@ -32784,7 +32784,7 @@ index 889e188e920edb284f04b264bcdd06146f54a4cb..2199a9e2a0141c646d108f2687a27f1d
private final Long2ObjectLinkedOpenHashMap<CompletableFuture<BitSet>> regionCacheForBlender = new Long2ObjectLinkedOpenHashMap<>();
private static final int REGION_CACHE_SIZE = 1024;
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
index 783a2d80f6197dd0af0dc81909f0353a8ea2ecf4..7da388ffab162c282cad0f297bb7304f3c2abbaf 100644
index 4eb07097986aac67421dd8e6a17cc5436da91187..984db72272d552c7210bd6f437ea88694ddd2828 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler;
@@ -33324,7 +33324,7 @@ index 7dc1ffffd9d0fec54dbc254c154ee85ee750174d..778bd73a938c94ecb85ca0f8b686ff4e
record PackedChunk<T>(Int2ObjectMap<T> sectionsByY, boolean versionChanged) {
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index cf6e2053d81f7b0f8c8e58b9c0fad3285ebc047d..70a9972252576e039ac126f6057a6ed66b80cdfc 100644
index 3b55e7fb27d680204b8621666ae9200870def3eb..879d411775a2fece1d8a970300cb3a550baa6305 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -148,7 +148,7 @@ public record SerializableChunkData(
@@ -33700,10 +33700,10 @@ index 342c83309b19c64d86e0dd97c1756c96be52772b..423779a2b690f387a4f0bd07b97b50e0
}
}
diff --git a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
index 29d9f6e54421c539e9e55ab9f51b4c872da3fbb8..d77016287f5f9a0964d56f05d2d5256ef2e6e86c 100644
index 6d61739574155f89511b9adcaf1174841bdc7da7..65728ef17e63d71833677fdcbd5bb90794b4822b 100644
--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -78,7 +78,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
@@ -77,7 +77,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
return CompletableFuture.supplyAsync(() -> {
this.doCreateBiomes(blender, randomState, structureManager, chunk);
return chunk;
@@ -33712,7 +33712,7 @@ index 29d9f6e54421c539e9e55ab9f51b4c872da3fbb8..d77016287f5f9a0964d56f05d2d5256e
}
private void doCreateBiomes(Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) {
@@ -318,7 +318,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
@@ -317,7 +317,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
}
return var20;
@@ -34002,7 +34002,7 @@ index ca23af013967b50420ebee178878ea79333de53b..d41b9266625ca6c5e32c5126f35a1f77
public int getLightSectionCount() {
diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java
index 130ef38a50f1df1faa26b433b0c605a4507f71af..f6daca279788c3d983a9ee213df85d5d93fc6eed 100644
index 86fd2b831f42bdb5bd045e44b26489d5a8697dd9..e30499bdcd6600e5c9d4a755c1182fb6dff3735f 100644
--- a/net/minecraft/world/level/material/FlowingFluid.java
+++ b/net/minecraft/world/level/material/FlowingFluid.java
@@ -45,6 +45,48 @@ public abstract class FlowingFluid extends Fluid {

View File

@@ -60,7 +60,7 @@ index 3dff97f13586be3b52bbe786852c185f6753a019..ff6503bf8eb88d1264c3d848a89d0255
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f7117281649b7a 100644
index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b75c7d7e59 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -90,6 +90,13 @@ public class ServerEntity {
@@ -77,7 +77,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
public void sendChanges() {
// Paper start - optimise collisions
if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) {
@@ -130,7 +137,7 @@ public class ServerEntity {
@@ -131,7 +138,7 @@ public class ServerEntity {
this.sendDirtyEntityData();
}
@@ -86,7 +86,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
byte b = Mth.packDegrees(this.entity.getYRot());
byte b1 = Mth.packDegrees(this.entity.getXRot());
boolean flag = Math.abs(b - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1;
@@ -165,7 +172,7 @@ public class ServerEntity {
@@ -166,7 +173,7 @@ public class ServerEntity {
long l1 = this.positionCodec.encodeY(vec3);
long l2 = this.positionCodec.encodeZ(vec3);
boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L;
@@ -95,7 +95,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
@@ -230,6 +237,7 @@ public class ServerEntity {
@@ -231,6 +238,7 @@ public class ServerEntity {
}
this.entity.hasImpulse = false;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java
@@ -33,11 +_,11 @@
@@ -33,17 +_,18 @@
public class MappedRegistry<T> implements WritableRegistry<T> {
private final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
@@ -17,6 +17,29 @@
private Lifecycle registryLifecycle;
private final Map<TagKey<T>, HolderSet.Named<T>> frozenTags = new IdentityHashMap<>();
MappedRegistry.TagSet<T> allTags = MappedRegistry.TagSet.unbound();
private boolean frozen;
@Nullable
private Map<T, Holder.Reference<T>> unregisteredIntrusiveHolders;
+ public final Map<ResourceLocation, T> temporaryUnfrozenMap = new HashMap<>(); // Paper - support pre-filling in registry mod API
@Override
public Stream<HolderSet.Named<T>> listTags() {
@@ -114,6 +_,7 @@
this.toId.put(value, size);
this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
+ this.temporaryUnfrozenMap.put(key.location(), value); // Paper - support pre-filling in registry mod API
return reference;
}
}
@@ -275,6 +_,7 @@
return this;
} else {
this.frozen = true;
+ this.temporaryUnfrozenMap.clear(); // Paper - support pre-filling in registry mod API
this.byValue.forEach((object, reference) -> reference.bindValue((T)object));
List<ResourceLocation> list = this.byKey
.entrySet()
@@ -509,4 +_,13 @@
Stream<HolderSet.Named<T>> getTags();

View File

@@ -26,7 +26,7 @@
ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
@@ -328,7 +_,14 @@
@@ -328,16 +_,34 @@
}
public static void bootStrap() {
@@ -41,6 +41,26 @@
freeze();
validate(REGISTRY);
}
private static void createContents() {
+ // Paper start - class-load org.bukkit.Registry
+ // we have to class-load Registry here to create all the CraftRegistry instances
+ // that will be created when Registry is class-loaded before RegistryAccess#getRegistry
+ // would try to create them in lockReferenceHolder
+ try {
+ Class.forName(org.bukkit.Registry.class.getName());
+ } catch (final ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ }
+ // Paper end - class-load org.bukkit.Registry
LOADERS.forEach((resourceLocation, supplier) -> {
if (supplier.get() == null) {
LOGGER.error("Unable to bootstrap registry '{}'", resourceLocation);
}
+ io.papermc.paper.registry.PaperRegistryAccess.instance().lockReferenceHolders(ResourceKey.createRegistryKey(resourceLocation)); // Paper - lock reference holder creation
});
}
@@ -346,6 +_,7 @@
for (Registry<?> registry : REGISTRY) {

View File

@@ -34,11 +34,12 @@
} catch (Exception var14) {
loadingErrors.put(
resourceKey,
@@ -283,7 +_,8 @@
@@ -283,7 +_,9 @@
}
}
- TagLoader.loadTagsForRegistry(resourceManager, registry);
+ io.papermc.paper.registry.PaperRegistryAccess.instance().lockReferenceHolders(registry.key()); // Paper - lock reference holders
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), conversions); // Paper - run pre-freeze listeners
+ TagLoader.loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - tag lifecycle - add cause
}

View File

@@ -1193,15 +1193,18 @@
return ReloadableServerResources.loadResources(
closeableResourceManager,
this.registries,
@@ -1520,6 +_,7 @@
@@ -1520,20 +_,39 @@
)
.thenAcceptAsync(
reloadableResources -> {
+ io.papermc.paper.command.brigadier.PaperBrigadier.moveBukkitCommands(this.resources.managers().getCommands(), reloadableResources.managers().commands); // Paper
this.resources.close();
this.resources = reloadableResources;
this.packRepository.setSelected(selectedIds);
@@ -1529,11 +_,29 @@
- this.packRepository.setSelected(selectedIds);
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
);
this.worldData.setDataConfiguration(worldDataConfiguration);
this.resources.managers.updateStaticRegistryTags();
this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures());
@@ -1232,6 +1235,33 @@
},
this
);
@@ -1550,7 +_,7 @@
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
- packRepository.reload();
+ packRepository.reload(true); // Paper - will load resource packs
if (safeMode) {
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
} else {
@@ -1605,7 +_,7 @@
private static WorldDataConfiguration configureRepositoryWithSelection(
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
) {
- packRepository.setSelected(selectedPacks);
+ packRepository.setSelected(selectedPacks, true); // Paper - add pendingReload flag to determine required pack loading - before the initial server load
enableForcedFeaturePacks(packRepository, enabledFeatures);
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
@@ -1637,7 +_,7 @@
}
}
- packRepository.setSelected(set);
+ packRepository.setSelected(set, true); // Paper - add pendingReload flag to determine required pack loading - before the initial server start
}
}
@@ -1652,10 +_,11 @@
if (this.isEnforceWhitelist()) {
PlayerList playerList = commandSource.getServer().getPlayerList();

View File

@@ -9,6 +9,15 @@
LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
return null;
@@ -24,7 +_,7 @@
}
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
- packRepository.reload();
+ packRepository.reload(true); // Paper - will perform a full reload
Collection<String> list = Lists.newArrayList(selectedIds);
Collection<String> disabled = worldData.getDataConfiguration().dataPacks().getDisabled();
@@ -36,6 +_,16 @@
return list;

View File

@@ -29,7 +29,7 @@
removedPassengers(passengers, this.lastPassengers)
.forEach(
removedPassenger -> {
@@ -102,10 +_,10 @@
@@ -102,13 +_,14 @@
this.lastPassengers = passengers;
}
@@ -42,7 +42,12 @@
+ MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level);
if (savedData != null) {
for (ServerPlayer serverPlayer : this.level.players()) {
- for (ServerPlayer serverPlayer : this.level.players()) {
+ for (final net.minecraft.server.network.ServerPlayerConnection connection : this.trackedPlayers) { // Paper
+ final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
savedData.tickCarriedBy(serverPlayer, item);
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
if (updatePacket != null) {
@@ -141,7 +_,13 @@
} else {
this.teleportDelay++;

View File

@@ -1342,17 +1342,18 @@
}
public SectionPos getLastSectionPos() {
@@ -1930,21 +_,54 @@
@@ -1930,21 +_,55 @@
}
@Override
- public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) {
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent) { // CraftBukkit - SPIGOT-2942: Add boolean to call event
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) { // Paper start - Extend HumanEntity#dropItem API
ItemEntity itemEntity = this.createItemStackToDrop(droppedItem, dropAround, traceItem);
if (itemEntity == null) {
return null;
} else {
+ // CraftBukkit start - fire PlayerDropItemEvent
+ if (entityOperation != null) entityOperation.accept((org.bukkit.entity.Item) itemEntity.getBukkitEntity());
+ if (callEvent) {
+ org.bukkit.entity.Player player = this.getBukkitEntity();
+ org.bukkit.entity.Item drop = (org.bukkit.entity.Item) itemEntity.getBukkitEntity();

View File

@@ -95,7 +95,7 @@
}
}
@@ -88,30 +_,117 @@
@@ -88,30 +_,119 @@
public void handlePong(ServerboundPongPacket packet) {
}
@@ -208,15 +208,16 @@
Profiler.get().push("keepAlive");
long millis = Util.getMillis();
- if (!this.isSingleplayerOwner() && millis - this.keepAliveTime >= 15000L) {
- if (this.keepAlivePending) {
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE);
+ // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings
+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2
+ final long elapsedTime = millis - this.keepAliveTime;
+ if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
+ if (this.keepAlivePending && !this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
if (this.keepAlivePending) {
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE);
+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
+ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
+ }
+ // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings
+ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
} else if (this.checkIfClosed(millis)) {
this.keepAlivePending = true;
this.keepAliveTime = millis;

View File

@@ -0,0 +1,76 @@
--- a/net/minecraft/server/packs/repository/PackRepository.java
+++ b/net/minecraft/server/packs/repository/PackRepository.java
@@ -21,9 +_,13 @@
private final Set<RepositorySource> sources;
private Map<String, Pack> available = ImmutableMap.of();
private List<Pack> selected = ImmutableList.of();
+ private final net.minecraft.world.level.validation.DirectoryValidator validator; // Paper - add validator
- public PackRepository(RepositorySource... sources) {
- this.sources = ImmutableSet.copyOf(sources);
+ // Paper start - add validator
+ public PackRepository(net.minecraft.world.level.validation.DirectoryValidator validator, RepositorySource... providers) {
+ this.validator = validator;
+ // Paper end - add validator
+ this.sources = ImmutableSet.copyOf(providers);
}
public static String displayPackList(Collection<Pack> packs) {
@@ -31,9 +_,14 @@
}
public void reload() {
+ // Paper start - add pendingReload flag to determine required pack loading
+ this.reload(false);
+ }
+ public void reload(final boolean pendingReload) {
+ // Paper end - add pendingReload flag to determine required pack loading
List<String> list = this.selected.stream().map(Pack::getId).collect(ImmutableList.toImmutableList());
this.available = this.discoverAvailable();
- this.selected = this.rebuildSelected(list);
+ this.selected = this.rebuildSelected(list, pendingReload); // Paper - add pendingReload flag to determine required pack loading
}
private Map<String, Pack> discoverAvailable() {
@@ -43,16 +_,23 @@
repositorySource.loadPacks(pack -> map.put(pack.getId(), pack));
}
- return ImmutableMap.copyOf(map);
+ // Paper start - custom plugin-loaded datapacks
+ final io.papermc.paper.datapack.PaperDatapackRegistrar registrar = new io.papermc.paper.datapack.PaperDatapackRegistrar(this.validator, map);
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callStaticRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.DATAPACK_DISCOVERY,
+ registrar,
+ io.papermc.paper.plugin.bootstrap.BootstrapContext.class
+ );
+ return ImmutableMap.copyOf(registrar.discoveredPacks);
+ // Paper end - custom plugin-loaded datapacks
}
public boolean isAbleToClearAnyPack() {
- List<Pack> list = this.rebuildSelected(List.of());
+ List<Pack> list = this.rebuildSelected(List.of(), false); // Paper - add pendingReload flag to determine required pack loading
return !this.selected.equals(list);
}
- public void setSelected(Collection<String> ids) {
- this.selected = this.rebuildSelected(ids);
+ public void setSelected(Collection<String> ids, final boolean pendingReload) { // Paper - add pendingReload flag to determine required pack loading
+ this.selected = this.rebuildSelected(ids, pendingReload); // Paper - add pendingReload flag to determine required pack loading
}
public boolean addPack(String id) {
@@ -79,11 +_,11 @@
}
}
- private List<Pack> rebuildSelected(Collection<String> ids) {
+ private List<Pack> rebuildSelected(Collection<String> ids, boolean pendingReload) { // Paper - add pendingReload flag to determine required pack loading
List<Pack> list = this.getAvailablePacks(ids).collect(Util.toMutableList());
for (Pack pack : this.available.values()) {
- if (pack.isRequired() && !list.contains(pack)) {
+ if (pack.isRequired() && !list.contains(pack) && pendingReload) { // Paper - add pendingReload flag to determine required pack loading
pack.getDefaultPosition().insert(list, pack, Pack::selectionConfig, false);
}
}

View File

@@ -9,7 +9,7 @@
.applyDevelopmentConfig()
.pushJarResources()
.build(VANILLA_PACK_INFO);
@@ -68,7 +_,18 @@
@@ -68,15 +_,26 @@
@Nullable
@Override
protected Pack createBuiltinPack(String id, Pack.ResourcesSupplier resources, Component title) {
@@ -29,3 +29,13 @@
}
public static PackRepository createPackRepository(Path folder, DirectoryValidator validator) {
- return new PackRepository(new ServerPacksSource(validator), new FolderRepositorySource(folder, PackType.SERVER_DATA, PackSource.WORLD, validator));
+ return new PackRepository(validator, new ServerPacksSource(validator), new FolderRepositorySource(folder, PackType.SERVER_DATA, PackSource.WORLD, validator)); // Paper - add validator
}
public static PackRepository createVanillaTrustedRepository() {
- return new PackRepository(new ServerPacksSource(new DirectoryValidator(path -> true)));
+ return new PackRepository(new DirectoryValidator(path -> true), new ServerPacksSource(new DirectoryValidator(path -> true))); // Paper - add validator
}
public static PackRepository createPackRepository(LevelStorageSource.LevelStorageAccess level) {

View File

@@ -706,52 +706,44 @@
public void awardKillScore(Entity entity, DamageSource damageSource) {
if (entity instanceof ServerPlayer) {
@@ -1752,34 +_,70 @@
@@ -1752,15 +_,22 @@
}
public boolean saveAsPassenger(CompoundTag compound) {
- if (this.removalReason != null && !this.removalReason.shouldSave()) {
+ // CraftBukkit start - allow excluding certain data when saving
+ return this.saveAsPassenger(compound, true);
+ // Paper start - Raw entity serialization API
+ return this.saveAsPassenger(compound, true, false, false);
+ }
+
+ public boolean saveAsPassenger(CompoundTag compound, boolean includeAll) {
+ public boolean saveAsPassenger(CompoundTag compound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization) {
+ // Paper end - Raw entity serialization API
+ // CraftBukkit end
if (this.removalReason != null && !this.removalReason.shouldSave()) {
+ if (this.removalReason != null && !this.removalReason.shouldSave() && !forceSerialization) { // Paper - Raw entity serialization API
return false;
} else {
String encodeId = this.getEncodeId();
- String encodeId = this.getEncodeId();
- if (encodeId == null) {
+ if (!this.persist || encodeId == null) { // CraftBukkit - persist flag
+ String encodeId = this.getEncodeId(includeNonSaveable); // Paper - Raw entity serialization API
+ if ((!this.persist && !forceSerialization) || encodeId == null) { // CraftBukkit - persist flag // Paper - Raw entity serialization API
return false;
} else {
compound.putString("id", encodeId);
- this.saveWithoutId(compound);
+ this.saveWithoutId(compound, includeAll); // CraftBukkit - pass on includeAll
+ this.saveWithoutId(compound, includeAll, includeNonSaveable, forceSerialization); // CraftBukkit - pass on includeAll // Paper - Raw entity serialization API
return true;
}
}
}
+
+ // Paper start - Entity serialization api
+ public boolean serializeEntity(CompoundTag compound) {
+ List<Entity> pass = new java.util.ArrayList<>(this.getPassengers());
+ this.passengers = ImmutableList.of();
+ boolean result = save(compound);
+ this.passengers = ImmutableList.copyOf(pass);
+ return result;
+ }
+ // Paper end - Entity serialization api
public boolean save(CompoundTag compound) {
return !this.isPassenger() && this.saveAsPassenger(compound);
@@ -1771,15 +_,37 @@
}
public CompoundTag saveWithoutId(CompoundTag compound) {
+ // CraftBukkit start - allow excluding certain data when saving
+ return this.saveWithoutId(compound, true);
+ // Paper start - Raw entity serialization API
+ return this.saveWithoutId(compound, true, false, false);
+ }
+
+ public CompoundTag saveWithoutId(CompoundTag compound, boolean includeAll) {
+ public CompoundTag saveWithoutId(CompoundTag compound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization) {
+ // Paper end - Raw entity serialization API
+ // CraftBukkit end
try {
- if (this.vehicle != null) {
@@ -827,7 +819,7 @@
for (Entity entity : this.getPassengers()) {
CompoundTag compoundTag = new CompoundTag();
- if (entity.saveAsPassenger(compoundTag)) {
+ if (entity.saveAsPassenger(compoundTag, includeAll)) { // CraftBukkit - pass on includeAll
+ if (entity.saveAsPassenger(compoundTag, includeAll, includeNonSaveable, forceSerialization)) { // CraftBukkit - pass on includeAll // Paper - Raw entity serialization API
listTag.add(compoundTag);
}
}
@@ -935,19 +927,30 @@
} catch (Throwable var17) {
CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT");
CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded");
@@ -1949,6 +_,12 @@
return type.canSerialize() && key != null ? key.toString() : null;
}
@@ -1944,10 +_,21 @@
@Nullable
public final String getEncodeId() {
+ // Paper start - Raw entity serialization API
+ return getEncodeId(false);
+ }
+ public final @Nullable String getEncodeId(boolean includeNonSaveable) {
+ // Paper end - Raw entity serialization API
EntityType<?> type = this.getType();
ResourceLocation key = EntityType.getKey(type);
- return type.canSerialize() && key != null ? key.toString() : null;
- }
+ return (type.canSerialize() || includeNonSaveable) && key != null ? key.toString() : null; // Paper - Raw entity serialization API
+ }
+
+ // CraftBukkit start - allow excluding certain data when saving
+ protected void addAdditionalSaveData(CompoundTag tag, boolean includeAll) {
+ this.addAdditionalSaveData(tag);
+ }
+ // CraftBukkit end
+
protected abstract void readAdditionalSaveData(CompoundTag tag);
protected abstract void addAdditionalSaveData(CompoundTag tag);
@@ -1990,11 +_,61 @@
@Nullable

View File

@@ -48,7 +48,12 @@
List<Entity> entities = this.level()
.getEntities(
this,
@@ -172,22 +_,30 @@
@@ -168,26 +_,34 @@
}
private void spawnFire(int extraIgnitions) {
- if (!this.visualOnly && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
+ if (!this.visualOnly && !this.isEffect && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { // Paper - prevent any fire if only effect
BlockPos blockPos = this.blockPosition();
BlockState state = BaseFireBlock.getState(this.level(), blockPos);
if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) {

View File

@@ -112,16 +112,21 @@
this.removeEntitiesOnShoulder();
}
}
@@ -717,6 +_,13 @@
@@ -717,6 +_,18 @@
@Nullable
public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) {
+ // CraftBukkit start - SPIGOT-2942: Add boolean to call event
+ return this.drop(droppedItem, dropAround, includeThrowerName, true);
+ return this.drop(droppedItem, dropAround, includeThrowerName, true, null);
+ }
+
+ @Nullable
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent) {
+ return this.drop(droppedItem, dropAround, includeThrowerName, callEvent, null);
+ }
+
+ @Nullable
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) {
+ // CraftBukkit end
if (!droppedItem.isEmpty() && this.level().isClientSide) {
this.swing(InteractionHand.MAIN_HAND);

View File

@@ -34,9 +34,9 @@
- BlockState blockState = this.getBlockState(traversePos);
- FluidState fluidState = this.getFluidState(traversePos);
+ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
+ default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos) {
+ // Paper start - Add predicate for blocks when raytracing
+ return clip(raytrace1, blockposition, null);
+ return clip(traverseContext, traversePos, null);
+ }
+
+ default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {

View File

@@ -5,11 +5,11 @@
}
- if (!canSetSpawn(level)) {
+ if (false && !canSetSpawn(level)) { // CraftBukkit - moved world and biome check into EntityHuman
+ if (false && !canSetSpawn(level)) { // CraftBukkit - moved world and biome check into Player
level.removeBlock(pos, false);
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
if (level.getBlockState(blockPos).is(this)) {
@@ -103,22 +_,62 @@
@@ -103,22 +_,56 @@
level.explode(null, level.damageSources().badRespawnPointExplosion(center), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK);
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
@@ -21,20 +21,20 @@
return InteractionResult.SUCCESS_SERVER;
} else {
+ // CraftBukkit start
+ BlockState finaliblockdata = state;
+ BlockPos finalblockposition = pos;
+ final BlockState finalBlockState = state;
+ final BlockPos finalBlockPos = pos;
+ // CraftBukkit end
player.startSleepInBed(pos).ifLeft(bedSleepingProblem -> {
+ // Paper start - PlayerBedFailEnterEvent
+ if (bedSleepingProblem != null) {
+ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.values()[bedSleepingProblem.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(level, finalblockposition), !level.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(bedSleepingProblem.getMessage()));
+ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.values()[bedSleepingProblem.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(level, finalBlockPos), !level.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(bedSleepingProblem.getMessage()));
+ if (!event.callEvent()) {
+ return;
+ }
+ // Paper end - PlayerBedFailEnterEvent
+ // CraftBukkit start - handling bed explosion from below here
+ if (event.getWillExplode()) { // Paper - PlayerBedFailEnterEvent
+ this.explodeBed(finaliblockdata, level, finalblockposition);
+ this.explodeBed(finalBlockState, level, finalBlockPos);
+ } else
+ // CraftBukkit end
if (bedSleepingProblem.getMessage() != null) {
@@ -49,24 +49,18 @@
}
}
+ // CraftBukkit start
+ private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) {
+ {
+ {
+ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition).getState(); // CraftBukkit - capture BlockState before remove block
+ world.removeBlock(blockposition, false);
+ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite());
+ // CraftBukkit start - Copied from the above method
+ private InteractionResult explodeBed(BlockState state, Level level, BlockPos pos) {
+ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos).getState(); // CraftBukkit - capture BlockState before remove block
+ level.removeBlock(pos, false);
+ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
+ if (level.getBlockState(blockPos).is(this)) {
+ level.removeBlock(blockPos, false);
+ }
+
+ if (world.getBlockState(blockposition1).getBlock() == this) {
+ world.removeBlock(blockposition1, false);
+ }
+
+ Vec3 vec3d = blockposition.getCenter();
+
+ world.explode(null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ return InteractionResult.SUCCESS;
+ }
+ }
+ Vec3 center = pos.getCenter();
+ level.explode(null, level.damageSources().badRespawnPointExplosion(center, blockState), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ return InteractionResult.SUCCESS_SERVER;
+ }
+ // CraftBukkit end
+

View File

@@ -19,8 +19,8 @@
- this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, null);
+ // CraftBukkit start - tilt dripleaf
+ org.bukkit.event.Cancellable cancellable;
+ if (entity instanceof net.minecraft.world.entity.player.Player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((net.minecraft.world.entity.player.Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);

View File

@@ -133,7 +133,7 @@
+ return 0; // CraftBukkit
+ }
+ // CraftBukkit start
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
+ return 0;
+ }
+ // CraftBukkit end

View File

@@ -1,13 +1,5 @@
--- a/net/minecraft/world/level/block/BushBlock.java
+++ b/net/minecraft/world/level/block/BushBlock.java
@@ -6,6 +_,7 @@
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.ScheduledTickAccess;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -35,9 +_,15 @@
BlockState neighborState,
RandomSource random
@@ -18,7 +10,7 @@
+ // CraftBukkit start
+ if (!state.canSurvive(level, pos)) {
+ // Suppress during worldgen
+ if (!(level instanceof net.minecraft.server.level.ServerLevel world1 && world1.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world1, pos).isCancelled()) { // Paper
+ if (!(level instanceof net.minecraft.server.level.ServerLevel serverLevel && serverLevel.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(serverLevel, pos).isCancelled()) { // Paper
+ return Blocks.AIR.defaultBlockState();
+ }
+ }

View File

@@ -29,7 +29,7 @@
- player.getFoodData().eat(2, 0.1F);
- int bitesValue = state.getValue(BITES);
+ // CraftBukkit start
+ // entityhuman.getFoodData().eat(2, 0.1F);
+ // player.getFoodData().eat(2, 0.1F);
+ int oldFoodLevel = player.getFoodData().foodLevel;
+
+ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);

View File

@@ -10,8 +10,8 @@
+ return InteractionResult.SUCCESS;
+ }
+
+ if (entity instanceof net.minecraft.world.entity.player.Player) {
+ org.bukkit.event.player.PlayerHarvestBlockEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (net.minecraft.world.entity.player.Player) entity, net.minecraft.world.InteractionHand.MAIN_HAND, java.util.Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1)));
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
+ org.bukkit.event.player.PlayerHarvestBlockEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, net.minecraft.world.InteractionHand.MAIN_HAND, java.util.Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1)));
+ if (event.isCancelled()) {
+ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block
+ }

View File

@@ -39,8 +39,8 @@
public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) {
+ // CraftBukkit start
+ if (entity != null && !(entity instanceof Player)) {
+ BlockState iblockdata1 = ComposterBlock.empty(entity, state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) {
+ BlockState emptyState = ComposterBlock.empty(entity, state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, emptyState)) {
+ return state;
+ }
+ }
@@ -100,9 +100,9 @@
public static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
- public EmptyContainer() {
+ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit
+ public EmptyContainer(LevelAccessor levelAccessor, BlockPos blockPos) { // CraftBukkit
super(0);
+ this.bukkitOwner = new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit
+ this.bukkitOwner = new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(levelAccessor, blockPos, this); // CraftBukkit
}
@Override

View File

@@ -31,8 +31,8 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt);
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else {
+ destinationInventory = containerAt.getOwner().getInventory();
+ }
@@ -57,8 +57,8 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt);
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else {
+ destinationInventory = containerAt.getOwner().getInventory();
+ }

View File

@@ -4,16 +4,15 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
- if (dropExperience) {
- this.tryDropExperience(level, pos, stack, this.xpRange);
- }
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ if (flag) {
+ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange);
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
- this.tryDropExperience(level, pos, stack, this.xpRange);
- }
+ return this.tryDropExperience(level, pos, stack, this.xpRange);
+ }
+
+ return 0;

View File

@@ -39,8 +39,8 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt);
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else {
+ destinationInventory = containerAt.getOwner().getInventory();
+ }

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
@@ -78,16 +_,15 @@
@@ -78,16 +_,17 @@
PlayerEnderChestContainer enderChestInventory = player.getEnderChestInventory();
if (enderChestInventory != null && level.getBlockEntity(pos) instanceof EnderChestBlockEntity enderChestBlockEntity) {
BlockPos blockPos = pos.above();
@@ -18,7 +18,9 @@
+ // Paper start - Fix InventoryOpenEvent cancellation - moved up;
+ enderChestInventory.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
+ if (level instanceof ServerLevel serverLevel && player.openMenu(
+ new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, enderChestInventory), CONTAINER_TITLE)
+ new SimpleMenuProvider(
+ (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
+ )
+ ).isPresent()) {
+ // Paper end - Fix InventoryOpenEvent cancellation - moved up;
player.awardStat(Stats.OPEN_ENDERCHEST);

View File

@@ -1,13 +1,5 @@
--- a/net/minecraft/world/level/block/FireBlock.java
+++ b/net/minecraft/world/level/block/FireBlock.java
@@ -14,6 +_,7 @@
import net.minecraft.tags.BiomeTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
@@ -122,7 +_,25 @@
BlockState neighborState,
RandomSource random
@@ -40,7 +32,7 @@
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- level.scheduleTick(pos, this, getFireTickDelay(level.random));
+ level.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(level)); // Paper - Add fire-tick-delay option
+ level.scheduleTick(pos, this, getFireTickDelay(level)); // Paper - Add fire-tick-delay option
if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
if (!state.canSurvive(level, pos)) {
- level.removeBlock(pos, false);
@@ -154,7 +146,7 @@
- protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
- super.onPlace(state, level, pos, oldState, isMoving);
- level.scheduleTick(pos, this, getFireTickDelay(level.random));
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving, UseOnContext context) {
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving, net.minecraft.world.item.context.UseOnContext context) {
+ super.onPlace(state, level, pos, oldState, isMoving, context);
+ // CraftBukkit end
+ level.scheduleTick(pos, this, FireBlock.getFireTickDelay(level)); // Paper - Add fire-tick-delay option
@@ -162,8 +154,8 @@
- private static int getFireTickDelay(RandomSource random) {
- return 30 + random.nextInt(10);
+ private static int getFireTickDelay(Level world) { // Paper - Add fire-tick-delay option
+ return world.paperConfig().environment.fireTickDelay + world.random.nextInt(10); // Paper - Add fire-tick-delay option
+ private static int getFireTickDelay(Level level) { // Paper - Add fire-tick-delay option
+ return level.paperConfig().environment.fireTickDelay + level.random.nextInt(10); // Paper - Add fire-tick-delay option
}
@Override

View File

@@ -41,33 +41,33 @@
+ // CraftBukkit start
+ LayeredCauldronBlock.lowerFillLevel(state, level, pos, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.UNKNOWN);
+ }
+ public static boolean lowerFillLevel(BlockState state, Level level, BlockPos BlockPos, Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason) {
+ public static boolean lowerFillLevel(BlockState state, Level level, BlockPos pos, Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason) {
+ int i = (Integer) state.getValue(LayeredCauldronBlock.LEVEL) - 1;
+ BlockState iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (BlockState) state.setValue(LayeredCauldronBlock.LEVEL, i);
+
+ return LayeredCauldronBlock.changeLevel(level, BlockPos, iblockdata1, entity, reason);
+ return LayeredCauldronBlock.changeLevel(level, pos, iblockdata1, entity, reason);
+ }
+
+ // CraftBukkit start
+ // Paper start - Call CauldronLevelChangeEvent
+ public static boolean changeLevel(Level world, BlockPos pos, BlockState newBlock, @javax.annotation.Nullable Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason) { // Paper - entity is nullable
+ return changeLevel(world, pos, newBlock, entity, reason, true);
+ public static boolean changeLevel(Level level, BlockPos pos, BlockState newBlock, @javax.annotation.Nullable Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason) { // Paper - entity is nullable
+ return changeLevel(level, pos, newBlock, entity, reason, true);
+ }
+
+ public static boolean changeLevel(Level world, BlockPos pos, BlockState newBlock, @javax.annotation.Nullable Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason, boolean sendGameEvent) { // Paper - entity is nullable
+ public static boolean changeLevel(Level level, BlockPos pos, BlockState newBlock, @javax.annotation.Nullable Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason, boolean sendGameEvent) { // Paper - entity is nullable
+ // Paper end - Call CauldronLevelChangeEvent
+ org.bukkit.craftbukkit.block.CraftBlockState newState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(world, pos);
+ org.bukkit.craftbukkit.block.CraftBlockState newState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(level, pos);
+ newState.setData(newBlock);
+
+ org.bukkit.event.block.CauldronLevelChangeEvent event = new org.bukkit.event.block.CauldronLevelChangeEvent(
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, pos),
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
+ (entity == null) ? null : entity.getBukkitEntity(), reason, newState
+ );
+ if (!event.callEvent()) {
+ return false;
+ }
+ newState.update(true);
+ if (sendGameEvent) world.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(newBlock)); // Paper - Call CauldronLevelChangeEvent
+ if (sendGameEvent) level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(newBlock)); // Paper - Call CauldronLevelChangeEvent
+ return true;
+ }
+ // CraftBukkit end

View File

@@ -6,9 +6,9 @@
}
+ // Paper start - prevent unintended light block manipulation
+ @Override
+ protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, net.minecraft.world.InteractionHand hand, BlockHitResult hit) {
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || (world instanceof final net.minecraft.server.level.ServerLevel serverLevel && !player.mayInteract(serverLevel, pos)) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.InteractionResult.PASS; } // Paper - Prevent unintended light block manipulation
+ return super.useItemOn(stack, state, world, pos, player, hand, hit);
+ protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, net.minecraft.world.InteractionHand hand, BlockHitResult hitResult) {
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || (level instanceof final net.minecraft.server.level.ServerLevel serverLevel && !player.mayInteract(serverLevel, pos)) || !player.mayUseItemAt(pos, hitResult.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.InteractionResult.PASS; } // Paper - Prevent unintended light block manipulation
+ return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
+ }
+ // Paper end - prevent unintended light block manipulation

View File

@@ -11,21 +11,21 @@
+ }
+ }
+ // Paper start - Configurable speed for water flowing over lava
+ public int getFlowSpeed(Level world, BlockPos blockposition) {
+ public int getFlowSpeed(Level level, BlockPos pos) {
+ if (net.minecraft.core.registries.BuiltInRegistries.FLUID.wrapAsHolder(this.fluid).is(FluidTags.WATER)) {
+ if (
+ isLava(world, blockposition.north(1)) ||
+ isLava(world, blockposition.south(1)) ||
+ isLava(world, blockposition.west(1)) ||
+ isLava(world, blockposition.east(1))
+ isLava(level, pos.north(1)) ||
+ isLava(level, pos.south(1)) ||
+ isLava(level, pos.west(1)) ||
+ isLava(level, pos.east(1))
+ ) {
+ return world.paperConfig().environment.waterOverLavaFlowSpeed;
+ return level.paperConfig().environment.waterOverLavaFlowSpeed;
+ }
+ }
+ return this.fluid.getTickDelay(world);
+ return this.fluid.getTickDelay(level);
+ }
+ private static boolean isLava(Level world, BlockPos blockPos) {
+ final FluidState fluidState = world.getFluidIfLoaded(blockPos);
+ private static boolean isLava(Level level, BlockPos pos) {
+ final FluidState fluidState = level.getFluidIfLoaded(pos);
+ return fluidState != null && fluidState.is(FluidTags.LAVA);
+ }
+ // Paper end - Configurable speed for water flowing over lava

View File

@@ -29,20 +29,6 @@
}
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 3);
@@ -104,6 +_,13 @@
private void playNote(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) {
if (state.getValue(INSTRUMENT).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) {
+ // CraftBukkit start
+ // org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
+ // if (event.isCancelled()) {
+ // return;
+ // }
+ // CraftBukkit end
+ // Paper - move NotePlayEvent call to fix instrument/note changes; TODO any way to cancel the game event?
level.blockEvent(pos, this, 0, 0);
level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos);
}
@@ -121,7 +_,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {

View File

@@ -20,8 +20,8 @@
+ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager();
+ org.bukkit.event.Cancellable cancellable;
+
+ if (entity instanceof Player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ if (entity instanceof Player player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ manager.callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);

View File

@@ -14,8 +14,8 @@
if (!entity.isSteppingCarefully()) {
- interact(state, level, pos);
+ // CraftBukkit start
+ if (entity instanceof Player) {
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ if (entity instanceof Player player) {
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ if (!event.isCancelled()) {
+ RedStoneOreBlock.interact(level.getBlockState(pos), level, pos, entity); // add entity
+ }
@@ -71,15 +71,14 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
- if (dropExperience) {
- this.tryDropExperience(level, pos, stack, UniformInt.of(1, 5));
+ // CraftBukkit start - Delegated to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ if (flag) {
+ return this.tryDropExperience(worldserver, blockposition, itemstack, UniformInt.of(1, 5));
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
- this.tryDropExperience(level, pos, stack, UniformInt.of(1, 5));
+ return this.tryDropExperience(level, pos, stack, UniformInt.of(1, 5));
}
+
+ return 0;

View File

@@ -5,9 +5,9 @@
}
+ // Paper start - Call BlockFadeEvent
+ private void rescheduleTick(ServerLevel world, BlockPos pos) {
+ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time
+ world.scheduleTick(pos, this, (baseDelay / 3) + world.random.nextInt(RANDOM_HATCH_OFFSET_TICKS));
+ private void rescheduleTick(ServerLevel level, BlockPos pos) {
+ int baseDelay = hatchBoost(level, pos) ? level.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : level.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time
+ level.scheduleTick(pos, this, (baseDelay / 3) + level.random.nextInt(RANDOM_HATCH_OFFSET_TICKS));
+ // reschedule to avoid being stuck here and behave like the other calls (see #onPlace)
+ }
+ // Paper end - Call BlockFadeEvent

View File

@@ -1,21 +1,65 @@
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -173,9 +_,18 @@
@@ -127,10 +_,10 @@
if (optionalValue.isPresent()) {
Direction direction = optionalValue.get();
boolean flag = hookState.getOptionalValue(ATTACHED).orElse(false);
- boolean flag1 = hookState.getOptionalValue(POWERED).orElse(false);
+ boolean flag1 = hookState.getOptionalValue(POWERED).orElse(false); // Paper - diff on change, for event below
Block block = hookState.getBlock();
boolean flag2 = !attaching;
- boolean flag3 = false;
+ boolean flag3 = false; // Paper - diff on change, for event below
int i = 0;
BlockState[] blockStates = new BlockState[42];
@@ -166,21 +_,48 @@
flag2 &= i > 1;
flag3 &= flag2;
BlockState blockState1 = block.defaultBlockState().trySetValue(ATTACHED, Boolean.valueOf(flag2)).trySetValue(POWERED, Boolean.valueOf(flag3));
+ boolean cancelledEmitterHook = false, cancelledReceiverHook = false; // Paper - Call BlockRedstoneEvent
+ boolean wasPowered = flag1, willBePowered = flag3; // Paper - OBFHELPER
if (i > 0) {
BlockPos blockPosx = pos.relative(direction, i);
+ // Paper start - Call BlockRedstoneEvent
+ if (wasPowered != willBePowered) {
+ int newCurrent = willBePowered ? 15 : 0;
+ org.bukkit.event.block.BlockRedstoneEvent event = new org.bukkit.event.block.BlockRedstoneEvent(
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPosx), wasPowered ? 15 : 0, newCurrent
+ );
+ event.callEvent();
+ cancelledReceiverHook = event.getNewCurrent() != newCurrent;
+ }
+ if (!cancelledReceiverHook) { // always trigger two events even when the first hook current change is cancelled
+ // Paper end - Call BlockRedstoneEvent
Direction opposite = direction.getOpposite();
level.setBlock(blockPosx, blockState1.setValue(FACING, opposite), 3);
notifyNeighbors(block, level, blockPosx, opposite);
emitState(level, blockPosx, flag2, flag3, flag, flag1);
}
+ // CraftBukkit start
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), 15, 0);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() > 0) {
+ return;
- }
+ } // Paper - Call BlockRedstoneEvent
+ }
+ // CraftBukkit end
+ // Paper start - Call BlockRedstoneEvent
+ if (wasPowered != willBePowered) {
+ int newCurrent = willBePowered ? 15 : 0;
+ org.bukkit.event.block.BlockRedstoneEvent event = new org.bukkit.event.block.BlockRedstoneEvent(
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), wasPowered ? 15 : 0, newCurrent
+ );
+ event.callEvent();
+ cancelledEmitterHook = event.getNewCurrent() != newCurrent;
+ }
+ // Paper end - Call BlockRedstoneEvent
+ if (!cancelledEmitterHook) { // Paper - Call BlockRedstoneEvent
emitState(level, pos, flag2, flag3, flag, flag1);
if (!attaching) {
+ if (level.getBlockState(pos).is(Blocks.TRIPWIRE_HOOK)) // Paper - Validate tripwire hook placement before update
level.setBlock(pos, blockState1.setValue(FACING, direction), 3);
if (shouldNotifyNeighbours) {
notifyNeighbors(block, level, pos, direction);
}
}
+ } // Paper - Call BlockRedstoneEvent
if (flag != flag2) {
for (int i2 = 1; i2 < i; i2++) {

View File

@@ -1,11 +1,9 @@
--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -54,11 +_,16 @@
return new SignText();
@@ -55,10 +_,15 @@
}
- public boolean isFacingFrontText(Player player) {
+ public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) {
public boolean isFacingFrontText(Player player) {
+ // Paper start - More Sign Block API
+ return this.isFacingFrontText(player.getX(), player.getZ());
+ }
@@ -15,8 +13,8 @@
Vec3 signHitboxCenterPosition = signBlock.getSignHitboxCenterPosition(this.getBlockState());
- double d = player.getX() - (this.getBlockPos().getX() + signHitboxCenterPosition.x);
- double d1 = player.getZ() - (this.getBlockPos().getZ() + signHitboxCenterPosition.z);
+ double d = x - ((double) this.getBlockPos().getX() + signHitboxCenterPosition.x); // Paper - More Sign Block API
+ double d1 = z - ((double) this.getBlockPos().getZ() + signHitboxCenterPosition.z); // Paper - More Sign Block AP
+ double d = x - (this.getBlockPos().getX() + signHitboxCenterPosition.x); // Paper - More Sign Block API
+ double d1 = z - (this.getBlockPos().getZ() + signHitboxCenterPosition.z); // Paper - More Sign Block AP
float yRotationDegrees = signBlock.getYRotationDegrees(this.getBlockState());
float f = (float)(Mth.atan2(d1, d) * 180.0F / (float)Math.PI) - 90.0F;
return Mth.degreesDifferenceAbs(yRotationDegrees, f) <= 90.0F;
@@ -136,14 +134,14 @@
+ }
+ };
+
+ private CommandSourceStack createCommandSourceStack(@Nullable Player player, Level world, BlockPos pos) {
+ private CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos pos) {
+ // CraftBukkit end
String string = player == null ? "Sign" : player.getName().getString();
Component component = (Component)(player == null ? Component.literal("Sign") : player.getDisplayName());
- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player);
+
+ // Paper start - Fix commands from signs not firing command events
+ CommandSource commandSource = world.paperConfig().misc.showSignClickCommandFailureMsgsToPlayer ? new io.papermc.paper.commands.DelegatingCommandSource(this.commandSource) {
+ CommandSource commandSource = level.paperConfig().misc.showSignClickCommandFailureMsgsToPlayer ? new io.papermc.paper.commands.DelegatingCommandSource(this.commandSource) {
+ @Override
+ public void sendSystemMessage(Component message) {
+ if (player instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) {
@@ -158,7 +156,7 @@
+ } : this.commandSource;
+ // Paper end - Fix commands from signs not firing command events
+ // CraftBukkit - this
+ return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, string, component, world.getServer(), player); // Paper - Fix commands from signs not firing command events
+ return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player); // Paper - Fix commands from signs not firing command events
}
@Override

View File

@@ -64,9 +64,9 @@
- LoadingCache<UUID, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById;
- return loadingCache != null ? loadingCache.getUnchecked(profileUuid) : CompletableFuture.completedFuture(Optional.empty());
+ // Paper start - player profile events
+ public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID uuid, @Nullable String name) {
+ public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID profileUuid, @Nullable String name) {
+ LoadingCache<com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile>, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById;
+ return loadingCache != null ? loadingCache.getUnchecked(new com.mojang.datafixers.util.Pair<>(uuid, name != null ? new com.mojang.authlib.GameProfile(uuid, name) : null)) : CompletableFuture.completedFuture(Optional.empty());
+ return loadingCache != null ? loadingCache.getUnchecked(new com.mojang.datafixers.util.Pair<>(profileUuid, name != null ? new com.mojang.authlib.GameProfile(profileUuid, name) : null)) : CompletableFuture.completedFuture(Optional.empty());
+ // Paper end - player profile events
}

View File

@@ -1,24 +1,5 @@
--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java
@@ -145,6 +_,18 @@
i = 2;
}
+ // CraftBukkit start
+ // if (!this.isSticky) { // Paper - Fix sticky pistons and BlockPistonRetractEvent; Move further down
+ // org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ // BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.<org.bukkit.block.Block>of(), CraftBlock.notchToBlockFace(enumdirection));
+ // world.getCraftServer().getPluginManager().callEvent(event);
+ //
+ // if (event.isCancelled()) {
+ // return;
+ // }
+ // }
+ // PAIL: checkME - what happened to setTypeAndData?
+ // CraftBukkit end
level.blockEvent(pos, this, i, direction.get3DDataValue());
}
}
@@ -174,6 +_,12 @@
@Override
protected boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) {

View File

@@ -9,8 +9,8 @@
+ }
+
+ // CraftBukkit start
+ protected void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, @Nullable net.minecraft.world.item.context.UseOnContext context) {
+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag);
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston, @Nullable net.minecraft.world.item.context.UseOnContext context) {
+ this.onPlace(state, level, pos, oldState, movedByPiston);
+ }
+ // CraftBukkit end

View File

@@ -64,27 +64,23 @@
}
public abstract ChunkStatus getPersistedStatus();
@@ -446,6 +_,26 @@
@@ -446,6 +_,22 @@
throw new ReportedException(crashReport);
}
}
+ // CraftBukkit start
+ public void setBiome(int i, int j, int k, Holder<Biome> biome) {
+ public void setBiome(int x, int y, int z, Holder<Biome> biome) {
+ try {
+ int l = QuartPos.fromBlock(this.getMinY());
+ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1;
+ int j1 = Mth.clamp(j, l, i1);
+ int k1 = this.getSectionIndex(QuartPos.toBlock(j1));
+
+ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome);
+ int minY = QuartPos.fromBlock(this.getMinY());
+ int maxY = minY + QuartPos.fromBlock(this.getHeight()) - 1;
+ int clampedY = Mth.clamp(y, minY, maxY);
+ int sectionIndex = this.getSectionIndex(QuartPos.toBlock(clampedY));
+ this.sections[sectionIndex].setBiome(x & 3, clampedY & 3, z & 3, biome);
+ } catch (Throwable throwable) {
+ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome");
+ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set");
+
+ crashreportsystemdetails.setDetail("Location", () -> {
+ return CrashReportCategory.formatLocation(this, i, j, k);
+ });
+ throw new ReportedException(crashreport);
+ CrashReport report = CrashReport.forThrowable(throwable, "Setting biome");
+ CrashReportCategory reportCategory = report.addCategory("Biome being set");
+ reportCategory.setDetail("Location", () -> CrashReportCategory.formatLocation(this, x, y, z));
+ throw new ReportedException(report);
+ }
+ }
+ // CraftBukkit end

View File

@@ -94,24 +94,24 @@
}
}
+ // CraftBukkit start
+ public void applyBiomeDecoration(WorldGenLevel world, ChunkAccess chunk, StructureManager structureAccessor) {
+ this.applyBiomeDecoration(world, chunk, structureAccessor, true);
+ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) {
+ this.applyBiomeDecoration(level, chunk, structureManager, true);
+ }
+
+ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) {
+ if (vanilla) {
+ this.addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager);
+ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager, boolean addVanillaDecorations) {
+ if (addVanillaDecorations) {
+ this.addVanillaDecorations(level, chunk, structureManager);
+ }
+
+ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld();
+ org.bukkit.World world = level.getMinecraftWorld().getWorld();
+ // only call when a populator is present (prevents unnecessary entity conversion)
+ if (!world.getPopulators().isEmpty()) {
+ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos());
+ int x = ichunkaccess.getPos().x;
+ int z = ichunkaccess.getPos().z;
+ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(level, chunk.getPos());
+ int x = chunk.getPos().x;
+ int z = chunk.getPos().z;
+ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) {
+ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed()));
+ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z);
+ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(level.getSeed()));
+ seededrandom.setDecorationSeed(level.getSeed(), x, z);
+ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion);
+ }
+ limitedRegion.saveEntities();

View File

@@ -29,7 +29,7 @@
) {
super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
- this.level = level;
+ this.level = (net.minecraft.server.level.ServerLevel) level; // CraftBukkit - type
+ this.level = (ServerLevel) level; // CraftBukkit - type
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
for (Heightmap.Types types : Heightmap.Types.values()) {

View File

@@ -37,8 +37,8 @@
return this.biomes.get(x, y, z);
}
+ // CraftBukkit start
+ public void setBiome(int i, int j, int k, Holder<Biome> biome) {
+ this.biomes.set(i, j, k, biome);
+ public void setBiome(int x, int y, int z, Holder<Biome> biome) {
+ this.biomes.set(x, y, z, biome);
+ }
+ // CraftBukkit end

View File

@@ -1,41 +1,10 @@
--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -38,17 +_,63 @@
@@ -38,17 +_,30 @@
return this.worker.isOldChunkAround(pos, radius);
}
+ // CraftBukkit start
+ private boolean check(net.minecraft.server.level.ServerChunkCache cps, int x, int z) {
+ if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full"
+ ChunkPos pos = new ChunkPos(x, z);
+ if (cps != null) {
+ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
+ if (cps.hasChunk(x, z)) {
+ return true;
+ }
+ }
+
+ CompoundTag nbt;
+ try {
+ nbt = this.read(pos).get().orElse(null);
+ } catch (InterruptedException | java.util.concurrent.ExecutionException ex) {
+ throw new RuntimeException(ex);
+ }
+ if (nbt != null) {
+ CompoundTag level = nbt.getCompound("Level");
+ if (level.getBoolean("TerrainPopulated")) {
+ return true;
+ }
+
+ net.minecraft.world.level.chunk.status.ChunkStatus status = net.minecraft.world.level.chunk.status.ChunkStatus.byName(level.getString("Status"));
+ if (status != null && status.isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.FEATURES)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public CompoundTag upgradeChunkTag(
- ResourceKey<Level> levelKey,
+ ResourceKey<net.minecraft.world.level.dimension.LevelStem> levelKey,
@@ -44,7 +13,7 @@
- Optional<ResourceKey<MapCodec<? extends ChunkGenerator>>> chunkGeneratorKey
+ Optional<ResourceKey<MapCodec<? extends ChunkGenerator>>> chunkGeneratorKey,
+ ChunkPos pos,
+ @Nullable net.minecraft.world.level.LevelAccessor generatoraccess
+ @Nullable net.minecraft.world.level.LevelAccessor levelAccessor
+ // CraftBukkit end
) {
int version = getVersion(chunkData);
@@ -56,10 +25,8 @@
+ if (version < 1466) {
+ CompoundTag level = chunkData.getCompound("Level");
+ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
+ net.minecraft.server.level.ServerChunkCache cps = (generatoraccess == null) ? null : ((net.minecraft.server.level.ServerLevel) generatoraccess).getChunkSource();
+ if (this.check(cps, pos.x - 1, pos.z) && this.check(cps, pos.x - 1, pos.z - 1) && this.check(cps, pos.x, pos.z - 1)) {
+ level.putBoolean("LightPopulated", true);
+ }
+ // Light is purged updating to 1.14+. We need to set light populated to true so the converter recognizes the chunk as being "full"
+ level.putBoolean("LightPopulated", true);
+ }
+ }
+ // CraftBukkit end
@@ -72,7 +39,7 @@
+ // Spigot start - SPIGOT-6806: Quick and dirty way to prevent below zero generation in old chunks, by setting the status to heightmap instead of empty
+ boolean stopBelowZero = false;
+ boolean belowZeroGenerationInExistingChunks = (generatoraccess != null) ? ((net.minecraft.server.level.ServerLevel) generatoraccess).spigotConfig.belowZeroGenerationInExistingChunks : org.spigotmc.SpigotConfig.belowZeroGenerationInExistingChunks;
+ boolean belowZeroGenerationInExistingChunks = (levelAccessor != null) ? ((net.minecraft.server.level.ServerLevel) levelAccessor).spigotConfig.belowZeroGenerationInExistingChunks : org.spigotmc.SpigotConfig.belowZeroGenerationInExistingChunks;
+
+ if (version <= 2730 && !belowZeroGenerationInExistingChunks) {
+ stopBelowZero = "full".equals(chunkData.getCompound("Level").getString("Status"));

View File

@@ -46,7 +46,7 @@
return false;
}
}
@@ -331,13 +_,18 @@
@@ -331,6 +_,11 @@
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
chunkData.position(5);
fileChannel.write(chunkData);
@@ -58,11 +58,3 @@
}
return () -> Files.move(path, externalChunkFile, StandardCopyOption.REPLACE_EXISTING);
}
private void writeHeader() throws IOException {
- this.header.position(0);
+ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error
this.file.write(this.header, 0L);
}

View File

@@ -80,8 +80,8 @@
}
+ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading.
+ if (this.persistentDataContainer instanceof CompoundTag) {
+ chunkAccess.persistentDataContainer.putAll((CompoundTag) this.persistentDataContainer);
+ if (this.persistentDataContainer instanceof CompoundTag compoundTag) {
+ chunkAccess.persistentDataContainer.putAll(compoundTag);
+ }
+ // CraftBukkit end
+
@@ -107,8 +107,8 @@
}
+ // CraftBukkit start - read/write
+ private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> iregistry) {
+ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
+ private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> biomeRegistry) {
+ return PalettedContainer.codecRW(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
+ }
+ // CraftBukkit end
+
@@ -168,8 +168,8 @@
if (structureStart != null) {
+ // CraftBukkit start - load persistent data for structure start
+ net.minecraft.nbt.Tag persistentBase = compound.getCompound(string).get("StructureBukkitValues");
+ if (persistentBase instanceof CompoundTag) {
+ structureStart.persistentDataContainer.putAll((CompoundTag) persistentBase);
+ if (persistentBase instanceof CompoundTag compoundTag) {
+ structureStart.persistentDataContainer.putAll(compoundTag);
+ }
+ // CraftBukkit end
map.put(structure, structureStart);

View File

@@ -5,8 +5,8 @@
void setRemoved(Entity.RemovalReason removalReason);
+ // CraftBukkit start - add Bukkit remove cause
+ default void setRemoved(Entity.RemovalReason entity_removalreason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) {
+ this.setRemoved(entity_removalreason);
+ default void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause eventCause) {
+ this.setRemoved(removalReason);
+ }
+ // CraftBukkit end
+

View File

@@ -5,8 +5,8 @@
}
+ // CraftBukkit start - add method to get all entities in chunk
+ public List<Entity> getEntities(ChunkPos chunkCoordIntPair) {
+ return this.sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList());
+ public List<Entity> getEntities(ChunkPos chunkPos) {
+ return this.sectionStorage.getExistingSectionsInChunk(chunkPos.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList());
+ }
+
+ public boolean isPending(long pair) {

View File

@@ -1,10 +1,5 @@
--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -1,3 +_,4 @@
+// keep
package net.minecraft.world.level.levelgen;
import com.google.common.annotations.VisibleForTesting;
@@ -218,7 +_,7 @@
@Override
public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) {

View File

@@ -26,32 +26,32 @@
}
+ // CraftBukkit start
+ protected boolean placeCraftBlockEntity(ServerLevelAccessor serverLevelAccessor, BlockPos pos, org.bukkit.craftbukkit.block.CraftBlockEntityState<?> craftBlockEntityState, int flags) {
+ if (serverLevelAccessor instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+ protected boolean placeCraftBlockEntity(ServerLevelAccessor levelAccessor, BlockPos pos, org.bukkit.craftbukkit.block.CraftBlockEntityState<?> craftBlockEntityState, int flags) {
+ if (levelAccessor instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+ return transformerAccess.setCraftBlock(pos, craftBlockEntityState, flags);
+ }
+ boolean result = serverLevelAccessor.setBlock(pos, craftBlockEntityState.getHandle(), flags);
+ BlockEntity tileEntity = serverLevelAccessor.getBlockEntity(pos);
+ if (tileEntity != null) {
+ tileEntity.loadWithComponents(craftBlockEntityState.getSnapshotNBT(), serverLevelAccessor.registryAccess());
+ boolean result = levelAccessor.setBlock(pos, craftBlockEntityState.getHandle(), flags);
+ BlockEntity blockEntity = levelAccessor.getBlockEntity(pos);
+ if (blockEntity != null) {
+ blockEntity.loadWithComponents(craftBlockEntityState.getSnapshotNBT(), levelAccessor.registryAccess());
+ }
+ return result;
+ }
+
+ protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) {
+ protected void placeCraftSpawner(ServerLevelAccessor levelAccessor, BlockPos pos, org.bukkit.entity.EntityType entityType, int flags) {
+ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information
+ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(worldAccess, position, Blocks.SPAWNER.defaultBlockState(), null);
+ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(levelAccessor, pos, Blocks.SPAWNER.defaultBlockState(), null);
+ spawner.setSpawnedType(entityType);
+ this.placeCraftBlockEntity(worldAccess, position, spawner, i);
+ this.placeCraftBlockEntity(levelAccessor, pos, spawner, flags);
+ }
+
+ protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, ResourceKey<LootTable> loottableKey) {
+ protected void setCraftLootTable(ServerLevelAccessor levelAccessor, BlockPos pos, RandomSource randomSource, ResourceKey<LootTable> lootTable) {
+ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information.
+ net.minecraft.world.level.block.entity.BlockEntity tileEntity = worldAccess.getBlockEntity(position);
+ if (tileEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity tileEntityLootable) {
+ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong());
+ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(worldAccess, position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata(worldAccess.registryAccess())), 3);
+ net.minecraft.world.level.block.entity.BlockEntity blockEntity = levelAccessor.getBlockEntity(pos);
+ if (blockEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity lootContainerBlockEntity) {
+ lootContainerBlockEntity.setLootTable(lootTable, randomSource.nextLong());
+ if (levelAccessor instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+ transformerAccess.setCraftBlock(pos, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(levelAccessor, pos, blockEntity.getBlockState(), lootContainerBlockEntity.saveWithFullMetadata(levelAccessor.registryAccess())), 3);
+ }
+ }
+ }

View File

@@ -58,7 +58,7 @@
}
}
+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(world, pos, state); } // Paper - Add BlockBreakBlockEvent
+ protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(level, pos, state); } // Paper - Add BlockBreakBlockEvent
protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state);
protected int getSlopeDistance(LevelReader level, BlockPos pos, int depth, Direction direction, BlockState state, FlowingFluid.SpreadContext spreadContext) {

View File

@@ -7,9 +7,9 @@
-
+ // Paper start - Add BlockBreakBlockEvent
+ @Override
+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) {
+ BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
+ Block.dropResources(state, world, pos, tileentity, source);
+ protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state, BlockPos source) {
+ BlockEntity tileentity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null;
+ Block.dropResources(state, level, pos, tileentity, source);
+ }
+ // Paper end - Add BlockBreakBlockEvent
@Override

View File

@@ -82,12 +82,12 @@
- Optional<CompoundTag> optional = this.load(player, ".dat");
+ // CraftBukkit start
+ return this.load(player.getName().getString(), player.getStringUUID()).map((tag) -> {
+ if (player instanceof ServerPlayer) {
+ CraftPlayer player1 = (CraftPlayer) player.getBukkitEntity();
+ if (player instanceof ServerPlayer serverPlayer) {
+ CraftPlayer craftPlayer = serverPlayer.getBukkitEntity();
+ // Only update first played if it is older than the one we have
+ long modified = new File(this.playerDir, player.getStringUUID() + ".dat").lastModified();
+ if (modified < player1.getFirstPlayed()) {
+ player1.setFirstPlayed(modified);
+ if (modified < craftPlayer.getFirstPlayed()) {
+ craftPlayer.setFirstPlayed(modified);
+ }
+ }
+