Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: MiniDigger | Martin <admin@minidigger.dev>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Shane Freeder <theboyetronic@gmail.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com>
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
Nassim Jahnke
2025-04-12 17:26:44 +02:00
parent 0767902699
commit f00727c57e
2092 changed files with 50551 additions and 48729 deletions

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/BaseCommandBlock.java
+++ b/net/minecraft/world/level/BaseCommandBlock.java
@@ -32,6 +_,11 @@
@@ -37,6 +_,11 @@
private String command = "";
@Nullable
private Component customName;
@@ -12,7 +12,7 @@
public int getSuccessCount() {
return this.successCount;
@@ -126,7 +_,7 @@
@@ -114,7 +_,7 @@
this.successCount++;
}
});
@@ -21,7 +21,7 @@
} catch (Throwable var6) {
CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block");
CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed");
@@ -162,6 +_,7 @@
@@ -150,6 +_,7 @@
@Override
public void sendSystemMessage(Component component) {
if (this.trackOutput) {
@@ -29,7 +29,7 @@
this.lastOutput = Component.literal("[" + TIME_FORMAT.format(new Date()) + "] ").append(component);
this.onUpdated();
}
@@ -184,7 +_,7 @@
@@ -172,7 +_,7 @@
}
public InteractionResult usedBy(Player player) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/BaseSpawner.java
+++ b/net/minecraft/world/level/BaseSpawner.java
@@ -44,13 +_,15 @@
@@ -46,13 +_,15 @@
public int maxNearbyEntities = 6;
public int requiredPlayerRange = 16;
public int spawnRange = 4;
@@ -8,7 +8,7 @@
public void setEntityId(EntityType<?> type, @Nullable Level level, RandomSource random, BlockPos pos) {
this.getOrCreateNextSpawnData(level, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString());
+ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282
+ this.spawnPotentials = WeightedList.of(); // CraftBukkit - SPIGOT-3496, MC-92282
}
public boolean isNearPlayer(Level level, BlockPos pos) {
@@ -17,7 +17,7 @@
}
public void clientTick(Level level, BlockPos pos) {
@@ -73,13 +_,19 @@
@@ -75,13 +_,19 @@
}
public void serverTick(ServerLevel serverLevel, BlockPos pos) {
@@ -39,15 +39,15 @@
} else {
boolean flag = false;
RandomSource random = serverLevel.getRandom();
@@ -113,6 +_,21 @@
@@ -118,6 +_,21 @@
continue;
}
+ // Paper start - PreCreatureSpawnEvent
+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent(
+ io.papermc.paper.util.MCUtil.toLocation(serverLevel, d, d1, d2),
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(vec3, serverLevel.getWorld()),
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(optional.get()),
+ io.papermc.paper.util.MCUtil.toLocation(serverLevel, pos)
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, serverLevel)
+ );
+ if (!event.callEvent()) {
+ flag = true;
@@ -59,17 +59,17 @@
+ // Paper end - PreCreatureSpawnEvent
+
Entity entity = EntityType.loadEntityRecursive(entityToSpawn, serverLevel, EntitySpawnReason.SPAWNER, entity1 -> {
entity1.moveTo(d, d1, d2, entity1.getYRot(), entity1.getXRot());
entity1.snapTo(vec3.x, vec3.y, vec3.z, entity1.getYRot(), entity1.getXRot());
return entity1;
@@ -133,6 +_,7 @@
@@ -138,6 +_,7 @@
return;
}
+ entity.preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; preserve entity motion from tag
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), random.nextFloat() * 360.0F, 0.0F);
entity.snapTo(entity.getX(), entity.getY(), entity.getZ(), random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob mob) {
if (nextSpawnData.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(serverLevel, EntitySpawnReason.SPAWNER)
@@ -147,9 +_,22 @@
@@ -152,9 +_,22 @@
}
nextSpawnData.getEquipment().ifPresent(mob::equip);
@@ -93,7 +93,7 @@
this.delay(serverLevel, pos);
return;
}
@@ -160,7 +_,7 @@
@@ -165,7 +_,7 @@
((Mob)entity).spawnAnim();
}
@@ -102,39 +102,26 @@
}
}
@@ -184,7 +_,13 @@
@@ -189,12 +_,14 @@
}
public void load(@Nullable Level level, BlockPos pos, CompoundTag tag) {
+ // Paper start - use larger int if set
+ if (tag.contains("Paper.Delay")) {
+ this.spawnDelay = tag.getInt("Paper.Delay");
+ } else {
this.spawnDelay = tag.getShort("Delay");
+ }
+ // Paper end
boolean flag = tag.contains("SpawnData", 10);
if (flag) {
SpawnData spawnData = SpawnData.CODEC
@@ -205,9 +_,15 @@
this.spawnPotentials = SimpleWeightedRandomList.single(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData());
}
+ // Paper start - use ints if set
+ if (tag.contains("Paper.MinSpawnDelay", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ this.minSpawnDelay = tag.getInt("Paper.MinSpawnDelay");
+ this.maxSpawnDelay = tag.getInt("Paper.MaxSpawnDelay");
+ this.spawnCount = tag.getShort("SpawnCount");
+ } else // Paper end
if (tag.contains("MinSpawnDelay", 99)) {
- this.minSpawnDelay = tag.getShort("MinSpawnDelay");
- this.maxSpawnDelay = tag.getShort("MaxSpawnDelay");
+ this.minSpawnDelay = tag.getInt("MinSpawnDelay"); // Paper - short -> int
+ this.maxSpawnDelay = tag.getInt("MaxSpawnDelay"); // Paper - short -> int
this.spawnCount = tag.getShort("SpawnCount");
}
@@ -224,9 +_,20 @@
- this.spawnDelay = tag.getShortOr("Delay", (short)20);
+ this.spawnDelay = tag.getIntOr("Paper.Delay", tag.getShortOr("Delay", (short) 20)); // Paper - use int if set
tag.read("SpawnData", SpawnData.CODEC).ifPresent(spawnData -> this.setNextSpawnData(level, pos, spawnData));
this.spawnPotentials = tag.read("SpawnPotentials", SpawnData.LIST_CODEC)
- .orElseGet(() -> WeightedList.of(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData()));
- this.minSpawnDelay = tag.getIntOr("MinSpawnDelay", 200);
- this.maxSpawnDelay = tag.getIntOr("MaxSpawnDelay", 800);
+ .orElseGet(() -> WeightedList.of(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData()));
+ // Paper start - use int if set
+ this.minSpawnDelay = tag.getIntOr("Paper.MinSpawnDelay", tag.getIntOr("MinSpawnDelay", 200));
+ this.maxSpawnDelay = tag.getIntOr("Paper.MaxSpawnDelay", tag.getIntOr("MaxSpawnDelay", 800));
+ // Paper end - use int if set
this.spawnCount = tag.getIntOr("SpawnCount", 4);
this.maxNearbyEntities = tag.getIntOr("MaxNearbyEntities", 6);
this.requiredPlayerRange = tag.getIntOr("RequiredPlayerRange", 16);
@@ -203,9 +_,19 @@
}
public CompoundTag save(CompoundTag tag) {
@@ -142,16 +129,15 @@
- tag.putShort("MinSpawnDelay", (short)this.minSpawnDelay);
- tag.putShort("MaxSpawnDelay", (short)this.maxSpawnDelay);
+ // Paper start
+ if (spawnDelay > Short.MAX_VALUE) {
+ if (this.spawnDelay > Short.MAX_VALUE) {
+ tag.putInt("Paper.Delay", this.spawnDelay);
+ }
+ tag.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay));
+
+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) {
+ if (this.minSpawnDelay > Short.MAX_VALUE || this.maxSpawnDelay > Short.MAX_VALUE) {
+ tag.putInt("Paper.MinSpawnDelay", this.minSpawnDelay);
+ tag.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay);
+ }
+
+ tag.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay));
+ tag.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay));
+ // Paper end

View File

@@ -1,25 +1,18 @@
--- a/net/minecraft/world/level/BlockGetter.java
+++ b/net/minecraft/world/level/BlockGetter.java
@@ -11,6 +_,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
+import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@@ -33,6 +_,16 @@
@@ -33,6 +_,17 @@
BlockState getBlockState(BlockPos pos);
+ // Paper start - if loaded util
+ @Nullable BlockState getBlockStateIfLoaded(BlockPos blockposition);
+ @Nullable BlockState getBlockStateIfLoaded(BlockPos pos);
+
+ default @Nullable Block getBlockIfLoaded(BlockPos blockposition) {
+ BlockState type = this.getBlockStateIfLoaded(blockposition);
+ default @Nullable net.minecraft.world.level.block.Block getBlockIfLoaded(BlockPos pos) {
+ BlockState type = this.getBlockStateIfLoaded(pos);
+ return type == null ? null : type.getBlock();
+ }
+ @Nullable FluidState getFluidIfLoaded(BlockPos blockposition);
+
+ @Nullable FluidState getFluidIfLoaded(BlockPos pos);
+ // Paper end
+
FluidState getFluidState(BlockPos pos);
@@ -39,7 +32,7 @@
+ return clip(traverseContext, traversePos, null);
+ }
+
+ default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos, @Nullable java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
+ // Paper start - Prevent raytrace from loading chunks
+ BlockState blockState = this.getBlockStateIfLoaded(traversePos);
@@ -67,7 +60,7 @@
+ return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
+ }
+
+ default BlockHitResult clip(ClipContext context, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ default BlockHitResult clip(ClipContext context, @Nullable java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
+ return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> {
+ return this.clip(raytrace1, blockposition, canCollide); // CraftBukkit - moved into separate method // Paper - Add predicate for blocks when raytracing

View File

@@ -6,12 +6,12 @@
+ // Paper start
+ @Override
+ public @org.jetbrains.annotations.Nullable BlockState getBlockStateIfLoaded(final BlockPos blockposition) {
+ public @Nullable BlockState getBlockStateIfLoaded(final BlockPos pos) {
+ return null;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable FluidState getFluidIfLoaded(final BlockPos blockposition) {
+ public @Nullable FluidState getFluidIfLoaded(final BlockPos pos) {
+ return null;
+ }
+ // Paper end

View File

@@ -6,12 +6,12 @@
+ // Paper start - If loaded util
+ @Override
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
+ public final FluidState getFluidIfLoaded(BlockPos pos) {
+ return Fluids.EMPTY.defaultFluidState();
+ }
+
+ @Override
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
+ public final BlockState getBlockStateIfLoaded(BlockPos pos) {
+ return Blocks.AIR.defaultBlockState();
+ }
+ // Paper end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/GameRules.java
+++ b/net/minecraft/world/level/GameRules.java
@@ -32,6 +_,14 @@
@@ -34,6 +_,14 @@
import org.slf4j.Logger;
public class GameRules {
@@ -15,7 +15,7 @@
public static final int DEFAULT_RANDOM_TICK_SPEED = 3;
static final Logger LOGGER = LogUtils.getLogger();
private static final Map<GameRules.Key<?>, GameRules.Type<?>> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing(entry -> entry.id));
@@ -81,10 +_,10 @@
@@ -86,10 +_,10 @@
"sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)
);
public static final GameRules.Key<GameRules.BooleanValue> RULE_REDUCEDDEBUGINFO = register(
@@ -28,7 +28,7 @@
serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, b));
}
})
@@ -108,8 +_,8 @@
@@ -113,8 +_,8 @@
"doWeatherCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)
);
public static final GameRules.Key<GameRules.BooleanValue> RULE_LIMITED_CRAFTING = register(
@@ -39,7 +39,7 @@
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, value.get() ? 1.0F : 0.0F));
}
})
@@ -133,8 +_,8 @@
@@ -138,8 +_,8 @@
"doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)
);
public static final GameRules.Key<GameRules.BooleanValue> RULE_DO_IMMEDIATE_RESPAWN = register(
@@ -50,7 +50,7 @@
serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, value.get() ? 1.0F : 0.0F));
}
})
@@ -205,16 +_,17 @@
@@ -210,11 +_,11 @@
public static final GameRules.Key<GameRules.IntegerValue> RULE_MINECART_MAX_SPEED = register(
"minecartMaxSpeed",
GameRules.Category.MISC,
@@ -65,13 +65,15 @@
serverLevel.setDefaultSpawnPos(serverLevel.getSharedSpawnPos(), serverLevel.getSharedSpawnAngle());
})
);
@@ -223,6 +_,7 @@
);
private final Map<GameRules.Key<?>, GameRules.Value<?>> rules;
private final FeatureFlagSet enabledFeatures;
+ private final GameRules.Value<?>[] gameruleArray; // Paper - Perf: Use array for gamerule storage
private static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
GameRules.Key<T> key = new GameRules.Key<>(name, category);
@@ -242,10 +_,21 @@
public static <T extends GameRules.Value<T>> GameRules.Type<T> getType(GameRules.Key<T> key) {
return (GameRules.Type<T>)GAME_RULE_TYPES.get(key);
@@ -270,10 +_,21 @@
private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules, FeatureFlagSet enabledFeatures) {
this.rules = rules;
this.enabledFeatures = enabledFeatures;
@@ -94,7 +96,7 @@
if (value == null) {
throw new IllegalArgumentException("Tried to access invalid game rule");
} else {
@@ -286,13 +_,13 @@
@@ -314,13 +_,13 @@
}
}
@@ -112,7 +114,7 @@
}
public boolean getBoolean(GameRules.Key<GameRules.BooleanValue> key) {
@@ -306,7 +_,7 @@
@@ -334,7 +_,7 @@
public static class BooleanValue extends GameRules.Value<GameRules.BooleanValue> {
private boolean value;
@@ -121,7 +123,7 @@
return new GameRules.Type<>(
BoolArgumentType::bool,
type -> new GameRules.BooleanValue(type, defaultValue),
@@ -326,17 +_,21 @@
@@ -355,17 +_,21 @@
}
@Override
@@ -129,7 +131,7 @@
- this.value = BoolArgumentType.getBool(context, paramName);
+ // Paper start - Add WorldGameRuleChangeEvent
+ protected void updateFromArgument(CommandContext<CommandSourceStack> context, String paramName, GameRules.Key<BooleanValue> gameRuleKey) {
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule<Boolean>) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(context, paramName)));
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(context, paramName)));
+ if (!event.callEvent()) return;
+ this.value = Boolean.parseBoolean(event.getValue());
+ // Paper end - Add WorldGameRuleChangeEvent
@@ -147,16 +149,7 @@
}
@Override
@@ -345,7 +_,7 @@
}
@Override
- protected void deserialize(String value) {
+ public void deserialize(String value) { // PAIL - protected->public
this.value = Boolean.parseBoolean(value);
}
@@ -365,9 +_,9 @@
@@ -394,9 +_,9 @@
}
@Override
@@ -168,7 +161,7 @@
}
}
@@ -405,7 +_,7 @@
@@ -434,7 +_,7 @@
public static class IntegerValue extends GameRules.Value<GameRules.IntegerValue> {
private int value;
@@ -177,7 +170,7 @@
return new GameRules.Type<>(
IntegerArgumentType::integer,
type -> new GameRules.IntegerValue(type, defaultValue),
@@ -416,7 +_,7 @@
@@ -446,7 +_,7 @@
}
static GameRules.Type<GameRules.IntegerValue> create(
@@ -186,7 +179,7 @@
) {
return new GameRules.Type<>(
() -> IntegerArgumentType.integer(min, max),
@@ -437,17 +_,21 @@
@@ -468,17 +_,21 @@
}
@Override
@@ -194,7 +187,7 @@
- this.value = IntegerArgumentType.getInteger(context, paramName);
+ // Paper start - Add WorldGameRuleChangeEvent
+ protected void updateFromArgument(CommandContext<CommandSourceStack> context, String paramName, GameRules.Key<IntegerValue> gameRuleKey) {
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule<Integer>) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(context, paramName)));
+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(context, paramName)));
+ if (!event.callEvent()) return;
+ this.value = Integer.parseInt(event.getValue());
+ // Paper end - Add WorldGameRuleChangeEvent
@@ -212,16 +205,7 @@
}
@Override
@@ -456,7 +_,7 @@
}
@Override
- protected void deserialize(String value) {
+ public void deserialize(String value) { // PAIL - protected->public
this.value = safeParse(value);
}
@@ -498,13 +_,17 @@
@@ -529,13 +_,17 @@
}
@Override
@@ -241,24 +225,25 @@
final String id;
private final GameRules.Category category;
@@ -544,14 +_,14 @@
@@ -575,7 +_,7 @@
public static class Type<T extends GameRules.Value<T>> {
final Supplier<ArgumentType<?>> argument;
private final Function<GameRules.Type<T>, T> constructor;
- final BiConsumer<MinecraftServer, T> callback;
+ final BiConsumer<ServerLevel, T> callback; // CraftBukkit - per-world
private final GameRules.VisitorCaller<T> visitorCaller;
final Class<T> valueClass;
final FeatureFlagSet requiredFeatures;
@@ -583,7 +_,7 @@
Type(
Supplier<ArgumentType<?>> argument,
Function<GameRules.Type<T>, T> constructor,
- BiConsumer<MinecraftServer, T> callback,
+ BiConsumer<ServerLevel, T> callback, // CraftBukkit - per-world
GameRules.VisitorCaller<T> visitorCaller,
FeatureFlagSet requiredFeature
) {
@@ -586,20 +_,20 @@
Class<T> valueClass,
FeatureFlagSet requiredFeatures
@@ -620,16 +_,16 @@
this.type = type;
}
@@ -282,12 +267,7 @@
}
}
- protected abstract void deserialize(String value);
+ public abstract void deserialize(String value); // PAIL - private->public
public abstract String serialize();
@@ -614,7 +_,7 @@
@@ -648,7 +_,7 @@
protected abstract T copy();

View File

