Upstream Paper's upgrade to vineflower 12.0.0 (#1782)

This commit is contained in:
granny
2026-05-31 16:42:41 -07:00
committed by GitHub
parent dc4a255969
commit 3fe5edd4b5
116 changed files with 1321 additions and 1333 deletions

View File

@@ -8,7 +8,7 @@
public CrashReport(final String title, final Throwable t) {
this.title = title;
@@ -129,7 +_,7 @@
@@ -126,7 +_,7 @@
}
public String getFriendlyReport(final ReportType reportType) {
@@ -17,7 +17,7 @@
}
public @Nullable Path getSaveFile() {
@@ -159,7 +_,7 @@
@@ -156,7 +_,7 @@
}
public boolean saveToFile(final Path file, final ReportType reportType) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -268,11 +_,11 @@
@@ -267,11 +_,11 @@
JfrCommand.register(this.dispatcher);
}
@@ -14,7 +14,7 @@
RaidCommand.register(this.dispatcher, context);
DebugPathCommand.register(this.dispatcher);
DebugMobSpawningCommand.register(this.dispatcher);
@@ -300,6 +_,14 @@
@@ -299,6 +_,14 @@
StopCommand.register(this.dispatcher);
TransferCommand.register(this.dispatcher);
WhitelistCommand.register(this.dispatcher);
@@ -29,7 +29,7 @@
}
if (commandSelection.includeIntegrated) {
@@ -522,6 +_,7 @@
@@ -521,6 +_,7 @@
private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<CommandSourceStack> root) {
// Paper end - Perf: Async command map building
new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) root, true).callEvent(); // Paper - Brigadier API
@@ -37,7 +37,7 @@
org.bukkit.event.player.PlayerCommandSendEvent event = new org.bukkit.event.player.PlayerCommandSendEvent(player.getBukkitEntity(), new java.util.LinkedHashSet<>(bukkit));
event.getPlayer().getServer().getPluginManager().callEvent(event);
@@ -532,6 +_,8 @@
@@ -531,6 +_,8 @@
}
}
// CraftBukkit end

View File

