diff --git a/gradle.properties b/gradle.properties index 8fcdcc1c8..0f6dfa3c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ group=net.pl3x.purpur version=1.17-R0.1-SNAPSHOT packageVersion=1_17_R1 -paperCommit=961b98f9cb5457a739ab61d4bb31f5867d9d4586 +paperCommit=22280c5f554bcdf245e94254ce5acba55ad5cd98 org.gradle.parallel=true org.gradle.jvmargs=-Xmx3G diff --git a/patches/server-unmapped/0199-Gamemode-extra-permissions.patch b/patches/server-unmapped/0199-Gamemode-extra-permissions.patch deleted file mode 100644 index b0dfe0d0c..000000000 --- a/patches/server-unmapped/0199-Gamemode-extra-permissions.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 30 Apr 2021 13:39:39 -0500 -Subject: [PATCH] Gamemode extra permissions - - -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index 4480fe75cfad35a5104b5116c5ec2c80d18f15f5..d73daa29f784283e03ad2ea3126cca7e572602d4 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -190,6 +190,21 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - } - // CraftBukkit end - -+ // Purpur start -+ public boolean testPermission(int i, String bukkitPermission) { -+ if (hasPermission(i, bukkitPermission)) { -+ return true; -+ } -+ String permissionMessage = getWorld().getServer().getPermissionMessage(); -+ if (permissionMessage.length() != 0) { -+ for (String line : permissionMessage.replace("", bukkitPermission).split("\n")) { -+ sendFailureMessage(new ChatComponentText(line)); -+ } -+ } -+ return false; -+ } -+ // Purpur end -+ - public Vec3D getPosition() { - return this.d; - } -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemode.java b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -index 8da48d9cbadfbe83ae8410cf49d78df49f50fb08..323fa988529a7ad316a4dc8d3fc0f62b1478c334 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamemode.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -@@ -55,6 +55,21 @@ public class CommandGamemode { - } - - private static int a(CommandContext commandcontext, Collection collection, EnumGamemode enumgamemode) { -+ // Purpur start -+ if (net.pl3x.purpur.PurpurConfig.commandGamemodeRequiresPermission) { -+ String gamemode = enumgamemode.getName(); -+ CommandListenerWrapper sender = commandcontext.getSource(); -+ if (!sender.testPermission(2, "minecraft.command.gamemode." + gamemode)) { -+ return 0; -+ } -+ if (sender.getEntity() instanceof EntityPlayer) { -+ EntityPlayer player = (EntityPlayer) sender.getEntity(); -+ if ((collection.size() > 1 || !collection.contains(player)) && !sender.testPermission(2, "minecraft.command.gamemode." + gamemode + ".other")) { -+ return 0; -+ } -+ } -+ } -+ // Purpur end - int i = 0; - Iterator iterator = collection.iterator(); - -diff --git a/src/main/java/net/minecraft/world/level/EnumGamemode.java b/src/main/java/net/minecraft/world/level/EnumGamemode.java -index eea551a68ba44927cb23560b898dd2c17f041442..1b049bdc897aaf1f0cb9b6dfeaf3a1e44214aef1 100644 ---- a/src/main/java/net/minecraft/world/level/EnumGamemode.java -+++ b/src/main/java/net/minecraft/world/level/EnumGamemode.java -@@ -20,6 +20,7 @@ public enum EnumGamemode { - return this.f; - } - -+ public String getName() { return b(); } // Purpur - OBFHELPER - public String b() { - return this.g; - } -diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 9e384f575cd072aac635eb14209daf68f83fc692..9f5bcec2c41e24310fe9b34bd51050f62164f1b1 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -211,6 +211,11 @@ public class PurpurConfig { - disableGiveCommandDrops = getBoolean("settings.disable-give-dropping", disableGiveCommandDrops); - } - -+ public static boolean commandGamemodeRequiresPermission = false; -+ private static void commandSettings() { -+ commandGamemodeRequiresPermission = getBoolean("settings.command.gamemode.requires-specific-permission", commandGamemodeRequiresPermission); -+ } -+ - public static boolean barrelSixRows = false; - public static boolean enderChestSixRows = false; - public static boolean enderChestPermissionRows = false; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index f0a57d225b81a505ff12425155ba838d8fad990c..9341bba9e48d4def2609d759a0dea7e099d5d777 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -23,7 +23,15 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "kick", "Allows the user to kick players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "stop", "Allows the user to stop the server", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands); -- DefaultPermissions.registerPermission(PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands); -+ // Purpur start -+ Permission gamemodeVanilla = DefaultPermissions.registerPermission(PREFIX + "gamemode", "Allows the user to change the gamemode", PermissionDefault.OP, commands); -+ for (net.minecraft.world.level.EnumGamemode enumgamemode : net.minecraft.world.level.EnumGamemode.values()) { -+ Permission gamemodeSelf = DefaultPermissions.registerPermission(PREFIX + "gamemode." + enumgamemode.getName(), "Allows the user to set " + enumgamemode.getName() + " gamemode for self", PermissionDefault.OP); -+ Permission gamemodeOther = DefaultPermissions.registerPermission(PREFIX + "gamemode." + enumgamemode.getName() + ".other", "Allows the user to set " + enumgamemode.getName() + " gamemode for other players", PermissionDefault.OP); -+ gamemodeSelf.addParent(gamemodeOther, true); -+ gamemodeVanilla.addParent(gamemodeSelf, true); -+ } -+ // Purpur end - DefaultPermissions.registerPermission(PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands); diff --git a/patches/server-unmapped/0200-Config-for-changing-the-blocks-that-turn-into-paths.patch b/patches/server-unmapped/0200-Config-for-changing-the-blocks-that-turn-into-paths.patch deleted file mode 100644 index a4558dd3e..000000000 --- a/patches/server-unmapped/0200-Config-for-changing-the-blocks-that-turn-into-paths.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 12emin34 -Date: Thu, 29 Apr 2021 23:56:02 +0200 -Subject: [PATCH] Config for changing the blocks that turn into paths - - -diff --git a/src/main/java/net/minecraft/world/item/ItemSpade.java b/src/main/java/net/minecraft/world/item/ItemSpade.java -index 9ba8ae49e18fb8714b434715bd669b8e22004cd7..c0c87d0dc8d6f02597219cd6a74e6ed7856ea229 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSpade.java -+++ b/src/main/java/net/minecraft/world/item/ItemSpade.java -@@ -43,7 +43,7 @@ public class ItemSpade extends ItemTool { - return EnumInteractionResult.PASS; - } else { - EntityHuman entityhuman = itemactioncontext.getEntity(); -- IBlockData iblockdata1 = (IBlockData) ItemSpade.a.get(iblockdata.getBlock()); -+ IBlockData iblockdata1 = world.purpurConfig.shovelTurnsBlockToGrassPath.contains(iblockdata.getBlock()) ? Blocks.GRASS_PATH.getBlockData() : ItemSpade.a.get(iblockdata.getBlock()); // Purpur - IBlockData iblockdata2 = null; - - if (iblockdata1 != null && world.getType(blockposition.up()).isAir()) { -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3d3e4e686cd74145b002b2df276e61762697918b..e082de2fdbd4803f5c79699b813062291f8e2bb7 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -469,6 +469,16 @@ public class PurpurWorldConfig { - totemOfUndyingWorksInInventory = getBoolean("gameplay-mechanics.player.totem-of-undying-works-in-inventory", totemOfUndyingWorksInInventory); - } - -+ public List shovelTurnsBlockToGrassPath = new ArrayList<>(); -+ private void shovelSettings() { -+ getList("gameplay-mechanics.shovel-turns-block-to-grass-path", new ArrayList(){{ -+ add("minecraft:grass_block"); -+ }}).forEach(key -> { -+ Block block = IRegistry.BLOCK.get(new MinecraftKey(key.toString())); -+ if (block != Blocks.AIR) shovelTurnsBlockToGrassPath.add(block); -+ }); -+ } -+ - public boolean silkTouchEnabled = false; - public String silkTouchSpawnerName = "Spawner"; - public List silkTouchSpawnerLore = new ArrayList<>(); diff --git a/patches/server-unmapped/0201-Allows-you-to-change-the-thrust-limit-of-a-piston-by.patch b/patches/server-unmapped/0201-Allows-you-to-change-the-thrust-limit-of-a-piston-by.patch deleted file mode 100644 index 8c5c9d2d1..000000000 --- a/patches/server-unmapped/0201-Allows-you-to-change-the-thrust-limit-of-a-piston-by.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctaEnkoda -Date: Sun, 2 May 2021 23:14:54 +0200 -Subject: [PATCH] Allows you to change the thrust limit of a piston by World - - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java b/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java -index 6c9c4ab65b7e42efa68027057242e25b70313081..cbe34059659e0f80ff384508b01e516cd7c5e28a 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java -@@ -12,7 +12,7 @@ import net.minecraft.world.level.material.EnumPistonReaction; - - public class PistonExtendsChecker { - -- private final World a; -+ private final World a; public World getWorld() { return a; } // Purpur - OBFHELPER - private final BlockPosition b; - private final boolean c; - private final BlockPosition d; -@@ -86,7 +86,7 @@ public class PistonExtendsChecker { - } else { - int i = 1; - -- if (i + this.f.size() > 12) { -+ if (i + this.f.size() > this.getWorld().purpurConfig.pistonBlockPushLimit) { // Purpur - return false; - } else { - while (a(block)) { -@@ -100,7 +100,7 @@ public class PistonExtendsChecker { - } - - ++i; -- if (i + this.f.size() > 12) { -+ if (i + this.f.size() > this.getWorld().purpurConfig.pistonBlockPushLimit) { // Purpur - return false; - } - } -@@ -148,7 +148,7 @@ public class PistonExtendsChecker { - return true; - } - -- if (this.f.size() >= 12) { -+ if (this.f.size() >= this.getWorld().purpurConfig.pistonBlockPushLimit) { // Purpur - return false; - } - -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e082de2fdbd4803f5c79699b813062291f8e2bb7..07c66f9d41e7a74021dde6702d654710e400e93b 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -2155,4 +2155,9 @@ public class PurpurWorldConfig { - magmaBlockDamageWhenSneaking = getBoolean("blocks.magma-block.damage-when-sneaking", magmaBlockDamageWhenSneaking); - magmaBlockDamageWithFrostWalker = getBoolean("blocks.magma-block.damage-with-frost-walker", magmaBlockDamageWithFrostWalker); - } -+ -+ public int pistonBlockPushLimit = 12; -+ private void pistonSettings() { -+ pistonBlockPushLimit = getInt("blocks.piston.block-push-limit", pistonBlockPushLimit); -+ } - } diff --git a/patches/server-unmapped/0202-Allows-change-broadcast-message-by-player.patch b/patches/server-unmapped/0202-Allows-change-broadcast-message-by-player.patch deleted file mode 100644 index 1495d2de0..000000000 --- a/patches/server-unmapped/0202-Allows-change-broadcast-message-by-player.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctaEnkoda -Date: Mon, 3 May 2021 01:33:14 +0200 -Subject: [PATCH] Allows change broadcast message by player - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index a1ee1066108985a95abddb03ff447b5a14f4f85f..4720644ae82f76f835f14c0b3a00e7b7874fb1e2 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -60,7 +60,7 @@ public class AdvancementDataPlayer { - private static final TypeToken> c = new TypeToken>() { - }; - private final DataFixer d; -- private final PlayerList e; -+ private final PlayerList e; public PlayerList getPlayerList() { return e; } // Purpur - OBFHELPER - private final File f; - public final Map data = Maps.newLinkedHashMap(); - private final Set h = Sets.newLinkedHashSet(); -@@ -325,7 +325,13 @@ public class AdvancementDataPlayer { - advancement.d().a(this.player); - // Paper start - Add Adventure message to PlayerAdvancementDoneEvent - if (message != null && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -- this.e.sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); -+ // Purpur Start - AdvancementMessage By Player -+ if (net.pl3x.purpur.PurpurConfig.advancementOnlyBroadcastToAffectedPlayer) { -+ this.player.sendMessage(PaperAdventure.asVanilla(message), SystemUtils.getNullUUID()); -+ } else { -+ getPlayerList().sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); -+ } -+ // Purpur End - // Paper end - } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 8b957fe6c88ae4eded4a89846cae2df4456c04bf..2b4d106ac59248dc2f7e73b4c549d807ff8ca628 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -859,7 +859,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - }); - ScoreboardTeamBase scoreboardteambase = this.getScoreboardTeam(); -- -+ if (net.pl3x.purpur.PurpurConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendMessage(ichatbasecomponent); else // Purpur - if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) { - if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) { - this.server.getPlayerList().a((EntityHuman) this, ichatbasecomponent); -diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 9f5bcec2c41e24310fe9b34bd51050f62164f1b1..3234089f2b6da7d32e0c5c15f2120557a456efd0 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -289,4 +289,16 @@ public class PurpurConfig { - private static void tpsCatchup() { - tpsCatchup = getBoolean("settings.tps-catchup", tpsCatchup); - } -+ -+ public static boolean advancementOnlyBroadcastToAffectedPlayer = false; -+ public static boolean deathMessageOnlyBroadcastToAffectedPlayer = false; -+ private static void broadcastSettings() { -+ if (version < 13) { -+ boolean oldValue = getBoolean("settings.advancement.only-broadcast-to-affected-player", false); -+ set("settings.broadcasts.advancement.only-broadcast-to-affected-player", oldValue); -+ set("settings.advancement.only-broadcast-to-affected-player", null); -+ } -+ advancementOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.advancement.only-broadcast-to-affected-player", advancementOnlyBroadcastToAffectedPlayer); -+ deathMessageOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.death.only-broadcast-to-affected-player", deathMessageOnlyBroadcastToAffectedPlayer); -+ } - } diff --git a/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch b/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch deleted file mode 100644 index e7632c032..000000000 --- a/patches/server-unmapped/0203-Fix-SPIGOT-6278.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 10 May 2021 02:08:53 -0500 -Subject: [PATCH] Fix SPIGOT-6278 - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -index f34ee0cf7a31cd7a9ee8f7e7ae76e9008f6da35b..77af7152a2e5ff99e98a0063947427c0d18aabcb 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java -@@ -200,7 +200,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow { - - @Override - public boolean isTypeNotPersistent(double d0) { -- return !this.isPersistent(); -+ return true || !this.isPersistent(); // Purpur - fix SPIGOT-6278 - } - - @Override diff --git a/patches/server-unmapped/0204-Implement-Mob-Blindness.patch b/patches/server-unmapped/0204-Implement-Mob-Blindness.patch deleted file mode 100644 index 010e558c2..000000000 --- a/patches/server-unmapped/0204-Implement-Mob-Blindness.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Encode42 -Date: Tue, 11 May 2021 21:00:53 -0400 -Subject: [PATCH] Implement Mob Blindness - -Ported from https://github.com/raltsmc/mobblindness - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 89ae9836b0712ae78a8dfefe688d95d53b1156e2..314516477a07ada0cc44f1d8826c9724be85e1a1 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -922,6 +922,18 @@ public abstract class EntityLiving extends Entity { - if (entitytypes == EntityTypes.SKELETON && item == Items.SKELETON_SKULL || entitytypes == EntityTypes.ZOMBIE && item == Items.ZOMBIE_HEAD || entitytypes == EntityTypes.CREEPER && item == Items.CREEPER_HEAD) { - d0 *= 0.5D; - } -+ -+ // Purpur start -+ if (entity instanceof EntityLiving) { -+ EntityLiving livingEntity = (EntityLiving) entity; -+ if (livingEntity.hasEffect(MobEffects.BLINDNESS)) { -+ int amplifier = livingEntity.getEffect(MobEffects.BLINDNESS).getAmplifier(); -+ for (int i = 0; i < amplifier; i++) { -+ d0 *= world.purpurConfig.mobsBlindnessMultiplier; -+ } -+ } -+ } -+ // Purpur end - } - - return d0; -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 07c66f9d41e7a74021dde6702d654710e400e93b..b8622f687b4fd70aaee5fa44cc50b8ee38582582 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -542,6 +542,11 @@ public class PurpurWorldConfig { - mobsSpawnOnBlueIce = getBoolean("blocks.blue_ice.allow-mob-spawns", mobsSpawnOnBlueIce); - } - -+ public double mobsBlindnessMultiplier = 1; -+ private void blindnessSettings() { -+ mobsBlindnessMultiplier = getDouble("gameplay-mechanics.entity-blindness-multiplier", mobsBlindnessMultiplier); -+ } -+ - public boolean chestOpenWithBlockOnTop = false; - private void chestSettings() { - chestOpenWithBlockOnTop = getBoolean("blocks.chest.open-with-solid-block-on-top", chestOpenWithBlockOnTop); diff --git a/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch b/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch deleted file mode 100644 index 27859bb04..000000000 --- a/patches/server-unmapped/0207-Iron-golem-poppy-calms-anger.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 13 May 2021 21:22:51 -0500 -Subject: [PATCH] Iron golem poppy calms anger - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalReceiveFlower.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalReceiveFlower.java -new file mode 100644 -index 0000000000000000000000000000000000000000..6a288fead988d424aa369b8ef6378ab3c9ec16af ---- /dev/null -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalReceiveFlower.java -@@ -0,0 +1,79 @@ -+package net.minecraft.world.entity.ai.goal.target; -+ -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.animal.EntityIronGolem; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.Blocks; -+ -+import java.util.EnumSet; -+import java.util.UUID; -+ -+public class PathfinderGoalReceiveFlower extends PathfinderGoal { -+ private final EntityIronGolem entity; -+ private EntityPlayer target; -+ private int cooldown; -+ -+ public PathfinderGoalReceiveFlower(EntityIronGolem entity) { -+ this.entity = entity; -+ this.setTypes(EnumSet.of(Type.MOVE, Type.LOOK)); -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ if (this.entity.getHoldingFlowerTick() > 0) { -+ return false; -+ } -+ if (!this.entity.isAngry()) { -+ return false; -+ } -+ UUID uuid = this.entity.getAngerTarget(); -+ if (uuid == null) { -+ return false; -+ } -+ Entity target = ((WorldServer) this.entity.world).getEntity(uuid); -+ if (!(target instanceof EntityPlayer)) { -+ return false; -+ } -+ EntityPlayer player = (EntityPlayer) target; -+ if (!isHoldingFlower(player)) { -+ return false; -+ } -+ this.target = player; -+ return true; -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return this.cooldown > 0; -+ } -+ -+ @Override -+ public void start() { -+ this.cooldown = 100; -+ this.entity.pacify(); -+ this.entity.holdFlower(true); -+ } -+ -+ @Override -+ public void onTaskReset() { -+ this.entity.holdFlower(false); -+ this.target = null; -+ } -+ -+ @Override -+ public void tick() { -+ this.entity.getControllerLook().lookAt(this.target, 30.0F, 30.0F); -+ --this.cooldown; -+ } -+ -+ private boolean isHoldingFlower(EntityPlayer player) { -+ return isPoppy(player.getItemInMainHand()) || isPoppy(player.getItemInOffHand()); -+ } -+ -+ private boolean isPoppy(ItemStack item) { -+ return item.getItem() == Blocks.POPPY.getItem(); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 9ee82c908008190e31034e614c241fc7a66248e1..402a8733905ebbbb9c1d962bafa7fd806a9253cc 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -42,6 +42,7 @@ import net.minecraft.world.entity.ai.goal.PathfinderGoalStrollVillageGolem; - import net.minecraft.world.entity.ai.goal.target.PathfinderGoalDefendVillage; - import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; - import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget; -+import net.minecraft.world.entity.ai.goal.target.PathfinderGoalReceiveFlower; - import net.minecraft.world.entity.ai.goal.target.PathfinderGoalUniversalAngerReset; - import net.minecraft.world.entity.monster.EntityCreeper; - import net.minecraft.world.entity.monster.IMonster; -@@ -60,7 +61,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - - protected static final DataWatcherObject b = DataWatcher.a(EntityIronGolem.class, DataWatcherRegistry.a); - private int c; -- private int d; -+ private int d; public int getHoldingFlowerTick() { return d; } // Purpur - OBFHELPER - private static final IntRange bo = TimeRange.a(20, 39); - private int bp; - private UUID bq; -@@ -91,6 +92,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - protected void initPathfinder() { - if (world.purpurConfig.ironGolemCanSwim) this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur - this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur -+ if (world.purpurConfig.ironGolemPoppyCalm) this.goalSelector.addGoal(0, new PathfinderGoalReceiveFlower(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, true)); - this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F)); - this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false)); -@@ -241,6 +243,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - return EntityIronGolem.CrackLevel.a(this.getHealth() / this.getMaxHealth()); - } - -+ public void holdFlower(boolean flag) { t(flag); } // Purpur - OBFHELPER - public void t(boolean flag) { - if (flag) { - this.d = 400; -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 5659e75177f3c5acb935b0f6dc0b720853602108..ffb8d505a723d61bd6311f4116524d9a99a27f62 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1183,6 +1183,7 @@ public class PurpurWorldConfig { - public boolean ironGolemRidableInWater = false; - public boolean ironGolemCanSwim = false; - public double ironGolemMaxHealth = 100.0D; -+ public boolean ironGolemPoppyCalm = false; - private void ironGolemSettings() { - ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); - ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); -@@ -1193,6 +1194,7 @@ public class PurpurWorldConfig { - set("mobs.iron_golem.attributes.max_health", oldValue); - } - ironGolemMaxHealth = getDouble("mobs.iron_golem.attributes.max_health", ironGolemMaxHealth); -+ ironGolemPoppyCalm = getBoolean("mobs.iron_golem.poppy-calms-anger", ironGolemPoppyCalm); - } - - public boolean llamaRidable = false; diff --git a/patches/server-unmapped/0208-Breedable-parrots.patch b/patches/server-unmapped/0208-Breedable-parrots.patch deleted file mode 100644 index 17c70602a..000000000 --- a/patches/server-unmapped/0208-Breedable-parrots.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 13 May 2021 22:17:50 -0500 -Subject: [PATCH] Breedable parrots - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index 2f51e80a02817f1e36c8fe9542809ab881263a16..abfb08ff562ef4c8971b12f6f64ede08dca15cd0 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -44,6 +44,7 @@ import net.minecraft.world.entity.GroupDataEntity; - import net.minecraft.world.entity.ai.attributes.AttributeProvider; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.ai.control.ControllerMoveFlying; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowEntity; - import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowOwner; -@@ -75,7 +76,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - }; - private static final Item bw = Items.COOKIE; -- private static final Set bx = Sets.newHashSet(new Item[]{Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS}); -+ private static final Set bx = Sets.newHashSet(new Item[]{Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS}); public static Set temptItems() { return bx; } // Purpur - OBFHELPER - private static final Map, SoundEffect> by = (Map) SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // CraftBukkit - decompile error - hashmap.put(EntityTypes.BLAZE, SoundEffects.ENTITY_PARROT_IMITATE_BLAZE); - hashmap.put(EntityTypes.CAVE_SPIDER, SoundEffects.ENTITY_PARROT_IMITATE_SPIDER); -@@ -205,6 +206,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); - this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur - this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); // Purpur -+ if (world.purpurConfig.parrotBreedable) this.goalSelector.addGoal(1, new PathfinderGoalBreed(this, 1.0D)); // Purpur - this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(2, new PathfinderGoalSit(this)); - this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true)); -@@ -309,6 +311,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - } - -+ if (world.purpurConfig.parrotBreedable) return super.b(entityhuman, enumhand); // Purpur - return EnumInteractionResult.a(this.world.isClientSide); - } else if (itemstack.getItem() == EntityParrot.bw) { - if (!entityhuman.abilities.canInstantlyBuild) { -@@ -334,7 +337,7 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - @Override - public boolean k(ItemStack itemstack) { -- return false; -+ return world.purpurConfig.parrotBreedable && temptItems().contains(itemstack.getItem()); // Purpur - } - - public static boolean c(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -@@ -353,13 +356,13 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - - @Override - public boolean mate(EntityAnimal entityanimal) { -- return false; -+ return super.mate(entityanimal); // Purpur - } - - @Nullable - @Override - public EntityAgeable createChild(WorldServer worldserver, EntityAgeable entityageable) { -- return null; -+ return worldserver.purpurConfig.parrotBreedable ? EntityTypes.PARROT.create(worldserver) : null; // Purpur - } - - @Override -diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index ffb8d505a723d61bd6311f4116524d9a99a27f62..db8b31972b38f907a53b4f63465c83d1f47f4dc3 100644 ---- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -1345,6 +1345,7 @@ public class PurpurWorldConfig { - public boolean parrotRidableInWater = false; - public double parrotMaxY = 256D; - public double parrotMaxHealth = 6.0D; -+ public boolean parrotBreedable = false; - private void parrotSettings() { - parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); - parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); -@@ -1355,6 +1356,7 @@ public class PurpurWorldConfig { - set("mobs.parrot.attributes.max_health", oldValue); - } - parrotMaxHealth = getDouble("mobs.parrot.attributes.max_health", parrotMaxHealth); -+ parrotBreedable = getBoolean("mobs.parrot.can-breed", parrotBreedable); - } - - public boolean phantomRidable = false; diff --git a/patches/server/0188-Gamemode-extra-permissions.patch b/patches/server/0188-Gamemode-extra-permissions.patch new file mode 100644 index 000000000..a04f2abc4 --- /dev/null +++ b/patches/server/0188-Gamemode-extra-permissions.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Fri, 30 Apr 2021 13:39:39 -0500 +Subject: [PATCH] Gamemode extra permissions + + +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index f1ebfd810fd06e62d796110345aa36ce4a94e2fd..99f2fd5a91e2812338cc5f2d616015a28f2fbe1a 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -193,6 +193,21 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + } + // CraftBukkit end + ++ // Purpur start ++ public boolean testPermission(int i, String bukkitPermission) { ++ if (hasPermission(i, bukkitPermission)) { ++ return true; ++ } ++ String permissionMessage = getLevel().getServer().server.getPermissionMessage(); ++ if (!permissionMessage.isBlank()) { ++ for (String line : permissionMessage.replace("", bukkitPermission).split("\n")) { ++ sendFailure(new TextComponent(line)); ++ } ++ } ++ return false; ++ } ++ // Purpur end ++ + public Vec3 getPosition() { + return this.worldPosition; + } +diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +index 79f6089b934124c3309c6bee2e48b36b937252e0..dff8ef0a1a2e52792070d93685c290023d31ce95 100644 +--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +@@ -49,6 +49,18 @@ public class GameModeCommand { + } + + private static int setMode(CommandContext context, Collection targets, GameType gameMode) { ++ // Purpur start ++ if (net.pl3x.purpur.PurpurConfig.commandGamemodeRequiresPermission) { ++ String gamemode = gameMode.getName(); ++ CommandSourceStack sender = context.getSource(); ++ if (!sender.testPermission(2, "minecraft.command.gamemode." + gamemode)) { ++ return 0; ++ } ++ if (sender.getEntity() instanceof ServerPlayer player && (targets.size() > 1 || !targets.contains(player)) && !sender.testPermission(2, "minecraft.command.gamemode." + gamemode + ".other")) { ++ return 0; ++ } ++ } ++ // Purpur end + int i = 0; + + for(ServerPlayer serverPlayer : targets) { +diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java +index b402edaa5deaaa6e5fef3036c84060234f0c5d34..29e94a0cfdc749d2785be28b81fd1bad9063b048 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java +@@ -186,6 +186,11 @@ public class PurpurConfig { + disableGiveCommandDrops = getBoolean("settings.disable-give-dropping", disableGiveCommandDrops); + } + ++ public static boolean commandGamemodeRequiresPermission = false; ++ private static void commandSettings() { ++ commandGamemodeRequiresPermission = getBoolean("settings.command.gamemode.requires-specific-permission", commandGamemodeRequiresPermission); ++ } ++ + public static boolean barrelSixRows = false; + public static boolean enderChestSixRows = false; + public static boolean enderChestPermissionRows = false; +diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +index 6cc517b394bafefce50d877761e5b2eee8e14c78..46ca899a7abddea108f6ff1b4ca14ca5cd3112ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +@@ -23,7 +23,15 @@ public final class CommandPermissions { + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "kick", "Allows the user to kick players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stop", "Allows the user to stop the server", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands); +- DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands); ++ // Purpur start ++ Permission gamemodeVanilla = DefaultPermissions.registerPermission(PREFIX + "gamemode", "Allows the user to change the gamemode", PermissionDefault.OP, commands); ++ for (net.minecraft.world.level.GameType gametype : net.minecraft.world.level.GameType.values()) { ++ Permission gamemodeSelf = DefaultPermissions.registerPermission(PREFIX + "gamemode." + gametype.getName(), "Allows the user to set " + gametype.getName() + " gamemode for self", PermissionDefault.OP); ++ Permission gamemodeOther = DefaultPermissions.registerPermission(PREFIX + "gamemode." + gametype.getName() + ".other", "Allows the user to set " + gametype.getName() + " gamemode for other players", PermissionDefault.OP); ++ gamemodeSelf.addParent(gamemodeOther, true); ++ gamemodeVanilla.addParent(gamemodeSelf, true); ++ } ++ // Purpur end + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands); diff --git a/patches/server/0189-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch b/patches/server/0189-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch new file mode 100644 index 000000000..e05695cf6 --- /dev/null +++ b/patches/server/0189-Config-for-changing-the-blocks-that-turn-into-dirt-p.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 12emin34 +Date: Thu, 29 Apr 2021 23:56:02 +0200 +Subject: [PATCH] Config for changing the blocks that turn into dirt paths + + +diff --git a/src/main/java/net/minecraft/world/item/ShovelItem.java b/src/main/java/net/minecraft/world/item/ShovelItem.java +index e5562b407bba35ab93bf8bc3c22ac9d45e8353cb..c688bb73cd062f36524cfc231cb691f29f7998c2 100644 +--- a/src/main/java/net/minecraft/world/item/ShovelItem.java ++++ b/src/main/java/net/minecraft/world/item/ShovelItem.java +@@ -33,7 +33,7 @@ public class ShovelItem extends DiggerItem { + return InteractionResult.PASS; + } else { + Player player = context.getPlayer(); +- BlockState blockState2 = FLATTENABLES.get(blockState.getBlock()); ++ BlockState blockState2 = level.purpurConfig.shovelTurnsBlockToGrassPath.contains(blockState.getBlock()) ? Blocks.DIRT_PATH.defaultBlockState() : null; // Purpur + BlockState blockState3 = null; + if (blockState2 != null && level.getBlockState(blockPos.above()).isAir()) { + level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index 091aa6423d7b35dc4ec813412316f166510be016..d9c3c63c644bd4c73974a4fb5f8bf6e7d7e286eb 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -377,6 +377,21 @@ public class PurpurWorldConfig { + snowballProjectileOffset = getDouble("gameplay-mechanics.projectile-offset.snowball", snowballProjectileOffset); + } + ++ public List shovelTurnsBlockToGrassPath = new ArrayList<>(); ++ private void shovelSettings() { ++ getList("gameplay-mechanics.shovel-turns-block-to-grass-path", new ArrayList(){{ ++ add("minecraft:coarse_dirt"); ++ add("minecraft:dirt"); ++ add("minecraft:grass_block"); ++ add("minecraft:mycelium"); ++ add("minecraft:podzol"); ++ add("minecraft:rooted_dirt"); ++ }}).forEach(key -> { ++ Block block = Registry.BLOCK.get(new ResourceLocation(key.toString())); ++ if (block != Blocks.AIR) shovelTurnsBlockToGrassPath.add(block); ++ }); ++ } ++ + public boolean silkTouchEnabled = false; + public String silkTouchSpawnerName = "Spawner"; + public List silkTouchSpawnerLore = new ArrayList<>(); diff --git a/patches/server/0190-Configurable-piston-push-limit.patch b/patches/server/0190-Configurable-piston-push-limit.patch new file mode 100644 index 000000000..ec75faf74 --- /dev/null +++ b/patches/server/0190-Configurable-piston-push-limit.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoctaEnkoda +Date: Sun, 2 May 2021 23:14:54 +0200 +Subject: [PATCH] Configurable piston push limit + + +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java b/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java +index 744d91546d1a810f60a43c15ed74b4158f341a4a..354538daefa603f6df5a139b6bff87dbb4cef178 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java +@@ -86,7 +86,7 @@ public class PistonStructureResolver { + return true; + } else { + int i = 1; +- if (i + this.toPush.size() > 12) { ++ if (i + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur + return false; + } else { + while(isSticky(blockState)) { +@@ -98,7 +98,7 @@ public class PistonStructureResolver { + } + + ++i; +- if (i + this.toPush.size() > 12) { ++ if (i + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur + return false; + } + } +@@ -142,7 +142,7 @@ public class PistonStructureResolver { + return true; + } + +- if (this.toPush.size() >= 12) { ++ if (this.toPush.size() >= this.level.purpurConfig.pistonBlockPushLimit) { // Purpur + return false; + } + +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index d9c3c63c644bd4c73974a4fb5f8bf6e7d7e286eb..414c5201b37c469ebf69011aa9919d4e7287078a 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -609,6 +609,11 @@ public class PurpurWorldConfig { + magmaBlockDamageWithFrostWalker = getBoolean("blocks.magma-block.damage-with-frost-walker", magmaBlockDamageWithFrostWalker); + } + ++ public int pistonBlockPushLimit = 12; ++ private void pistonSettings() { ++ pistonBlockPushLimit = getInt("blocks.piston.block-push-limit", pistonBlockPushLimit); ++ } ++ + public boolean powderSnowBypassMobGriefing = false; + private void powderSnowSettings() { + powderSnowBypassMobGriefing = getBoolean("blocks.powder_snow.bypass-mob-griefing", powderSnowBypassMobGriefing); diff --git a/patches/server/0191-Configurable-broadcast-settings.patch b/patches/server/0191-Configurable-broadcast-settings.patch new file mode 100644 index 000000000..62402ffa8 --- /dev/null +++ b/patches/server/0191-Configurable-broadcast-settings.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: DoctaEnkoda +Date: Mon, 3 May 2021 01:33:14 +0200 +Subject: [PATCH] Configurable broadcast settings + + +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index c46df052a5a39d92688f51377ee1f7b5b5b36faa..d7d2a975386cecb0d50b4f7ed37de8ad20ca9bad 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -301,6 +301,7 @@ public class PlayerAdvancements { + advancement.getRewards().grant(this.player); + // Paper start - Add Adventure message to PlayerAdvancementDoneEvent + if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ if (net.pl3x.purpur.PurpurConfig.advancementOnlyBroadcastToAffectedPlayer) this.player.sendMessage(message); else // Purpur + this.playerList.broadcastMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.NIL_UUID); + // Paper end + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 177c61a306b9e07eb7aabbac664616cc23bfef5b..4775d9feb52dc899a30d34cdc0ab84149f085d8c 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -874,6 +874,7 @@ public class ServerPlayer extends Player { + }); + Team scoreboardteambase = this.getTeam(); + ++ if (net.pl3x.purpur.PurpurConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendMessage(ichatbasecomponent); else // Purpur + if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { + if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { + this.server.getPlayerList().broadcastToTeam((Player) this, ichatbasecomponent); +diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java +index 29e94a0cfdc749d2785be28b81fd1bad9063b048..ca66d67d0c3314b01f980586d62929ee3beff2b8 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java +@@ -150,6 +150,18 @@ public class PurpurConfig { + pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); + } + ++ public static boolean advancementOnlyBroadcastToAffectedPlayer = false; ++ public static boolean deathMessageOnlyBroadcastToAffectedPlayer = false; ++ private static void broadcastSettings() { ++ if (version < 13) { ++ boolean oldValue = getBoolean("settings.advancement.only-broadcast-to-affected-player", false); ++ set("settings.broadcasts.advancement.only-broadcast-to-affected-player", oldValue); ++ set("settings.advancement.only-broadcast-to-affected-player", null); ++ } ++ advancementOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.advancement.only-broadcast-to-affected-player", advancementOnlyBroadcastToAffectedPlayer); ++ deathMessageOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.death.only-broadcast-to-affected-player", deathMessageOnlyBroadcastToAffectedPlayer); ++ } ++ + public static int dungeonSeed = -1; + public static int endSpikeSeed = -1; + private static void seedSettings() { diff --git a/patches/server/0192-Fix-SPIGOT-6278.patch b/patches/server/0192-Fix-SPIGOT-6278.patch new file mode 100644 index 000000000..8fb1db3e7 --- /dev/null +++ b/patches/server/0192-Fix-SPIGOT-6278.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 10 May 2021 02:08:53 -0500 +Subject: [PATCH] Fix SPIGOT-6278 + + +diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +index 04ffda7f06e48365d091c30a149203f118168a4b..9e42dd636c78fdf7e94521b3f72c52a77563f8c9 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -217,7 +217,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + + @Override + public boolean removeWhenFarAway(double distanceSquared) { +- return !this.isPersistenceRequired(); ++ return true || !this.isPersistenceRequired(); // Purpur - fix SPIGOT-6278 + } + + @Override diff --git a/patches/server/0193-Configurable-mob-blindness.patch b/patches/server/0193-Configurable-mob-blindness.patch new file mode 100644 index 000000000..4fe6e5c40 --- /dev/null +++ b/patches/server/0193-Configurable-mob-blindness.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Encode42 +Date: Tue, 11 May 2021 21:00:53 -0400 +Subject: [PATCH] Configurable mob blindness + +Ported from https://github.com/raltsmc/mobblindness + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 6e22b2ced13625bac9dc631310610bc5ccfc0c4f..c7cbdd7becb53767cbd652719ebe88646df21220 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -992,6 +992,17 @@ public abstract class LivingEntity extends Entity { + if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { + d0 *= 0.5D; + } ++ ++ // Purpur start ++ if (entity instanceof LivingEntity entityliving) { ++ if (entityliving.hasEffect(MobEffects.BLINDNESS)) { ++ int amplifier = entityliving.getEffect(MobEffects.BLINDNESS).getAmplifier(); ++ for (int i = 0; i < amplifier; i++) { ++ d0 *= this.level.purpurConfig.mobsBlindnessMultiplier; ++ } ++ } ++ } ++ // Purpur end + } + + return d0; +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index 414c5201b37c469ebf69011aa9919d4e7287078a..7908252c543c75d0f1e4310806fbb2b78d550c63 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -430,6 +430,7 @@ public class PurpurWorldConfig { + public boolean persistentDroppableEntityDisplayNames = false; + public boolean projectilesBypassMobGriefing = false; + public boolean tickFluids = true; ++ public double mobsBlindnessMultiplier = 1; + public double tridentLoyaltyVoidReturnHeight = 0.0D; + public double voidDamageHeight = -64.0D; + public double voidDamageDealt = 4.0D; +@@ -451,6 +452,7 @@ public class PurpurWorldConfig { + persistentDroppableEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-droppable-entity-display-names", persistentDroppableEntityDisplayNames); + projectilesBypassMobGriefing = getBoolean("gameplay-mechanics.projectiles-bypass-mob-griefing", projectilesBypassMobGriefing); + tickFluids = getBoolean("gameplay-mechanics.tick-fluids", tickFluids); ++ mobsBlindnessMultiplier = getDouble("gameplay-mechanics.entity-blindness-multiplier", mobsBlindnessMultiplier); + tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); + voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight); + voidDamageDealt = getDouble("gameplay-mechanics.void-damage-dealt", voidDamageDealt); diff --git a/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch b/patches/server/0194-Hide-hidden-players-from-entity-selector.patch similarity index 63% rename from patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch rename to patches/server/0194-Hide-hidden-players-from-entity-selector.patch index 2cfdf76da..47c18579a 100644 --- a/patches/server-unmapped/0205-Hide-hidden-players-from-entity-selector.patch +++ b/patches/server/0194-Hide-hidden-players-from-entity-selector.patch @@ -5,65 +5,64 @@ Subject: [PATCH] Hide hidden players from entity selector diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java -index ee3123ac8a568d915ca4e1b42fc1196c269b287e..82125185233bdc59ef93d376e7327180c98c794d 100644 +index 0fb8f32427843f4bfd90ab88ecb3ab3e4a4fda31..f99f1ba7f912a2fd503e12c446b342a8d04356a0 100644 --- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java +++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java -@@ -169,10 +169,10 @@ public class EntitySelector { +@@ -184,10 +184,10 @@ public class EntitySelector { - if (this.j != null) { - entityplayer = commandlistenerwrapper.getServer().getPlayerList().getPlayer(this.j); -- return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new EntityPlayer[]{entityplayer})); + if (this.playerName != null) { + entityplayer = commandlistenerwrapper.getServer().getPlayerList().getPlayerByName(this.playerName); +- return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + return entityplayer == null || !canSee(commandlistenerwrapper, entityplayer) ? Collections.emptyList() : Lists.newArrayList(entityplayer); // Purpur - } else if (this.k != null) { - entityplayer = commandlistenerwrapper.getServer().getPlayerList().getPlayer(this.k); -- return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new EntityPlayer[]{entityplayer})); + } else if (this.entityUUID != null) { + entityplayer = commandlistenerwrapper.getServer().getPlayerList().getPlayer(this.entityUUID); +- return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + return entityplayer == null || !canSee(commandlistenerwrapper, entityplayer) ? Collections.emptyList() : Lists.newArrayList(entityplayer); // Purpur } else { - Vec3D vec3d = (Vec3D) this.f.apply(commandlistenerwrapper.getPosition()); - Predicate predicate = this.a(vec3d); -@@ -182,7 +182,7 @@ public class EntitySelector { - EntityPlayer entityplayer1 = (EntityPlayer) commandlistenerwrapper.getEntity(); + Vec3 vec3d = (Vec3) this.position.apply(commandlistenerwrapper.getPosition()); + Predicate predicate = this.getPredicate(vec3d); +@@ -197,7 +197,7 @@ public class EntitySelector { + ServerPlayer entityplayer1 = (ServerPlayer) commandlistenerwrapper.getEntity(); if (predicate.test(entityplayer1)) { -- return Lists.newArrayList(new EntityPlayer[]{entityplayer1}); +- return Lists.newArrayList(new ServerPlayer[]{entityplayer1}); + return !canSee(commandlistenerwrapper, entityplayer1) ? Collections.emptyList() : Lists.newArrayList(entityplayer1); // Purpur } } -@@ -195,6 +195,7 @@ public class EntitySelector { +@@ -207,6 +207,7 @@ public class EntitySelector { - predicate.getClass(); - object = worldserver.a(predicate::test); -+ ((List) object).removeIf(entityplayer3 -> !canSee(commandlistenerwrapper, (EntityPlayer) entityplayer3)); // Purpur + if (this.isWorldLimited()) { + object = commandlistenerwrapper.getLevel().getPlayers(predicate); ++ ((List) object).removeIf(entityplayer3 -> !canSee(commandlistenerwrapper, (ServerPlayer) entityplayer3)); // Purpur } else { object = Lists.newArrayList(); Iterator iterator = commandlistenerwrapper.getServer().getPlayerList().getPlayers().iterator(); -@@ -202,7 +203,7 @@ public class EntitySelector { +@@ -214,7 +215,7 @@ public class EntitySelector { while (iterator.hasNext()) { - EntityPlayer entityplayer2 = (EntityPlayer) iterator.next(); + ServerPlayer entityplayer2 = (ServerPlayer) iterator.next(); - if (predicate.test(entityplayer2)) { + if (predicate.test(entityplayer2) && canSee(commandlistenerwrapper, entityplayer2)) { // Purpur ((List) object).add(entityplayer2); } } -@@ -244,4 +245,11 @@ public class EntitySelector { - public static IChatMutableComponent a(List list) { - return ChatComponentUtils.b(list, Entity::getScoreboardDisplayName); +@@ -256,4 +257,10 @@ public class EntitySelector { + public static Component joinNames(List list) { + return ComponentUtils.formatList(list, Entity::getDisplayName); } + + // Purpur start -+ private boolean canSee(CommandListenerWrapper commandlistenerwrapper, EntityPlayer target) { -+ Entity entity = commandlistenerwrapper.getEntity(); -+ return !net.pl3x.purpur.PurpurConfig.hideHiddenPlayersFromEntitySelector || !(entity instanceof EntityPlayer) || ((EntityPlayer) entity).getBukkitEntity().canSee(target.getBukkitEntity()); ++ private boolean canSee(CommandSourceStack sender, ServerPlayer target) { ++ return !net.pl3x.purpur.PurpurConfig.hideHiddenPlayersFromEntitySelector || !(sender.getEntity() instanceof ServerPlayer player) || player.getBukkitEntity().canSee(target.getBukkitEntity()); + } + // Purpur end } diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java -index 3234089f2b6da7d32e0c5c15f2120557a456efd0..475e7dcf01d3779664a8e5fc4c1c4c7550c50750 100644 +index ca66d67d0c3314b01f980586d62929ee3beff2b8..377744474ad802e138892511adb56ee02bc4ce48 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java -@@ -212,8 +212,10 @@ public class PurpurConfig { +@@ -199,8 +199,10 @@ public class PurpurConfig { } public static boolean commandGamemodeRequiresPermission = false; diff --git a/patches/server-unmapped/0206-Config-for-health-to-impact-Creeper-explosion-radius.patch b/patches/server/0195-Config-for-health-to-impact-Creeper-explosion-radius.patch similarity index 50% rename from patches/server-unmapped/0206-Config-for-health-to-impact-Creeper-explosion-radius.patch rename to patches/server/0195-Config-for-health-to-impact-Creeper-explosion-radius.patch index 3ef06697b..9f0799b4d 100644 --- a/patches/server-unmapped/0206-Config-for-health-to-impact-Creeper-explosion-radius.patch +++ b/patches/server/0195-Config-for-health-to-impact-Creeper-explosion-radius.patch @@ -4,39 +4,39 @@ Date: Thu, 29 Apr 2021 20:28:18 -0400 Subject: [PATCH] Config for health to impact Creeper explosion radius -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 27d5e9fc5ec1396e95180fc14e8a61b030cfd1e6..d2ae28bb1a2db6dde2aa7c95589656b6eaf3072d 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -341,9 +341,10 @@ public class EntityCreeper extends EntityMonster { - if (!this.world.isClientSide) { - Explosion.Effect explosion_effect = this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) && world.purpurConfig.creeperAllowGriefing ? Explosion.Effect.DESTROY : Explosion.Effect.NONE; // Purpur +diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +index 02494dcc8a342f65b2855612aebeb019095abf65..d66c8866f3c6b1412a6c1876c62e3b29316a0923 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -352,9 +352,10 @@ public class Creeper extends Monster implements PowerableMob { + if (!this.level.isClientSide) { + Explosion.BlockInteraction explosion_effect = (this.level.purpurConfig.creeperBypassMobGriefing || this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && level.purpurConfig.creeperAllowGriefing ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.NONE; // Purpur float f = this.isPowered() ? 2.0F : 1.0F; -+ float multiplier = this.world.purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur ++ float multiplier = this.level.purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur // CraftBukkit start - ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), this.explosionRadius * f, false); -+ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), multiplier * (this.explosionRadius * f), false); // Purpur - this.world.getServer().getPluginManager().callEvent(event); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (this.explosionRadius * f) * multiplier, false); // Purpur + this.level.getCraftServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { - this.killed = true; + this.dead = true; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index b8622f687b4fd70aaee5fa44cc50b8ee38582582..5659e75177f3c5acb935b0f6dc0b720853602108 100644 +index 7908252c543c75d0f1e4310806fbb2b78d550c63..c3e07c7b7a81f74c3c2d8035ba516b30b55591da 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -@@ -830,6 +830,7 @@ public class PurpurWorldConfig { - public boolean creeperRidable = false; - public boolean creeperRidableInWater = false; +@@ -858,6 +858,7 @@ public class PurpurWorldConfig { + public boolean creeperAllowGriefing = true; + public boolean creeperBypassMobGriefing = false; public boolean creeperExplodeWhenKilled = false; + public boolean creeperHealthRadius = false; - public boolean creeperAllowGriefing = true; - public double creeperChargedChance = 0.0D; - public double creeperMaxHealth = 20.0D; -@@ -837,6 +838,7 @@ public class PurpurWorldConfig { + private void creeperSettings() { creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable); creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater); +@@ -871,6 +872,7 @@ public class PurpurWorldConfig { + creeperAllowGriefing = getBoolean("mobs.creeper.allow-griefing", creeperAllowGriefing); + creeperBypassMobGriefing = getBoolean("mobs.creeper.bypass-mob-griefing", creeperBypassMobGriefing); creeperExplodeWhenKilled = getBoolean("mobs.creeper.explode-when-killed", creeperExplodeWhenKilled); + creeperHealthRadius = getBoolean("mobs.creeper.health-impacts-explosion", creeperHealthRadius); - creeperAllowGriefing = getBoolean("mobs.creeper.allow-griefing", creeperAllowGriefing); - creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); - if (PurpurConfig.version < 10) { + } + + public boolean dolphinRidable = false; diff --git a/patches/server/0196-Iron-golem-poppy-calms-anger.patch b/patches/server/0196-Iron-golem-poppy-calms-anger.patch new file mode 100644 index 000000000..f02455b32 --- /dev/null +++ b/patches/server/0196-Iron-golem-poppy-calms-anger.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 13 May 2021 21:22:51 -0500 +Subject: [PATCH] Iron golem poppy calms anger + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +index f4e983da7206923ee0b0f984e65a6c2b3a6a8aeb..cea3725009af1bc746a593c4db63ed630889cd21 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +@@ -91,6 +91,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + protected void registerGoals() { + if (level.purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur + this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur ++ if (this.level.purpurConfig.ironGolemPoppyCalm) this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.ReceiveFlower(this)); // Purpur + this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true)); + this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F)); + this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6D, false)); +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index c3e07c7b7a81f74c3c2d8035ba516b30b55591da..fd47ff6042f9943de2ba54a1c283fe84978a2f4d 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -1225,6 +1225,7 @@ public class PurpurWorldConfig { + public boolean ironGolemRidableInWater = false; + public boolean ironGolemCanSwim = false; + public double ironGolemMaxHealth = 100.0D; ++ public boolean ironGolemPoppyCalm = false; + private void ironGolemSettings() { + ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable); + ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater); +@@ -1235,6 +1236,7 @@ public class PurpurWorldConfig { + set("mobs.iron_golem.attributes.max_health", oldValue); + } + ironGolemMaxHealth = getDouble("mobs.iron_golem.attributes.max_health", ironGolemMaxHealth); ++ ironGolemPoppyCalm = getBoolean("mobs.iron_golem.poppy-calms-anger", ironGolemPoppyCalm); + } + + public boolean llamaRidable = false; +diff --git a/src/main/java/net/pl3x/purpur/entity/ai/ReceiveFlower.java b/src/main/java/net/pl3x/purpur/entity/ai/ReceiveFlower.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f2f04547509b48c4c13b21e35d77c0ed36086f6b +--- /dev/null ++++ b/src/main/java/net/pl3x/purpur/entity/ai/ReceiveFlower.java +@@ -0,0 +1,78 @@ ++package net.pl3x.purpur.entity.ai; ++ ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.animal.IronGolem; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.Blocks; ++ ++import java.util.EnumSet; ++import java.util.UUID; ++ ++public class ReceiveFlower extends Goal { ++ private final IronGolem irongolem; ++ private ServerPlayer target; ++ private int cooldown; ++ ++ public ReceiveFlower(IronGolem entity) { ++ this.irongolem = entity; ++ setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ if (this.irongolem.getOfferFlowerTick() > 0) { ++ return false; ++ } ++ if (!this.irongolem.isAngry()) { ++ return false; ++ } ++ UUID uuid = this.irongolem.getPersistentAngerTarget(); ++ if (uuid == null) { ++ return false; ++ } ++ Entity target = ((ServerLevel) this.irongolem.level).getEntity(uuid); ++ if (!(target instanceof ServerPlayer player)) { ++ return false; ++ } ++ if (!isOfferingFlower(player)) { ++ return false; ++ } ++ this.target = player; ++ return true; ++ } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return this.cooldown > 0; ++ } ++ ++ @Override ++ public void start() { ++ this.cooldown = 100; ++ this.irongolem.stopBeingAngry(); ++ this.irongolem.offerFlower(true); ++ } ++ ++ @Override ++ public void stop() { ++ this.irongolem.offerFlower(false); ++ this.target = null; ++ } ++ ++ @Override ++ public void tick() { ++ this.irongolem.getLookControl().setLookAt(this.target, 30.0F, 30.0F); ++ --this.cooldown; ++ } ++ ++ private boolean isOfferingFlower(ServerPlayer player) { ++ return isPoppy(player.getMainHandItem()) || isPoppy(player.getOffhandItem()); ++ } ++ ++ private boolean isPoppy(ItemStack item) { ++ return item.getItem() == Blocks.POPPY.asItem(); ++ } ++} diff --git a/patches/server/0197-Breedable-parrots.patch b/patches/server/0197-Breedable-parrots.patch new file mode 100644 index 000000000..cfa4c67d9 --- /dev/null +++ b/patches/server/0197-Breedable-parrots.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 13 May 2021 22:17:50 -0500 +Subject: [PATCH] Breedable parrots + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +index 553b0aff0ccc5baf41d5faae1a2fd88249dd5a74..73a58ee1e11396a77d2ff44c5eb1f87225402380 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +@@ -210,6 +210,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); // Purpur ++ if (this.level.purpurConfig.parrotBreedable) this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D)); // Purpur + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); +@@ -324,6 +325,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + } + } + ++ if (this.level.purpurConfig.parrotBreedable) return super.mobInteract(player, hand); // Purpur + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else if (itemstack.is(Parrot.POISONOUS_FOOD)) { + if (!player.getAbilities().instabuild) { +@@ -350,6 +352,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + @Override + public boolean isFood(ItemStack stack) { + return false; ++ return this.level.purpurConfig.parrotBreedable && Parrot.TAME_FOOD.contains(stack.getItem()); // Purpur + } + + public static boolean checkParrotSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { +@@ -368,13 +371,13 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + + @Override + public boolean canMate(Animal other) { +- return false; ++ return super.canMate(other); // Purpur + } + + @Nullable + @Override + public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) { +- return null; ++ return world.purpurConfig.parrotBreedable ? EntityType.PARROT.create(world) : null; // Purpur + } + + @Override +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +index fd47ff6042f9943de2ba54a1c283fe84978a2f4d..4da142bbe5197c1c5e5d7cc8c6282a544368df1a 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -1361,6 +1361,7 @@ public class PurpurWorldConfig { + public boolean parrotRidableInWater = false; + public double parrotMaxY = 256D; + public double parrotMaxHealth = 6.0D; ++ public boolean parrotBreedable = false; + private void parrotSettings() { + parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable); + parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater); +@@ -1371,6 +1372,7 @@ public class PurpurWorldConfig { + set("mobs.parrot.attributes.max_health", oldValue); + } + parrotMaxHealth = getDouble("mobs.parrot.attributes.max_health", parrotMaxHealth); ++ parrotBreedable = getBoolean("mobs.parrot.can-breed", parrotBreedable); + } + + public boolean phantomRidable = false;