@@ -1,68 +1,36 @@
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -24,8 +_,10 @@
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
+import io.papermc.paper.util.MCUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
@@ -79,6 +_,27 @@
@@ -83,6 +_,16 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Scoreboard;
+// CraftBukkit start
+import java.util.HashMap;
+import java.util.Map;
+import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket;
+import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket;
+import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket;
+import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket;
+import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket;
+import net.minecraft.world.level.border.BorderChangeListener;
+import net.minecraft.world.level.dimension.LevelStem;
+import org.bukkit.Bukkit;
+import net.minecraft.server.level.ServerLevel;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.block.CapturedBlockState;
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.util.CraftSpawnCategory;
+import org.bukkit.entity.SpawnCategory;
+import org.bukkit.event.block.BlockPhysicsEvent;
+// CraftBukkit end
+
public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCloseable {
public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
public static final ResourceKey<Level> OVERWORLD = ResourceKey.create(Registries.DIMENSION, ResourceLocation.withDefaultNamespace("overworld"));
@@ -91,7 +_,7 @@
public static final int TICKS_PER_DAY = 24000;
public static final int MAX_ENTITY_SPAWN_Y = 20000000;
public static final int MIN_ENTITY_SPAWN_Y = -20000000;
- protected final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList();
+ public final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList(); // Paper - public
protected final NeighborUpdater neighborUpdater;
private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
private boolean tickingBlockEntities;
@@ -117,6 +_,61 @@
@@ -121,6 +_,57 @@
private final DamageSources damageSources;
private long subTickCount;
+ // CraftBukkit start Added the following
+ // CraftBukkit start
+ private final CraftWorld world;
+ public boolean pvpMode;
+ public org.bukkit.generator.ChunkGenerator generator;
+
+ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
+ public boolean captureBlockStates = false;
+ public boolean captureTreeGeneration = false;
+ public boolean isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
+ public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
+ public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates
+ @Nullable
+ public List<net.minecraft.world.entity.item.ItemEntity> captureDrops;
+ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
+ public boolean populating;
@@ -74,11 +42,9 @@
+ }
+ // Paper end - add paper world config
+
+ public static BlockPos lastPhysicsProblem; // Spigot
+ private org.spigotmc.TickLimiter entityLimiter;
+ private org.spigotmc.TickLimiter tileLimiter;
+ public static @Nullable BlockPos lastPhysicsProblem; // Spigot
+ private int tileTickPosition;
+ public final Map<ServerExplosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
+ public final Map<ServerExplosion.CacheKey, Float> explosionDensityCache = new java.util.HashMap<>(); // Paper - Optimize explosions
+ public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here
+
+ public CraftWorld getWorld() {
@@ -86,7 +52,7 @@
+ }
+
+ public CraftServer getCraftServer() {
+ return (CraftServer) Bukkit.getServer();
+ return (CraftServer) org.bukkit.Bukkit.getServer();
+ }
+ // Paper start - Use getChunkIfLoadedImmediately
+ @Override
@@ -96,7 +62,7 @@
+ // Paper end - Use getChunkIfLoadedImmediately
+ // Paper start - per world ticks per spawn
+ private int getTicksPerSpawn(SpawnCategory spawnCategory) {
+ final int perWorld = this.paperConfig().entities.spawning.ticksPerSpawn.getInt(CraftSpawnCategory.toNMS(spawnCategory));
+ final int perWorld = this.paperConfig().entities.spawning.ticksPerSpawn.getInt(org.bukkit.craftbukkit.util.CraftSpawnCategory.toNMS(spawnCategory));
+ if (perWorld >= 0) {
+ return perWorld;
+ }
@@ -104,13 +70,12 @@
+ }
+ // Paper end
+
+
+ public abstract ResourceKey<LevelStem> getTypeKey();
+ public abstract ResourceKey<net.minecraft.world.level.dimension.LevelStem> getTypeKey();
+
protected Level(
WritableLevelData levelData,
ResourceKey<Level> dimension,
@@ -125,8 +_,26 @@
@@ -129,8 +_,24 @@
boolean isClientSide,
boolean isDebug,
long biomeZoomSeed,
@@ -127,18 +92,16 @@
+ this.generator = gen;
+ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
+
+ // CraftBukkit Ticks things
+ for (SpawnCategory spawnCategory : SpawnCategory.values()) {
+ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ this.ticksPerSpawnCategory.put(spawnCategory, this.getTicksPerSpawn(spawnCategory)); // Paper
+ if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ this.ticksPerSpawnCategory.put(spawnCategory, this.getTicksPerSpawn(spawnCategory));
+ }
+ }
+
+ // CraftBukkit end
this.levelData = levelData;
this.dimensionTypeRegistration = dimensionTypeRegistration;
final DimensionType dimensionType = dimensionTypeRegistration.value();
@@ -136,12 +_,12 @@
@@ -140,12 +_,12 @@
this.worldBorder = new WorldBorder() {
@Override
public double getCenterX() {
@@ -153,7 +116,7 @@
}
};
} else {
@@ -154,7 +_,86 @@
@@ -158,7 +_,84 @@
this.neighborUpdater = new CollectingNeighborUpdater(this, maxChainedNeighborUpdates);
this.registryAccess = registryAccess;
this.damageSources = new DamageSources(registryAccess);
@@ -162,30 +125,30 @@
+ // CraftBukkit start
+ this.getWorldBorder().world = (ServerLevel) this;
+ // From PlayerList.setPlayerFileData
+ this.getWorldBorder().addListener(new BorderChangeListener() {
+ this.getWorldBorder().addListener(new net.minecraft.world.level.border.BorderChangeListener() {
+ @Override
+ public void onBorderSizeSet(WorldBorder border, double size) {
+ Level.this.getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world);
+ Level.this.getCraftServer().getHandle().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket(border), border.world);
+ }
+
+ @Override
+ public void onBorderSizeLerping(WorldBorder border, double fromSize, double toSize, long time) {
+ Level.this.getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world);
+ Level.this.getCraftServer().getHandle().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket(border), border.world);
+ }
+
+ @Override
+ public void onBorderCenterSet(WorldBorder border, double centerX, double centerZ) {
+ Level.this.getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world);
+ Level.this.getCraftServer().getHandle().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket(border), border.world);
+ }
+
+ @Override
+ public void onBorderSetWarningTime(WorldBorder border, int warningTime) {
+ Level.this.getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world);
+ Level.this.getCraftServer().getHandle().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket(border), border.world);
+ }
+
+ @Override
+ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlockDistance) {
+ Level.this.getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world);
+ Level.this.getCraftServer().getHandle().broadcastAll(new net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket(border), border.world);
+ }
+
+ @Override
@@ -195,26 +158,24 @@
+ public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {}
+ });
+ // CraftBukkit end
+ this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
+ this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
+ }
+
+ // Paper start - Cancel hit for vanished players
+ // ret true if no collision
+ public final boolean checkEntityCollision(BlockState data, Entity source, net.minecraft.world.phys.shapes.CollisionContext voxelshapedcollision,
+ public final boolean checkEntityCollision(BlockState state, Entity source, net.minecraft.world.phys.shapes.CollisionContext collisionContext,
+ BlockPos position, boolean checkCanSee) {
+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape)
+ net.minecraft.world.phys.shapes.VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision);
+ if (voxelshape.isEmpty()) {
+ // Copied from CollisionGetter#isUnobstructed(BlockState, BlockPos, CollisionContext) & EntityGetter#isUnobstructed(Entity, VoxelShape)
+ net.minecraft.world.phys.shapes.VoxelShape collisionShape = state.getCollisionShape(this, position, collisionContext);
+ if (collisionShape.isEmpty()) {
+ return true;
+ }
+
+ voxelshape = voxelshape.move((double) position.getX(), (double) position.getY(), (double) position.getZ());
+ if (voxelshape.isEmpty()) {
+ collisionShape = collisionShape.move((double) position.getX(), (double) position.getY(), (double) position.getZ());
+ if (collisionShape.isEmpty()) {
+ return true;
+ }
+
+ List<Entity> entities = this.getEntities(null, voxelshape.bounds());
+ List<Entity> entities = this.getEntities(null, collisionShape.bounds());
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ Entity entity = entities.get(i);
+
@@ -223,14 +184,14 @@
+ continue;
+ }
+
+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity));
+ // !entity1.isRemoved() && entity1.blocksBuilding && (entity == null || !entity1.isPassengerOfSameVehicle(entity))
+ // elide the last check since vanilla calls with entity = null
+ // only we care about the source for the canSee check
+ if (entity.isRemoved() || !entity.blocksBuilding) {
+ continue;
+ }
+
+ if (net.minecraft.world.phys.shapes.Shapes.joinIsNotEmpty(voxelshape, net.minecraft.world.phys.shapes.Shapes.create(entity.getBoundingBox()), net.minecraft.world.phys.shapes.BooleanOp.AND)) {
+ if (net.minecraft.world.phys.shapes.Shapes.joinIsNotEmpty(collisionShape, net.minecraft.world.phys.shapes.Shapes.create(entity.getBoundingBox()), net.minecraft.world.phys.shapes.BooleanOp.AND)) {
+ return false;
+ }
+ }
@@ -241,7 +202,7 @@
@Override
public boolean isClientSide() {
@@ -167,8 +_,15 @@
@@ -171,8 +_,15 @@
return null;
}
@@ -258,7 +219,7 @@
}
public static boolean isInSpawnableBounds(BlockPos pos) {
@@ -176,21 +_,84 @@
@@ -180,21 +_,86 @@
}
private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
@@ -318,10 +279,11 @@
+ }
+
+ @Override
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ @Nullable
+ public final FluidState getFluidIfLoaded(BlockPos pos) {
+ ChunkAccess chunk = this.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
+
+ return chunk == null ? null : chunk.getFluidState(blockposition);
+ return chunk == null ? null : chunk.getFluidState(pos);
+ }
+
+ @Override
@@ -329,26 +291,27 @@
+ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper - Perf: Optimize Level.hasChunkAt(BlockPosition)Z
+ }
+
+ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline
+ return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null;
+ public final boolean isLoadedAndInBounds(BlockPos pos) { // Paper - final for inline
+ return getWorldBorder().isWithinBounds(pos) && getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4) != null;
+ }
+
+ public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final
+ public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in ServerLevel for ABI compat which has final
+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z);
+ }
+ public final @Nullable LevelChunk getChunkIfLoaded(BlockPos blockposition) {
+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+
+ public final @Nullable LevelChunk getChunkIfLoaded(BlockPos pos) {
+ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
+ }
+
+ // reduces need to do isLoaded before getType
+ public final @Nullable BlockState getBlockStateIfLoadedAndInBounds(BlockPos blockposition) {
+ return getWorldBorder().isWithinBounds(blockposition) ? getBlockStateIfLoaded(blockposition) : null;
+ public final @Nullable BlockState getBlockStateIfLoadedAndInBounds(BlockPos pos) {
+ return getWorldBorder().isWithinBounds(pos) ? getBlockStateIfLoaded(pos) : null;
+ }
+ // Paper end
@Nullable
@Override
@@ -210,6 +_,22 @@
@@ -214,6 +_,22 @@
@Override
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) {
@@ -360,34 +323,36 @@
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
+ CraftBlockState blockstate = this.capturedBlockStates.get(pos);
+ if (blockstate == null) {
+ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
+ blockstate = org.bukkit.craftbukkit.block.CapturedBlockState.getTreeBlockState(this, pos, flags);
+ this.capturedBlockStates.put(pos.immutable(), blockstate);
+ }
+ blockstate.setData(state);
+ blockstate.setFlag(flags);
+ blockstate.setFlags(flags);
+ return true;
+ }
+ // CraftBukkit end
if (this.isOutsideBuildHeight(pos)) {
return false;
} else if (!this.isClientSide && this.isDebug()) {
@@ -217,11 +_,28 @@
@@ -221,11 +_,31 @@
} else {
LevelChunk chunkAt = this.getChunkAt(pos);
Block block = state.getBlock();
- BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0);
+ // CraftBukkit start - capture blockstates
+ boolean captured = false;
+ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) {
+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot
+ blockstate.setFlag(flags); // Paper - set flag
+ this.capturedBlockStates.put(pos.immutable(), blockstate);
+ captured = true;
+ if (this.captureBlockStates) {
+ final CraftBlockState snapshot;
+ if (!this.capturedBlockStates.containsKey(pos)) {
+ snapshot = (CraftBlockState) org.bukkit.craftbukkit.block.CraftBlock.at(this, pos).getState(); // Paper - use CB getState to get a suitable snapshot
+ this.capturedBlockStates.put(pos.immutable(), snapshot);
+ captured = true;
+ } else {
+ snapshot = this.capturedBlockStates.get(pos);
+ }
+ snapshot.setFlags(flags); // Paper - always set the flag of the most recent call to mitigate issues with multiple update at the same pos with different flags
+ }
BlockState blockState = chunkAt.setBlockState(pos, state, flags);
+ // CraftBukkit end
+
+ BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag
+
if (blockState == null) {
+ // CraftBukkit start - remove blockstate if failed (or the same)
+ if (this.captureBlockStates && captured) {
@@ -401,9 +366,9 @@
if (blockState1 == state) {
if (blockState != blockState1) {
this.setBlocksDirty(pos, blockState, blockState1);
@@ -249,12 +_,76 @@
@@ -253,12 +_,68 @@
this.onBlockStateChange(pos, blockState, blockState1);
this.updatePOIOnBlockStateChange(pos, blockState, blockState1);
}
+ */
+
@@ -414,7 +379,7 @@
+ try {
+ this.notifyAndUpdatePhysics(pos, chunkAt, blockState, state, blockState1, flags, recursionLeft);
+ } catch (StackOverflowError ex) {
+ Level.lastPhysicsProblem = new BlockPos(pos);
+ Level.lastPhysicsProblem = pos.immutable();
+ }
+ // Spigot end
+ }
@@ -426,65 +391,57 @@
}
+ // CraftBukkit start - Split off from above in order to directly send client and physic updates
+ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, BlockState oldBlock, BlockState newBlock, BlockState actualBlock, int i, int j) {
+ BlockState iblockdata = newBlock;
+ BlockState iblockdata1 = oldBlock;
+ BlockState iblockdata2 = actualBlock;
+ if (iblockdata2 == iblockdata) {
+ if (iblockdata1 != iblockdata2) {
+ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2);
+ public void notifyAndUpdatePhysics(BlockPos pos, LevelChunk chunkAt, BlockState oldState, BlockState newState, BlockState currentState, int flags, int recursionLeft) {
+ BlockState state = newState;
+ BlockState blockState = oldState;
+ BlockState blockState1 = currentState;
+ if (blockState1 == state) {
+ if (blockState != blockState1) {
+ this.setBlocksDirty(pos, blockState, blockState1);
+ }
+
+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement
+ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i);
+ if ((flags & 2) != 0 && (!this.isClientSide || (flags & 4) == 0) && (this.isClientSide || chunkAt == null || (chunkAt.getFullStatus() != null && chunkAt.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement
+ this.sendBlockUpdated(pos, blockState, state, flags);
+ }
+
+ if ((i & 1) != 0) {
+ this.blockUpdated(blockposition, iblockdata1.getBlock());
+ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) {
+ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock());
+ if ((flags & 1) != 0) {
+ this.updateNeighborsAt(pos, blockState.getBlock());
+ if (!this.isClientSide && state.hasAnalogOutputSignal()) {
+ this.updateNeighbourForOutputSignal(pos, newState.getBlock());
+ }
+ }
+
+ if ((i & 16) == 0 && j > 0) {
+ int k = i & -34;
+ if ((flags & 16) == 0 && recursionLeft > 0) {
+ int i = flags & -34;
+
+ // CraftBukkit start
+ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
+ CraftWorld world = ((ServerLevel) this).getWorld();
+ blockState.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1); // Don't call an event for the old block to limit event spam
+ boolean cancelledUpdates = false; // Paper - Fix block place logic
+ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent
+ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata));
+ this.getCraftServer().getPluginManager().callEvent(event);
+
+ cancelledUpdates = event.isCancelled(); // Paper - Fix block place logic
+ if (((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent
+ org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent(org.bukkit.craftbukkit.block.CraftBlock.at(this, pos), CraftBlockData.fromData(state));
+ cancelledUpdates = !event.callEvent(); // Paper - Fix block place logic
+ }
+ // CraftBukkit end
+ if (!cancelledUpdates) { // Paper - Fix block place logic
+ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1);
+ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
+ state.updateNeighbourShapes(this, pos, i, recursionLeft - 1);
+ state.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1);
+ } // Paper - Fix block place logic
+ }
+
+ // CraftBukkit start - SPIGOT-5710
+ if (!this.preventPoiUpdated) {
+ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
+ }
+ // CraftBukkit end
+ this.updatePOIOnBlockStateChange(pos, blockState, blockState1);
+ }
+ }
+ // CraftBukkit end
+
public void onBlockStateChange(BlockPos pos, BlockState blockState, BlockState newState) {
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
}
@@ -271,13 +_,31 @@
@@ -275,13 +_,31 @@
return false;
} else {
FluidState fluidState = this.getFluidState(pos);
- if (!(blockState.getBlock() instanceof BaseFireBlock)) {
- this.levelEvent(2001, pos, Block.getId(blockState));
+ // Paper start - BlockDestroyEvent; while the above setAir method is named same and looks very similar
+ // Paper start - BlockDestroyEvent; while the above removeBlock method looks very similar
+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
+ // it doesn't imply destruction of a block that plays a sound effect / drops an item.
+ boolean playEffect = true;
@@ -513,7 +470,7 @@
}
boolean flag = this.setBlock(pos, fluidState.createLegacyBlock(), 3, recursionLeft);
@@ -344,10 +_,18 @@
@@ -345,10 +_,18 @@
@Override
public BlockState getBlockState(BlockPos pos) {
@@ -533,7 +490,7 @@
return chunk.getBlockState(pos);
}
}
@@ -454,32 +_,49 @@
@@ -463,32 +_,48 @@
this.pendingBlockEntityTickers.clear();
}
@@ -545,8 +502,7 @@
- TickingBlockEntity tickingBlockEntity = iterator.next();
+ var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<TickingBlockEntity>(); // Paper - Fix MC-117075; use removeAll
+ toRemove.add(null); // Paper - Fix MC-117075
+ for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
+ this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
+ for (this.tileTickPosition = 0; this.tileTickPosition < this.blockEntityTickers.size(); this.tileTickPosition++) { // Paper - Disable tick limiters
+ TickingBlockEntity tickingBlockEntity = this.blockEntityTickers.get(this.tileTickPosition);
+ // Spigot end
if (tickingBlockEntity.isRemoved()) {
@@ -591,7 +547,7 @@
public boolean shouldTickDeath(Entity entity) {
return true;
@@ -599,6 +_,19 @@
@@ -608,6 +_,19 @@
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
@@ -611,7 +567,7 @@
if (this.isOutsideBuildHeight(pos)) {
return null;
} else {
@@ -611,6 +_,12 @@
@@ -620,6 +_,12 @@
public void setBlockEntity(BlockEntity blockEntity) {
BlockPos blockPos = blockEntity.getBlockPos();
if (!this.isOutsideBuildHeight(blockPos)) {
@@ -624,7 +580,7 @@
this.getChunkAt(blockPos).addAndRegisterBlockEntity(blockEntity);
}
}
@@ -987,7 +_,8 @@
@@ -1009,7 +_,8 @@
BLOCK("block"),
MOB("mob"),
TNT("tnt"),

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/LevelAccessor.java
+++ b/net/minecraft/world/level/LevelAccessor.java
@@ -101,4 +_,6 @@
@@ -100,4 +_,6 @@
default void gameEvent(ResourceKey<GameEvent> gameEvent, BlockPos pos, GameEvent.Context context) {
this.gameEvent(this.registryAccess().lookupOrThrow(Registries.GAME_EVENT).getOrThrow(gameEvent), pos, context);
}

View File

@@ -6,7 +6,7 @@
}
+
+ // CraftBukkit start
+ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ default boolean addFreshEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ return false;
+ }
+ // CraftBukkit end

View File

@@ -1,20 +1,6 @@
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -49,6 +_,13 @@
import net.minecraft.world.phys.Vec3;
import org.slf4j.Logger;
+// CraftBukkit start
+import net.minecraft.world.level.storage.LevelData;
+import org.bukkit.craftbukkit.util.CraftSpawnCategory;
+import org.bukkit.entity.SpawnCategory;
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
+// CraftBukkit end
+
public final class NaturalSpawner {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int MIN_SPAWN_DISTANCE = 24;
@@ -72,6 +_,13 @@
@@ -73,6 +_,13 @@
if (!(entity instanceof Mob mob && (mob.isPersistenceRequired() || mob.requiresCustomPersistence()))) {
MobCategory category = entity.getType().getCategory();
if (category != MobCategory.MISC) {
@@ -28,7 +14,7 @@
BlockPos blockPos = entity.blockPosition();
chunkGetter.query(ChunkPos.asLong(blockPos), chunk -> {
MobSpawnSettings.MobSpawnCost mobSpawnCost = getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(entity.getType());
@@ -96,17 +_,34 @@
@@ -97,17 +_,34 @@
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
}
@@ -37,7 +23,7 @@
- NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives
+ NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives, ServerLevel level
) {
+ LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate
+ net.minecraft.world.level.storage.LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate
+ // CraftBukkit end
List<MobCategory> list = new ArrayList<>(SPAWNING_CATEGORIES.length);
@@ -45,8 +31,8 @@
+ // CraftBukkit start - Use per-world spawn limits
+ boolean spawnThisTick = true;
+ int limit = mobCategory.getMaxInstancesPerChunk();
+ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
+ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ org.bukkit.entity.SpawnCategory spawnCategory = org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(mobCategory);
+ if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0;
+ limit = level.getWorld().getSpawnLimit(spawnCategory);
+ }
@@ -65,13 +51,13 @@
}
}
@@ -126,6 +_,16 @@
@@ -127,6 +_,16 @@
profilerFiller.pop();
}
+ // Paper start - Add mobcaps commands
+ public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) {
+ final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category));
+ final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(category));
+ if (categoryLimit < 1) {
+ return categoryLimit;
+ }
@@ -82,7 +68,7 @@
public static void spawnCategoryForChunk(
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback
) {
@@ -151,8 +_,8 @@
@@ -152,8 +_,8 @@
StructureManager structureManager = level.structureManager();
ChunkGenerator generator = level.getChunkSource().getGenerator();
int y = pos.getY();
@@ -93,7 +79,7 @@
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
int i = 0;
@@ -174,7 +_,7 @@
@@ -175,7 +_,7 @@
Player nearestPlayer = level.getNearestPlayer(d, y, d1, -1.0, false);
if (nearestPlayer != null) {
double d2 = nearestPlayer.distanceToSqr(d, y, d1);
@@ -102,23 +88,22 @@
if (spawnerData == null) {
Optional<MobSpawnSettings.SpawnerData> randomSpawnMobAt = getRandomSpawnMobAt(
level, structureManager, generator, category, level.random, mutableBlockPos
@@ -187,8 +_,13 @@
ceil = spawnerData.minCount + level.random.nextInt(1 + spawnerData.maxCount - spawnerData.minCount);
@@ -188,7 +_,13 @@
ceil = spawnerData.minCount() + level.random.nextInt(1 + spawnerData.maxCount() - spawnerData.minCount());
}
- if (isValidSpawnPostitionForType(level, category, structureManager, generator, spawnerData, mutableBlockPos, d2)
- && filter.test(spawnerData.type, mutableBlockPos, chunk)) {
+ // Paper start - PreCreatureSpawnEvent
+ PreSpawnStatus doSpawning = isValidSpawnPostitionForType(level, category, structureManager, generator, spawnerData, mutableBlockPos, d2);
+ if (doSpawning == PreSpawnStatus.ABORT) {
+ return;
+ }
+ if (doSpawning == PreSpawnStatus.SUCCESS && filter.test(spawnerData.type, mutableBlockPos, chunk)) {
+ // Paper end - PreCreatureSpawnEvent
Mob mobForSpawn = getMobForSpawn(level, spawnerData.type);
+ if (doSpawning == PreSpawnStatus.SUCCESS
+ // Paper end - PreCreatureSpawnEvent
&& filter.test(spawnerData.type(), mutableBlockPos, chunk)) {
Mob mobForSpawn = getMobForSpawn(level, spawnerData.type());
if (mobForSpawn == null) {
return;
@@ -199,10 +_,15 @@
@@ -200,10 +_,15 @@
spawnGroupData = mobForSpawn.finalizeSpawn(
level, level.getCurrentDifficultyAt(mobForSpawn.blockPosition()), EntitySpawnReason.NATURAL, spawnGroupData
);
@@ -128,7 +113,7 @@
- callback.run(mobForSpawn, chunk);
+ // CraftBukkit start
+ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs.
+ level.addFreshEntityWithPassengers(mobForSpawn, (mobForSpawn instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) mobForSpawn.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL);
+ level.addFreshEntityWithPassengers(mobForSpawn, (mobForSpawn instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) mobForSpawn.getBukkitEntity()).isAdult()) ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.OCELOT_BABY : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL);
+ if (!mobForSpawn.isRemoved()) {
+ ++i;
+ ++i3;
@@ -138,8 +123,8 @@
if (i >= mobForSpawn.getMaxSpawnClusterSize()) {
return;
}
@@ -225,7 +_,15 @@
&& (Objects.equals(new ChunkPos(pos), chunk.getPos()) || level.isNaturalSpawningAllowed(pos));
@@ -231,7 +_,15 @@
}
}
- private static boolean isValidSpawnPostitionForType(
@@ -155,16 +140,15 @@
ServerLevel level,
MobCategory category,
StructureManager structureManager,
@@ -235,7 +_,20 @@
@@ -241,7 +_,19 @@
double distance
) {
EntityType<?> entityType = data.type;
EntityType<?> entityType = data.type();
- return entityType.getCategory() != MobCategory.MISC
+
+ // Paper start - PreCreatureSpawnEvent
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
+ io.papermc.paper.util.MCUtil.toLocation(level, pos),
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entityType), SpawnReason.NATURAL
+ org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level),
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entityType), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL
+ );
+ if (!event.callEvent()) {
+ if (event.shouldAbortSpawn()) {
@@ -173,11 +157,11 @@
+ return PreSpawnStatus.CANCELLED;
+ }
+ final boolean success = entityType.getCategory() != MobCategory.MISC
+ // Paper end - PreCreatureSpawnEvent
+ // Paper end - PreCreatureSpawnEvent
&& (
entityType.canSpawnFarFromPlayer()
|| !(distance > entityType.getCategory().getDespawnDistance() * entityType.getCategory().getDespawnDistance())
@@ -245,6 +_,7 @@
@@ -251,6 +_,7 @@
&& SpawnPlacements.isSpawnPositionOk(entityType, level, pos)
&& SpawnPlacements.checkSpawnRules(entityType, level, EntitySpawnReason.NATURAL, pos, level.random)
&& level.noCollision(entityType.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5));
@@ -185,7 +169,7 @@
}
@Nullable
@@ -258,6 +_,7 @@
@@ -263,6 +_,7 @@
LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(entityType));
} catch (Exception var4) {
LOGGER.warn("Failed to create mob", (Throwable)var4);
@@ -193,24 +177,24 @@
}
return null;
@@ -364,6 +_,7 @@
entity = spawnerData.type.create(levelAccessor.getLevel(), EntitySpawnReason.NATURAL);
@@ -369,6 +_,7 @@
entity = spawnerData.type().create(levelAccessor.getLevel(), EntitySpawnReason.NATURAL);
} catch (Exception var27) {
LOGGER.warn("Failed to create mob", (Throwable)var27);
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(var27); // Paper - ServerExceptionEvent
continue;
}
@@ -381,7 +_,7 @@
@@ -386,7 +_,7 @@
EntitySpawnReason.CHUNK_GENERATION,
spawnGroupData
);
- levelAccessor.addFreshEntityWithPassengers(mob);
+ levelAccessor.addFreshEntityWithPassengers(mob, SpawnReason.CHUNK_GEN); // CraftBukkit
+ levelAccessor.addFreshEntityWithPassengers(mob, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit
flag = true;
}
}
@@ -501,8 +_,10 @@
@@ -506,8 +_,10 @@
return this.unmodifiableMobCategoryCounts;
}