@@ -1,38 +1,42 @@
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -206,26 +_,27 @@
@@ -210,30 +_,31 @@
this.checkPermissions(sender);
if (this.playerName != null) {
ServerPlayer result = sender.getServer().getPlayerList().getPlayerByName(this.playerName);
- return result == null ? List.of() : List.of(result);
+ return result == null || !canSee(sender, result) ? List.of() : List.of(result); // Purpur - Hide hidden players from entity selector
} else if (this.entityUUID != null) {
}
if (this.entityUUID != null) {
ServerPlayer result = sender.getServer().getPlayerList().getPlayer(this.entityUUID);
- return result == null ? List.of() : List.of(result);
+ return result == null || !canSee(sender, result) ? List.of() : List.of(result); // Purpur - Hide hidden players from entity selector
} else {
Vec3 pos = this.position.apply(sender.getPosition());
AABB absoluteAabb = this.getAbsoluteAabb(pos);
Predicate<Entity> predicate = this.getPredicate(pos, absoluteAabb, null);
if (this.currentEntity) {
- return sender.getEntity() instanceof ServerPlayer player && predicate.test(player) ? List.of(player) : List.of();
+ return sender.getEntity() instanceof ServerPlayer player && predicate.test(player) && canSee(sender, player) ? List.of(player) : List.of(); // Purpur - Hide hidden players from entity selector
} else {
int limit = this.getResultLimit();
List<ServerPlayer> result;
if (this.isWorldLimited()) {
result = sender.getLevel().getPlayers(predicate, limit);
+ result.removeIf(entityplayer3 -> !canSee(sender, entityplayer3)); // Purpur - Hide hidden players from entity selector
} else {
result = new ObjectArrayList<>();
}
for (ServerPlayer player : sender.getServer().getPlayerList().getPlayers()) {
- if (predicate.test(player)) {
+ if (predicate.test(player) && canSee(sender, player)) { // Purpur - Hide hidden players from entity selector
result.add(player);
if (result.size() >= limit) {
return result;
@@ -283,4 +_,10 @@
Vec3 pos = this.position.apply(sender.getPosition());
AABB absoluteAabb = this.getAbsoluteAabb(pos);
Predicate<Entity> predicate = this.getPredicate(pos, absoluteAabb, null);
if (this.currentEntity) {
- return sender.getEntity() instanceof ServerPlayer player && predicate.test(player) ? List.of(player) : List.of();
+ return sender.getEntity() instanceof ServerPlayer player && predicate.test(player) && canSee(sender, player) ? List.of(player) : List.of(); // Purpur - Hide hidden players from entity selector
}
int limit = this.getResultLimit();
List<ServerPlayer> result;
if (this.isWorldLimited()) {
result = sender.getLevel().getPlayers(predicate, limit);
+ result.removeIf(entityplayer3 -> !canSee(sender, entityplayer3)); // Purpur - Hide hidden players from entity selector
} else {
result = new ObjectArrayList<>();
for (ServerPlayer player : sender.getServer().getPlayerList().getPlayers()) {
- if (predicate.test(player)) {
+ if (predicate.test(player) && canSee(sender, player)) { // Purpur - Hide hidden players from entity selector
result.add(player);
if (result.size() >= limit) {
return result;
@@ -289,4 +_,10 @@
public static Component joinNames(final List<? extends Entity> entities) {
return ComponentUtils.formatList(entities, Entity::getDisplayName);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -691,5 +_,22 @@
@@ -683,5 +_,22 @@
DispenserBlock.registerBehavior(Items.TNT_MINECART, new MinecartDispenseItemBehavior(EntityType.TNT_MINECART));
DispenserBlock.registerBehavior(Items.HOPPER_MINECART, new MinecartDispenseItemBehavior(EntityType.HOPPER_MINECART));
DispenserBlock.registerBehavior(Items.COMMAND_BLOCK_MINECART, new MinecartDispenseItemBehavior(EntityType.COMMAND_BLOCK_MINECART));

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
@@ -31,7 +_,7 @@
return false;
} else {
LivingEntity target = entities.getFirst();
- EquipmentSlot slot = target.getEquipmentSlotForItem(dispensed);
+ EquipmentSlot slot = source.level().purpurConfig.dispenserApplyCursedArmor ? target.getEquipmentSlotForItem(dispensed) : target.getEquipmentSlotForDispenserItem(dispensed); if (slot == null) return false; // Purpur - Dispenser curse of binding protection
ItemStack equip = dispensed.copyWithCount(1); // Paper - shrink below and single item in event
// CraftBukkit start
net.minecraft.world.level.Level world = source.level();
@@ -32,7 +_,7 @@
}
LivingEntity target = entities.getFirst();
- EquipmentSlot slot = target.getEquipmentSlotForItem(dispensed);
+ EquipmentSlot slot = source.level().purpurConfig.dispenserApplyCursedArmor ? target.getEquipmentSlotForItem(dispensed) : target.getEquipmentSlotForDispenserItem(dispensed); if (slot == null) return false; // Purpur - Dispenser curse of binding protection
ItemStack equip = dispensed.copyWithCount(1); // Paper - shrink below and single item in event
// CraftBukkit start
net.minecraft.world.level.Level world = source.level();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/GameTestHelper.java
+++ b/net/minecraft/gametest/framework/GameTestHelper.java
@@ -354,6 +_,8 @@
@@ -352,6 +_,8 @@
return gameType;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/network/Connection.java
+++ b/net/minecraft/network/Connection.java
@@ -554,11 +_,20 @@
@@ -552,11 +_,20 @@
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
private static int joinAttemptsThisTick; // Paper - Buffer joins to world
private static int currTick; // Paper - Buffer joins to world

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/network/chat/SignedMessageChain.java
+++ b/net/minecraft/network/chat/SignedMessageChain.java
@@ -49,7 +_,7 @@
SignedMessageLink link = SignedMessageChain.this.nextLink;
if (link == null) {
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
- } else if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
+ } else if (org.purpurmc.purpur.PurpurConfig.kickForOutOfOrderChat && body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) { // Purpur - Option to disable kick for out of order chat
this.setChainBroken();
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
} else {
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
}
- if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
+ if (org.purpurmc.purpur.PurpurConfig.kickForOutOfOrderChat && body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) { // Purpur - Option to disable kick for out of order chat
this.setChainBroken();
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
}

View File

@@ -25,7 +25,7 @@
getTPS(this.tickTimes1m, interval),
getTPS(this.tickTimes5m, interval),
getTPS(this.tickTimes15m, interval)
@@ -1057,6 +_,15 @@
@@ -1047,6 +_,15 @@
LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
@@ -41,7 +41,7 @@
// CraftBukkit start
if (this.server != null) {
this.server.spark.disable(); // Paper - spark
@@ -1151,6 +_,8 @@
@@ -1141,6 +_,8 @@
this.safeShutdown(wait, false);
}
public void safeShutdown(final boolean wait, final boolean isRestarting) {
@@ -50,7 +50,7 @@
this.isRestarting = isRestarting;
this.hasLoggedStop = true; // Paper - Debugging
if (this.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
@@ -1332,11 +_,21 @@
@@ -1322,11 +_,21 @@
}
// Paper end - Add onboarding message for initial server start
// Paper start - Improve outdated version checking
@@ -73,7 +73,7 @@
while (this.running) {
final long tickStart = System.nanoTime(); // Paper - improve tick loop
long thisTickNanos; // Paper - improve tick loop - diff on change, expect this to be tick interval
@@ -1350,9 +_,11 @@
@@ -1340,9 +_,11 @@
final long ticksBehind = Math.max(1L, this.tickSchedule.getPeriodsAhead(thisTickNanos, tickStart));
final long catchup = (long)Math.max(
1,
@@ -86,7 +86,7 @@
// adjust ticksBehind so that it is not greater-than catchup
if (ticksBehind - catchup > 0L) {
final long difference = ticksBehind - catchup;
@@ -1983,7 +_,7 @@
@@ -1973,7 +_,7 @@
}
public String getServerModName() {

View File

@@ -7,14 +7,14 @@
- if (level > enchantment.getMaxLevel()) {
+ if (!org.purpurmc.purpur.PurpurConfig.allowUnsafeEnchantCommand && level > enchantment.getMaxLevel()) { // Purpur - Config to allow unsafe enchants
throw ERROR_LEVEL_TOO_HIGH.create(level, enchantment.getMaxLevel());
} else {
int success = 0;
@@ -77,7 +_,7 @@
ItemStack item = target.getMainHandItem();
if (!item.isEmpty()) {
if (enchantment.canEnchant(item)
- && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(item).keySet(), enchantmentHolder)) {
+ && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(item).keySet(), enchantmentHolder) || (org.purpurmc.purpur.PurpurConfig.allowUnsafeEnchantCommand && !item.hasEnchantment(enchantmentHolder))) { // Purpur - Config to allow unsafe enchants
item.enchant(enchantmentHolder, level);
success++;
} else if (targets.size() == 1) {
}
@@ -78,7 +_,7 @@
ItemStack item = target.getMainHandItem();
if (!item.isEmpty()) {
if (enchantment.canEnchant(item)
- && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(item).keySet(), enchantmentHolder)) {
+ && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(item).keySet(), enchantmentHolder) || (org.purpurmc.purpur.PurpurConfig.allowUnsafeEnchantCommand && !item.hasEnchantment(enchantmentHolder))) { // Purpur - Config to allow unsafe enchants
item.enchant(enchantmentHolder, level);
success++;
} else if (targets.size() == 1) {

View File

@@ -1,10 +1,10 @@
--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -61,6 +_,7 @@
remaining -= size;
ItemStack copyToDrop = prototypeItemStack.copyWithCount(size);
boolean added = player.getInventory().add(copyToDrop);
+ if (org.purpurmc.purpur.PurpurConfig.disableGiveCommandDrops) continue; // Purpur - add config option for toggling give command dropping
if (added && copyToDrop.isEmpty()) {
ItemEntity drop = player.drop(prototypeItemStack.copy(), false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (drop != null) {
@@ -62,6 +_,7 @@
remaining -= size;
ItemStack copyToDrop = prototypeItemStack.copyWithCount(size);
boolean added = player.getInventory().add(copyToDrop);
+ if (org.purpurmc.purpur.PurpurConfig.disableGiveCommandDrops) continue; // Purpur - add config option for toggling give command dropping
if (added && copyToDrop.isEmpty()) {
ItemEntity drop = player.drop(prototypeItemStack.copy(), false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (drop != null) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -216,6 +_,7 @@
@@ -211,6 +_,7 @@
public void run() {
if (!org.bukkit.craftbukkit.Main.useConsole) return; // CraftBukkit
// Paper start - Use TerminalConsoleAppender
@@ -8,7 +8,7 @@
new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
/*
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
@@ -294,6 +_,15 @@
@@ -289,6 +_,15 @@
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
@@ -24,8 +24,8 @@
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
// this.worldData.setGameType(properties.gameMode.get()); // CraftBukkit - moved to world loading
@@ -336,6 +_,30 @@
if (true) throw new IllegalStateException("Failed to bind to port", var11); // Paper - Propagate failed to bind to port error
@@ -331,6 +_,30 @@
if (true) throw new IllegalStateException("Failed to bind to port", e); // Paper - Propagate failed to bind to port error
return false;
}
+ // Purpur start - UPnP Port Forwarding
@@ -55,13 +55,13 @@
// CraftBukkit start
this.server.loadPlugins();
@@ -410,6 +_,9 @@
MinecraftServerStatistics.registerJmxMonitoring(this);
LOGGER.info("JMX monitoring enabled");
}
@@ -406,6 +_,9 @@
MinecraftServerStatistics.registerJmxMonitoring(this);
LOGGER.info("JMX monitoring enabled");
}
+
+ org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur - Implement TPSBar
+ if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur - Give bee counts in beehives to Purpur clients
+ org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur - Implement TPSBar
+ if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur - Give bee counts in beehives to Purpur clients
this.saveEverything(false, true, true);
this.notificationManager().serverStarted();
this.saveEverything(false, true, true);
this.notificationManager().serverStarted();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/gui/MinecraftServerGui.java
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
@@ -40,6 +_,11 @@
@@ -39,6 +_,11 @@
private Thread logAppenderThread;
private final Collection<Runnable> finalizers = Lists.newArrayList();
private final AtomicBoolean isClosing = new AtomicBoolean();
@@ -12,7 +12,7 @@
public static MinecraftServerGui showFrameFor(final DedicatedServer server) {
try {
@@ -47,7 +_,7 @@
@@ -46,7 +_,7 @@
} catch (Exception var3) {
}
@@ -21,7 +21,7 @@
final MinecraftServerGui gui = new MinecraftServerGui(server);
frame.setDefaultCloseOperation(2);
frame.add(gui);
@@ -55,7 +_,7 @@
@@ -54,7 +_,7 @@
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// Paper start - Improve ServerGUI
@@ -30,7 +30,7 @@
try {
frame.setIconImage(javax.imageio.ImageIO.read(java.util.Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
} catch (java.io.IOException ignore) {
@@ -65,7 +_,7 @@
@@ -64,7 +_,7 @@
@Override
public void windowClosing(final WindowEvent event) {
if (!gui.isClosing.getAndSet(true)) {
@@ -39,7 +39,7 @@
server.halt(true);
gui.runFinalizers();
}
@@ -113,7 +_,7 @@
@@ -112,7 +_,7 @@
private JComponent buildChatPanel() {
JPanel panel = new JPanel(new BorderLayout());
@@ -48,7 +48,7 @@
JScrollPane scrollPane = new JScrollPane(chatArea, 22, 30);
chatArea.setEditable(false);
chatArea.setFont(MONOSPACED);
@@ -122,10 +_,43 @@
@@ -121,10 +_,43 @@
String text = chatField.getText().trim();
if (!text.isEmpty()) {
this.server.handleConsoleInput(text, this.server.createCommandSourceStack());
@@ -90,9 +90,9 @@
+ });
+ // Purpur end - GUI Improvements
chatArea.addFocusListener(new FocusAdapter() {
{
Objects.requireNonNull(MinecraftServerGui.this);
@@ -164,7 +_,7 @@
@Override
public void focusGained(final FocusEvent arg0) {
@@ -159,7 +_,7 @@
}
private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\e\\[[\\d;]*[^\\d;]"); // CraftBukkit // Paper
@@ -101,7 +101,7 @@
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(() -> this.print(console, scrollPane, line));
} else {
@@ -175,16 +_,29 @@
@@ -170,16 +_,29 @@
shouldScroll = scrollBar.getValue() + scrollBar.getSize().getHeight() + MONOSPACED.getSize() * 4 > scrollBar.getMaximum();
}

View File

@@ -170,7 +170,7 @@
? this.getDestroyType(GameRules.MOB_EXPLOSION_DROP_DECAY)
: Explosion.BlockInteraction.KEEP;
case TNT -> this.getDestroyType(GameRules.TNT_EXPLOSION_DROP_DECAY);
@@ -2919,7 +_,7 @@
@@ -2914,7 +_,7 @@
// Spigot start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start - Fix merchant inventory not closing on entity removal

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -454,6 +_,9 @@
@@ -435,6 +_,9 @@
public boolean isRealPlayer; // Paper
public com.destroystokyo.paper.event.entity.@Nullable PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
public org.bukkit.event.player.PlayerQuitEvent.@Nullable QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
@@ -10,7 +10,7 @@
// Paper start - rewrite chunk system
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
@@ -527,6 +_,9 @@
@@ -508,6 +_,9 @@
this.respawnConfig = input.read("respawn", ServerPlayer.RespawnConfig.CODEC).orElse(null);
this.spawnExtraParticlesOnFall = input.getBooleanOr("spawn_extra_particles_on_fall", false);
this.raidOmenPosition = input.read("raid_omen_position", BlockPos.CODEC).orElse(null);
@@ -20,7 +20,7 @@
// Paper start - Expand PlayerGameModeChangeEvent
this.loadGameTypes(input);
}
@@ -568,6 +_,9 @@
@@ -549,6 +_,9 @@
output.store("ShoulderEntityRight", CompoundTag.CODEC, this.getShoulderEntityRight());
}
this.getBukkitEntity().setExtraData(output); // CraftBukkit
@@ -30,7 +30,7 @@
}
private void saveParentVehicle(final ValueOutput playerOutput) {
@@ -1203,6 +_,7 @@
@@ -1179,6 +_,7 @@
// Paper - moved up to sendClientboundPlayerCombatKillPacket()
sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent
Team team = this.getTeam();
@@ -38,59 +38,66 @@
if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) {
this.server.getPlayerList().broadcastSystemMessage(deathMessage, false);
} else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
@@ -1311,6 +_,13 @@
if (this.isInvulnerableTo(level, source)) {
@@ -1288,6 +_,13 @@
return false;
} else {
+ // Purpur start - Add boat fall damage config
+ if (source.is(net.minecraft.tags.DamageTypeTags.IS_FALL)) {
+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.boat.Boat && !level().purpurConfig.boatsDoFallDamage) {
+ return false;
+ }
}
+ // Purpur start - Add boat fall damage config
+ if (source.is(net.minecraft.tags.DamageTypeTags.IS_FALL)) {
+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.boat.Boat && !level().purpurConfig.boatsDoFallDamage) {
+ return false;
+ }
+ // Purpur end - Add boat fall damage config
Entity entity = source.getEntity();
if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false.
!(entity instanceof Player playerx && !this.canHarmPlayer(playerx))
@@ -1570,6 +_,7 @@
+ }
+ // Purpur end - Add boat fall damage config
Entity entity = source.getEntity();
if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false.
!(entity instanceof Player player && !this.canHarmPlayer(player))
@@ -1529,7 +_,7 @@
}
profiler.pop();
profiler.push("placing");
+ this.portalPos = org.bukkit.craftbukkit.util.CraftLocation.toBlockPos(exit); // Purpur - Fix stuck in portals
this.setServerLevel(newLevel);
this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit - use internal teleport without event
this.connection.resetPosition();
@@ -1686,7 +_,7 @@
),
monster -> monster.isPreventingPlayerRest(this.level(), this)
);
- if (!monsters.isEmpty()) {
+ if (!this.level().purpurConfig.playerSleepNearMonsters && !monsters.isEmpty()) { // Purpur - Config to ignore nearby mobs when sleeping
return Either.left(Player.BedSleepingProblem.NOT_SAFE);
}
}
@@ -1726,8 +_,19 @@
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
if (!this.level().canSleepThroughNights()) {
- this.sendOverlayMessage(Component.translatable("sleep.not_possible"));
+ // Purpur start - Customizable sleeping actionbar messages
+ Component clientMessage;
+ if (org.purpurmc.purpur.PurpurConfig.sleepNotPossible.isBlank()) {
+ clientMessage = null;
+ } else if (!org.purpurmc.purpur.PurpurConfig.sleepNotPossible.equalsIgnoreCase("default")) {
+ clientMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepNotPossible));
+ } else {
+ clientMessage = Component.translatable("sleep.not_possible");
}
+ if (clientMessage != null) {
+ this.sendOverlayMessage(clientMessage);
+ }// Purpur end - Customizable sleeping actionbar messages
+ }
if (newLevel.dimension() == lastDimension) {
- this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit
+ this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit
this.connection.resetPosition();
transition.postTeleportTransition().onTransition(this);
return this;
@@ -1552,6 +_,7 @@
this.level().updateSleepingPlayerList();
return result;
@@ -1821,6 +_,7 @@
profiler.pop();
profiler.push("placing");
+ this.portalPos = org.bukkit.craftbukkit.util.CraftLocation.toBlockPos(exit); // Purpur - Fix stuck in portals
this.setServerLevel(newLevel);
this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit - use internal teleport without event
this.connection.resetPosition();
@@ -1664,7 +_,7 @@
new AABB(bedCenter.x() - 8.0, bedCenter.y() - 5.0, bedCenter.z() - 8.0, bedCenter.x() + 8.0, bedCenter.y() + 5.0, bedCenter.z() + 8.0),
monster -> monster.isPreventingPlayerRest(this.level(), this)
);
- if (!monsters.isEmpty()) {
+ if (!this.level().purpurConfig.playerSleepNearMonsters && !monsters.isEmpty()) { // Purpur - Config to ignore nearby mobs when sleeping
return Either.left(Player.BedSleepingProblem.NOT_SAFE);
}
}
@@ -1700,7 +_,17 @@
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
if (!this.level().canSleepThroughNights()) {
- this.sendOverlayMessage(Component.translatable("sleep.not_possible"));
+ // Purpur start - Customizable sleeping actionbar messages
+ Component clientMessage;
+ if (org.purpurmc.purpur.PurpurConfig.sleepNotPossible.isBlank()) {
+ clientMessage = null;
+ } else if (!org.purpurmc.purpur.PurpurConfig.sleepNotPossible.equalsIgnoreCase("default")) {
+ clientMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepNotPossible));
+ } else {
+ clientMessage = Component.translatable("sleep.not_possible");
+ } if (clientMessage != null) {
+ this.sendOverlayMessage(clientMessage);
+ }// Purpur end - Customizable sleeping actionbar messages
}
this.level().updateSleepingPlayerList();
@@ -1794,6 +_,7 @@
@Override
public void openTextEdit(final SignBlockEntity sign, final boolean isFrontText) {
@@ -98,7 +105,7 @@
this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos()));
this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), isFrontText));
}
@@ -2164,6 +_,26 @@
@@ -2138,6 +_,26 @@
this.lastSentExp = -1; // CraftBukkit - Added to reset
}
@@ -125,7 +132,7 @@
@Override
public void completeUsingItem() {
if (!this.useItem.isEmpty() && this.isUsingItem()) {
@@ -2403,6 +_,20 @@
@@ -2373,6 +_,20 @@
);
}
@@ -146,7 +153,7 @@
@Override
public void sendSystemMessage(final Component message) {
this.sendSystemMessage(message, false);
@@ -2554,7 +_,67 @@
@@ -2524,7 +_,67 @@
public void resetLastActionTime() {
this.lastActionTime = Util.getMillis();
@@ -215,7 +222,7 @@
public ServerStatsCounter getStats() {
return this.stats;
@@ -3179,4 +_,65 @@
@@ -3149,4 +_,65 @@
return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity();
}
// CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -371,6 +_,7 @@
@@ -370,6 +_,7 @@
}
return false;
}
@@ -16,7 +16,7 @@
BlockPos pos = hitResult.getBlockPos();
BlockState state = level.getBlockState(pos);
boolean cancelledBlock = false;
@@ -549,7 +_,7 @@
@@ -551,7 +_,7 @@
boolean haveSomethingInOurHands = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty();
boolean suppressUsingBlock = player.isSecondaryUseActive() && haveSomethingInOurHands;
ItemStack usedItemStack = itemStack.copy();
@@ -25,7 +25,7 @@
InteractionResult itemUse = state.useItemOn(player.getItemInHand(hand), level, player, hand, hitResult);
if (itemUse.consumesAction()) {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, pos, usedItemStack);
@@ -595,4 +_,18 @@
@@ -597,4 +_,18 @@
public void setLevel(final ServerLevel newLevel) {
this.level = newLevel;
}

View File

@@ -206,7 +206,7 @@
private boolean shouldCheckPlayerMovement(final boolean isFallFlying) {
if (this.isSingleplayerOwner()) {
return false;
@@ -2227,6 +_,7 @@
@@ -2229,6 +_,7 @@
boolean cancelled;
if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) {
@@ -214,7 +214,7 @@
org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemStack, hand);
cancelled = event.useItemInHand() == Event.Result.DENY;
} else {
@@ -2861,6 +_,7 @@
@@ -2863,6 +_,7 @@
ItemStack mainHandItem = this.player.getMainHandItem();
if (this.player.isWithinAttackRange(mainHandItem, targetBounds, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(3.0))) { // Paper - configurable lenience
if (!mainHandItem.has(DataComponents.PIERCING_WEAPON)) {
@@ -222,7 +222,7 @@
if (target instanceof ItemEntity
|| target instanceof ExperienceOrb
|| target == this.player
@@ -3642,7 +_,7 @@
@@ -3644,7 +_,7 @@
@Override
public void handleChangeGameMode(final ServerboundChangeGameModePacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -288,7 +_,7 @@
@@ -284,7 +_,7 @@
ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!");
ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(name)); // Spigot
} else {
@@ -8,4 +8,4 @@
+ ServerLoginPacketListenerImpl.this.disconnect(org.purpurmc.purpur.PurpurConfig.unverifiedUsername.equals("default") ? Component.translatable("multiplayer.disconnect.unverified_username") : io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.unverifiedUsername))); // Purpur - Config for unverified username message
ServerLoginPacketListenerImpl.LOGGER.error("Username '{}' tried to join with an invalid session", name);
}
} catch (AuthenticationUnavailableException var4) {
} catch (AuthenticationUnavailableException ignored) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -313,6 +_,7 @@
@@ -312,6 +_,7 @@
scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
}
// Paper end - Configurable player collision
@@ -8,7 +8,7 @@
// CraftBukkit start - moved down
LOGGER.info(
"{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", // Paper - add world identifier
@@ -437,6 +_,7 @@
@@ -432,6 +_,7 @@
}
public net.kyori.adventure.text.@Nullable Component remove(final ServerPlayer player, final net.kyori.adventure.text.Component leaveMessage) {
// Paper end - Fix kick event leave message not being sent
@@ -16,7 +16,7 @@
ServerLevel level = player.level();
player.awardStat(Stats.LEAVE_GAME);
// CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
@@ -771,6 +_,20 @@
@@ -768,6 +_,20 @@
}
}
@@ -37,7 +37,7 @@
public void broadcastAll(final Packet<?> packet, final ResourceKey<Level> dimension) {
for (ServerPlayer player : this.players) {
if (player.level().dimension() == dimension) {
@@ -864,6 +_,7 @@
@@ -861,6 +_,7 @@
case ADMINS -> EntityEvent.PERMISSION_LEVEL_ADMINS;
case OWNERS -> EntityEvent.PERMISSION_LEVEL_OWNERS;
};
@@ -45,7 +45,7 @@
player.connection.send(new ClientboundEntityEventPacket(player, eventId));
}
@@ -875,7 +_,7 @@
@@ -872,7 +_,7 @@
// Paper start - whitelist verify event / login event
public LoginResult canBypassFullServerLogin(final NameAndId nameAndId, final LoginResult currentResult) {

View File

@@ -15,7 +15,7 @@
+ public float maxUpStep; // Purpur - Add option to set armorstand step height
public boolean noPhysics;
- public final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
+ public final RandomSource random; // Paper - Share random for entities to make them more random // Add toggle for RNG manipulation
+ public final RandomSource random; // Paper - Share random for entities to make them more random // Purpur - Add toggle for RNG manipulation
public int tickCount;
private int remainingFireTicks;
private final EntityFluidInteraction fluidInteraction = new EntityFluidInteraction(Set.of(FluidTags.WATER, FluidTags.LAVA));
@@ -69,7 +69,7 @@
this.onBelowWorld();
}
}
@@ -2005,7 +_,7 @@
@@ -2007,7 +_,7 @@
}
public boolean fireImmune() {
@@ -78,7 +78,7 @@
}
public boolean causeFallDamage(final double fallDistance, final float damageModifier, final DamageSource damageSource) {
@@ -2591,7 +_,7 @@
@@ -2593,7 +_,7 @@
output.putBoolean("Bukkit.invisible", this.persistentInvisibility);
}
// SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
@@ -87,7 +87,7 @@
output.putInt("Bukkit.MaxAirSupply", this.getMaxAirSupply());
}
output.putInt("Spigot.ticksLived", this.totalEntityAge); // Paper
@@ -2678,6 +_,11 @@
@@ -2679,6 +_,11 @@
output.putBoolean("Paper.FreezeLock", true);
}
// Paper end
@@ -96,28 +96,28 @@
+ output.putBoolean("Purpur.FireImmune", immuneToFire);
+ }
+ // Purpur end - Fire immune API
} catch (Throwable var7) {
CrashReport report = CrashReport.forThrowable(var7, "Saving entity NBT");
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Saving entity NBT");
CrashReportCategory category = report.addCategory("Entity being saved");
@@ -2800,6 +_,9 @@
@@ -2802,6 +_,9 @@
}
freezeLocked = input.getBooleanOr("Paper.FreezeLock", false);
// Paper end
+
+ immuneToFire = input.read("Purpur.FireImmune", com.mojang.serialization.Codec.BOOL).orElse(null); // Purpur - Fire immune API
+
} catch (Throwable var7) {
CrashReport report = CrashReport.forThrowable(var7, "Loading entity NBT");
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Loading entity NBT");
CrashReportCategory category = report.addCategory("Entity being loaded");
@@ -3068,6 +_,7 @@
if (this.isAlive() && this instanceof Leashable leashablex) {
if (leashablex.getLeashHolder() == player) {
@@ -3067,6 +_,7 @@
if (this.isAlive() && this instanceof Leashable leashable) {
if (leashable.getLeashHolder() == player) {
if (!this.level().isClientSide()) {
+ if (hand == InteractionHand.OFF_HAND && (level().purpurConfig.villagerCanBeLeashed || level().purpurConfig.wanderingTraderCanBeLeashed) && this instanceof net.minecraft.world.entity.npc.villager.AbstractVillager) return InteractionResult.CONSUME; // Purpur - Allow leashing villagers
// Paper start - EntityUnleashEvent
if (!org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerUnleashEntityEvent(
leashablex, player, hand, !player.hasInfiniteMaterials(), true
@@ -3498,15 +_,18 @@
leashable, player, hand, !player.hasInfiniteMaterials(), true
@@ -3500,15 +_,18 @@
return Vec3.directionFromRotation(this.getRotationVector());
}
@@ -137,7 +137,7 @@
}
}
}
@@ -4236,7 +_,7 @@
@@ -4238,7 +_,7 @@
}
public boolean canUsePortal(final boolean ignorePassenger) {
@@ -146,7 +146,7 @@
}
public boolean canTeleport(final Level from, final Level to) {
@@ -4786,6 +_,12 @@
@@ -4788,6 +_,12 @@
return Mth.lerp(partial, this.yRotO, this.yRot);
}
@@ -159,7 +159,7 @@
public boolean touchingUnloadedChunk() {
AABB box = this.getBoundingBox().inflate(1.0);
int x0 = Mth.floor(box.minX);
@@ -5089,7 +_,7 @@
@@ -5091,7 +_,7 @@
}
public float maxUpStep() {

View File

@@ -31,7 +31,7 @@
}
@Override
@@ -1046,15 +_,33 @@
@@ -1048,15 +_,33 @@
}
if (targetingEntity != null) {
@@ -74,40 +74,40 @@
return visibilityPercent;
}
@@ -1101,6 +_,7 @@
Iterator<MobEffectInstance> iterator = this.activeEffects.values().iterator();
while (iterator.hasNext()) {
MobEffectInstance effect = iterator.next();
+ if (cause == EntityPotionEffectEvent.Cause.MILK && !this.level().purpurConfig.milkClearsBeneficialEffects && effect.getEffect().value().isBeneficial()) continue; // Purpur - Milk Keeps Beneficial Effects
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED);
if (event.isCancelled()) {
continue;
@@ -1432,6 +_,24 @@
this.stopSleeping();
}
@@ -1106,6 +_,7 @@
Iterator<MobEffectInstance> iterator = this.activeEffects.values().iterator();
while (iterator.hasNext()) {
MobEffectInstance effect = iterator.next();
+ if (cause == EntityPotionEffectEvent.Cause.MILK && !this.level().purpurConfig.milkClearsBeneficialEffects && effect.getEffect().value().isBeneficial()) continue; // Purpur - Milk Keeps Beneficial Effects
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED);
if (event.isCancelled()) {
continue;
@@ -1438,7 +_,23 @@
this.stopSleeping();
}
+ // Purpur start - One Punch Man!
+ if (source.getEntity() instanceof net.minecraft.world.entity.player.Player player && source.getEntity().level().purpurConfig.creativeOnePunch && !source.is(DamageTypeTags.IS_PROJECTILE)) {
+ if (player.isCreative()) {
+ org.apache.commons.lang3.mutable.MutableDouble attackDamage = new org.apache.commons.lang3.mutable.MutableDouble();
+ player.getMainHandItem().forEachModifier(EquipmentSlot.MAINHAND, (attributeHolder, attributeModifier) -> {
+ if (attributeModifier.operation() == AttributeModifier.Operation.ADD_VALUE) {
+ attackDamage.addAndGet(attributeModifier.amount());
+ }
+ });
+
+ if (attackDamage.doubleValue() == 0.0D) {
+ // One punch!
+ damage = this.getHealth();
- this.noActionTime = 0;
+ // Purpur start - One Punch Man!
+ if (source.getEntity() instanceof net.minecraft.world.entity.player.Player player && source.getEntity().level().purpurConfig.creativeOnePunch && !source.is(DamageTypeTags.IS_PROJECTILE)) {
+ if (player.isCreative()) {
+ org.apache.commons.lang3.mutable.MutableDouble attackDamage = new org.apache.commons.lang3.mutable.MutableDouble();
+ player.getMainHandItem().forEachModifier(EquipmentSlot.MAINHAND, (attributeHolder, attributeModifier) -> {
+ if (attributeModifier.operation() == AttributeModifier.Operation.ADD_VALUE) {
+ attackDamage.addAndGet(attributeModifier.amount());
+ }
+ });
+
+ if (attackDamage.doubleValue() == 0.0D) {
+ // One punch!
+ damage = this.getHealth();
+ }
+ }
+ // Purpur end - One Punch Man!
+
this.noActionTime = 0;
if (damage < 0.0F) {
damage = 0.0F;
@@ -1693,10 +_,10 @@
+ }
+ // Purpur end - One Punch Man!this.noActionTime = 0;
if (damage < 0.0F) {
damage = 0.0F;
}
@@ -1699,10 +_,10 @@
protected @Nullable Player resolvePlayerResponsibleForDamage(final DamageSource source) {
Entity sourceEntity = source.getEntity();
if (sourceEntity instanceof Player playerSource) {
@@ -120,26 +120,25 @@
} else {
this.lastHurtByPlayer = null;
this.lastHurtByPlayerMemoryTime = 0;
@@ -1747,6 +_,18 @@
}
@@ -1754,6 +_,17 @@
}
}
+ // Purpur start - Totems work in inventory
+ if (level().purpurConfig.totemOfUndyingWorksInInventory && this instanceof ServerPlayer player && (itemStack == null || itemStack.getItem() != Items.TOTEM_OF_UNDYING) && player.getBukkitEntity().hasPermission("purpur.inventory_totem")) {
+ for (ItemStack item : player.getInventory().getNonEquipmentItems()) {
+ if (item.getItem() == Items.TOTEM_OF_UNDYING) {
+ itemStack = item;
+ protectionItem = item.copy();
+ break;
+ }
+ // Purpur start - Totems work in inventory
+ if (level().purpurConfig.totemOfUndyingWorksInInventory && this instanceof ServerPlayer player && (itemStack == null || itemStack.getItem() != Items.TOTEM_OF_UNDYING) && player.getBukkitEntity().hasPermission("purpur.inventory_totem")) {
+ for (ItemStack item : player.getInventory().getNonEquipmentItems()) {
+ if (item.getItem() == Items.TOTEM_OF_UNDYING) {
+ itemStack = item;
+ protectionItem = item.copy();
+ break;
+ }
+ }
+ // Purpur end - Totems work in inventory
+
final org.bukkit.inventory.EquipmentSlot handSlot = (usedHand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(usedHand) : null;
final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot);
event.setCancelled(protectionItem == null);
@@ -1921,6 +_,7 @@
+ }
+ // Purpur end - Totems work in inventory
final org.bukkit.inventory.EquipmentSlot handSlot = (usedHand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(usedHand) : null;
final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot);
event.setCancelled(protectionItem == null);
@@ -1927,6 +_,7 @@
boolean playerKilled = this.lastHurtByPlayerMemoryTime > 0;
this.dropEquipment(level); // CraftBukkit - from below
if (this.shouldDropLoot(level)) {
@@ -147,7 +146,7 @@
this.dropFromLootTable(level, source, playerKilled);
// Paper start
final boolean prev = this.clearEquipmentSlots;
@@ -1929,6 +_,7 @@
@@ -1935,6 +_,7 @@
// Paper end
this.dropCustomDeathLoot(level, source, playerKilled);
this.clearEquipmentSlots = prev; // Paper
@@ -155,7 +154,7 @@
}
// CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment
@@ -3256,6 +_,7 @@
@@ -3264,6 +_,7 @@
float dmg = (float)(diff * 10.0 - 3.0);
if (dmg > 0.0F) {
this.playSound(this.getFallDamageSound((int)dmg), 1.0F, 1.0F);
@@ -163,7 +162,7 @@
this.hurt(this.damageSources().flyIntoWall(), dmg);
}
}
@@ -4740,6 +_,12 @@
@@ -4749,6 +_,12 @@
? slot == EquipmentSlot.MAINHAND && this.canUseSlot(EquipmentSlot.MAINHAND)
: slot == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.typeHolder());
}

View File

@@ -61,7 +61,7 @@
// Paper start - allow changing despawnInPeaceful
this.despawnInPeacefulOverride = readDespawnInPeacefulOverride(input);
}
@@ -1256,7 +_,7 @@
@@ -1251,7 +_,7 @@
);
}
@@ -70,7 +70,7 @@
return groupData;
}
@@ -1613,6 +_,7 @@
@@ -1608,6 +_,7 @@
}
this.postPiercingAttack();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
+++ b/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
@@ -29,6 +_,7 @@
@@ -33,6 +_,7 @@
@Override
public double sanitizeValue(final double value) {

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -90,7 +_,7 @@
};
// Paper start - optimise POI searches
java.util.List<Pair<Holder<PoiType>, BlockPos>> poiPositionsRaw = new java.util.ArrayList<>();
- ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), SCAN_RANGE, Double.MAX_VALUE, PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw);
+ ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), level.purpurConfig.villagerAcquirePoiSearchRadius, Double.MAX_VALUE, PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw); // Purpur - Configurable villager search radius
Set<Pair<Holder<PoiType>, BlockPos>> poiPositions = new java.util.HashSet<>(poiPositionsRaw.size());
for (Pair<Holder<PoiType>, BlockPos> pair : poiPositionsRaw) {
if (validPoi.test(level, pair.getSecond())) {
@@ -96,7 +_,7 @@
};
// Paper start - optimise POI searches
java.util.List<Pair<Holder<PoiType>, BlockPos>> poiPositionsRaw = new java.util.ArrayList<>();
- ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), SCAN_RANGE, Double.MAX_VALUE, PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw);
+ ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.findNearestPoiPositions(poiManager, poiType, cacheTest, body.blockPosition(), level.purpurConfig.villagerAcquirePoiSearchRadius, Double.MAX_VALUE, PoiManager.Occupancy.HAS_SPACE, ca.spottedleaf.moonrise.patches.poi_lookup.PoiAccess.LOAD_FOR_SEARCHING, 5, poiPositionsRaw); // Purpur - Configurable villager search radius
Set<Pair<Holder<PoiType>, BlockPos>> poiPositions = new java.util.HashSet<>(poiPositionsRaw.size());
for (Pair<Holder<PoiType>, BlockPos> pair : poiPositionsRaw) {
if (validPoi.test(level, pair.getSecond())) {

View File

@@ -8,7 +8,7 @@
if (!this.llama.isLeashed() && !this.llama.inCaravan()) {
List<Entity> llamas = this.llama
.level()
@@ -70,6 +_,7 @@
@@ -74,6 +_,7 @@
@Override
public boolean canContinueToUse() {

View File

@@ -1,7 +1,7 @@
--- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
@@ -54,7 +_,7 @@
}
@@ -56,7 +_,7 @@
return true;
};
Set<Pair<Holder<PoiType>, BlockPos>> pois = poiManager.findAllWithType(
- e -> e.is(PoiTypes.HOME), cacheTest, body.blockPosition(), AcquirePoi.SCAN_RANGE, PoiManager.Occupancy.ANY

View File

@@ -1,13 +1,13 @@
--- a/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
+++ b/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
@@ -63,6 +_,10 @@
return false;
} else if (this.selector != null && !this.selector.test(target, level)) {
@@ -67,6 +_,10 @@
if (this.selector != null && !this.selector.test(target, level)) {
return false;
+ // Purpur start - AFK API
+ } else if (!level.purpurConfig.idleTimeoutTargetPlayer && target instanceof net.minecraft.server.level.ServerPlayer player && player.isAfk()) {
+ return false;
+ // Purpur end - AFK API
} else {
if (targeter == null) {
if (this.isCombat && (!target.canBeSeenAsEnemy() || level.getDifficulty() == Difficulty.PEACEFUL)) {
}
if (targeter == null) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/bee/Bee.java
+++ b/net/minecraft/world/entity/animal/bee/Bee.java
@@ -172,7 +_,7 @@
@@ -171,7 +_,7 @@
// Paper end - Fix MC-167279
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(PathType.FIRE_IN_NEIGHBOR, -1.0F);
@@ -9,7 +9,7 @@
this.setPathfindingMalus(PathType.WATER_BORDER, 16.0F);
this.setPathfindingMalus(PathType.COCOA, -1.0F);
this.setPathfindingMalus(PathType.FENCE, -1.0F);
@@ -363,13 +_,19 @@
@@ -362,13 +_,19 @@
if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
boolean wantsToEnterHive = this.hasNectar()
|| this.isTiredOfLookingForNectar()
@@ -30,7 +30,7 @@
public void setStayOutOfHiveCountdown(final int ticks) {
this.stayOutOfHiveCountdown = ticks;
}
@@ -390,7 +_,7 @@
@@ -389,7 +_,7 @@
@Override
protected void customServerAiStep(final ServerLevel level) {
boolean hasStung = this.hasStung();
@@ -39,7 +39,7 @@
this.underWaterTicks++;
} else {
this.underWaterTicks = 0;
@@ -400,6 +_,7 @@
@@ -399,6 +_,7 @@
this.hurtServer(level, this.damageSources().drown(), 1.0F);
}
@@ -47,7 +47,7 @@
if (hasStung) {
this.timeSinceSting++;
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
@@ -1168,6 +_,7 @@
@@ -1132,6 +_,7 @@
Bee.this.savedFlowerPos = nearbyPos.get();
Bee.this.navigation
.moveTo(Bee.this.savedFlowerPos.getX() + 0.5, Bee.this.savedFlowerPos.getY() + 0.5, Bee.this.savedFlowerPos.getZ() + 0.5, 1.2F);
@@ -55,7 +55,7 @@
return true;
} else {
Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
@@ -1214,6 +_,7 @@
@@ -1178,6 +_,7 @@
this.pollinating = false;
Bee.this.navigation.stop();
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
@@ -63,7 +63,7 @@
}
@Override
@@ -1260,6 +_,7 @@
@@ -1224,6 +_,7 @@
this.setWantedPos();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/fox/Fox.java
+++ b/net/minecraft/world/entity/animal/fox/Fox.java
@@ -364,6 +_,11 @@
@@ -363,6 +_,11 @@
}
private void setTargetGoals() {
@@ -12,7 +12,7 @@
if (this.getVariant() == Fox.Variant.RED) {
this.targetSelector.addGoal(4, this.landTargetGoal);
this.targetSelector.addGoal(4, this.turtleEggTargetGoal);
@@ -391,6 +_,7 @@
@@ -390,6 +_,7 @@
public void setVariant(final Fox.Variant variant) {
this.entityData.set(DATA_TYPE_ID, variant.getId());
@@ -20,7 +20,7 @@
}
@Override
@@ -716,6 +_,29 @@
@@ -715,6 +_,29 @@
return slot == EquipmentSlot.MAINHAND;
}
// Paper end

View File

@@ -42,11 +42,11 @@
this.readPersistentAngerSaveData(this.level(), input);
}
@@ -267,6 +_,7 @@
float pitch = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, pitch);
itemStack.consume(1, player);
+ if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - Iron golem calm anger options
return InteractionResult.SUCCESS;
}
}
@@ -269,6 +_,7 @@
float pitch = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, pitch);
itemStack.consume(1, player);
+ if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - Iron golem calm anger options
return InteractionResult.SUCCESS;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/polarbear/PolarBear.java
+++ b/net/minecraft/world/entity/animal/polarbear/PolarBear.java
@@ -67,6 +_,29 @@
@@ -66,6 +_,29 @@
super(type, level);
}
@@ -30,7 +30,7 @@
@Override
public @Nullable AgeableMob getBreedOffspring(final ServerLevel level, final AgeableMob partner) {
return EntityType.POLAR_BEAR.create(level, EntitySpawnReason.BREEDING);
@@ -74,7 +_,7 @@
@@ -73,7 +_,7 @@
@Override
public boolean isFood(final ItemStack itemStack) {
@@ -39,7 +39,7 @@
}
@Override
@@ -83,6 +_,12 @@
@@ -82,6 +_,12 @@
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal());
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0, bear -> bear.isBaby() ? DamageTypeTags.PANIC_CAUSES : DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));

View File

@@ -39,7 +39,7 @@
if (this.tentacleMovement < Mth.PI) {
float tentacleScale = this.tentacleMovement / Mth.PI;
this.tentacleAngle = Mth.sin(tentacleScale * tentacleScale * Mth.PI) * Mth.PI * 0.25F;
@@ -321,7 +_,7 @@
@@ -316,7 +_,7 @@
int noActionTime = this.squid.getNoActionTime();
if (noActionTime > 100) {
this.squid.movementVector = Vec3.ZERO;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/animal/wolf/Wolf.java
+++ b/net/minecraft/world/entity/animal/wolf/Wolf.java
@@ -97,6 +_,37 @@
@@ -96,6 +_,37 @@
public static final TargetingConditions.Selector PREY_SELECTOR = (target, level) -> target.is(EntityType.SHEEP)
|| target.is(EntityType.RABBIT)
|| target.is(EntityType.FOX);
@@ -38,7 +38,7 @@
private static final float START_HEALTH = 8.0F;
private static final float TAME_HEALTH = 40.0F;
private static final float ARMOR_REPAIR_UNIT = 0.125F;
@@ -118,12 +_,47 @@
@@ -117,12 +_,47 @@
this.setPathfindingMalus(PathType.ON_TOP_OF_POWDER_SNOW, -1.0F);
}
@@ -86,7 +86,7 @@
this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F));
this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, true));
this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 2.0F));
@@ -136,7 +_,7 @@
@@ -135,7 +_,7 @@
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
this.targetSelector.addGoal(3, new HurtByTargetGoal(this).setAlertOthers());
this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
@@ -95,7 +95,7 @@
this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false));
this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true));
@@ -231,6 +_,7 @@
@@ -230,6 +_,7 @@
protected void addAdditionalSaveData(final ValueOutput output) {
super.addAdditionalSaveData(output);
output.store("CollarColor", DyeColor.LEGACY_ID_CODEC, this.getCollarColor());
@@ -103,7 +103,7 @@
VariantUtils.writeVariant(output, this.getVariant());
this.addPersistentAngerSaveData(output);
this.getSoundVariant()
@@ -245,6 +_,10 @@
@@ -244,6 +_,10 @@
super.readAdditionalSaveData(input);
VariantUtils.readVariant(input, Registries.WOLF_VARIANT).ifPresent(this::setVariant);
this.setCollarColor(input.read("CollarColor", DyeColor.LEGACY_ID_CODEC).orElse(DEFAULT_COLLAR_COLOR));
@@ -114,7 +114,7 @@
this.readPersistentAngerSaveData(this.level(), input);
input.read("sound_variant", ResourceKey.codec(Registries.WOLF_SOUND_VARIANT))
.flatMap(soundVariant -> this.registryAccess().lookupOrThrow(Registries.WOLF_SOUND_VARIANT).get((ResourceKey<WolfSoundVariant>)soundVariant))
@@ -268,6 +_,10 @@
@@ -267,6 +_,10 @@
}
this.setSoundVariant(WolfSoundVariants.pickRandomSoundVariant(this.registryAccess(), level.getRandom()));
@@ -125,7 +125,7 @@
return super.finalizeSpawn(level, difficulty, spawnReason, groupData);
}
@@ -316,6 +_,11 @@
@@ -315,6 +_,11 @@
public void tick() {
super.tick();
if (this.isAlive()) {

View File

@@ -34,23 +34,23 @@
}
@Override
@@ -115,15 +_,17 @@
@@ -118,15 +_,17 @@
}
// CraftBukkit end
if (!source.is(DamageTypeTags.IS_EXPLOSION)) {
+ if (shouldExplode()) {// Purpur - End crystal explosion options
DamageSource damageSource = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null;
// CraftBukkit start
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, getExplosionPower(), hasExplosionFire()); // Purpur - End crystal explosion options
if (event.isCancelled()) {
return false;
}
// CraftBukkit end
if (!source.is(DamageTypeTags.IS_EXPLOSION)) {
+ if (shouldExplode()) {// Purpur - End crystal explosion options
DamageSource damageSource = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null;
// CraftBukkit start
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, getExplosionPower(), hasExplosionFire()); // Purpur - End crystal explosion options
if (event.isCancelled()) {
return false;
}
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // Paper - add Bukkit remove cause
- level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.BLOCK);
+ level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), getExplosionEffect()); // Purpur - End crystal explosion options
+ } else this.unsetRemoved(); // Purpur - End crystal explosion options
} else {
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // Paper - add Bukkit remove cause
// CraftBukkit end
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // Paper - add Bukkit remove cause
- level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.BLOCK);
+ level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), getExplosionEffect()); // Purpur - End crystal explosion options
+ } else this.unsetRemoved(); // Purpur - End crystal explosion options
} else {
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // Paper - add Bukkit remove cause
// CraftBukkit end

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -959,6 +_,7 @@
@@ -960,6 +_,7 @@
@Override
protected boolean canRide(final Entity vehicle) {
@@ -8,7 +8,7 @@
return false;
}
@@ -994,7 +_,7 @@
@@ -995,7 +_,7 @@
boolean shouldDrop = level.getGameRules().get(GameRules.MOB_DROPS);
int xpCount = 500;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -82,6 +_,7 @@
@@ -81,6 +_,7 @@
private static final TargetingConditions.Selector LIVING_ENTITY_SELECTOR = (target, level) -> !target.is(EntityTypeTags.WITHER_FRIENDS)
&& target.attackable();
private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0).selector(LIVING_ENTITY_SELECTOR);
@@ -8,7 +8,7 @@
public WitherBoss(final EntityType<? extends WitherBoss> type, final Level level) {
super(type, level);
@@ -90,6 +_,16 @@
@@ -89,6 +_,16 @@
this.xpReward = 50;
}
@@ -25,7 +25,7 @@
@Override
protected PathNavigation createNavigation(final Level level) {
FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level);
@@ -122,6 +_,7 @@
@@ -121,6 +_,7 @@
protected void addAdditionalSaveData(final ValueOutput output) {
super.addAdditionalSaveData(output);
output.putInt("Invul", this.getInvulnerableTicks());
@@ -33,7 +33,7 @@
}
@Override
@@ -131,6 +_,7 @@
@@ -130,6 +_,7 @@
if (this.hasCustomName()) {
this.bossEvent.setName(this.getDisplayName());
}
@@ -41,7 +41,7 @@
}
@Override
@@ -274,7 +_,7 @@
@@ -273,7 +_,7 @@
level.explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
}
// CraftBukkit end
@@ -50,7 +50,7 @@
// CraftBukkit start - Use relative location for far away sounds
// level.globalLevelEvent(LevelEvent.SOUND_WITHER_BOSS_SPAWN, this.blockPosition(), 0);
int viewDistance = level.getCraftServer().getViewDistance() * 16;
@@ -378,8 +_,10 @@
@@ -377,8 +_,10 @@
}
}
@@ -63,7 +63,7 @@
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
@@ -576,6 +_,7 @@
@@ -579,6 +_,7 @@
@Override
protected boolean canRide(final Entity vehicle) {

View File

@@ -14,7 +14,7 @@
}
public ArmorStand(final Level level, final double x, final double y, final double z) {
@@ -523,6 +_,7 @@
@@ -546,6 +_,7 @@
// Paper start - Allow ArmorStands not to tick
@Override
public void tick() {
@@ -22,7 +22,7 @@
if (!this.canTick) {
if (this.noTickEquipmentDirty) {
this.noTickEquipmentDirty = false;
@@ -809,4 +_,19 @@
@@ -832,4 +_,19 @@
}
}
// Paper end

View File

@@ -29,9 +29,9 @@
+ } else if (this.isInvulnerableToBase(source)) {
+ // Purpur end - Item entity immunities
return false;
} else if (!level.getGameRules().get(GameRules.MOB_GRIEFING) && source.getEntity() instanceof Mob) {
return false;
@@ -517,6 +_,12 @@
}
@@ -521,6 +_,12 @@
public void setItem(final ItemStack itemStack) {
this.getEntityData().set(DATA_ITEM, itemStack);
this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(itemStack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate

View File

@@ -18,22 +18,23 @@
final com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity());
event.setCancelled(!shouldAttack);
return event.callEvent();
@@ -373,6 +_,7 @@
@@ -373,7 +_,7 @@
public boolean hurtServer(final ServerLevel level, final DamageSource source, final float damage) {
if (this.isInvulnerableTo(level, source)) {
return false;
+ } else if (org.purpurmc.purpur.PurpurConfig.endermanShortHeight && source.is(net.minecraft.world.damagesource.DamageTypes.IN_WALL)) { return false; // Purpur - no suffocation damage if short height - Short enderman height
} else {
AbstractThrownPotion thrownPotion = source.getDirectEntity() instanceof AbstractThrownPotion potion ? potion : null;
if (!source.is(DamageTypeTags.IS_PROJECTILE) && thrownPotion == null) { // Paper - EndermanEscapeEvent - diff on change - below logic relies on this path covering non-projectile damage.
@@ -387,6 +_,7 @@
} else {
boolean hurtWithCleanWater = thrownPotion != null && this.hurtWithCleanWater(level, source, thrownPotion, damage);
- }
+ } else if (org.purpurmc.purpur.PurpurConfig.endermanShortHeight && source.is(net.minecraft.world.damagesource.DamageTypes.IN_WALL)) { return false; } // Purpur - no suffocation damage if short height - Short enderman height
+ if (!hurtWithCleanWater && level.purpurConfig.endermanIgnoreProjectiles) return super.hurtServer(level, source, damage); // Purpur - Config to disable Enderman teleport on projectile hit
if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
for (int i = 0; i < 64; i++) {
if (this.teleport()) {
AbstractThrownPotion thrownPotion = source.getDirectEntity() instanceof AbstractThrownPotion potion ? potion : null;
if (!source.is(DamageTypeTags.IS_PROJECTILE) && thrownPotion == null) { // Paper - EndermanEscapeEvent - diff on change - below logic relies on this path covering non-projectile damage.
@@ -388,6 +_,7 @@
} else {
boolean hurtWithCleanWater = thrownPotion != null && this.hurtWithCleanWater(level, source, thrownPotion, damage);
+ if (!hurtWithCleanWater && level.purpurConfig.endermanIgnoreProjectiles) return super.hurtServer(level, source, damage); // Purpur - Config to disable Enderman teleport on projectile hit
if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
for (int i = 0; i < 64; i++) {
if (this.teleport()) {
@@ -430,7 +_,7 @@
@Override

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Guardian.java
+++ b/net/minecraft/world/entity/monster/Guardian.java
@@ -308,6 +_,11 @@
@@ -310,6 +_,11 @@
final BlockPos pos,
final RandomSource random
) {

View File

@@ -11,7 +11,7 @@
+ // Purpur end - Config to disable hostile mob spawn on ice
if (level.getBrightness(LightLayer.SKY, pos) > random.nextInt(32)) {
return false;
} else {
}
@@ -113,6 +_,11 @@
public static boolean checkAnyLightMonsterSpawnRules(
final EntityType<? extends Monster> type, final LevelAccessor level, final EntitySpawnReason spawnReason, final BlockPos pos, final RandomSource random

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -167,7 +_,11 @@
@@ -166,7 +_,11 @@
final ServerLevelAccessor level, final DifficultyInstance difficulty, final EntitySpawnReason spawnReason, final @Nullable SpawnGroupData groupData
) {
this.anchorPoint = this.blockPosition().above(5);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/Shulker.java
+++ b/net/minecraft/world/entity/monster/Shulker.java
@@ -94,6 +_,22 @@
@@ -93,6 +_,22 @@
this.lookControl = new Shulker.ShulkerLookControl(this);
}
@@ -23,7 +23,7 @@
@Override
protected void registerGoals() {
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true));
@@ -455,11 +_,21 @@
@@ -454,11 +_,21 @@
private void hitByShulkerBullet() {
Vec3 oldPosition = this.position();
AABB oldAabb = this.getBoundingBox();
@@ -49,7 +49,7 @@
if (baby != null) {
baby.setVariant(this.getVariant());
baby.snapTo(oldPosition);
@@ -566,7 +_,7 @@
@@ -565,7 +_,7 @@
}
public Optional<DyeColor> getVariant() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -669,14 +_,24 @@
@@ -666,14 +_,24 @@
}
public static boolean isWearingSafeArmor(final LivingEntity livingEntity) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
+++ b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
@@ -142,7 +_,7 @@
@@ -137,7 +_,7 @@
this.populateDefaultEquipmentEnchantments(level, random, difficulty);
this.reassessWeaponGoal();
this.setCanPickUpLoot(level.getLevel().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot
@@ -9,7 +9,7 @@
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
this.setDropChance(EquipmentSlot.HEAD, 0.0F);
}
@@ -189,7 +_,7 @@
@@ -184,7 +_,7 @@
double distanceToTarget = Math.sqrt(xd * xd + zd * zd);
if (this.level() instanceof ServerLevel serverLevel) {
Projectile.Delayed<AbstractArrow> delayedEntity = Projectile.spawnProjectileUsingShootDelayed( // Paper - delayed

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
@@ -128,7 +_,19 @@
@@ -127,7 +_,19 @@
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
@@ -21,7 +21,7 @@
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
}
@@ -543,7 +_,7 @@
@@ -540,7 +_,7 @@
}
}

View File

@@ -92,15 +92,15 @@
profiler.pop();
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
@@ -344,6 +_,7 @@
return InteractionResult.CONSUME;
}
+ if (this.level().purpurConfig.villagerAllowTrading) // Purpur - Add config for villager trading
this.startTrading(player);
@@ -347,6 +_,7 @@
return InteractionResult.CONSUME;
}
@@ -485,7 +_,7 @@
+ if (this.level().purpurConfig.villagerAllowTrading) // Purpur - Add config for villager trading
this.startTrading(player);
}
@@ -487,7 +_,7 @@
public void updateDemand() {
for (MerchantOffer offer : this.getOffers()) {
@@ -109,7 +109,7 @@
}
}
@@ -685,7 +_,7 @@
@@ -687,7 +_,7 @@
@Override
public boolean canBreed() {
@@ -118,7 +118,7 @@
}
private boolean hungry() {
@@ -891,6 +_,7 @@
@@ -893,6 +_,7 @@
}
public void spawnGolemIfNeeded(final ServerLevel level, final long timestamp, final int villagersNeededToAgree) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
@@ -61,6 +_,13 @@
@@ -60,6 +_,13 @@
super(type, level);
}
@@ -14,7 +14,7 @@
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new FloatGoal(this));
@@ -78,7 +_,7 @@
@@ -77,7 +_,7 @@
.addGoal(
0,
new UseItemGoal<>(
@@ -23,7 +23,7 @@
)
);
this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this));
@@ -121,8 +_,10 @@
@@ -120,8 +_,10 @@
return InteractionResult.CONSUME;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
@@ -133,7 +_,17 @@
@@ -135,7 +_,17 @@
int xPosition = referencePosition.getX() + this.random.nextInt(radius * 2) - radius;
int zPosition = referencePosition.getZ() + this.random.nextInt(radius * 2) - radius;
int yPosition = level.getHeight(SpawnPlacements.getHeightmapType(EntityType.WANDERING_TRADER), xPosition, zPosition);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -174,11 +_,20 @@
@@ -173,11 +_,20 @@
public float hurtDir;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
@@ -21,7 +21,7 @@
@Override
public org.bukkit.craftbukkit.entity.CraftHumanEntity getBukkitEntity() {
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
@@ -239,6 +_,12 @@
@@ -242,6 +_,12 @@
@Override
public void tick() {
@@ -34,7 +34,7 @@
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
@@ -296,6 +_,17 @@
@@ -299,6 +_,17 @@
this.turtleHelmetTick();
}
@@ -52,7 +52,7 @@
this.cooldowns.tick();
this.updatePlayerPose();
}
@@ -501,7 +_,7 @@
@@ -504,7 +_,7 @@
List<Entity> orbs = Lists.newArrayList();
for (Entity entity : entities) {
@@ -61,7 +61,7 @@
orbs.add(entity);
} else if (!entity.isRemoved()) {
this.touch(entity);
@@ -1044,7 +_,7 @@
@@ -1052,7 +_,7 @@
criticalAttack = criticalAttack && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
if (criticalAttack) {
damageSource = damageSource.critical(); // Paper - critical damage API
@@ -70,7 +70,7 @@
}
float totalDamage = baseDamage + magicBoost;
@@ -1740,7 +_,23 @@
@@ -1748,7 +_,23 @@
@Override
protected int getBaseExperienceReward(final ServerLevel level) {
@@ -95,7 +95,7 @@
}
@Override
@@ -1783,6 +_,13 @@
@@ -1791,6 +_,13 @@
public boolean addItem(final ItemStack itemStack) {
return this.inventory.add(itemStack);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/projectile/throwableitemprojectile/Snowball.java
+++ b/net/minecraft/world/entity/projectile/throwableitemprojectile/Snowball.java
@@ -56,9 +_,39 @@
@@ -54,9 +_,39 @@
protected void onHitEntity(final EntityHitResult hitResult) {
super.onHitEntity(hitResult);
Entity entity = hitResult.getEntity();

View File

@@ -26,17 +26,17 @@
Iterator<Raid> raidIterator = this.raidMap.values().iterator();
while (raidIterator.hasNext()) {
@@ -137,11 +_,11 @@
// }
@@ -139,11 +_,12 @@
// }
if (!raid.isStarted() || (raid.isInProgress() && raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel())) { // CraftBukkit - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished
- // CraftBukkit start
+ if (level.purpurConfig.raidCooldownSeconds != 0 && playerCooldowns.containsKey(player.getUUID())) return null; // Purpur - Raid cooldown setting// CraftBukkit start
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(level, raid, player)) {
player.removeEffect(net.minecraft.world.effect.MobEffects.RAID_OMEN);
return null;
- }
+ }if (level.purpurConfig.raidCooldownSeconds != 0) playerCooldowns.put(player.getUUID(), level.purpurConfig.raidCooldownSeconds); // Purpur - Raid cooldown setting
if (!raid.isStarted() || (raid.isInProgress() && raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel())) { // CraftBukkit - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished
+ if (level.purpurConfig.raidCooldownSeconds != 0 && playerCooldowns.containsKey(player.getUUID())) return null; // Purpur - Raid cooldown setting
// CraftBukkit start
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(level, raid, player)) {
player.removeEffect(net.minecraft.world.effect.MobEffects.RAID_OMEN);
return null;
- }
+ }if (level.purpurConfig.raidCooldownSeconds != 0) playerCooldowns.put(player.getUUID(), level.purpurConfig.raidCooldownSeconds); // Purpur - Raid cooldown setting
if (!raid.isStarted() && !this.raidMap.containsValue(raid)) {
this.raidMap.put(this.getUniqueId(), raid);
if (!raid.isStarted() && !this.raidMap.containsValue(raid)) {
this.raidMap.put(this.getUniqueId(), raid);

View File

@@ -6,6 +6,6 @@
if (deltaMovement.length() > 0.01) {
- return deltaMovement.normalize().scale(deltaMovement.length() + 0.06);
+ return deltaMovement.normalize().scale(deltaMovement.length() + this.level().purpurConfig.poweredRailBoostModifier); // Purpur - Configurable powered rail boost modifier
} else {
Vec3 powerDirection = this.minecart.getRedstoneDirection(pos);
return powerDirection.lengthSqr() <= 0.0 ? deltaMovement : powerDirection.scale(deltaMovement.length() + 0.2);
}
Vec3 powerDirection = this.minecart.getRedstoneDirection(pos);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -65,6 +_,7 @@
@@ -64,6 +_,7 @@
private final List<ContainerListener> containerListeners = Lists.newArrayList();
private @Nullable ContainerSynchronizer synchronizer;
private boolean suppressRemoteUpdates;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java
+++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java
@@ -122,7 +_,13 @@
@@ -121,7 +_,13 @@
} else if (slotIndex != 1 && slotIndex != 0) {
if (this.canSmelt(stack)) {
if (!this.moveItemStackTo(stack, 0, 1, false)) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/inventory/EnchantmentMenu.java
+++ b/net/minecraft/world/inventory/EnchantmentMenu.java
@@ -64,6 +_,22 @@
@@ -63,6 +_,22 @@
return access.getLocation();
}
// CraftBukkit end
@@ -23,7 +23,7 @@
};
// Paper end - Add missing InventoryHolders
this.access = access;
@@ -92,6 +_,16 @@
@@ -83,6 +_,16 @@
return EnchantmentMenu.EMPTY_SLOT_LAPIS_LAZULI;
}
});
@@ -40,7 +40,7 @@
this.addStandardInventorySlots(inventory, 8, 84);
this.addDataSlot(DataSlot.shared(this.costs, 0));
this.addDataSlot(DataSlot.shared(this.costs, 1));
@@ -308,7 +_,7 @@
@@ -301,7 +_,7 @@
@Override
public void removed(final Player player) {
super.removed(player);

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -105,11 +_,13 @@
@@ -92,11 +_,13 @@
@Override
public void onTake(final Player player, final ItemStack carried) {
access.execute((level, pos) -> {
@@ -15,7 +15,7 @@
// Paper end - Fire BlockExpEvent on grindstone use
}
@@ -138,7 +_,7 @@
@@ -125,7 +_,7 @@
for (Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
Holder<Enchantment> enchant = entry.getKey();
int lvl = entry.getIntValue();
@@ -24,7 +24,7 @@
amount += enchant.value().getMinCost(lvl);
}
}
@@ -216,16 +_,76 @@
@@ -205,16 +_,76 @@
for (Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
Holder<Enchantment> enchant = entry.getKey();
@@ -103,7 +103,7 @@
);
if (item.is(Items.ENCHANTED_BOOK) && newEnchantments.isEmpty()) {
item = item.transmuteCopy(Items.BOOK);
@@ -238,6 +_,22 @@
@@ -227,6 +_,22 @@
}
item.set(DataComponents.REPAIR_COST, repairCost);
@@ -126,7 +126,7 @@
return item;
}
@@ -294,7 +_,9 @@
@@ -283,7 +_,9 @@
return ItemStack.EMPTY;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -177,7 +_,9 @@
@@ -160,7 +_,9 @@
return ItemStack.EMPTY;
}

View File

@@ -1,41 +1,42 @@
--- a/net/minecraft/world/item/AxeItem.java
+++ b/net/minecraft/world/item/AxeItem.java
@@ -65,13 +_,15 @@
if (playerHasBlockingItemUseIntent(context)) {
@@ -66,14 +_,16 @@
return InteractionResult.PASS;
} else {
- Optional<BlockState> newBlock = this.evaluateNewBlockState(level, pos, player, level.getBlockState(pos));
+ Optional<org.purpurmc.purpur.tool.Actionable> newBlock = this.evaluateActionable(level, pos, player, level.getBlockState(pos)); // Purpur - Tool actionable options
if (newBlock.isEmpty()) {
return InteractionResult.PASS;
} else {
+ org.purpurmc.purpur.tool.Actionable actionable = newBlock.get(); // Purpur - Tool actionable options
+ BlockState state = actionable.into().withPropertiesOf(level.getBlockState(pos)); // Purpur - Tool actionable options
ItemStack itemInHand = context.getItemInHand();
// Paper start - EntityChangeBlockEvent
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, newBlock.get())) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, state)) { // Purpur - Tool actionable options
return InteractionResult.PASS;
}
// Paper end
@@ -79,8 +_,15 @@
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, pos, itemInHand);
}
}
- level.setBlock(pos, newBlock.get(), Block.UPDATE_ALL_IMMEDIATE);
- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, newBlock.get()));
+ // Purpur start - Tool actionable options
+ level.setBlock(pos, state, Block.UPDATE_ALL_IMMEDIATE);
+ actionable.drops().forEach((drop, chance) -> {
+ if (level.getRandom().nextDouble() < chance) {
+ Block.popResourceFromFace(level, pos, context.getClickedFace(), new ItemStack(drop));
+ }
+ });
+ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, state));
+ // Purpur end - Tool actionable options
if (player != null) {
itemInHand.hurtAndBreak(1, player, context.getHand().asEquipmentSlot());
}
- Optional<BlockState> newBlock = this.evaluateNewBlockState(level, pos, player, level.getBlockState(pos));
+ Optional<org.purpurmc.purpur.tool.Actionable> newBlock = this.evaluateActionable(level, pos, player, level.getBlockState(pos)); // Purpur - Tool actionable options
if (newBlock.isEmpty()) {
return InteractionResult.PASS;
}
+ org.purpurmc.purpur.tool.Actionable actionable = newBlock.get(); // Purpur - Tool actionable options
+ BlockState state = actionable.into().withPropertiesOf(level.getBlockState(pos)); // Purpur - Tool actionable options
ItemStack itemInHand = context.getItemInHand();
// Paper start - EntityChangeBlockEvent
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, newBlock.get())) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, state)) { // Purpur - Tool actionable options
return InteractionResult.PASS;
}
// Paper end
@@ -81,8 +_,15 @@
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, pos, itemInHand);
}
- level.setBlock(pos, newBlock.get(), Block.UPDATE_ALL_IMMEDIATE);
- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, newBlock.get()));
+ // Purpur start - Tool actionable options
+ level.setBlock(pos, state, Block.UPDATE_ALL_IMMEDIATE);
+ actionable.drops().forEach((drop, chance) -> {
+ if (level.getRandom().nextDouble() < chance) {
+ Block.popResourceFromFace(level, pos, context.getClickedFace(), new ItemStack(drop));
+ }
+ });
+ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, state));
+ // Purpur end - Tool actionable options
if (player != null) {
itemInHand.hurtAndBreak(1, player, context.getHand().asEquipmentSlot());
}
@@ -97,21 +_,23 @@
&& !player.isSecondaryUseActive();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -132,7 +_,16 @@
@@ -134,7 +_,16 @@
protected boolean updateCustomBlockEntityTag(
final BlockPos pos, final Level level, final @Nullable Player player, final ItemStack itemStack, final BlockState placedState
) {
@@ -18,15 +18,15 @@
}
protected @Nullable BlockState getPlacementState(final BlockPlaceContext context) {
@@ -194,6 +_,7 @@
}
@@ -197,6 +_,7 @@
}
if (!type.onlyOpCanSetNbt() || player != null && (player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place")))) { // Spigot - add permission
+ if (!(level.purpurConfig.silkTouchEnabled && blockEntity instanceof net.minecraft.world.level.block.entity.SpawnerBlockEntity && player.getBukkitEntity().hasPermission("purpur.drop.spawners"))) // Purpur - Silk touch spawners
return customData.loadInto(blockEntity, level.registryAccess());
}
if (!type.onlyOpCanSetNbt() || player != null && (player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place")))) { // Spigot - add permission
+ if (!(level.purpurConfig.silkTouchEnabled && blockEntity instanceof net.minecraft.world.level.block.entity.SpawnerBlockEntity && player.getBukkitEntity().hasPermission("purpur.drop.spawners"))) // Purpur - Silk touch spawners
return customData.loadInto(blockEntity, level.registryAccess());
}
@@ -234,6 +_,7 @@
@@ -236,6 +_,7 @@
public void onDestroyed(final ItemEntity entity) {
ItemContainerContents container = entity.getItem().set(DataComponents.CONTAINER, ItemContainerContents.EMPTY);
if (container != null) {

View File

@@ -11,16 +11,16 @@
+ // Purpur end - Infinity bow settings
if (projectile.isEmpty()) {
return false;
} else {
@@ -38,7 +_,7 @@
} else {
List<ItemStack> firedProjectiles = draw(itemStack, projectile, player);
if (level instanceof ServerLevel serverLevel && !firedProjectiles.isEmpty()) {
- this.shoot(serverLevel, player, player.getUsedItemHand(), itemStack, firedProjectiles, pow * 3.0F, 1.0F, pow == 1.0F, null, pow); // Paper - Pass draw strength
+ this.shoot(serverLevel, player, player.getUsedItemHand(), itemStack, firedProjectiles, pow * 3.0F, (float) serverLevel.purpurConfig.bowProjectileOffset, pow == 1.0F, null, pow); // Paper - Pass draw strength // Purpur - Projectile offset config
}
}
@@ -40,7 +_,7 @@
level.playSound(
List<ItemStack> firedProjectiles = draw(itemStack, projectile, player);
if (level instanceof ServerLevel serverLevel && !firedProjectiles.isEmpty()) {
- this.shoot(serverLevel, player, player.getUsedItemHand(), itemStack, firedProjectiles, pow * 3.0F, 1.0F, pow == 1.0F, null, pow); // Paper - Pass draw strength
+ this.shoot(serverLevel, player, player.getUsedItemHand(), itemStack, firedProjectiles, pow * 3.0F, (float) serverLevel.purpurConfig.bowProjectileOffset, pow == 1.0F, null, pow); // Paper - Pass draw strength // Purpur - Projectile offset config
}
level.playSound(
@@ -95,7 +_,7 @@
public InteractionResult use(final Level level, final Player player, final InteractionHand hand) {
ItemStack itemStack = player.getItemInHand(hand);
@@ -28,5 +28,5 @@
- if (!player.hasInfiniteMaterials() && !foundProjectile) {
+ if (!player.hasInfiniteMaterials() && !foundProjectile && !(level.purpurConfig.infinityWorksWithoutArrows && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY, itemStack) > 0)) { // Purpur - Infinity bow settings
return InteractionResult.FAIL;
} else {
player.startUsingItem(hand);
}

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/item/BucketItem.java
+++ b/net/minecraft/world/item/BucketItem.java
@@ -146,7 +_,7 @@
// CraftBukkit end
if (!canPlaceFluidInsideBlock) {
@@ -152,7 +_,7 @@
return hitResult != null && this.emptyContents(user, level, hitResult.getBlockPos().relative(hitResult.getDirection()), null, direction, clicked, itemStack, hand); // CraftBukkit
- } else if (level.environmentAttributes().getValue(EnvironmentAttributes.WATER_EVAPORATES, pos) && this.content.is(FluidTags.WATER)) {
+ } else if ((level.environmentAttributes().getValue(EnvironmentAttributes.WATER_EVAPORATES, pos) || (level.isTheEnd() && !org.purpurmc.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) && this.content.is(FluidTags.WATER)) { // Purpur - Add allow water in end world option
}
- if (level.environmentAttributes().getValue(EnvironmentAttributes.WATER_EVAPORATES, pos) && this.content.is(FluidTags.WATER)) {
+ if ((level.environmentAttributes().getValue(EnvironmentAttributes.WATER_EVAPORATES, pos) || (level.isTheEnd() && !org.purpurmc.purpur.PurpurConfig.allowWaterPlacementInTheEnd)) && this.content.is(FluidTags.WATER)) { // Purpur - Add allow water in end world option
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/world/item/DyeColor.java
+++ b/net/minecraft/world/item/DyeColor.java
@@ -154,4 +_,10 @@
}
}
return null;
}
+
+ // Purpur start - Shulker spawn from bullet options

View File

@@ -7,5 +7,5 @@
- if (!blockState.is(Blocks.OBSIDIAN) && !blockState.is(Blocks.BEDROCK)) {
+ if (!level.purpurConfig.endCrystalPlaceAnywhere && !blockState.is(Blocks.OBSIDIAN) && !blockState.is(Blocks.BEDROCK)) { // Purpur - place end crystal on any block
return InteractionResult.FAIL;
} else {
BlockPos above = pos.above();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/item/HoeItem.java
+++ b/net/minecraft/world/item/HoeItem.java
@@ -44,15 +_,25 @@
@@ -44,16 +_,26 @@
public InteractionResult useOn(final UseOnContext context) {
Level level = context.getLevel();
BlockPos pos = context.getClickedPos();
@@ -11,23 +11,24 @@
+ org.purpurmc.purpur.tool.Tillable tillable = level.purpurConfig.hoeTillables.get(clickedBlock);
+ if (tillable == null) {
return InteractionResult.PASS;
} else {
- Predicate<UseOnContext> predicate = logicPair.getFirst();
- Consumer<UseOnContext> action = logicPair.getSecond();
+ Predicate<UseOnContext> predicate = tillable.condition().predicate();
+ Consumer<UseOnContext> action = (ctx) -> {
+ level.setBlock(pos, tillable.into().defaultBlockState(), 11);
+ tillable.drops().forEach((drop, chance) -> {
+ if (level.getRandom().nextDouble() < chance) {
+ Block.popResourceFromFace(level, pos, ctx.getClickedFace(), new ItemStack(drop));
+ }
+ });
+ };
+ // Purpur end - Tool actionable options
if (predicate.test(context)) {
Player player = context.getPlayer();
- level.playSound(player, pos, SoundEvents.HOE_TILL, SoundSource.BLOCKS, 1.0F, 1.0F);
+ if (!TILLABLES.containsKey(clickedBlock)) level.playSound(null, pos, SoundEvents.HOE_TILL, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - Tool actionable options - force sound
if (!level.isClientSide()) {
action.accept(context);
if (player != null) {
}
- Predicate<UseOnContext> predicate = logicPair.getFirst();
- Consumer<UseOnContext> action = logicPair.getSecond();
+ Predicate<UseOnContext> predicate = tillable.condition().predicate();
+ Consumer<UseOnContext> action = (ctx) -> {
+ level.setBlock(pos, tillable.into().defaultBlockState(), 11);
+ tillable.drops().forEach((drop, chance) -> {
+ if (level.getRandom().nextDouble() < chance) {
+ Block.popResourceFromFace(level, pos, ctx.getClickedFace(), new ItemStack(drop));
+ }
+ });
+ };
+ // Purpur end - Tool actionable options
if (predicate.test(context)) {
Player player = context.getPlayer();
- level.playSound(player, pos, SoundEvents.HOE_TILL, SoundSource.BLOCKS, 1.0F, 1.0F);
+ if (!TILLABLES.containsKey(clickedBlock)) level.playSound(null, pos, SoundEvents.HOE_TILL, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - Tool actionable options - force sound
if (!level.isClientSide()) {
action.accept(context);
if (player != null) {

View File

@@ -1,21 +1,21 @@
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -452,6 +_,7 @@
// revert back all captured blocks
for (org.bukkit.block.BlockState blockstate : blocks) {
((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).revertPlace();
+ ((org.bukkit.craftbukkit.block.CraftBlock) blockstate.getBlock()).getBlockState().getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed
}
@@ -453,6 +_,7 @@
// revert back all captured blocks
for (org.bukkit.block.BlockState blockstate : blocks) {
((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).revertPlace();
+ ((org.bukkit.craftbukkit.block.CraftBlock) blockstate.getBlock()).getBlockState().getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed
}
SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
@@ -475,6 +_,7 @@
if (!(block.getBlock() instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // Containers get placed automatically
block.onPlace(level, newPos, oldBlock, true, context);
}
+ block.getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed
level.notifyAndUpdatePhysics(newPos, null, oldBlock, block, level.getBlockState(newPos), updateFlags, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point
SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
@@ -476,6 +_,7 @@
if (!(block.getBlock() instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // Containers get placed automatically
block.onPlace(level, newPos, oldBlock, true, context);
}
+ block.getBlock().forgetPlacer(); // Purpur - Store placer on Block when placed
level.notifyAndUpdatePhysics(newPos, null, oldBlock, block, level.getBlockState(newPos), updateFlags, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point
}
@@ -591,6 +_,26 @@
return this.isDamageableItem() && this.getDamageValue() > 0;
}
@@ -43,7 +43,7 @@
public int getDamageValue() {
return Mth.clamp(this.getOrDefault(DataComponents.DAMAGE, 0), 0, this.getMaxDamage());
}
@@ -1246,6 +_,12 @@
@@ -1254,6 +_,12 @@
public boolean isEnchanted() {
return !this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).isEmpty();
}

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/item/ProjectileWeaponItem.java
+++ b/net/minecraft/world/item/ProjectileWeaponItem.java
@@ -114,6 +_,8 @@
arrowx.setCritArrow(true);
arrow.setCritArrow(true);
}
+ arrowx.setActualEnchantments(weapon.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting
+ arrow.setActualEnchantments(weapon.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting
+
return arrowx;
return arrow;
}

View File

@@ -1,17 +1,18 @@
--- a/net/minecraft/world/item/ShovelItem.java
+++ b/net/minecraft/world/item/ShovelItem.java
@@ -46,9 +_,12 @@
BlockState newState = FLATTENABLES.get(blockState.getBlock());
BlockState updatedState = null;
Runnable afterAction = null; // Paper
+ org.purpurmc.purpur.tool.Flattenable flattenable = level.purpurConfig.shovelFlattenables.get(blockState.getBlock()); // Purpur - Tool actionable options
if (newState != null && level.getBlockState(pos.above()).isAir()) {
- afterAction = () -> level.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
- updatedState = newState;
@@ -47,9 +_,12 @@
BlockState newState = FLATTENABLES.get(blockState.getBlock());
BlockState updatedState = null;
Runnable afterAction = null; // Paper
- if (newState != null && level.getBlockState(pos.above()).isAir()) {
- afterAction = () -> level.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
- updatedState = newState;
+ org.purpurmc.purpur.tool.Flattenable flattenable = level.purpurConfig.shovelFlattenables.get(blockState.getBlock()); // Purpur - Tool actionable options
+ if (newState != null && level.getBlockState(pos.above()).isAir()) {
+ // Purpur start - Tool actionable options
+ afterAction = () -> {if (!FLATTENABLES.containsKey(blockState.getBlock())) level.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);}; // Paper
+ updatedState = flattenable.into().defaultBlockState();
+ afterAction = () -> {if (!FLATTENABLES.containsKey(blockState.getBlock())) level.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);}; // Paper
+ updatedState = flattenable.into().defaultBlockState();
+ // Purpur end - Tool actionable options
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
afterAction = () -> { // Paper
if (!level.isClientSide()) {
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
afterAction = () -> { // Paper
if (!level.isClientSide()) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/item/SpawnEggItem.java
+++ b/net/minecraft/world/item/SpawnEggItem.java
@@ -62,6 +_,23 @@
@@ -64,6 +_,23 @@
return InteractionResult.FAIL;
} else {
if (level.paperConfig().entities.spawning.disableMobSpawnerSpawnEggTransformation) return InteractionResult.FAIL; // Paper - Allow disabling mob spawner spawn egg transformation

View File

@@ -1,19 +1,19 @@
--- a/net/minecraft/world/item/TridentItem.java
+++ b/net/minecraft/world/item/TridentItem.java
@@ -82,7 +_,7 @@
if (riptideStrength == 0.0F) {
ItemStack thrownItemStack = itemStack.copyWithCount(1); // Paper
Projectile.Delayed<ThrownTrident> tridentDelayed = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent(
- ThrownTrident::new, serverLevel, thrownItemStack, player, 0.0F, 2.5F, 1.0F
+ ThrownTrident::new, serverLevel, thrownItemStack, player, 0.0F, 2.5F, (float) serverLevel.purpurConfig.tridentProjectileOffset // Purpur - Projectile offset config
);
// Paper start - PlayerLaunchProjectileEvent
com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity());
@@ -92,6 +_,7 @@
return false;
}
ThrownTrident trident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent
+ trident.setActualEnchantments(itemStack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting
if (event.shouldConsume()) {
thrownItemStack.hurtWithoutBreaking(1, player); // Paper - PlayerLaunchProjectileEvent - use thrownItemStack; pickup item damage
}
@@ -84,7 +_,7 @@
if (riptideStrength == 0.0F) {
ItemStack thrownItemStack = itemStack.copyWithCount(1); // Paper
Projectile.Delayed<ThrownTrident> tridentDelayed = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent(
- ThrownTrident::new, serverLevel, thrownItemStack, player, 0.0F, 2.5F, 1.0F
+ ThrownTrident::new, serverLevel, thrownItemStack, player, 0.0F, 2.5F, (float) serverLevel.purpurConfig.tridentProjectileOffset // Purpur - Projectile offset config
);
// Paper start - PlayerLaunchProjectileEvent
com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity());
@@ -94,6 +_,7 @@
return false;
}
ThrownTrident trident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent
+ trident.setActualEnchantments(itemStack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting
if (event.shouldConsume()) {
thrownItemStack.hurtWithoutBreaking(1, player); // Paper - PlayerLaunchProjectileEvent - use thrownItemStack; pickup item damage
}

View File

@@ -8,7 +8,7 @@
public boolean isExact() {
return this.itemStacks != null;
@@ -86,6 +_,11 @@
@@ -88,6 +_,11 @@
return this.itemStacks.contains(input); // Paper - Improve exact choice recipe ingredients (hashing FTW!)
}
// CraftBukkit end

View File

@@ -64,7 +64,7 @@
this.generator = generator;
this.world = new CraftWorld((ServerLevel) this, worldKey, biomeProvider, environment);
@@ -2194,4 +_,14 @@
@@ -2197,4 +_,14 @@
return this.moonrise$getEntityLookup().getEntityCount(); // Paper - rewrite chunk system
}
// Paper end - allow patching this logic

View File

@@ -7,4 +7,4 @@
+ if (!((net.minecraft.world.level.LevelAccessor) level).getMinecraftWorld().purpurConfig.coralDieOutsideWater) return true; // Purpur - Config to not let coral die
if (state.getValue(WATERLOGGED)) {
return true;
} else {
}

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/net/minecraft/world/level/block/BaseFireBlock.java
@@ -215,7 +_,7 @@
boolean hasObsidian = false;
@@ -216,7 +_,7 @@
boolean hasObsidian = false;
for (Direction face : Direction.values()) {
- if (level.getBlockState(testPos.set(pos).move(face)).is(Blocks.OBSIDIAN)) {
+ if (PortalShape.FRAME.test(level.getBlockState(testPos.set(pos).move(face)), level, testPos)) { // Purpur - Crying obsidian valid for portal frames
hasObsidian = true;
break;
}
for (Direction face : Direction.values()) {
- if (level.getBlockState(testPos.set(pos).move(face)).is(Blocks.OBSIDIAN)) {
+ if (PortalShape.FRAME.test(level.getBlockState(testPos.set(pos).move(face)), level, testPos)) { // Purpur - Crying obsidian valid for portal frames
hasObsidian = true;
break;
}

View File

@@ -1,20 +1,20 @@
--- a/net/minecraft/world/level/block/BedBlock.java
+++ b/net/minecraft/world/level/block/BedBlock.java
@@ -100,7 +_,7 @@
}
@@ -101,7 +_,7 @@
}
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
if (bedRule.explodes()) return this.explodeBed(state, level, pos); // Paper - check explode first
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
if (bedRule.explodes()) return this.explodeBed(state, level, pos); // Paper - check explode first
@@ -153,7 +_,7 @@
}
Vec3 center = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(center).causingBlockSnapshot(blockState), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(center).causingBlockSnapshot(blockState), null, center, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // CraftBukkit - add state // Purpur - Implement bed explosion options
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // CraftBukkit - add state // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
}
// CraftBukkit end

View File

@@ -11,7 +11,7 @@
// Paper start - Protect Bedrock and End Portal/Frames from being destroyed
public final boolean isDestroyable() {
return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
@@ -411,7 +_,7 @@
@@ -415,7 +_,7 @@
event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
@@ -20,7 +20,7 @@
}
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
@@ -429,7 +_,7 @@
@@ -433,7 +_,7 @@
public static void dropResources(final BlockState state, final LevelAccessor level, final BlockPos pos, final @Nullable BlockEntity blockEntity) {
if (level instanceof ServerLevel serverLevel) {
@@ -29,7 +29,7 @@
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
}
}
@@ -450,11 +_,30 @@
@@ -454,11 +_,30 @@
, final boolean dropExperience // Paper - Properly handle xp dropping
) {
if (level instanceof ServerLevel serverLevel) {
@@ -61,7 +61,7 @@
public static void popResource(final Level level, final BlockPos pos, final ItemStack itemStack) {
double halfHeight = EntityType.ITEM.getHeight() / 2.0;
RandomSource random = level.getRandom();
@@ -544,7 +_,15 @@
@@ -548,7 +_,15 @@
}
public void setPlacedBy(final Level level, final BlockPos pos, final BlockState state, final @Nullable LivingEntity by, final ItemStack itemStack) {
@@ -78,7 +78,7 @@
public boolean isPossibleToRespawnInThis(final BlockState state) {
return !state.isSolid() && !state.liquid();
@@ -555,7 +_,7 @@
@@ -559,7 +_,7 @@
}
public void fallOn(final Level level, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) {

View File

@@ -1,10 +1,10 @@
--- a/net/minecraft/world/level/block/CakeBlock.java
+++ b/net/minecraft/world/level/block/CakeBlock.java
@@ -118,6 +_,7 @@
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
@@ -119,6 +_,7 @@
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
if (!event.isCancelled()) {
+ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur - Burp after eating food fills hunger bar completely
player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
}
if (!event.isCancelled()) {
+ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur - Burp after eating food fills hunger bar completely
player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -352,6 +_,7 @@
@@ -347,6 +_,7 @@
}
public static boolean isBlockedChestByBlock(final BlockGetter level, final BlockPos pos) {

View File

@@ -1,13 +1,14 @@
--- a/net/minecraft/world/level/block/DoorBlock.java
+++ b/net/minecraft/world/level/block/DoorBlock.java
@@ -200,6 +_,7 @@
@@ -200,7 +_,7 @@
protected InteractionResult useWithoutItem(BlockState state, final Level level, final BlockPos pos, final Player player, final BlockHitResult hitResult) {
if (!this.type.canOpenByHand()) {
return InteractionResult.PASS;
+ } else if (requiresRedstone(level, state, pos)) { return InteractionResult.CONSUME; // Purpur - Option to make doors require redstone
} else {
state = state.cycle(OPEN);
level.setBlock(pos, state, Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE);
- }
+ } else if (requiresRedstone(level, state, pos)) { return InteractionResult.CONSUME; } // Purpur - Option to make doors require redstone
state = state.cycle(OPEN);
level.setBlock(pos, state, Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE);
@@ -280,4 +_,18 @@
public static boolean isWoodenDoor(final BlockState state) {
return state.getBlock() instanceof DoorBlock door && door.type().canOpenByHand();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -194,20 +_,20 @@
@@ -196,20 +_,20 @@
@VisibleForTesting
public static void maybeTransferFluid(final BlockState state, final ServerLevel level, final BlockPos pos, final float randomValue) {

View File

@@ -7,5 +7,5 @@
- if (searchDepth >= 8) {
+ if (searchDepth >= level.purpurConfig.railActivationRange) { // Purpur - Config for powered rail activation distance
return false;
} else {
int x = pos.getX();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -180,7 +_,7 @@
@@ -176,7 +_,7 @@
}
};
Vec3 boomPos = pos.getCenter();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -195,6 +_,21 @@
@@ -190,6 +_,21 @@
}
ItemStack fuel = entity.items.get(1);
@@ -22,7 +22,7 @@
ItemStack ingredient = entity.items.get(0);
boolean hasIngredient = !ingredient.isEmpty();
boolean hasFuel = !fuel.isEmpty();
@@ -273,6 +_,8 @@
@@ -268,6 +_,8 @@
if (changed) {
setChanged(level, pos, state);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -142,6 +_,16 @@
@@ -138,6 +_,16 @@
public double getEffectRange() {
if (this.effectRange < 0) {
@@ -17,7 +17,7 @@
return this.levels * 10 + 10;
} else {
return effectRange;
@@ -170,6 +_,7 @@
@@ -166,6 +_,7 @@
int y = pos.getY();
int z = pos.getZ();
BlockPos checkPos;
@@ -25,7 +25,7 @@
if (entity.lastCheckY < y) {
checkPos = pos;
entity.checkingBeamSections = Lists.newArrayList();
@@ -199,11 +_,15 @@
@@ -195,11 +_,15 @@
}
}
} else {
@@ -42,7 +42,7 @@
lastBeamSection.increaseHeight();
}
@@ -214,11 +_,11 @@
@@ -210,11 +_,11 @@
int previousLevels = entity.levels;
if (level.getGameTime() % 80L == 0L) {

View File

@@ -9,7 +9,7 @@
private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400;
private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400;
public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600;
@@ -157,11 +_,33 @@
@@ -157,10 +_,32 @@
return spawned;
}
@@ -33,24 +33,12 @@
public int getOccupantCount() {
return this.stored.size();
}
+
+ // Purpur start - Stored Bee API
+ public List<BeeData> getStored() {
+ return stored;
+ }
+ // Purpur end - Stored Bee API
+
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -400,8 +_,8 @@
registration.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
}
- private static class BeeData {
- private final BeehiveBlockEntity.Occupant occupant;
+ public static class BeeData { // Purpur - make public - Stored Bee API
+ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public - Stored Bee API
private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
private int ticksInHive;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -108,6 +_,10 @@
@@ -107,6 +_,10 @@
input.read("PublicBukkitValues", CompoundTag.CODEC)
.ifPresent(this.persistentDataContainer::putAll);
// Paper end - read persistent data container
@@ -11,7 +11,7 @@
}
public final void loadWithComponents(final ValueInput input) {
@@ -120,6 +_,11 @@
@@ -119,6 +_,11 @@
}
protected void saveAdditional(final ValueOutput output) {
@@ -23,7 +23,7 @@
}
public final CompoundTag saveWithFullMetadata(final HolderLookup.Provider registries) {
@@ -414,4 +_,16 @@
@@ -395,4 +_,16 @@
return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos();
}
}

View File

@@ -1,7 +1,7 @@
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
@@ -150,7 +_,7 @@
BlockPos testPos = worldPosition.offset(ox, oy, ozx);
@@ -151,7 +_,7 @@
BlockPos testPos = worldPosition.offset(ox, oy, oz);
BlockState testBlock = level.getBlockState(testPos);
- for (Block type : VALID_BLOCKS) {
@@ -9,7 +9,7 @@
if (testBlock.is(type)) {
effectBlocks.add(testPos);
}
@@ -165,13 +_,13 @@
@@ -166,13 +_,13 @@
private static void applyEffects(final Level level, final BlockPos worldPosition, final List<BlockPos> effectBlocks) {
// CraftBukkit start
@@ -26,7 +26,7 @@
// CraftBukkit start
return effectRange;
}
@@ -204,7 +_,7 @@
@@ -205,7 +_,7 @@
EntityReference<LivingEntity> newDestroyTarget = updateDestroyTarget(entity.destroyTarget, level, worldPosition, isActive);
LivingEntity targetEntity = EntityReference.getLivingEntity(newDestroyTarget, level);
if (damageTarget && targetEntity != null) { // CraftBukkit
@@ -35,13 +35,12 @@
level.playSound(
null, targetEntity.getX(), targetEntity.getY(), targetEntity.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F
);
@@ -225,19 +_,25 @@
return selectNewTarget(level, pos);
} else {
LivingEntity targetEntity = EntityReference.getLivingEntity(target, level);
- return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), 8.0) ? target : null;
+ return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? target : null; // Purpur - Conduit behavior configuration
@@ -229,18 +_,24 @@
}
LivingEntity targetEntity = EntityReference.getLivingEntity(target, level);
- return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), 8.0) ? target : null;
+ return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? target : null; // Purpur - Conduit behavior configuration
}
private static @Nullable EntityReference<LivingEntity> selectNewTarget(final ServerLevel level, final BlockPos pos) {

View File

@@ -35,7 +35,7 @@
);
}
}
@@ -309,6 +_,27 @@
@@ -310,6 +_,27 @@
commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, level, LevelBasedPermissionSet.GAMEMASTER, textName, displayName, level.getServer(), player // Paper - Fix commands from signs not firing command events
);
}

View File

@@ -1,29 +1,29 @@
--- a/net/minecraft/world/level/block/piston/PistonStructureResolver.java
+++ b/net/minecraft/world/level/block/piston/PistonStructureResolver.java
@@ -81,7 +_,7 @@
return true;
} else {
int blockCount = 1;
- if (blockCount + this.toPush.size() > 12) {
+ if (blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
@@ -90,7 +_,7 @@
}
int blockCount = 1;
- if (blockCount + this.toPush.size() > 12) {
+ if (blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
@@ -105,7 +_,7 @@
break;
}
- if (++blockCount + this.toPush.size() > 12) {
+ if (++blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
} else {
while (isSticky(nextState)) {
@@ -95,7 +_,7 @@
break;
}
}
}
@@ -149,7 +_,7 @@
return true;
}
- if (++blockCount + this.toPush.size() > 12) {
+ if (++blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
}
@@ -139,7 +_,7 @@
return true;
}
- if (this.toPush.size() >= 12) {
+ if (this.toPush.size() >= this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
- if (this.toPush.size() >= 12) {
+ if (this.toPush.size() >= this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -108,6 +_,7 @@
@@ -105,6 +_,7 @@
}
// Paper end - Entity load/save limit per chunk
TagValueOutput output = TagValueOutput.createWithContext(reporter.forChild(e.problemPath()), e.registryAccess());

View File

@@ -4,8 +4,8 @@
// Paper start
private static void printOversizedLog(String msg, Path file, int x, int z) {
- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // Purpur - Rebrand
- LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4);
+ LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4); // Purpur - Rebrand
}
private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/material/FlowingFluid.java
+++ b/net/minecraft/world/level/material/FlowingFluid.java
@@ -235,7 +_,7 @@
@@ -234,7 +_,7 @@
}
}
@@ -9,7 +9,7 @@
BlockState belowState = level.getBlockState(mutablePos.setWithOffset(pos, Direction.DOWN));
FluidState belowFluid = belowState.getFluidState();
if (belowState.isSolid() || this.isSourceBlockOfThisType(belowFluid)) {
@@ -321,6 +_,12 @@
@@ -320,6 +_,12 @@
}
protected abstract boolean canConvertToSource(ServerLevel level);

View File

@@ -1,20 +1,20 @@
--- a/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -249,7 +_,7 @@
if ((best == null || best.costMalus < 0.0F)
&& jumpSize > 0
&& (pathType != PathType.FENCE || this.canWalkOverFences())
- && pathType != PathType.UNPASSABLE_RAIL
+ && (this.mob.level().purpurConfig.mobsIgnoreRails || pathType != PathType.UNPASSABLE_RAIL) // Purpur - Config to allow mobs to pathfind over rails
&& pathType != PathType.TRAPDOOR
&& pathType != PathType.POWDER_SNOW) {
best = this.tryJumpOn(x, y, z, jumpSize, nodeHeight, travelDirection, blockPathTypeCurrent, reusablePos);
@@ -517,7 +_,7 @@
return PathType.TRAPDOOR;
} else if (blockState.is(Blocks.POWDER_SNOW)) {
@@ -252,7 +_,7 @@
if ((best == null || best.costMalus < 0.0F)
&& jumpSize > 0
&& (pathType != PathType.FENCE || this.canWalkOverFences())
- && pathType != PathType.UNPASSABLE_RAIL
+ && (this.mob.level().purpurConfig.mobsIgnoreRails || pathType != PathType.UNPASSABLE_RAIL) // Purpur - Config to allow mobs to pathfind over rails
&& pathType != PathType.TRAPDOOR
&& pathType != PathType.POWDER_SNOW) {
best = this.tryJumpOn(x, y, z, jumpSize, nodeHeight, travelDirection, blockPathTypeCurrent, reusablePos);
@@ -533,7 +_,7 @@
return PathType.POWDER_SNOW;
- } else if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ } else if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur - Stonecutter damage
}
- if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur - Stonecutter damage
return PathType.DAMAGING;
} else if (blockState.is(Blocks.HONEY_BLOCK)) {
return PathType.STICKY_HONEY;
}

View File

@@ -1,12 +1,9 @@
--- a/net/minecraft/world/phys/AABB.java
+++ b/net/minecraft/world/phys/AABB.java
@@ -485,5 +_,11 @@
return new AABB(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
@@ -486,4 +_,9 @@
}
}
- }
+
+ }
}
+ // Purpur start - Stop squids floating on top of water - tuinity added method
+ public final AABB offsetY(double dy) {
+ return new AABB(this.minX, this.minY + dy, this.minZ, this.maxX, this.maxY + dy, this.maxZ);