View File

@@ -1,14 +1,6 @@
--- a/net/minecraft/world/level/PathNavigationRegion.java
+++ b/net/minecraft/world/level/PathNavigationRegion.java
@@ -8,6 +_,7 @@
import net.minecraft.core.Holder;
import net.minecraft.core.SectionPos;
import net.minecraft.core.registries.Registries;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
@@ -66,13 +_,37 @@
@@ -66,13 +_,41 @@
private ChunkAccess getChunk(int x, int z) {
int i = x - this.centerX;
int i1 = z - this.centerZ;
@@ -22,7 +14,8 @@
}
+
+ // Paper start - if loaded util
+ private @Nullable ChunkAccess getChunkIfLoaded(int x, int z) {
+ @Nullable
+ private ChunkAccess getChunkIfLoaded(int x, int z) {
+ // Based on getChunk(int, int)
+ int xx = x - this.centerX;
+ int zz = z - this.centerZ;
@@ -32,16 +25,19 @@
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public final FluidState getFluidIfLoaded(BlockPos blockposition) {
+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ return chunk == null ? null : chunk.getFluidState(blockposition);
+ public final FluidState getFluidIfLoaded(BlockPos pos) {
+ ChunkAccess chunk = getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4);
+ return chunk == null ? null : chunk.getFluidState(pos);
+ }
+
+ @Nullable
+ @Override
+ public final BlockState getBlockStateIfLoaded(BlockPos blockposition) {
+ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ return chunk == null ? null : chunk.getBlockState(blockposition);
+ public final BlockState getBlockStateIfLoaded(BlockPos pos) {
+ ChunkAccess chunk = getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4);
+ return chunk == null ? null : chunk.getBlockState(pos);
+ }
+ // Paper end

View File

@@ -1,18 +1,15 @@
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -33,6 +_,17 @@
@@ -33,6 +_,14 @@
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import net.minecraft.world.entity.boss.EnderDragonPart;
+import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
+import net.minecraft.world.level.block.Blocks;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.Location;
+import org.bukkit.event.block.BlockExplodeEvent;
+// CraftBukkit end
+
public class ServerExplosion implements Explosion {
@@ -60,7 +57,7 @@
if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockPos, blockState, f)) {
set.add(blockPos);
+ // Paper start - prevent headless pistons from forming
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && blockState.is(Blocks.MOVING_PISTON)) {
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && blockState.is(net.minecraft.world.level.block.Blocks.MOVING_PISTON)) {
+ net.minecraft.world.level.block.entity.BlockEntity extension = this.level.getBlockEntity(blockPos);
+ if (extension instanceof net.minecraft.world.level.block.piston.PistonMovingBlockEntity blockEntity && blockEntity.isSourcePiston()) {
+ net.minecraft.core.Direction direction = blockState.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
@@ -77,7 +74,7 @@
int floor5 = Mth.floor(this.center.z + f + 1.0);
-
- for (Entity entity : this.level.getEntities(this.source, new AABB(floor, floor2, floor4, floor1, floor3, floor5))) {
+ List <Entity> list = this.level.getEntities(excludeSourceFromDamage ? this.source : null, new AABB(floor, floor2, floor4, floor1, floor3, floor5), entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source
+ List <Entity> list = this.level.getEntities(this.excludeSourceFromDamage ? this.source : null, new AABB(floor, floor2, floor4, floor1, floor3, floor5), entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source
+ for (Entity entity : list) { // Paper - used in loop
if (!entity.ignoreExplosion(this)) {
double d = Math.sqrt(entity.distanceToSqr(this.center)) / f;
@@ -96,8 +93,8 @@
+ // Thinks to note:
+ // - Setting a velocity to a EnderDragonPart is ignored (and therefore not needed)
+ // - Damaging EnderDragonPart while forward the damage to EnderDragon
+ // - Damaging EntityEnderDragon does nothing
+ // - EnderDragon hitbock always covers the other parts and is therefore always present
+ // - Damaging EnderDragon does nothing
+ // - EnderDragon hitbox always covers the other parts and is therefore always present
+ if (entity instanceof EnderDragonPart) {
+ continue;
+ }
@@ -108,7 +105,7 @@
+ for (EnderDragonPart dragonPart : ((EnderDragon) entity).getSubEntities()) {
+ // Calculate damage separately for each EntityComplexPart
+ if (list.contains(dragonPart)) {
+ dragonPart.hurtServer(this.level, this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity, f1));
+ dragonPart.hurtServer(this.level, this.damageSource, this.damageCalculator.getEntityDamageAmount(this, dragonPart, f1));
+ }
+ }
+ } else {
@@ -129,7 +126,7 @@
} else {
d5 = d4;
}
@@ -206,10 +_,18 @@
@@ -206,8 +_,16 @@
d2 *= d5;
d3 *= d5;
Vec3 vec3 = new Vec3(d1, d2, d3);
@@ -137,30 +134,25 @@
+ if (entity instanceof LivingEntity) {
+ // Paper start - knockback events
+ io.papermc.paper.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) entity.getBukkitEntity(), this.source, this.damageSource.getEntity() != null ? this.damageSource.getEntity() : this.source, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.EXPLOSION, d5, vec3);
+ vec3 = event.isCancelled() ? Vec3.ZERO : org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getKnockback());
+ vec3 = event.isCancelled() ? Vec3.ZERO : org.bukkit.craftbukkit.util.CraftVector.toVec3(event.getKnockback());
+ // Paper end - knockback events
+ }
+ // CraftBukkit end
entity.push(vec3);
if (entity instanceof Player) {
Player player = (Player)entity;
- if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) {
+ if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying) && !level.paperConfig().environment.disableExplosionKnockback) { // Paper - Option to disable explosion knockback
this.hitPlayers.put(player, vec3);
}
- if (entity instanceof Player player && !player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) {
+ if (entity instanceof Player player && !player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying) && !level.paperConfig().environment.disableExplosionKnockback) { // Paper - Option to disable explosion knockback
this.hitPlayers.put(player, vec3);
}
@@ -225,7 +_,61 @@
@@ -222,7 +_,56 @@
List<ServerExplosion.StackCollector> list = new ArrayList<>();
Util.shuffle(blocks, this.level.random);
+ // CraftBukkit start
+ org.bukkit.World bworld = this.level.getWorld();
+ Location location = CraftLocation.toBukkit(this.center, bworld);
+
+ Location location = CraftLocation.toBukkit(this.center, this.level.getWorld());
+ List<org.bukkit.block.Block> blockList = new ObjectArrayList<>();
+ for (int i1 = blocks.size() - 1; i1 >= 0; i1--) {
+ BlockPos cpos = blocks.get(i1);
+ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ());
+ org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, blocks.get(i1));
+ if (!bblock.getType().isAir()) {
+ blockList.add(bblock);
+ }
@@ -169,24 +161,22 @@
+ List<org.bukkit.block.Block> bukkitBlocks;
+
+ if (this.source != null) {
+ EntityExplodeEvent event = CraftEventFactory.callEntityExplodeEvent(this.source, blockList, this.yield, this.getBlockInteraction());
+ org.bukkit.event.entity.EntityExplodeEvent event = CraftEventFactory.callEntityExplodeEvent(this.source, blockList, this.yield, this.getBlockInteraction());
+ this.wasCanceled = event.isCancelled();
+ bukkitBlocks = event.blockList();
+ this.yield = event.getYield();
+ } else {
+ org.bukkit.block.Block block = location.getBlock();
+ org.bukkit.block.BlockState blockState = (this.damageSource.causingBlockSnapshot() != null) ? this.damageSource.causingBlockSnapshot() : block.getState();
+ BlockExplodeEvent event = CraftEventFactory.callBlockExplodeEvent(block, blockState, blockList, this.yield, this.getBlockInteraction());
+ org.bukkit.event.block.BlockExplodeEvent event = CraftEventFactory.callBlockExplodeEvent(block, blockState, blockList, this.yield, this.getBlockInteraction());
+ this.wasCanceled = event.isCancelled();
+ bukkitBlocks = event.blockList();
+ this.yield = event.getYield();
+ }
+
+ blocks.clear();
+
+ for (org.bukkit.block.Block bblock : bukkitBlocks) {
+ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ());
+ blocks.add(coords);
+ blocks.add(((org.bukkit.craftbukkit.block.CraftBlock) bblock).getPosition());
+ }
+
+ if (this.wasCanceled) {
@@ -196,13 +186,13 @@
+
for (BlockPos blockPos : blocks) {
+ // CraftBukkit start - TNTPrimeEvent
+ BlockState iblockdata = this.level.getBlockState(blockPos);
+ Block block = iblockdata.getBlock();
+ if (block instanceof net.minecraft.world.level.block.TntBlock) {
+ BlockState state = this.level.getBlockState(blockPos);
+ Block block = state.getBlock();
+ if (level.getGameRules().getBoolean(GameRules.RULE_TNT_EXPLODES) && block instanceof net.minecraft.world.level.block.TntBlock) {
+ Entity sourceEntity = this.source == null ? null : this.source;
+ BlockPos sourceBlock = sourceEntity == null ? BlockPos.containing(this.center) : null;
+ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) {
+ this.level.sendBlockUpdated(blockPos, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client
+ this.level.sendBlockUpdated(blockPos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), state, 3); // Update the block on the client
+ continue;
+ }
+ }
@@ -211,7 +201,7 @@
this.level
.getBlockState(blockPos)
.onExplosionHit(this.level, blockPos, this, (itemStack, blockPos1) -> addOrAppendStack(list, itemStack, blockPos1));
@@ -239,12 +_,21 @@
@@ -236,12 +_,21 @@
private void createFire(List<BlockPos> blocks) {
for (BlockPos blockPos : blocks) {
if (this.level.random.nextInt(3) == 0 && this.level.getBlockState(blockPos).isAir() && this.level.getBlockState(blockPos.below()).isSolidRender()) {
@@ -234,15 +224,7 @@
this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
this.hurtEntities();
@@ -261,6 +_,7 @@
}
private static void addOrAppendStack(List<ServerExplosion.StackCollector> stackCollectors, ItemStack stack, BlockPos pos) {
+ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-5425
for (ServerExplosion.StackCollector stackCollector : stackCollectors) {
stackCollector.tryMerge(stack);
if (stack.isEmpty()) {
@@ -342,4 +_,86 @@
@@ -339,4 +_,86 @@
}
}
}

View File

@@ -15,7 +15,17 @@
Builder<StructureStart> builder = ImmutableList.builder();
for (Entry<Structure, LongSet> entry : allReferences.entrySet()) {
@@ -118,10 +_,20 @@
@@ -114,14 +_,29 @@
}
public StructureStart getStructureWithPieceAt(BlockPos pos, HolderSet<Structure> structures) {
- return this.getStructureWithPieceAt(pos, structures::contains);
+ // Paper start - Fix swamp hut cat generation deadlock
+ return this.getStructureWithPieceAt(pos, structures, null);
+ }
+ public StructureStart getStructureWithPieceAt(BlockPos pos, HolderSet<Structure> structures, final @Nullable ServerLevelAccessor levelAccessor) {
+ return this.getStructureWithPieceAt(pos, structures::contains, levelAccessor);
+ // Paper end - Fix swamp hut cat generation deadlock
}
public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate<Holder<Structure>> predicate) {

View File

@@ -0,0 +1,40 @@
--- a/net/minecraft/world/level/TicketStorage.java
+++ b/net/minecraft/world/level/TicketStorage.java
@@ -161,7 +_,7 @@
}
private static boolean isTicketSameTypeAndLevel(Ticket first, Ticket second) {
- return second.getType() == first.getType() && second.getTicketLevel() == first.getTicketLevel();
+ return second.getType() == first.getType() && second.getTicketLevel() == first.getTicketLevel() && java.util.Objects.equals(second.getIdentifier(), first.getIdentifier()); // Paper - add identifier
}
public int getTicketLevelAt(long chunkPos, boolean requireSimulation) {
@@ -264,7 +_,7 @@
}
public void deactivateTicketsOnClosing() {
- this.removeTicketIf(ticket -> ticket.getType() != TicketType.UNKNOWN, this.deactivatedTickets);
+ this.removeTicketIf(ticket -> ticket.getType() != TicketType.UNKNOWN && ticket.getType() != TicketType.CHUNK_LOAD && ticket.getType() != TicketType.FUTURE_AWAIT, this.deactivatedTickets);
}
public void removeTicketIf(Predicate<Ticket> predicate, @Nullable Long2ObjectOpenHashMap<List<Ticket>> tickets) {
@@ -369,4 +_,19 @@
public interface ChunkUpdated {
void update(long chunkPos, int i, boolean ticketLevel);
}
+ // Paper start
+ public boolean addPluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ // Keep inline with force loading
+ return addTicket(pos.toLong(), new Ticket(TicketType.PLUGIN_TICKET, ChunkMap.FORCED_TICKET_LEVEL, value));
+ }
+
+ public boolean removePluginRegionTicket(final ChunkPos pos, final org.bukkit.plugin.Plugin value) {
+ // Keep inline with force loading
+ return removeTicket(pos.toLong(), new Ticket(TicketType.PLUGIN_TICKET, ChunkMap.FORCED_TICKET_LEVEL, value));
+ }
+
+ public void removeAllPluginRegionTickets(TicketType ticketType, int ticketLevel, org.bukkit.plugin.Plugin ticketIdentifier) {
+ removeTicketIf(ticket -> ticket.getType() == ticketType && ticket.getTicketLevel() == ticketLevel && ticket.getIdentifier() == ticketIdentifier, null);
+ }
+ // Paper end
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/biome/Biome.java
+++ b/net/minecraft/world/level/biome/Biome.java
@@ -176,7 +_,7 @@
@@ -177,7 +_,7 @@
}
public boolean shouldSnow(LevelReader level, BlockPos pos) {

View File

@@ -1,43 +1,36 @@
--- a/net/minecraft/world/level/biome/MobSpawnSettings.java
+++ b/net/minecraft/world/level/biome/MobSpawnSettings.java
@@ -75,8 +_,40 @@
@@ -70,9 +_,33 @@
}
public static class Builder {
+ // Paper start - Perf: keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it
+ public static class MobList extends java.util.ArrayList<MobSpawnSettings.SpawnerData> {
+ java.util.Set<MobSpawnSettings.SpawnerData> biomes = new java.util.HashSet<>();
+
+ public static class MobListBuilder<E> extends WeightedList.Builder<E> {
+ @Override
+ public boolean contains(Object o) {
+ return biomes.contains(o);
+ }
+
+ @Override
+ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) {
+ biomes.add(BiomeSettingsMobs);
+ return super.add(BiomeSettingsMobs);
+ }
+
+ @Override
+ public MobSpawnSettings.SpawnerData remove(int index) {
+ MobSpawnSettings.SpawnerData removed = super.remove(index);
+ if (removed != null) {
+ biomes.remove(removed);
+ }
+ return removed;
+ }
+
+ @Override
+ public void clear() {
+ biomes.clear();
+ super.clear();
+ public WeightedList<E> build() {
+ return new WeightedSpawnerDataList<>(this.result.build());
+ }
+ }
+ // use toImmutableEnumMap collector
private final Map<MobCategory, List<MobSpawnSettings.SpawnerData>> spawners = Stream.of(MobCategory.values())
- .collect(ImmutableMap.toImmutableMap(key -> (MobCategory)key, value -> Lists.newArrayList()));
+ .collect(Maps.toImmutableEnumMap(mobCategory -> (MobCategory)mobCategory, mobCategory -> new MobList())); // Use MobList instead of ArrayList
+
+ public static class WeightedSpawnerDataList<E> extends WeightedList<E> {
+ private final java.util.Set<E> spawnerDataSet = new java.util.HashSet<>();
+
+ public WeightedSpawnerDataList(final java.util.List<? extends net.minecraft.util.random.Weighted<E>> items) {
+ super(items);
+ for (final net.minecraft.util.random.Weighted<E> item : items) {
+ this.spawnerDataSet.add(item.value());
+ }
+ }
+
+ @Override
+ public boolean contains(final E element) {
+ return this.spawnerDataSet.contains(element);
+ }
+ }
private final Map<MobCategory, WeightedList.Builder<MobSpawnSettings.SpawnerData>> spawners = Util.makeEnumMap(
- MobCategory.class, mobCategory -> WeightedList.builder()
+ MobCategory.class, mobCategory -> new MobListBuilder<>()
);
+ // Paper end - Perf: keep track of data in a pair set to give O(1) contains calls
private final Map<EntityType<?>, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap();
private float creatureGenerationProbability = 0.1F;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/AbstractCauldronBlock.java
+++ b/net/minecraft/world/level/block/AbstractCauldronBlock.java
@@ -58,7 +_,7 @@
@@ -62,7 +_,7 @@
ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult
) {
CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem());

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/AnvilBlock.java
+++ b/net/minecraft/world/level/block/AnvilBlock.java
@@ -62,8 +_,9 @@
@@ -57,8 +_,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (!level.isClientSide) {

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/level/block/BambooSaplingBlock.java
+++ b/net/minecraft/world/level/block/BambooSaplingBlock.java
@@ -43,7 +_,7 @@
@@ -38,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) {
+ if (random.nextFloat() < (level.spigotConfig.bambooModifier / (100.0f * 3)) && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (random.nextFloat() < (level.spigotConfig.bambooModifier / (100.0F * 3)) && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
this.growBamboo(level, pos);
}
}
@@ -99,6 +_,6 @@
@@ -89,6 +_,6 @@
}
protected void growBamboo(Level level, BlockPos state) {

View File

@@ -1,18 +1,18 @@
--- a/net/minecraft/world/level/block/BambooStalkBlock.java
+++ b/net/minecraft/world/level/block/BambooStalkBlock.java
@@ -130,9 +_,9 @@
@@ -120,9 +_,9 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (state.getValue(STAGE) == 0) {
- if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) {
+ if (random.nextFloat() < (level.spigotConfig.bambooModifier / (100.0f * 3)) && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (random.nextFloat() < (level.spigotConfig.bambooModifier / (100.0F * 3)) && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = this.getHeightBelowUpToMax(level, pos) + 1;
- if (i < 16) {
+ if (i < level.paperConfig().maxGrowthHeight.bamboo.max) { // Paper - Configurable cactus/bamboo/reed growth height
this.growBamboo(state, level, pos, random, i);
}
}
@@ -168,7 +_,7 @@
@@ -158,7 +_,7 @@
public boolean isValidBonemealTarget(LevelReader level, BlockPos pos, BlockState state) {
int heightAboveUpToMax = this.getHeightAboveUpToMax(level, pos);
int heightBelowUpToMax = this.getHeightBelowUpToMax(level, pos);
@@ -21,7 +21,7 @@
}
@Override
@@ -186,7 +_,7 @@
@@ -176,7 +_,7 @@
for (int i2 = 0; i2 < i1; i2++) {
BlockPos blockPos = pos.above(heightAboveUpToMax);
BlockState blockState = level.getBlockState(blockPos);
@@ -30,7 +30,7 @@
return;
}
@@ -206,29 +_,38 @@
@@ -191,27 +_,38 @@
BlockPos blockPos = pos.below(2);
BlockState blockState1 = level.getBlockState(blockPos);
BambooLeaves bambooLeaves = BambooLeaves.NONE;
@@ -54,12 +54,10 @@
int i = state.getValue(AGE) != 1 && !blockState1.is(Blocks.BAMBOO) ? 0 : 1;
- int i1 = (age < 11 || !(random.nextFloat() < 0.25F)) && age != 15 ? 0 : 1;
- level.setBlock(
- pos.above(), this.defaultBlockState().setValue(AGE, Integer.valueOf(i)).setValue(LEAVES, bambooLeaves).setValue(STAGE, Integer.valueOf(i1)), 3
- );
- level.setBlock(pos.above(), this.defaultBlockState().setValue(AGE, i).setValue(LEAVES, bambooLeaves).setValue(STAGE, i1), 3);
+ int i1 = (age < level.paperConfig().maxGrowthHeight.bamboo.min || random.nextFloat() >= 0.25F) && age != (level.paperConfig().maxGrowthHeight.bamboo.max - 1) ? 0 : 1; // Paper - Configurable cactus/bamboo/reed growth height
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), this.defaultBlockState().setValue(net.minecraft.world.level.block.BambooStalkBlock.AGE, i).setValue(BambooStalkBlock.LEAVES, bambooLeaves).setValue(net.minecraft.world.level.block.BambooStalkBlock.STAGE, i1), 3)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), this.defaultBlockState().setValue(AGE, i).setValue(LEAVES, bambooLeaves).setValue(STAGE, i1), 3)) {
+ if (shouldUpdateOthers) {
+ level.setBlock(pos.below(), blockState.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3);
+ level.setBlock(blockPos, blockState1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3);
@@ -76,7 +74,7 @@
i++;
}
@@ -238,7 +_,7 @@
@@ -221,7 +_,7 @@
protected int getHeightBelowUpToMax(BlockGetter level, BlockPos pos) {
int i = 0;

View File

@@ -1,29 +1,27 @@
--- a/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/net/minecraft/world/level/block/BaseFireBlock.java
@@ -12,6 +_,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
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.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -128,6 +_,7 @@
@@ -129,11 +_,12 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
effectApplier.apply(InsideBlockEffectType.FIRE_IGNITE);
effectApplier.runAfter(InsideBlockEffectType.FIRE_IGNITE, entity1 -> entity1.hurt(entity1.level().damageSources().inFire(), this.fireDamage));
}
- public static void fireIgnite(Entity entity) {
+ public static void fireIgnite(Entity entity, BlockPos pos) { // Paper - track position inside effect was triggered on
if (!entity.fireImmune()) {
if (entity.getRemainingFireTicks() < 0) {
entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1);
@@ -137,7 +_,18 @@
@@ -143,30 +_,41 @@
}
if (entity.getRemainingFireTicks() >= 0) {
- entity.igniteForSeconds(8.0F);
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), entity.getBukkitEntity(), 8.0F);
+ level.getCraftServer().getPluginManager().callEvent(event);
+ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(entity.level(), pos), entity.getBukkitEntity(), 8.0F);
+ entity.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ entity.igniteForSeconds(event.getDuration(), false);
@@ -35,13 +33,11 @@
+ // CraftBukkit end
}
}
@@ -146,24 +_,24 @@
}
@Override
- protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving, UseOnContext context) { // CraftBukkit - context
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving, net.minecraft.world.item.context.UseOnContext context) { // CraftBukkit - context
if (!oldState.is(state.getBlock())) {
if (inPortalDimension(level)) {
Optional<PortalShape> optional = PortalShape.findEmptyPortalShape(level, pos, Direction.Axis.X);
@@ -65,7 +61,7 @@
}
@Override
@@ -208,4 +_,12 @@
@@ -211,4 +_,12 @@
}
}
}

View File

@@ -1,25 +1,22 @@
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
@@ -81,6 +_,7 @@
@@ -82,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide) {
int signalForState = this.getSignalForState(state);
if (signalForState == 0) {
@@ -93,6 +_,19 @@
@@ -94,6 +_,16 @@
int signalStrength = this.getSignalStrength(level, pos);
boolean flag = currentSignal > 0;
boolean flag1 = signalStrength > 0;
+
+ // CraftBukkit start - Interact Pressure Plate
+ org.bukkit.World bworld = level.getWorld();
+ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager();
+
+ // CraftBukkit start - Interact Pressure Plate
+ if (flag != flag1) {
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), currentSignal, signalStrength);
+ manager.callEvent(eventRedstone);
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), currentSignal, signalStrength);
+ eventRedstone.callEvent();
+
+ flag1 = eventRedstone.getNewCurrent() > 0;
+ signalStrength = eventRedstone.getNewCurrent();
@@ -28,7 +25,7 @@
if (currentSignal != signalStrength) {
BlockState blockState = this.setSignalForState(state, signalStrength);
level.setBlock(pos, blockState, 2);
@@ -145,7 +_,13 @@
@@ -142,7 +_,13 @@
}
protected static int getEntityCount(Level level, AABB box, Class<? extends Entity> entityClass) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/BedBlock.java
+++ b/net/minecraft/world/level/block/BedBlock.java
@@ -92,7 +_,7 @@
@@ -90,7 +_,7 @@
}
}
@@ -9,7 +9,7 @@
level.removeBlock(pos, false);
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
if (level.getBlockState(blockPos).is(this)) {
@@ -103,22 +_,56 @@
@@ -101,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)) {
@@ -67,7 +67,7 @@
public static boolean canSetSpawn(Level level) {
return level.dimensionType().bedWorks();
}
@@ -311,6 +_,11 @@
@@ -299,6 +_,11 @@
if (!level.isClientSide) {
BlockPos blockPos = pos.relative(state.getValue(FACING));
level.setBlock(blockPos, state.setValue(PART, BedPart.HEAD), 3);
@@ -76,6 +76,6 @@
+ return;
+ }
+ // CraftBukkit end
level.blockUpdated(pos, Blocks.AIR);
level.updateNeighborsAt(pos, Blocks.AIR);
state.updateNeighbourShapes(level, pos, 3);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/net/minecraft/world/level/block/BeehiveBlock.java
@@ -91,8 +_,8 @@
@@ -88,8 +_,8 @@
}
@Override
@@ -11,7 +11,7 @@
if (!level.isClientSide && te instanceof BeehiveBlockEntity beehiveBlockEntity) {
if (!EnchantmentHelper.hasTag(stack, EnchantmentTags.PREVENTS_BEE_SPAWNS_WHEN_MINING)) {
beehiveBlockEntity.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
@@ -100,7 +_,7 @@
@@ -97,7 +_,7 @@
this.angerNearbyBees(level, pos);
}
@@ -20,12 +20,12 @@
}
}
@@ -122,14 +_,14 @@
@@ -119,14 +_,14 @@
for (Bee bee : entitiesOfClass) {
if (bee.getTarget() == null) {
Player player = Util.getRandom(entitiesOfClass1, level.random);
- bee.setTarget(player);
+ bee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit
+ bee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER); // CraftBukkit
}
}
}
@@ -37,7 +37,7 @@
}
@Override
@@ -141,8 +_,19 @@
@@ -138,8 +_,19 @@
if (honeyLevelValue >= 5) {
Item item = stack.getItem();
if (stack.is(Items.SHEARS)) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/BellBlock.java
+++ b/net/minecraft/world/level/block/BellBlock.java
@@ -142,6 +_,11 @@
@@ -137,6 +_,11 @@
direction = level.getBlockState(pos).getValue(FACING);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/BigDripleafBlock.java
+++ b/net/minecraft/world/level/block/BigDripleafBlock.java
@@ -136,7 +_,7 @@
@@ -129,7 +_,7 @@
@Override
protected void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) {
@@ -9,10 +9,10 @@
}
@Override
@@ -199,9 +_,23 @@
@@ -192,9 +_,23 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide) {
if (state.getValue(TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) {
@@ -22,7 +22,7 @@
+ 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()));
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+
@@ -34,7 +34,7 @@
}
}
}
@@ -213,9 +_,9 @@
@@ -206,9 +_,9 @@
} else {
Tilt tilt = state.getValue(TILT);
if (tilt == Tilt.UNSTABLE) {
@@ -46,7 +46,7 @@
} else if (tilt == Tilt.FULL) {
resetTilt(state, level, pos);
}
@@ -238,8 +_,11 @@
@@ -231,8 +_,11 @@
return entity.onGround() && entity.position().y > pos.getY() + 0.6875F;
}
@@ -60,7 +60,7 @@
if (sound != null) {
playTiltSound(level, pos, sound);
}
@@ -251,18 +_,26 @@
@@ -244,18 +_,26 @@
}
private static void resetTilt(BlockState state, Level level, BlockPos pos) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -90,6 +_,21 @@
@@ -99,6 +_,21 @@
public static final int UPDATE_LIMIT = 512;
protected final StateDefinition<Block, BlockState> stateDefinition;
private BlockState defaultBlockState;
@@ -22,7 +22,7 @@
@Nullable
private Item item;
private static final int CACHE_SIZE = 256;
@@ -272,6 +_,27 @@
@@ -318,6 +_,27 @@
return state.getDrops(builder);
}
@@ -49,8 +49,8 @@
+
public static void dropResources(BlockState state, Level level, BlockPos pos) {
if (level instanceof ServerLevel) {
getDrops(state, (ServerLevel)level, pos, null).forEach(itemStack -> popResource(level, pos, itemStack));
@@ -287,9 +_,14 @@
getDrops(state, (ServerLevel)level, pos, null).forEach(stack -> popResource(level, pos, stack));
@@ -333,9 +_,14 @@
}
public static void dropResources(BlockState state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
@@ -60,13 +60,13 @@
+ public static void dropResources(BlockState state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
+ // Paper end - Properly handle xp dropping
if (level instanceof ServerLevel) {
getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, itemStack));
getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(stack -> popResource(level, pos, stack));
- state.spawnAfterBreak((ServerLevel)level, pos, tool, true);
+ state.spawnAfterBreak((ServerLevel) level, pos, tool, dropExperience); // Paper - Properly handle xp dropping
+ state.spawnAfterBreak((ServerLevel)level, pos, tool, dropExperience); // Paper - Properly handle xp dropping
}
}
@@ -320,13 +_,24 @@
@@ -366,13 +_,25 @@
if (level instanceof ServerLevel serverLevel && !stack.isEmpty() && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
ItemEntity itemEntity = itemEntitySupplier.get();
itemEntity.setDefaultPickUpDelay();
@@ -85,7 +85,8 @@
+ // Paper start - add entity parameter
+ popExperience(level, pos, amount, null);
+ }
+ public void popExperience(ServerLevel level, BlockPos pos, int amount, net.minecraft.world.entity.Entity entity) {
+
+ public void popExperience(ServerLevel level, BlockPos pos, int amount, @Nullable net.minecraft.world.entity.Entity entity) {
+ // Paper end - add entity parameter
if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
- ExperienceOrb.award(level, Vec3.atCenterOf(pos), amount);
@@ -93,17 +94,18 @@
}
}
@@ -345,10 +_,18 @@
@@ -391,10 +_,19 @@
return this.defaultBlockState();
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix drops not preventing stats/food exhaustion
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - fix drops not preventing stats/food exhaustion
public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start - fix drops not preventing stats/food exhaustion
+ // Paper start - fix drops not preventing stats/food exhaustion
+ this.playerDestroy(level, player, pos, state, blockEntity, tool, true, true);
+ }
+
+ public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
+ // Paper end - fix drops not preventing stats/food exhaustion
+ // Paper end - fix drops not preventing stats/food exhaustion
player.awardStat(Stats.BLOCK_MINED.get(this));
- player.causeFoodExhaustion(0.005F);
- dropResources(state, level, pos, blockEntity, player, tool);
@@ -114,7 +116,7 @@
}
public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
@@ -469,12 +_,33 @@
@@ -533,12 +_,20 @@
return this.builtInRegistryHolder;
}
@@ -123,32 +125,18 @@
int i = EnchantmentHelper.processBlockExperience(level, heldItem, amount.sample(level.getRandom()));
if (i > 0) {
- this.popExperience(level, pos, i);
- }
- }
+ // CraftBukkit start
+ //this.popExperience(level, pos, i);
+ return i;
+ // CraftBukkit end
+ }
+ return 0; // CraftBukkit
}
- }
+ return 0;
+ }
+ // CraftBukkit start
+
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
+ return 0;
+ }
+ // CraftBukkit end
+
+ // Spigot start
+ public static float range(float min, float value, float max) {
+ if (value < min) {
+ return min;
+ }
+ if (value > max) {
+ return max;
+ }
+ return value;
+ }
+ // Spigot end
record ShapePairKey(VoxelShape first, VoxelShape second) {
@Override

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
@@ -68,8 +_,7 @@
@@ -63,8 +_,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {

View File

@@ -1,10 +1,10 @@
--- a/net/minecraft/world/level/block/BubbleColumnBlock.java
+++ b/net/minecraft/world/level/block/BubbleColumnBlock.java
@@ -48,6 +_,7 @@
@@ -49,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
BlockState blockState = level.getBlockState(pos.above());
if (blockState.isAir()) {
entity.onAboveBubbleCol(state.getValue(DRAG_DOWN));
boolean flag = blockState.getCollisionShape(level, pos).isEmpty() && blockState.getFluidState().isEmpty();
if (flag) {

View File

@@ -3,13 +3,13 @@
@@ -44,7 +_,13 @@
BlockState blockState1 = block.defaultBlockState()
.setValue(AmethystClusterBlock.FACING, direction)
.setValue(AmethystClusterBlock.WATERLOGGED, Boolean.valueOf(blockState.getFluidState().getType() == Fluids.WATER));
.setValue(AmethystClusterBlock.WATERLOGGED, blockState.getFluidState().getType() == Fluids.WATER);
- level.setBlockAndUpdate(blockPos, blockState1);
+ // Paper start - Have Amethyst throw both spread and grow events
+ if (block == Blocks.SMALL_AMETHYST_BUD) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState1, 3); // CraftBukkit
+ } else {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, blockState1);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, blockState1, 3);
+ }
+ // Paper end - Have Amethyst throw both spread and grow events
}

View File

@@ -1,21 +0,0 @@
--- a/net/minecraft/world/level/block/BushBlock.java
+++ b/net/minecraft/world/level/block/BushBlock.java
@@ -35,9 +_,15 @@
BlockState neighborState,
RandomSource random
) {
- return !state.canSurvive(level, pos)
- ? Blocks.AIR.defaultBlockState()
- : super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit start
+ if (!state.canSurvive(level, pos)) {
+ // Suppress during worldgen
+ 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();
+ }
+ }
+ return super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit end
}
@Override

View File

@@ -1,12 +1,12 @@
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -114,6 +_,19 @@
@@ -89,6 +_,19 @@
if (state.getValue(POWERED)) {
return InteractionResult.CONSUME;
} else {
+ // CraftBukkit start
+ boolean powered = state.getValue(ButtonBlock.POWERED);
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
@@ -20,21 +20,21 @@
this.press(state, level, pos, player);
return InteractionResult.SUCCESS;
}
@@ -179,6 +_,7 @@
@@ -150,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide && this.type.canButtonBeActivatedByArrows() && !state.getValue(POWERED)) {
this.checkPressed(state, level, pos);
}
@@ -190,7 +_,31 @@
@@ -161,7 +_,31 @@
: null;
boolean flag = abstractArrow != null;
boolean poweredValue = state.getValue(POWERED);
+ // CraftBukkit start - Call interact event when arrows turn on wooden buttons
+ if (poweredValue != flag && flag) {
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(abstractArrow.getBukkitEntity(), block);
+ level.getCraftServer().getPluginManager().callEvent(event);
+
@@ -46,7 +46,7 @@
if (flag != poweredValue) {
+ // CraftBukkit start
+ boolean powered = poweredValue;
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
@@ -57,6 +57,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)), 3);
level.setBlock(pos, state.setValue(POWERED, flag), 3);
this.updateNeighbours(state, level, pos);
this.playSound(null, level, pos, flag);

View File

@@ -1,30 +1,46 @@
--- a/net/minecraft/world/level/block/CactusBlock.java
+++ b/net/minecraft/world/level/block/CactusBlock.java
@@ -56,14 +_,16 @@
i++;
}
@@ -58,25 +_,29 @@
int ageValue = state.getValue(AGE);
- if (i < 3) {
+ if (i < level.paperConfig().maxGrowthHeight.cactus) { // Paper - Configurable cactus/bamboo/reed growth height
int ageValue = state.getValue(AGE);
- if (ageValue == 15) {
- level.setBlockAndUpdate(blockPos, this.defaultBlockState());
+
+ int modifier = level.spigotConfig.cactusModifier; // Spigot - SPIGOT-7159: Better modifier resolution
+ if (ageValue >= 15 || (modifier != 100 && random.nextFloat() < (modifier / (100.0f * 16)))) { // Spigot - SPIGOT-7159: Better modifier
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, this.defaultBlockState()); // CraftBukkit
BlockState blockState = state.setValue(AGE, Integer.valueOf(0));
level.setBlock(pos, blockState, 4);
level.neighborChanged(blockState, blockPos, this, null, false);
- } else {
+ } else if (modifier == 100 || random.nextFloat() < (modifier / (100.0f * 16))) { // Spigot - SPIGOT-7159: Better modifier resolution
level.setBlock(pos, state.setValue(AGE, Integer.valueOf(ageValue + 1)), 4);
while (level.getBlockState(pos.below(i)).is(this)) {
- if (++i == 3 && ageValue == 15) {
+ if (++i == level.paperConfig().maxGrowthHeight.cactus && ageValue == 15) { // Paper - Configurable cactus/bamboo/reed growth height
return;
}
}
@@ -113,7 +_,8 @@
if (ageValue == 8 && this.canSurvive(this.defaultBlockState(), level, pos.above())) {
- double d = i >= 3 ? 0.25 : 0.1;
+ double d = i >= level.paperConfig().maxGrowthHeight.cactus ? 0.25 : 0.1; // Paper - Configurable cactus/bamboo/reed growth height
if (random.nextDouble() <= d) {
- level.setBlockAndUpdate(blockPos, Blocks.CACTUS_FLOWER.defaultBlockState());
- }
- } else if (ageValue == 15 && i < 3) {
- level.setBlockAndUpdate(blockPos, this.defaultBlockState());
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, Blocks.CACTUS_FLOWER.defaultBlockState(), 3);
+ }
+ } else if (ageValue == 15 && i < level.paperConfig().maxGrowthHeight.cactus) { // Paper - Configurable cactus/bamboo/reed growth height
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, this.defaultBlockState(), 3)) {
+ return;
+ }
+ // Paper end
BlockState blockState = state.setValue(AGE, 0);
level.setBlock(pos, blockState, 260);
level.neighborChanged(blockState, blockPos, this, null, false);
}
if (ageValue < 15) {
- level.setBlock(pos, state.setValue(AGE, ageValue + 1), 260);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(AGE, ageValue + 1), 260); // Paper
}
}
}
@@ -124,7 +_,8 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
- entity.hurt(level.damageSources().cactus(), 1.0F);
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
+ entity.hurt(level.damageSources().cactus().eventBlockDamager(level, pos), 1.0F); // CraftBukkit

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/CakeBlock.java
+++ b/net/minecraft/world/level/block/CakeBlock.java
@@ -67,6 +_,12 @@
@@ -57,6 +_,12 @@
) {
Item item = stack.getItem();
if (stack.is(ItemTags.CANDLES) && state.getValue(BITES) == 0 && Block.byItem(item) instanceof CandleBlock candleBlock) {
@@ -13,7 +13,7 @@
stack.consume(1, player);
level.playSound(null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F);
level.setBlockAndUpdate(pos, CandleCakeBlock.byCandle(candleBlock));
@@ -97,9 +_,28 @@
@@ -87,9 +_,28 @@
if (!player.canEat(false)) {
return InteractionResult.PASS;
} else {
@@ -43,4 +43,4 @@
+ // Paper - move up
level.gameEvent(player, GameEvent.EAT, pos);
if (bitesValue < 6) {
level.setBlock(pos, state.setValue(BITES, Integer.valueOf(bitesValue + 1)), 3);
level.setBlock(pos, state.setValue(BITES, bitesValue + 1), 3);

View File

@@ -1,17 +1,17 @@
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -112,8 +_,9 @@
@@ -107,8 +_,9 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (state.getValue(LIT) && entity instanceof LivingEntity) {
- entity.hurt(level.damageSources().campfire(), this.fireDamage);
+ entity.hurt(level.damageSources().campfire().eventBlockDamager(level, pos), (float) this.fireDamage); // CraftBukkit
}
super.entityInside(state, level, pos, entity);
@@ -242,6 +_,11 @@
super.entityInside(state, level, pos, entity, effectApplier);
@@ -220,6 +_,11 @@
&& projectile.mayInteract(serverLevel, blockPos)
&& !state.getValue(LIT)
&& !state.getValue(WATERLOGGED)) {
@@ -20,6 +20,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(blockPos, state.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11);
level.setBlock(blockPos, state.setValue(BlockStateProperties.LIT, true), 11);
}
}

View File

@@ -1,18 +1,19 @@
--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java
+++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java
@@ -79,9 +_,13 @@
@@ -79,9 +_,14 @@
}
private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch patternMatch, Entity golem, BlockPos pos) {
- clearPatternBlocks(level, patternMatch);
+ // clearPatternBlocks(level, patternMatch); // CraftBukkit - moved down
golem.moveTo(pos.getX() + 0.5, pos.getY() + 0.05, pos.getZ() + 0.5, 0.0F, 0.0F);
+ // clearPatternBlocks(level, patternMatch); // Paper - moved down
golem.snapTo(pos.getX() + 0.5, pos.getY() + 0.05, pos.getZ() + 0.5, 0.0F, 0.0F);
- level.addFreshEntity(golem);
+ // Paper start
+ if (!level.addFreshEntity(golem, (golem.getType() == EntityType.SNOW_GOLEM) ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM)) {
+ return;
+ }
+ clearPatternBlocks(level, patternMatch); // CraftBukkit - from above
+ // CraftBukkit end
+ // Paper end
+ clearPatternBlocks(level, patternMatch); // Paper - from above
for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0))) {
CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, golem);

View File

@@ -24,4 +24,4 @@
+ // CraftBukkit end
float f = Mth.randomBetween(level.random, 0.8F, 1.2F);
level.playSound(null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f);
BlockState blockState = state.setValue(BERRIES, Boolean.valueOf(false));
BlockState blockState = state.setValue(BERRIES, false);

View File

@@ -4,9 +4,9 @@
@Override
protected BlockState getGrowIntoState(BlockState state, RandomSource random) {
- return super.getGrowIntoState(state, random).setValue(BERRIES, Boolean.valueOf(random.nextFloat() < 0.11F));
- return super.getGrowIntoState(state, random).setValue(BERRIES, random.nextFloat() < 0.11F);
- }
+ // Paper start - Fix Spigot growth modifiers
+ // Paper start - Fix Spigot growth modifiers
+ return this.getGrowIntoState(state, random, null);
+ }
+ @Override

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/CeilingHangingSignBlock.java
+++ b/net/minecraft/world/level/block/CeilingHangingSignBlock.java
@@ -184,6 +_,6 @@
@@ -166,6 +_,6 @@
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {

View File

@@ -5,7 +5,7 @@
float f = 0.05688889F;
if (random.nextFloat() < 0.05688889F) {
- this.getNextState(state, level, pos, random).ifPresent(blockState -> level.setBlockAndUpdate(pos, blockState));
+ this.getNextState(state, level, pos, random).ifPresent(blockState -> org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, blockState)); // CraftBukkit
+ this.getNextState(state, level, pos, random).ifPresent(blockState -> org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, blockState, 3)); // CraftBukkit
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -85,7 +_,7 @@
@@ -82,7 +_,7 @@
@Override
public Optional<MenuProvider> acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) {
final Container container = new CompoundContainer(first, second);
@@ -9,7 +9,7 @@
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
@@ -103,10 +_,10 @@
@@ -100,10 +_,10 @@
if (first.hasCustomName()) {
return first.getDisplayName();
} else {
@@ -22,7 +22,7 @@
}
@Override
@@ -120,6 +_,34 @@
@@ -117,6 +_,34 @@
}
};
@@ -57,7 +57,7 @@
@Override
public MapCodec<? extends ChestBlock> codec() {
return CODEC;
@@ -245,8 +_,7 @@
@@ -225,8 +_,7 @@
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (level instanceof ServerLevel serverLevel) {
MenuProvider menuProvider = this.getMenuProvider(state, level, pos);
@@ -67,7 +67,7 @@
player.awardStat(this.getOpenChestStat());
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
}
@@ -285,7 +_,14 @@
@@ -265,7 +_,14 @@
@Nullable
@Override
public MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) {
@@ -83,7 +83,7 @@
}
public static DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction> opennessCombiner(final LidBlockEntity lid) {
@@ -328,6 +_,11 @@
@@ -308,6 +_,11 @@
}
private static boolean isCatSittingOnChest(LevelAccessor level, BlockPos pos) {

View File

@@ -4,18 +4,18 @@
}
if (flag && allNeighborsEmpty(level, blockPos, null) && level.isEmptyBlock(pos.above(2))) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, ageValue), 2)) { // CraftBukkit - add event
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, this.defaultBlockState().setValue(AGE, ageValue), 2)) { // CraftBukkit - add event
level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2);
this.placeGrownFlower(level, blockPos, ageValue);
+ } // CraftBukkit
} else if (ageValue < 4) {
int i = random.nextInt(4);
if (flag1) {
@@ -112,18 +_,28 @@
@@ -112,30 +_,40 @@
if (level.isEmptyBlock(blockPos1)
&& level.isEmptyBlock(blockPos1.below())
&& allNeighborsEmpty(level, blockPos1, randomDirection.getOpposite())) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, ageValue + 1), 2)) { // CraftBukkit - add event
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos1, this.defaultBlockState().setValue(AGE, ageValue + 1), 2)) { // CraftBukkit - add event
this.placeGrownFlower(level, blockPos1, ageValue + 1);
flag2 = true;
+ } // CraftBukkit
@@ -26,20 +26,34 @@
level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2);
} else {
+ // CraftBukkit start - add event
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(AGE, 5), 2)) {
this.placeDeadFlower(level, pos);
+ }
+ // CraftBukkit end
}
} else {
+ // CraftBukkit start - add event
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(AGE, 5), 2)) {
this.placeDeadFlower(level, pos);
+ }
+ // CraftBukkit end
}
}
}
}
private void placeGrownFlower(Level level, BlockPos pos, int age) {
- level.setBlock(pos, this.defaultBlockState().setValue(AGE, age), 2);
+ // level.setBlock(pos, this.defaultBlockState().setValue(AGE, age), 2); // Paper - already done above in the event call
level.levelEvent(1033, pos, 0);
}
private void placeDeadFlower(Level level, BlockPos pos) {
- level.setBlock(pos, this.defaultBlockState().setValue(AGE, 5), 2);
+ // level.setBlock(pos, this.defaultBlockState().setValue(AGE, 5), 2); // Paper - already done above in the event call
level.levelEvent(1034, pos, 0);
}
@@ -261,6 +_,11 @@
protected void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) {
BlockPos blockPos = hit.getBlockPos();

View File

@@ -1,24 +1,24 @@
--- a/net/minecraft/world/level/block/CocoaBlock.java
+++ b/net/minecraft/world/level/block/CocoaBlock.java
@@ -64,10 +_,10 @@
@@ -50,10 +_,10 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- if (level.random.nextInt(5) == 0) {
+ if (level.random.nextFloat() < (level.spigotConfig.cocoaModifier / (100.0f * 5))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (level.random.nextFloat() < (level.spigotConfig.cocoaModifier / (100.0F * 5))) { // Spigot - SPIGOT-7159: Better modifier resolution
int ageValue = state.getValue(AGE);
if (ageValue < 2) {
- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(ageValue + 1)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(CocoaBlock.AGE, ageValue + 1), 2); // CraftBukkit
- level.setBlock(pos, state.setValue(AGE, ageValue + 1), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(AGE, ageValue + 1), 2); // CraftBukkit
}
}
}
@@ -141,7 +_,7 @@
@@ -116,7 +_,7 @@
@Override
public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) {
- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(state.getValue(AGE) + 1)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(CocoaBlock.AGE, state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit
- level.setBlock(pos, state.setValue(AGE, state.getValue(AGE) + 1), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(AGE, state.getValue(AGE) + 1), 2); // CraftBukkit
}
@Override

View File

@@ -5,7 +5,7 @@
private void setPoweredAndUpdate(Level level, BlockPos pos, CommandBlockEntity blockEntity, boolean powered) {
boolean isPowered = blockEntity.isPowered();
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ int old = isPowered ? 15 : 0;
+ int current = powered ? 15 : 0;
+

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -170,8 +_,18 @@
@@ -168,8 +_,18 @@
boolean shouldTurnOn = this.shouldTurnOn(level, pos, state);
boolean poweredValue = state.getValue(POWERED);
if (poweredValue && !shouldTurnOn) {
@@ -9,13 +9,13 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2);
level.setBlock(pos, state.setValue(POWERED, false), 2);
} else if (!poweredValue && shouldTurnOn) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2);
level.setBlock(pos, state.setValue(POWERED, true), 2);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ComposterBlock.java
+++ b/net/minecraft/world/level/block/ComposterBlock.java
@@ -243,6 +_,11 @@
@@ -252,6 +_,11 @@
if (levelValue < 8 && COMPOSTABLES.containsKey(stack.getItem())) {
if (levelValue < 7 && !level.isClientSide) {
BlockState blockState = addItem(player, state, level, pos, stack);
@@ -12,7 +12,7 @@
level.levelEvent(1500, pos, state != blockState ? 1 : 0);
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
stack.consume(1, player);
@@ -268,7 +_,19 @@
@@ -277,7 +_,19 @@
public static BlockState insertItem(Entity entity, BlockState state, ServerLevel level, ItemStack stack, BlockPos pos) {
int levelValue = state.getValue(LEVEL);
if (levelValue < 7 && COMPOSTABLES.containsKey(stack.getItem())) {
@@ -33,7 +33,7 @@
stack.shrink(1);
return blockState;
} else {
@@ -277,6 +_,14 @@
@@ -286,6 +_,14 @@
}
public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) {
@@ -48,7 +48,7 @@
if (!level.isClientSide) {
Vec3 vec3 = Vec3.atLowerCornerWithOffset(pos, 0.5, 1.01, 0.5).offsetRandom(level.random, 0.7F);
ItemEntity itemEntity = new ItemEntity(level, vec3.x(), vec3.y(), vec3.z(), new ItemStack(Items.BONE_MEAL));
@@ -296,14 +_,39 @@
@@ -305,14 +_,39 @@
return blockState;
}
@@ -80,7 +80,7 @@
return state;
} else {
int i = levelValue + 1;
BlockState blockState = state.setValue(LEVEL, Integer.valueOf(i));
BlockState blockState = state.setValue(LEVEL, i);
+ // Paper start - move the EntityChangeBlockEvent here to avoid conflict later for the compost events
+ if (entity != null && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, blockState)) {
+ return null;
@@ -89,7 +89,7 @@
level.setBlock(pos, blockState, 3);
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState));
if (i == 7) {
@@ -348,13 +_,14 @@
@@ -357,13 +_,14 @@
if (levelValue == 8) {
return new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL));
} else {
@@ -106,7 +106,7 @@
}
@Override
@@ -381,6 +_,7 @@
@@ -390,6 +_,7 @@
public InputContainer(BlockState state, LevelAccessor level, BlockPos pos) {
super(1);
@@ -114,7 +114,7 @@
this.state = state;
this.level = level;
this.pos = pos;
@@ -412,6 +_,11 @@
@@ -421,6 +_,11 @@
if (!item.isEmpty()) {
this.changed = true;
BlockState blockState = ComposterBlock.addItem(null, this.state, this.level, this.pos, item);
@@ -126,7 +126,7 @@
this.level.levelEvent(1500, this.pos, blockState != this.state ? 1 : 0);
this.removeItemNoUpdate(0);
}
@@ -426,6 +_,7 @@
@@ -435,6 +_,7 @@
public OutputContainer(BlockState state, LevelAccessor level, BlockPos pos, ItemStack stack) {
super(stack);
@@ -134,7 +134,7 @@
this.state = state;
this.level = level;
this.pos = pos;
@@ -453,8 +_,15 @@
@@ -462,8 +_,15 @@
@Override
public void setChanged() {

View File

@@ -9,6 +9,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2);
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, false), 2);
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/CoralPlantBlock.java
+++ b/net/minecraft/world/level/block/CoralPlantBlock.java
@@ -43,6 +_,11 @@
@@ -42,6 +_,11 @@
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!scanForWater(state, level, pos)) {
@@ -9,6 +9,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2);
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, false), 2);
}
}

View File

@@ -9,6 +9,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)).setValue(FACING, state.getValue(FACING)), 2);
level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, false).setValue(FACING, state.getValue(FACING)), 2);
}
}

View File

@@ -1,19 +1,11 @@
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -11,6 +_,7 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
+import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResult;
@@ -159,6 +_,13 @@
@@ -152,6 +_,13 @@
} else {
RecipeHolder<CraftingRecipe> recipeHolder = potentialResults.get();
ItemStack itemStack = recipeHolder.value().assemble(var11, level.registryAccess());
+ // CraftBukkit start
+ org.bukkit.event.block.CrafterCraftEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callCrafterCraftEvent(pos, level, crafterBlockEntity, itemStack, recipeHolder);
+ org.bukkit.event.block.CrafterCraftEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callCrafterCraftEvent(pos, level, itemStack, recipeHolder);
+ if (event.isCancelled()) {
+ return;
+ }
@@ -22,7 +14,7 @@
if (itemStack.isEmpty()) {
level.levelEvent(1050, pos, 0);
} else {
@@ -193,7 +_,25 @@
@@ -186,7 +_,25 @@
Container containerAt = HopperBlockEntity.getContainerAt(level, pos.relative(direction));
ItemStack itemStack = stack.copy();
if (containerAt != null && (containerAt instanceof CrafterBlockEntity || stack.getCount() > containerAt.getMaxStackSize(stack))) {
@@ -31,7 +23,7 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ if (containerAt instanceof net.minecraft.world.CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else {
+ destinationInventory = containerAt.getOwner().getInventory();
@@ -48,7 +40,7 @@
ItemStack itemStack1 = itemStack.copyWithCount(1);
ItemStack itemStack2 = HopperBlockEntity.addItem(crafter, containerAt, itemStack1, direction.getOpposite());
if (!itemStack2.isEmpty()) {
@@ -203,7 +_,25 @@
@@ -196,7 +_,25 @@
itemStack.shrink(1);
}
} else if (containerAt != null) {
@@ -57,7 +49,7 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ if (containerAt instanceof net.minecraft.world.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/CropBlock.java
+++ b/net/minecraft/world/level/block/CropBlock.java
@@ -88,8 +_,25 @@
@@ -80,8 +_,25 @@
int age = this.getAge(state);
if (age < this.getMaxAge()) {
float growthSpeed = getGrowthSpeed(this, level, pos);
@@ -22,25 +22,25 @@
+ modifier = level.spigotConfig.wheatModifier;
+ }
+
+ if (random.nextFloat() < (modifier / (100.0f * (Math.floor((25.0F / growthSpeed) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (random.nextFloat() < (modifier / (100.0F * (Math.floor((25.0F / growthSpeed) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ // Spigot end
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(age + 1), 2); // CraftBukkit
}
}
}
@@ -102,7 +_,7 @@
i = maxAge;
}
@@ -89,7 +_,7 @@
- level.setBlock(pos, this.getStateForAge(i), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i), 2); // CraftBukkit
public void growCrops(Level level, BlockPos pos, BlockState state) {
int min = Math.min(this.getMaxAge(), this.getAge(state) + this.getBonemealAgeIncrease(level));
- level.setBlock(pos, this.getStateForAge(min), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(min), 2); // CraftBukkit
}
protected int getBonemealAgeIncrease(Level level) {
@@ -164,7 +_,8 @@
@@ -151,7 +_,8 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
- if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
+ if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit

View File

@@ -5,6 +5,6 @@
i = Mth.clamp(i, 0, 15);
if (state.getValue(POWER) != i) {
+ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, state.getValue(DaylightDetectorBlock.POWER), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent
level.setBlock(pos, state.setValue(POWER, Integer.valueOf(i)), 3);
level.setBlock(pos, state.setValue(POWER, i), 3);
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -237,6 +_,11 @@
@@ -210,6 +_,11 @@
protected void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) {
BlockPos blockPos = hit.getBlockPos();
if (level instanceof ServerLevel serverLevel && projectile.mayInteract(serverLevel, blockPos) && projectile.mayBreak(serverLevel)) {
@@ -9,6 +9,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(blockPos, state.setValue(CRACKED, Boolean.valueOf(true)), 4);
level.setBlock(blockPos, state.setValue(CRACKED, true), 260);
level.destroyBlock(blockPos, true, projectile);
}

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/level/block/DetectorRailBlock.java
+++ b/net/minecraft/world/level/block/DetectorRailBlock.java
@@ -54,6 +_,7 @@
@@ -49,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide) {
if (!state.getValue(POWERED)) {
this.checkPressed(level, pos, state);
@@ -84,6 +_,7 @@
@@ -79,6 +_,7 @@
private void checkPressed(Level level, BlockPos pos, BlockState state) {
if (this.canSurvive(state, level, pos)) {
@@ -16,13 +16,13 @@
boolean poweredValue = state.getValue(POWERED);
boolean flag = false;
List<AbstractMinecart> interactingMinecartOfType = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, entity -> true);
@@ -91,6 +_,16 @@
@@ -86,6 +_,16 @@
flag = true;
}
+ // CraftBukkit start
+ if (poweredValue != flag) {
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(block, flag ? 15 : 0, flag ? 15 : 0);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
@@ -31,5 +31,5 @@
+ }
+ // CraftBukkit end
if (flag && !poweredValue) {
BlockState blockState = state.setValue(POWERED, Boolean.valueOf(true));
BlockState blockState = state.setValue(POWERED, true);
level.setBlock(pos, blockState, 3);

View File

@@ -9,13 +9,13 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2);
level.setBlock(pos, state.setValue(POWERED, false), 2);
} else if (!poweredValue) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2);
level.setBlock(pos, state.setValue(POWERED, true), 2);
if (!shouldTurnOn) {
level.scheduleTick(pos, this, this.getDelay(state), TickPriority.VERY_HIGH);

View File

@@ -1,13 +1,5 @@
--- a/net/minecraft/world/level/block/DispenserBlock.java
+++ b/net/minecraft/world/level/block/DispenserBlock.java
@@ -50,6 +_,7 @@
private static final DefaultDispenseItemBehavior DEFAULT_BEHAVIOR = new DefaultDispenseItemBehavior();
public static final Map<Item, DispenseItemBehavior> DISPENSER_REGISTRY = new IdentityHashMap<>();
private static final int TRIGGER_DURATION = 4;
+ public static boolean eventFired = false; // CraftBukkit
@Override
public MapCodec<? extends DispenserBlock> codec() {
@@ -71,8 +_,7 @@
@Override
@@ -18,7 +10,7 @@
player.awardStat(dispenserBlockEntity instanceof DropperBlockEntity ? Stats.INSPECT_DROPPER : Stats.INSPECT_DISPENSER);
}
@@ -87,18 +_,27 @@
@@ -87,17 +_,26 @@
BlockSource blockSource = new BlockSource(level, pos, state, dispenserBlockEntity);
int randomSlot = dispenserBlockEntity.getRandomSlot(level.random);
if (randomSlot < 0) {
@@ -31,18 +23,17 @@
DispenseItemBehavior dispenseMethod = this.getDispenseMethod(level, item);
if (dispenseMethod != DispenseItemBehavior.NOOP) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(level, pos, item, randomSlot)) return; // Paper - Add BlockPreDispenseEvent
+ DispenserBlock.eventFired = false; // CraftBukkit - reset event status
dispenserBlockEntity.setItem(randomSlot, dispenseMethod.dispense(blockSource, item));
}
}
}
}
+
+ // Paper start - Fix NPE with equippable and items without behavior
+ public static DispenseItemBehavior getDispenseBehavior(BlockSource pointer, ItemStack stack) {
+ return ((DispenserBlock) pointer.state().getBlock()).getDispenseMethod(pointer.level(), stack);
+ }
+ // Paper end - Fix NPE with equippable and items without behavior
protected DispenseItemBehavior getDispenseMethod(Level level, ItemStack item) {
if (!item.isItemEnabled(level.enabledFeatures())) {
return DEFAULT_BEHAVIOR;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/DoorBlock.java
+++ b/net/minecraft/world/level/block/DoorBlock.java
@@ -229,9 +_,22 @@
@@ -222,9 +_,22 @@
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -112,11 +_,16 @@
@@ -110,11 +_,16 @@
}
@Override

View File

@@ -1,22 +1,5 @@
--- a/net/minecraft/world/level/block/DropperBlock.java
+++ b/net/minecraft/world/level/block/DropperBlock.java
@@ -8,6 +_,7 @@
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@@ -23,7 +_,7 @@
public class DropperBlock extends DispenserBlock {
private static final Logger LOGGER = LogUtils.getLogger();
public static final MapCodec<DropperBlock> CODEC = simpleCodec(DropperBlock::new);
- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior();
+ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit
@Override
public MapCodec<DropperBlock> codec() {
@@ -53,6 +_,7 @@
BlockSource blockSource = new BlockSource(level, pos, state, dispenserBlockEntity);
int randomSlot = dispenserBlockEntity.getRandomSlot(level.random);
@@ -39,7 +22,7 @@
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer compoundContainer) {
+ if (containerAt instanceof net.minecraft.world.CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else {
+ destinationInventory = containerAt.getOwner().getInventory();

View File

@@ -1,22 +1,22 @@
--- a/net/minecraft/world/level/block/EndGatewayBlock.java
+++ b/net/minecraft/world/level/block/EndGatewayBlock.java
@@ -89,10 +_,15 @@
@@ -90,10 +_,15 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)
&& !level.isClientSide
&& level.getBlockEntity(pos) instanceof TheEndGatewayBlockEntity theEndGatewayBlockEntity
&& !theEndGatewayBlockEntity.isCoolingDown()) {
+ // Paper start - call EntityPortalEnterEvent
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type
+ if (!event.callEvent()) return;
+ // Paper end - call EntityPortalEnterEvent
entity.setAsInsidePortal(this, pos);
TheEndGatewayBlockEntity.triggerCooldown(level, pos, state, theEndGatewayBlockEntity);
}
@@ -107,9 +_,9 @@
@@ -108,9 +_,9 @@
return null;
} else {
return entity instanceof ThrownEnderpearl

View File

@@ -1,13 +1,13 @@
--- a/net/minecraft/world/level/block/EndPortalBlock.java
+++ b/net/minecraft/world/level/block/EndPortalBlock.java
@@ -56,8 +_,15 @@
@@ -57,8 +_,15 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // CraftBukkit start - Entity in portal
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.ENDER); // Paper - add portal type
+ level.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
+ // CraftBukkit end
@@ -16,7 +16,7 @@
serverPlayer.showEndCredits();
} else {
entity.setAsInsidePortal(this, pos);
@@ -67,7 +_,7 @@
@@ -68,7 +_,7 @@
@Override
public TeleportTransition getPortalDestination(ServerLevel level, Entity entity, BlockPos pos) {
@@ -25,7 +25,7 @@
ServerLevel level1 = level.getServer().getLevel(resourceKey);
if (level1 == null) {
return null;
@@ -78,7 +_,7 @@
@@ -79,7 +_,7 @@
float f;
Set<Relative> set;
if (flag) {
@@ -34,7 +34,7 @@
f = Direction.WEST.toYRot();
set = Relative.union(Relative.DELTA, Set.of(Relative.X_ROT));
if (entity instanceof ServerPlayer) {
@@ -88,15 +_,23 @@
@@ -89,15 +_,23 @@
f = 0.0F;
set = Relative.union(Relative.DELTA, Relative.ROTATION);
if (entity instanceof ServerPlayer serverPlayer) {
@@ -57,7 +57,7 @@
+ }
+ org.bukkit.Location to = event.getTo();
+
+ return new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3D(to), Vec3.ZERO, to.getYaw(), to.getPitch(), set, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL);
+ return new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3(to), Vec3.ZERO, to.getYaw(), to.getPitch(), set, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL);
+ // CraftBukkit end
}
}

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/world/level/block/EyeblossomBlock.java
+++ b/net/minecraft/world/level/block/EyeblossomBlock.java
@@ -99,6 +_,7 @@
@@ -100,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide()
&& level.getDifficulty() != Difficulty.PEACEFUL

View File

@@ -8,22 +8,22 @@
+ if (moistureValue == 0 && level.paperConfig().tickRates.dryFarmland != 1 && (level.paperConfig().tickRates.dryFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % level.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks
if (!isNearWater(level, pos) && !level.isRainingAt(pos.above())) {
if (moistureValue > 0) {
- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(moistureValue - 1)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, state.setValue(FarmBlock.MOISTURE, moistureValue - 1), 2); // CraftBukkit
- level.setBlock(pos, state.setValue(MOISTURE, moistureValue - 1), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, state.setValue(MOISTURE, moistureValue - 1), 2); // CraftBukkit
} else if (!shouldMaintainFarmland(level, pos)) {
turnToDirt(null, state, level, pos);
}
} else if (moistureValue < 7) {
- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(7)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit
- level.setBlock(pos, state.setValue(MOISTURE, 7), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, state.setValue(MOISTURE, 7), 2); // CraftBukkit
}
}
@Override
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) {
+ super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage.
if (level instanceof ServerLevel serverLevel
&& level.random.nextFloat() < fallDistance - 0.5F
&& level.random.nextFloat() < fallDistance - 0.5
&& entity instanceof LivingEntity
&& (entity instanceof Player || serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))
&& entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) {
@@ -32,7 +32,7 @@
+ if (entity instanceof Player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, 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()));
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/net/minecraft/world/level/block/FenceGateBlock.java
@@ -213,6 +_,17 @@
@@ -199,6 +_,17 @@
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {
if (!level.isClientSide) {
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
@@ -16,5 +16,5 @@
+ }
+ // CraftBukkit end
if (state.getValue(POWERED) != hasNeighborSignal) {
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)).setValue(OPEN, Boolean.valueOf(hasNeighborSignal)), 2);
level.setBlock(pos, state.setValue(POWERED, hasNeighborSignal).setValue(OPEN, hasNeighborSignal), 2);
if (state.getValue(OPEN) != hasNeighborSignal) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/FireBlock.java
+++ b/net/minecraft/world/level/block/FireBlock.java
@@ -122,7 +_,25 @@
@@ -101,7 +_,25 @@
BlockState neighborState,
RandomSource random
) {
@@ -27,95 +27,94 @@
}
@Override
@@ -162,10 +_,10 @@
@@ -141,11 +_,11 @@
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- level.scheduleTick(pos, this, getFireTickDelay(level.random));
+ 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);
+ this.fireExtinguished(level, pos); // CraftBukkit - invalid place location
}
BlockState blockState = level.getBlockState(pos.below());
@@ -184,26 +_,28 @@
if (!this.isValidFireLocation(level, pos)) {
BlockPos blockPos = pos.below();
if (!level.getBlockState(blockPos).isFaceSturdy(level, blockPos, Direction.UP) || ageValue > 3) {
- level.removeBlock(pos, false);
+ this.fireExtinguished(level, pos); // CraftBukkit - extinguished by rain
}
return;
}
if (ageValue == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) {
- level.removeBlock(pos, false);
+ this.fireExtinguished(level, pos); // CraftBukkit
return;
}
if (level.getGameRules().getBoolean(GameRules.RULE_ALLOWFIRETICKAWAYFROMPLAYERS) || level.anyPlayerCloseEnoughForSpawning(pos)) {
if (!state.canSurvive(level, pos)) {
- level.removeBlock(pos, false);
+ this.fireExtinguished(level, pos); // CraftBukkit - invalid place location
}
boolean isIncreasedFireBurnout = level.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT);
int i = isIncreasedFireBurnout ? -50 : 0;
- this.checkBurnOut(level, pos.east(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.west(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.below(), 250 + i, random, ageValue);
- this.checkBurnOut(level, pos.above(), 250 + i, random, ageValue);
- this.checkBurnOut(level, pos.north(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue);
+ // CraftBukkit start - add source blockposition to burn calls
+ this.checkBurnOut(level, pos.east(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.west(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.below(), 250 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.above(), 250 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.north(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue, pos);
+ // CraftBukkit end
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
BlockState blockState = level.getBlockState(pos.below());
@@ -164,26 +_,28 @@
if (!this.isValidFireLocation(level, pos)) {
BlockPos blockPos = pos.below();
if (!level.getBlockState(blockPos).isFaceSturdy(level, blockPos, Direction.UP) || ageValue > 3) {
- level.removeBlock(pos, false);
+ this.fireExtinguished(level, pos); // CraftBukkit - extinguished by rain
}
for (int i1 = -1; i1 <= 1; i1++) {
@@ -225,7 +_,15 @@
return;
}
if (i5 > 0 && random.nextInt(i4) <= i5 && (!level.isRaining() || !this.isNearRain(level, mutableBlockPos))) {
int min1 = Math.min(15, ageValue + random.nextInt(5) / 4);
- level.setBlock(mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3);
+ // CraftBukkit start - Call to stop spread of fire
+ if (level.getBlockState(mutableBlockPos).getBlock() != Blocks.FIRE) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, mutableBlockPos, pos).isCancelled()) {
+ continue;
+ }
if (ageValue == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) {
- level.removeBlock(pos, false);
+ this.fireExtinguished(level, pos); // CraftBukkit
return;
}
}
boolean isIncreasedFireBurnout = level.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT);
int i = isIncreasedFireBurnout ? -50 : 0;
- this.checkBurnOut(level, pos.east(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.west(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.below(), 250 + i, random, ageValue);
- this.checkBurnOut(level, pos.above(), 250 + i, random, ageValue);
- this.checkBurnOut(level, pos.north(), 300 + i, random, ageValue);
- this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue);
+ // CraftBukkit start - add source blockPos to burn calls
+ this.checkBurnOut(level, pos.east(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.west(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.below(), 250 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.above(), 250 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.north(), 300 + i, random, ageValue, pos);
+ this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue, pos);
+ // CraftBukkit end
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
for (int i1 = -1; i1 <= 1; i1++) {
@@ -205,7 +_,15 @@
if (i5 > 0 && random.nextInt(i4) <= i5 && (!level.isRaining() || !this.isNearRain(level, mutableBlockPos))) {
int min1 = Math.min(15, ageValue + random.nextInt(5) / 4);
- level.setBlock(mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3);
+ // CraftBukkit start - Call to stop spread of fire
+ if (!level.getBlockState(mutableBlockPos).is(Blocks.FIRE)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, mutableBlockPos, pos).isCancelled()) {
+ continue;
+ }
+
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3); // CraftBukkit
+ }
+ // CraftBukkit end
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3); // CraftBukkit
+ }
+ // CraftBukkit end
}
}
}
}
@@ -256,19 +_,42 @@
@@ -237,19 +_,40 @@
: this.igniteOdds.getInt(state.getBlock());
}
- private void checkBurnOut(Level level, BlockPos pos, int chance, RandomSource random, int age) {
+ private void checkBurnOut(Level level, BlockPos pos, int chance, RandomSource random, int age, BlockPos sourceposition) { // CraftBukkit add sourceposition
+ private void checkBurnOut(Level level, BlockPos pos, int chance, RandomSource random, int age, BlockPos sourcePos) { // CraftBukkit add sourcePos
int burnOdds = this.getBurnOdds(level.getBlockState(pos));
if (random.nextInt(chance) < burnOdds) {
BlockState blockState = level.getBlockState(pos);
+
+ // CraftBukkit start
+ org.bukkit.block.Block theBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block sourceBlock = level.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ());
+ org.bukkit.block.Block burnBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ org.bukkit.block.Block sourceBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, sourcePos);
+
+ org.bukkit.event.block.BlockBurnEvent event = new org.bukkit.event.block.BlockBurnEvent(theBlock, sourceBlock);
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ org.bukkit.event.block.BlockBurnEvent event = new org.bukkit.event.block.BlockBurnEvent(burnBlock, sourceBlock);
+ if (!event.callEvent()) {
+ return;
+ }
+
+ if (blockState.getBlock() instanceof TntBlock && !org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) {
+ if (blockState.getBlock() instanceof TntBlock && !org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourcePos)) {
+ return;
+ }
+ // CraftBukkit end
@@ -136,10 +135,10 @@
+ }
+ level.removeBlock(pos, false);
+ // Paper end - TNTPrimeEvent
TntBlock.explode(level, pos);
TntBlock.prime(level, pos);
}
}
@@ -310,13 +_,14 @@
@@ -291,13 +_,14 @@
}
@Override

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/FlowerPotBlock.java
+++ b/net/minecraft/world/level/block/FlowerPotBlock.java
@@ -67,6 +_,18 @@
@@ -66,6 +_,18 @@
} else if (!this.isEmpty()) {
return InteractionResult.CONSUME;
} else {
@@ -19,7 +19,7 @@
level.setBlock(pos, blockState, 3);
level.gameEvent(player, GameEvent.BLOCK_CHANGE, pos);
player.awardStat(Stats.POT_FLOWER);
@@ -81,6 +_,18 @@
@@ -80,6 +_,18 @@
return InteractionResult.CONSUME;
} else {
ItemStack itemStack = new ItemStack(this.potted);

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/level/block/FrogspawnBlock.java
+++ b/net/minecraft/world/level/block/FrogspawnBlock.java
@@ -89,6 +_,7 @@
@@ -90,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.getType().equals(EntityType.FALLING_BLOCK)) {
this.destroyBlock(level, pos);
}
@@ -101,6 +_,11 @@
@@ -102,6 +_,11 @@
}
private void hatchFrogspawn(ServerLevel level, BlockPos pos, RandomSource random) {
@@ -20,9 +20,9 @@
this.destroyBlock(level, pos);
level.playSound(null, pos, SoundEvents.FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
this.spawnTadpoles(level, pos, random);
@@ -121,7 +_,7 @@
@@ -122,7 +_,7 @@
int randomInt1 = random.nextInt(1, 361);
tadpole.moveTo(d, pos.getY() - 0.5, d1, randomInt1, 0.0F);
tadpole.snapTo(d, pos.getY() - 0.5, d1, randomInt1, 0.0F);
tadpole.setPersistenceRequired();
- level.addFreshEntity(tadpole);
+ level.addFreshEntity(tadpole, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/GrindstoneBlock.java
+++ b/net/minecraft/world/level/block/GrindstoneBlock.java
@@ -151,8 +_,7 @@
@@ -72,8 +_,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {

View File

@@ -21,7 +21,7 @@
BlockPos blockPos = pos.relative(this.growthDirection);
if (this.canGrowInto(level.getBlockState(blockPos))) {
- level.setBlockAndUpdate(blockPos, this.getGrowIntoState(state, level.random));
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, this.getGrowIntoState(state, level.random, level)); // CraftBukkit // Paper - Fix Spigot growth modifiers
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, this.getGrowIntoState(state, level.random, level), 3); // CraftBukkit // Paper - Fix Spigot growth modifiers
}
}
}

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/world/level/block/HoneyBlock.java
+++ b/net/minecraft/world/level/block/HoneyBlock.java
@@ -60,6 +_,7 @@
@@ -61,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (this.isSlidingDown(pos, entity)) {
this.maybeDoSlideAchievement(entity, pos);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/HopperBlock.java
+++ b/net/minecraft/world/level/block/HopperBlock.java
@@ -125,8 +_,7 @@
@@ -106,8 +_,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
@@ -10,10 +10,10 @@
player.awardStat(Stats.INSPECT_HOPPER);
}
@@ -178,6 +_,7 @@
@@ -158,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof HopperBlockEntity) {

View File

@@ -14,7 +14,7 @@
) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return neighborState.is(this)
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false))
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), false)
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
@@ -74,6 +_,7 @@

View File

@@ -3,7 +3,7 @@
@@ -52,7 +_,7 @@
Silverfish silverfish = EntityType.SILVERFISH.create(level, EntitySpawnReason.TRIGGERED);
if (silverfish != null) {
silverfish.moveTo(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0.0F, 0.0F);
silverfish.snapTo(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0.0F, 0.0F);
- level.addFreshEntity(silverfish);
+ level.addFreshEntity(silverfish, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason
silverfish.spawnAnim();

View File

@@ -1,10 +1,15 @@
--- a/net/minecraft/world/level/block/LavaCauldronBlock.java
+++ b/net/minecraft/world/level/block/LavaCauldronBlock.java
@@ -32,6 +_,7 @@
@@ -33,9 +_,10 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (this.isEntityInsideContent(state, pos, entity)) {
entity.lavaHurt();
- entity.lavaIgnite();
- entity.lavaHurt();
+ entity.lavaIgnite(pos); // Paper - track lava contact
+ entity.lavaHurt(pos); // Paper - track lava contact
}
}

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -61,35 +_,68 @@
@@ -62,35 +_,67 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (level instanceof ServerLevel serverLevel && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) {
- entity.clearFire();
@@ -22,32 +22,29 @@
- private void handleEntityOnFireInside(BlockState state, Level level, BlockPos pos) {
+ // CraftBukkit start
+ private boolean handleEntityOnFireInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ private boolean handleEntityOnFireInside(BlockState state, Level level, BlockPos pos, @javax.annotation.Nullable Entity entity) {
if (this.precipitationType == Biome.Precipitation.SNOW) {
- lowerFillLevel(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LEVEL, state.getValue(LEVEL)), level, pos);
+ return LayeredCauldronBlock.lowerFillLevel((BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL)), level, pos, entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.EXTINGUISH); // CraftBukkit
+ return lowerFillLevel(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LEVEL, state.getValue(LEVEL)), level, pos, entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.EXTINGUISH); // CraftBukkit
} else {
- lowerFillLevel(state, level, pos);
+ return LayeredCauldronBlock.lowerFillLevel(state, level, pos, entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.EXTINGUISH); // CraftBukkit
+ return lowerFillLevel(state, level, pos, entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.EXTINGUISH); // CraftBukkit
}
}
public static void lowerFillLevel(BlockState state, Level level, BlockPos pos) {
- int i = state.getValue(LEVEL) - 1;
- BlockState blockState = i == 0 ? Blocks.CAULDRON.defaultBlockState() : state.setValue(LEVEL, Integer.valueOf(i));
+ // Paper start
+ lowerFillLevel(state, level, pos, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.UNKNOWN);
+ }
+ public static boolean lowerFillLevel(BlockState state, Level level, BlockPos pos, @javax.annotation.Nullable Entity entity, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason reason) {
+ // Paper end
int i = state.getValue(LEVEL) - 1;
BlockState blockState = i == 0 ? Blocks.CAULDRON.defaultBlockState() : state.setValue(LEVEL, i);
- level.setBlockAndUpdate(pos, blockState);
- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState));
- }
+ // CraftBukkit start
+ LayeredCauldronBlock.lowerFillLevel(state, level, pos, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.UNKNOWN);
+ return changeLevel(level, pos, blockState, entity, reason); // Paper
+ }
+ 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, pos, iblockdata1, entity, reason);
+ }
+
+ // CraftBukkit start
+ // Paper start - Call CauldronLevelChangeEvent
+ 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
@@ -66,7 +63,7 @@
+ if (!event.callEvent()) {
+ return false;
+ }
+ newState.update(true);
+ newState.place(3);
+ if (sendGameEvent) level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(newBlock)); // Paper - Call CauldronLevelChangeEvent
+ return true;
+ }
@@ -78,18 +75,18 @@
BlockState blockState = state.cycle(LEVEL);
- level.setBlockAndUpdate(pos, blockState);
- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState));
+ LayeredCauldronBlock.changeLevel(level, pos, blockState, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit
+ changeLevel(level, pos, blockState, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit
}
}
@@ -107,8 +_,11 @@
@@ -108,8 +_,11 @@
protected void receiveStalactiteDrip(BlockState state, Level level, BlockPos pos, Fluid fluid) {
if (!this.isFull(state)) {
BlockState blockState = state.setValue(LEVEL, Integer.valueOf(state.getValue(LEVEL) + 1));
BlockState blockState = state.setValue(LEVEL, state.getValue(LEVEL) + 1);
- level.setBlockAndUpdate(pos, blockState);
- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState));
+ // CraftBukkit start
+ if (!LayeredCauldronBlock.changeLevel(level, pos, blockState, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) {
+ if (!changeLevel(level, pos, blockState, null, org.bukkit.event.block.CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) {
+ return;
+ }
+ // CraftBukkit end

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/level/block/LeavesBlock.java
+++ b/net/minecraft/world/level/block/LeavesBlock.java
@@ -63,6 +_,14 @@
@@ -56,6 +_,14 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (this.decaying(state)) {
+ // CraftBukkit start
+ org.bukkit.event.block.LeavesDecayEvent event = new org.bukkit.event.block.LeavesDecayEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ org.bukkit.event.block.LeavesDecayEvent event = new org.bukkit.event.block.LeavesDecayEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled() || level.getBlockState(pos).getBlock() != this) {
+ if (event.isCancelled() || !level.getBlockState(pos).is(this)) {
+ return;
+ }
+ // CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/LecternBlock.java
+++ b/net/minecraft/world/level/block/LecternBlock.java
@@ -169,7 +_,24 @@
@@ -136,7 +_,24 @@
private static void placeBook(@Nullable LivingEntity entity, Level level, BlockPos pos, BlockState state, ItemStack stack) {
if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) {
@@ -26,7 +26,7 @@
resetBookState(entity, level, pos, state, true);
level.playSound(null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F);
}
@@ -189,6 +_,16 @@
@@ -156,6 +_,16 @@
}
private static void changePowered(Level level, BlockPos pos, BlockState state, boolean powered) {
@@ -40,22 +40,10 @@
+ }
+ }
+ // Paper end - Call BlockRedstoneEvent properly
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(powered)), 3);
level.setBlock(pos, state.setValue(POWERED, powered), 3);
updateBelow(level, pos, state);
}
@@ -218,9 +_,10 @@
}
private void popBook(BlockState state, Level level, BlockPos pos) {
- if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) {
+ if (level.getBlockEntity(pos, false) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already
Direction direction = state.getValue(FACING);
ItemStack itemStack = lecternBlockEntity.getBook().copy();
+ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
float f = 0.25F * direction.getStepX();
float f1 = 0.25F * direction.getStepZ();
ItemEntity itemEntity = new ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack);
@@ -296,8 +_,7 @@
@@ -243,8 +_,7 @@
private void openScreen(Level level, BlockPos pos, Player player) {
BlockEntity blockEntity = level.getBlockEntity(pos);

View File

@@ -1,12 +1,12 @@
--- a/net/minecraft/world/level/block/LeverBlock.java
+++ b/net/minecraft/world/level/block/LeverBlock.java
@@ -100,6 +_,19 @@
@@ -68,6 +_,19 @@
makeParticle(blockState, level, pos, 1.0F);
}
} else {
+ // CraftBukkit start - Interact Lever
+ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/LightningRodBlock.java
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
@@ -84,6 +_,18 @@
@@ -82,6 +_,18 @@
}
public void onLightningStrike(BlockState state, Level level, BlockPos pos) {
@@ -16,6 +16,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 3);
level.setBlock(pos, state.setValue(POWERED, true), 3);
this.updateNeighbours(state, level, pos);
level.scheduleTick(pos, this, 8);

View File

@@ -48,7 +48,7 @@
- level.setBlockAndUpdate(pos, block.defaultBlockState());
- this.fizz(level, pos);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState(), 3)) {
+ this.fizz(level, pos);
+ }
+ // CraftBukkit end
@@ -59,7 +59,7 @@
- level.setBlockAndUpdate(pos, Blocks.BASALT.defaultBlockState());
- this.fizz(level, pos);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState(), 3)) {
+ this.fizz(level, pos);
+ }
+ // CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/MangrovePropaguleBlock.java
+++ b/net/minecraft/world/level/block/MangrovePropaguleBlock.java
@@ -123,7 +_,7 @@
@@ -103,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!isHanging(state)) {

View File

@@ -5,7 +5,7 @@
}
- return level.setBlock(pos.pos(), stateForPlacement, 2);
+ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), stateForPlacement, 2); // CraftBukkit
+ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), stateForPlacement, 2, true); // CraftBukkit
} else {
return false;
}

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/level/block/MushroomBlock.java
+++ b/net/minecraft/world/level/block/MushroomBlock.java
@@ -47,7 +_,7 @@
@@ -46,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- if (random.nextInt(25) == 0) {
+ if (random.nextFloat() < (level.spigotConfig.mushroomModifier / (100.0f * 25))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (random.nextFloat() < (level.spigotConfig.mushroomModifier / (100.0F * 25))) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = 5;
int i1 = 4;
@@ -60,6 +_,7 @@
@@ -59,6 +_,7 @@
}
BlockPos blockPos1 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
@@ -17,7 +17,7 @@
for (int i2 = 0; i2 < 4; i2++) {
if (level.isEmptyBlock(blockPos1) && state.canSurvive(level, blockPos1)) {
@@ -70,7 +_,7 @@
@@ -69,7 +_,7 @@
}
if (level.isEmptyBlock(blockPos1) && state.canSurvive(level, blockPos1)) {
@@ -26,7 +26,7 @@
}
}
}
@@ -93,6 +_,7 @@
@@ -92,6 +_,7 @@
return false;
} else {
level.removeBlock(pos, false);

View File

@@ -7,9 +7,9 @@
- if (level.dimensionType().natural()
+ if (level.spigotConfig.enableZombiePigmenPortalSpawns && level.dimensionType().natural() // Spigot
&& level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)
&& random.nextInt(2000) < level.getDifficulty().getId()) {
while (level.getBlockState(pos).is(this)) {
@@ -78,9 +_,13 @@
&& random.nextInt(2000) < level.getDifficulty().getId()
&& level.anyPlayerCloseEnoughForSpawning(pos)) {
@@ -79,9 +_,13 @@
}
if (level.getBlockState(pos).isValidSpawn(level, pos, EntityType.ZOMBIFIED_PIGLIN)) {
@@ -24,21 +24,21 @@
Entity vehicle = entity.getVehicle();
if (vehicle != null) {
vehicle.setPortalCooldown();
@@ -111,7 +_,13 @@
@@ -112,7 +_,13 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // CraftBukkit start - Entity in portal
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level), org.bukkit.PortalType.NETHER); // Paper - add portal type
+ level.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
+ // CraftBukkit end
entity.setAsInsidePortal(this, pos);
}
}
@@ -134,22 +_,46 @@
@@ -135,22 +_,46 @@
@Nullable
@Override
public TeleportTransition getPortalDestination(ServerLevel level, Entity entity, BlockPos pos) {
@@ -90,7 +90,7 @@
BlockUtil.FoundRectangle largestRectangleAround;
TeleportTransition.PostTeleportTransition postTeleportTransition;
if (optional.isPresent()) {
@@ -164,17 +_,22 @@
@@ -165,17 +_,22 @@
blockPos1 -> level.getBlockState(blockPos1) == blockState
);
postTeleportTransition = TeleportTransition.PLAY_PORTAL_SOUND.then(entity1 -> entity1.placePortalTicket(blockPos));
@@ -116,7 +116,7 @@
return getDimensionTransitionFromExit(entity, pos, largestRectangleAround, level, postTeleportTransition);
}
@@ -220,7 +_,7 @@
@@ -221,7 +_,7 @@
boolean flag = axis1 == Direction.Axis.X;
Vec3 vec3 = new Vec3(blockPos.getX() + (flag ? d2 : d4), blockPos.getY() + d3, blockPos.getZ() + (flag ? d4 : d2));
Vec3 vec31 = PortalShape.findCollisionFreePosition(vec3, level, entity, dimensions);

View File

@@ -1,12 +1,12 @@
--- a/net/minecraft/world/level/block/NetherWartBlock.java
+++ b/net/minecraft/world/level/block/NetherWartBlock.java
@@ -55,9 +_,9 @@
@@ -50,9 +_,9 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
int ageValue = state.getValue(AGE);
- if (ageValue < 3 && random.nextInt(10) == 0) {
+ if (ageValue < 3 && random.nextFloat() < (level.spigotConfig.wartModifier / (100.0f * 10))) { // Spigot - SPIGOT-7159: Better modifier resolution
state = state.setValue(AGE, Integer.valueOf(ageValue + 1));
+ if (ageValue < 3 && random.nextFloat() < (level.spigotConfig.wartModifier / (100.0F * 10))) { // Spigot - SPIGOT-7159: Better modifier resolution
state = state.setValue(AGE, ageValue + 1);
- level.setBlock(pos, state, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/NoteBlock.java
+++ b/net/minecraft/world/level/block/NoteBlock.java
@@ -70,6 +_,7 @@
@@ -64,6 +_,7 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
@@ -8,7 +8,7 @@
return this.setInstrument(context.getLevel(), context.getClickedPos(), this.defaultBlockState());
}
@@ -84,6 +_,7 @@
@@ -78,6 +_,7 @@
BlockState neighborState,
RandomSource random
) {
@@ -16,7 +16,7 @@
boolean flag = direction.getAxis() == Direction.Axis.Y;
return flag
? this.setInstrument(level, pos, state)
@@ -92,10 +_,12 @@
@@ -86,10 +_,12 @@
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {
@@ -28,8 +28,8 @@
+ state = level.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event
}
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 3);
@@ -121,7 +_,7 @@
level.setBlock(pos, state.setValue(POWERED, hasNeighborSignal), 3);
@@ -115,7 +_,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (!level.isClientSide) {
@@ -38,7 +38,7 @@
level.setBlock(pos, state, 3);
this.playNote(player, state, level, pos);
player.awardStat(Stats.TUNE_NOTEBLOCK);
@@ -145,9 +_,13 @@
@@ -139,9 +_,13 @@
@Override
protected boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) {
NoteBlockInstrument noteBlockInstrument = state.getValue(INSTRUMENT);
@@ -53,7 +53,7 @@
pitchFromNote = getPitchFromNote(noteValue);
level.addParticle(ParticleTypes.NOTE, pos.getX() + 0.5, pos.getY() + 1.2, pos.getZ() + 0.5, noteValue / 24.0, 0.0, 0.0);
} else {
@@ -163,7 +_,7 @@
@@ -157,7 +_,7 @@
holder = Holder.direct(SoundEvent.createVariableRangeEvent(customSoundId));
} else {

View File

@@ -9,13 +9,13 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2);
level.setBlock(pos, state.setValue(POWERED, false), 2);
} else {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2);
level.setBlock(pos, state.setValue(POWERED, true), 2);
level.scheduleTick(pos, this, 2);
}

View File

@@ -1,14 +1,14 @@
--- a/net/minecraft/world/level/block/PitcherCropBlock.java
+++ b/net/minecraft/world/level/block/PitcherCropBlock.java
@@ -107,6 +_,7 @@
@@ -118,6 +_,7 @@
@Override
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
serverLevel.destroyBlock(pos, true, entity);
}
@@ -131,7 +_,7 @@
@@ -140,7 +_,7 @@
@Override
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
float growthSpeed = CropBlock.getGrowthSpeed(this, level, pos);
@@ -17,10 +17,10 @@
if (flag) {
this.grow(level, state, pos, 1);
}
@@ -141,7 +_,7 @@
@@ -150,7 +_,7 @@
int min = Math.min(state.getValue(AGE) + ageIncrement, 4);
if (this.canGrow(level, pos, state, min)) {
BlockState blockState = state.setValue(AGE, Integer.valueOf(min));
BlockState blockState = state.setValue(AGE, min);
- level.setBlock(pos, blockState, 2);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, blockState, 2)) return; // Paper
if (isDouble(min)) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -147,6 +_,11 @@
@@ -143,6 +_,11 @@
&& projectile.mayBreak(serverLevel)
&& projectile instanceof ThrownTrident
&& projectile.getDeltaMovement().length() > 0.6) {
@@ -12,21 +12,21 @@
level.destroyBlock(blockPos, true);
}
}
@@ -155,7 +_,7 @@
@@ -151,7 +_,7 @@
@Override
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) {
if (state.getValue(TIP_DIRECTION) == Direction.UP && state.getValue(THICKNESS) == DripstoneThickness.TIP) {
- entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite());
+ entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite().eventBlockDamager(level, pos)); // CraftBukkit
- entity.causeFallDamage(fallDistance + 2.5, 2.0F, level.damageSources().stalagmite());
+ entity.causeFallDamage(fallDistance + 2.5, 2.0F, level.damageSources().stalagmite().eventBlockDamager(level, pos)); // CraftBukkit
} else {
super.fallOn(level, state, pos, entity, fallDistance);
}
@@ -213,10 +_,11 @@
@@ -209,10 +_,11 @@
if (blockPos != null) {
if (fluidAboveStalactite.get().sourceState.is(Blocks.MUD) && fluid == Fluids.WATER) {
BlockState blockState = Blocks.CLAY.defaultBlockState();
- level.setBlockAndUpdate(fluidAboveStalactite.get().pos, blockState);
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, fluidAboveStalactite.get().pos, blockState)) { // Paper - Call BlockFormEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, fluidAboveStalactite.get().pos, blockState, 3)) { // Paper - Call BlockFormEvent
Block.pushEntitiesUp(fluidAboveStalactite.get().sourceState, blockState, level, fluidAboveStalactite.get().pos);
level.gameEvent(GameEvent.BLOCK_CHANGE, fluidAboveStalactite.get().pos, GameEvent.Context.of(blockState));
level.levelEvent(1504, blockPos, 0);
@@ -34,7 +34,7 @@
} else {
BlockPos blockPos1 = findFillableCauldronBelowStalactiteTip(level, blockPos, fluid);
if (blockPos1 != null) {
@@ -380,17 +_,17 @@
@@ -364,17 +_,17 @@
if (isUnmergedTipWithDirection(blockState, direction.getOpposite())) {
createMergedTips(blockState, server, blockPos);
} else if (blockState.isAir() || blockState.is(Blocks.WATER)) {
@@ -49,13 +49,13 @@
.defaultBlockState()
.setValue(TIP_DIRECTION, direction)
.setValue(THICKNESS, thickness)
.setValue(WATERLOGGED, Boolean.valueOf(level.getFluidState(pos).getType() == Fluids.WATER));
.setValue(WATERLOGGED, level.getFluidState(pos).getType() == Fluids.WATER);
- level.setBlock(pos, blockState, 3);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, pos, blockState, 3); // CraftBukkit
}
private static void createMergedTips(BlockState state, LevelAccessor level, BlockPos pos) {
@@ -404,8 +_,8 @@
@@ -388,8 +_,8 @@
blockPos = pos.below();
}

View File

@@ -1,25 +1,25 @@
--- a/net/minecraft/world/level/block/PowderSnowBlock.java
+++ b/net/minecraft/world/level/block/PowderSnowBlock.java
@@ -58,6 +_,7 @@
@@ -60,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!(entity instanceof LivingEntity) || entity.getInBlockState().is(this)) {
entity.makeStuckInBlock(state, new Vec3(0.9F, 1.5, 0.9F));
if (level.isClientSide) {
@@ -80,8 +_,13 @@
entity.setIsInPowderSnow(true);
if (level instanceof ServerLevel serverLevel) {
if (entity.isOnFire()
- && (serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player)
+ // CraftBukkit - move down
&& entity.mayInteract(serverLevel, pos)) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) {
+ return;
+ }
+ // CraftBukkit end
level.destroyBlock(pos, false);
@@ -85,8 +_,13 @@
entity1 -> {
if (level instanceof ServerLevel serverLevel
&& entity1.isOnFire()
- && (serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity1 instanceof Player)
+ // CraftBukkit - move down
&& entity1.mayInteract(serverLevel, blockPos)) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity1, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity1 instanceof Player))) {
+ return;
+ }
+ // CraftBukkit end
level.destroyBlock(blockPos, false);
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
@@ -133,6 +_,13 @@
@@ -127,6 +_,13 @@
|| this.findPoweredRailSignal(level, pos, state, true, 0)
|| this.findPoweredRailSignal(level, pos, state, false, 0);
if (flag != poweredValue) {
@@ -11,6 +11,6 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)), 3);
level.setBlock(pos, state.setValue(POWERED, flag), 3);
level.updateNeighborsAt(pos.below(), this);
if (state.getValue(SHAPE).isSlope()) {

View File

@@ -1,14 +1,6 @@
--- a/net/minecraft/world/level/block/PressurePlateBlock.java
+++ b/net/minecraft/world/level/block/PressurePlateBlock.java
@@ -5,6 +_,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
@@ -46,7 +_,31 @@
@@ -46,7 +_,29 @@
case EVERYTHING -> Entity.class;
case MOBS -> LivingEntity.class;
};
@@ -16,15 +8,13 @@
+ // CraftBukkit start - Call interact event when turning on a pressure plate
+ for (Entity entity : getEntities(level, PressurePlateBlock.TOUCH_AABB.move(pos), clazz)) {
+ if (this.getSignalForState(level.getBlockState(pos)) == 0) {
+ org.bukkit.World bworld = level.getWorld();
+ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager();
+ org.bukkit.event.Cancellable cancellable;
+
+ if (entity instanceof Player player) {
+ 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(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ manager.callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+
+ // We only want to block turning the plate on if all events are cancelled

View File

@@ -20,7 +20,7 @@
+ RedStoneOreBlock.interact(level.getBlockState(pos), level, pos, entity); // add entity
+ }
+ } else {
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ RedStoneOreBlock.interact(level.getBlockState(pos), level, pos, entity); // add entity
@@ -52,7 +52,7 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3);
level.setBlock(pos, state.setValue(LIT, true), 3);
}
}
@@ -80,6 +_,11 @@
@@ -64,7 +64,7 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3);
level.setBlock(pos, state.setValue(LIT, false), 3);
}
}
@@ -87,9 +_,17 @@

View File

@@ -30,8 +30,8 @@
+
+ // CraftBukkit start
+ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager();
+ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ int oldCurrent = ((Boolean) state.getValue(RedstoneTorchBlock.LIT)).booleanValue() ? 15 : 0;
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ int oldCurrent = state.getValue(LIT) ? 15 : 0;
+
+ org.bukkit.event.block.BlockRedstoneEvent event = new org.bukkit.event.block.BlockRedstoneEvent(block, oldCurrent, oldCurrent);
+ // CraftBukkit end
@@ -46,7 +46,7 @@
+ }
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3);
level.setBlock(pos, state.setValue(LIT, false), 3);
if (isToggledTooFrequently(level, pos, true)) {
level.levelEvent(1502, pos, 0);
@@ -87,6 +_,15 @@
@@ -62,7 +62,7 @@
+ }
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3);
level.setBlock(pos, state.setValue(LIT, true), 3);
}
}
@@ -124,7 +_,12 @@

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -102,11 +_,16 @@
if (!level.isClientSide) {
ServerPlayer serverPlayer = (ServerPlayer)player;
if (serverPlayer.getRespawnDimension() != level.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) {
- serverPlayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true);
+ if (serverPlayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - Add PlayerSetSpawnEvent
@@ -103,11 +_,16 @@
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
ServerPlayer.RespawnConfig respawnConfig1 = new ServerPlayer.RespawnConfig(level.dimension(), pos, 0.0F, false);
if (respawnConfig == null || !respawnConfig.isSamePosition(respawnConfig1)) {
- serverPlayer.setRespawnPosition(respawnConfig1, true);
+ if (serverPlayer.setRespawnPosition(respawnConfig1, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - Add PlayerSetSpawnEvent
level.playSound(
null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F
);
@@ -18,7 +18,7 @@
}
}
@@ -140,6 +_,7 @@
@@ -141,6 +_,7 @@
}
private void explode(BlockState state, Level level, final BlockPos pos2) {
@@ -26,7 +26,7 @@
level.removeBlock(pos2, false);
boolean flag = Direction.Plane.HORIZONTAL.stream().map(pos2::relative).anyMatch(pos -> isWaterThatWouldFlow(pos, level));
final boolean flag1 = flag || level.getFluidState(pos2.above()).is(FluidTags.WATER);
@@ -153,7 +_,7 @@
@@ -154,7 +_,7 @@
};
Vec3 center = pos2.getCenter();
level.explode(

View File

@@ -5,7 +5,7 @@
@Override
public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) {
- level.setBlockAndUpdate(pos.below(), Blocks.HANGING_ROOTS.defaultBlockState());
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState(), 3); // CraftBukkit
}
@Override

View File

@@ -1,25 +1,25 @@
--- a/net/minecraft/world/level/block/SaplingBlock.java
+++ b/net/minecraft/world/level/block/SaplingBlock.java
@@ -26,6 +_,7 @@
protected static final float AABB_OFFSET = 6.0F;
protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0);
@@ -25,6 +_,7 @@
public static final IntegerProperty STAGE = BlockStateProperties.STAGE;
private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 12.0);
protected final TreeGrower treeGrower;
+ public static org.bukkit.TreeType treeType; // CraftBukkit
+ public static @javax.annotation.Nullable org.bukkit.TreeType treeType; // CraftBukkit
@Override
public MapCodec<? extends SaplingBlock> codec() {
@@ -45,7 +_,7 @@
@@ -44,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextInt(7) == 0) {
+ if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextFloat() < (level.spigotConfig.saplingModifier / (100.0f * 7))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextFloat() < (level.spigotConfig.saplingModifier / (100.0F * 7))) { // Spigot - SPIGOT-7159: Better modifier resolution
this.advanceTree(level, pos, state, random);
}
}
@@ -54,7 +_,33 @@
@@ -53,7 +_,34 @@
if (state.getValue(STAGE) == 0) {
level.setBlock(pos, state.cycle(STAGE), 4);
level.setBlock(pos, state.cycle(STAGE), 260);
} else {
- this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random);
+ // CraftBukkit start
@@ -42,8 +42,9 @@
+ }
+ if (event == null || !event.isCancelled()) {
+ for (org.bukkit.block.BlockState blockstate : blocks) {
+ org.bukkit.craftbukkit.block.CapturedBlockState.setBlockState(blockstate);
+ level.checkCapturedTreeStateForObserverNotify(pos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) blockstate;
+ craftBlockState.place(craftBlockState.getFlags());
+ level.checkCapturedTreeStateForObserverNotify(pos, craftBlockState); // Paper - notify observers even if grow failed
+ }
+ }
+ }

View File

@@ -1,9 +1,9 @@
--- a/net/minecraft/world/level/block/ScaffoldingBlock.java
+++ b/net/minecraft/world/level/block/ScaffoldingBlock.java
@@ -119,7 +_,7 @@
@@ -117,7 +_,7 @@
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
int distance = getDistance(level, pos);
BlockState blockState = state.setValue(DISTANCE, Integer.valueOf(distance)).setValue(BOTTOM, Boolean.valueOf(this.isBottom(level, pos, distance)));
BlockState blockState = state.setValue(DISTANCE, distance).setValue(BOTTOM, this.isBottom(level, pos, distance));
- if (blockState.getValue(DISTANCE) == 7) {
+ if (blockState.getValue(DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, blockState.getFluidState().createLegacyBlock()).isCancelled()) { // CraftBukkit - BlockFadeEvent // Paper - fix wrong block state
if (state.getValue(DISTANCE) == 7) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -108,6 +_,18 @@
@@ -102,6 +_,18 @@
&& level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity
&& level instanceof ServerLevel serverLevel
&& sculkSensorBlockEntity.getVibrationUser().canReceiveVibration(serverLevel, pos, GameEvent.STEP, GameEvent.Context.of(state))) {
@@ -9,7 +9,7 @@
+ 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()));
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+ if (cancellable.isCancelled()) {
@@ -19,7 +19,7 @@
sculkSensorBlockEntity.getListener().forceScheduleVibration(serverLevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position());
}
@@ -200,10 +_,19 @@
@@ -191,10 +_,19 @@
}
public static boolean canActivate(BlockState state) {
@@ -37,10 +37,10 @@
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, Integer.valueOf(0)), 3);
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, 0), 3);
level.scheduleTick(pos, state.getBlock(), 10);
updateNeighbours(level, pos, state);
@@ -215,6 +_,15 @@
@@ -206,6 +_,15 @@
}
public void activate(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int power, int frequency) {
@@ -53,10 +53,10 @@
+ }
+ power = eventRedstone.getNewCurrent();
+ // CraftBukkit end
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, Integer.valueOf(power)), 3);
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, power), 3);
level.scheduleTick(pos, state.getBlock(), this.getActiveTicks());
updateNeighbours(level, pos, state);
@@ -292,8 +_,16 @@
@@ -283,8 +_,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
@@ -69,9 +69,8 @@
- this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
+ return this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
}
- }
+
+ return 0;
+ // CraftBukkit end
+ }
}
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -66,6 +_,7 @@
@@ -60,6 +_,7 @@
if (level instanceof ServerLevel serverLevel) {
ServerPlayer serverPlayer = SculkShriekerBlockEntity.tryGetPlayer(entity);
if (serverPlayer != null) {
@@ -8,7 +8,7 @@
serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryShriek(serverLevel, serverPlayer));
}
}
@@ -144,9 +_,16 @@
@@ -128,9 +_,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);

Some files were not shown because too many files have changed in this diff Show More