mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Merge branch 'ver/1.21.4' into feat/quiver-bundle
This commit is contained in:
5108
purpur-server/minecraft-patches/features/0001-Ridables.patch
Normal file
5108
purpur-server/minecraft-patches/features/0001-Ridables.patch
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 23 May 2019 21:50:37 -0500
|
||||
Subject: [PATCH] Barrels and enderchests 6 rows
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 2d09f2a2c97f29ac0d941b7a3fb941102a5d545e..94abb9d8f6381aee000dbd0720477db8b7ca279c 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1027,6 +1027,27 @@ public abstract class PlayerList {
|
||||
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
|
||||
this.server.getCommands().sendCommands(player);
|
||||
} // Paper - Add sendOpLevel API
|
||||
+
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.enderChestSixRows && org.purpurmc.purpur.PurpurConfig.enderChestPermissionRows) {
|
||||
+ org.bukkit.craftbukkit.entity.CraftHumanEntity bukkit = player.getBukkitEntity();
|
||||
+ if (bukkit.hasPermission("purpur.enderchest.rows.six")) {
|
||||
+ player.sixRowEnderchestSlotCount = 54;
|
||||
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.five")) {
|
||||
+ player.sixRowEnderchestSlotCount = 45;
|
||||
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.four")) {
|
||||
+ player.sixRowEnderchestSlotCount = 36;
|
||||
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.three")) {
|
||||
+ player.sixRowEnderchestSlotCount = 27;
|
||||
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.two")) {
|
||||
+ player.sixRowEnderchestSlotCount = 18;
|
||||
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.one")) {
|
||||
+ player.sixRowEnderchestSlotCount = 9;
|
||||
+ }
|
||||
+ } else {
|
||||
+ player.sixRowEnderchestSlotCount = -1;
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
public boolean isWhiteListed(GameProfile profile) {
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index ca998a8a480af63d4a5f58a1f4490528a7b33c69..43657822f0660613078e9afa512000b5255a1537 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -202,6 +202,7 @@ public abstract class Player extends LivingEntity {
|
||||
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
|
||||
public int burpDelay = 0; // Purpur - Burp delay
|
||||
public boolean canPortalInstant = false; // Purpur - Add portal permission bypass
|
||||
+ public int sixRowEnderchestSlotCount = -1; // Purpur - Barrels and enderchests 6 rows
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
|
||||
index 280169afbd637eeb67ddf7eaeb4eecd464a128d5..ba7730a24831efa33de4c5ffce57bfa7177f89d6 100644
|
||||
--- a/net/minecraft/world/inventory/ChestMenu.java
|
||||
+++ b/net/minecraft/world/inventory/ChestMenu.java
|
||||
@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, 6);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu oneRow(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x1, syncId, playerInventory, inventory, 1);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu twoRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x2, syncId, playerInventory, inventory, 2);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu threeRows(int containerId, Inventory playerInventory, Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x3, containerId, playerInventory, container, 3);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu fourRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x4, syncId, playerInventory, inventory, 4);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu fiveRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x5, syncId, playerInventory, inventory, 5);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu sixRows(int containerId, Inventory playerInventory, Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6);
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
index a6a359bab2a727f4631b633a8bb370dd40decc75..d2d75e5c34c97300ce5da8c7ea70958aba31fa4a 100644
|
||||
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
@@ -25,11 +25,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
|
||||
}
|
||||
|
||||
public PlayerEnderChestContainer(Player owner) {
|
||||
- super(27);
|
||||
+ super(org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? 54 : 27); // Purpur - Barrels and enderchests 6 rows
|
||||
this.owner = owner;
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ @Override
|
||||
+ public int getContainerSize() {
|
||||
+ return owner.sixRowEnderchestSlotCount < 0 ? super.getContainerSize() : owner.sixRowEnderchestSlotCount;
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) {
|
||||
this.activeChest = enderChestBlockEntity;
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
index f5533960708bdbaf2eacefbc7c7c3123b7d26502..17aa27885b4431bf7b98799e02d080b5a0ecbbf1 100644
|
||||
--- a/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
@@ -85,8 +85,8 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
enderChestInventory.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
|
||||
if (level instanceof ServerLevel serverLevel && player.openMenu(
|
||||
new SimpleMenuProvider(
|
||||
- (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
|
||||
- )
|
||||
+ (containerId, playerInventory, player1) -> org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? getEnderChestSixRows(containerId, playerInventory, player, enderChestInventory) : ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
|
||||
+ ) // Purpur - Barrels and enderchests 6 rows
|
||||
).isPresent()) {
|
||||
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
|
||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||
@@ -100,6 +100,35 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ private ChestMenu getEnderChestSixRows(int syncId, net.minecraft.world.entity.player.Inventory inventory, Player player, PlayerEnderChestContainer playerEnderChestContainer) {
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.enderChestPermissionRows) {
|
||||
+ org.bukkit.craftbukkit.entity.CraftHumanEntity bukkitPlayer = player.getBukkitEntity();
|
||||
+ if (bukkitPlayer.hasPermission("purpur.enderchest.rows.six")) {
|
||||
+ player.sixRowEnderchestSlotCount = 54;
|
||||
+ return ChestMenu.sixRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.five")) {
|
||||
+ player.sixRowEnderchestSlotCount = 45;
|
||||
+ return ChestMenu.fiveRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.four")) {
|
||||
+ player.sixRowEnderchestSlotCount = 36;
|
||||
+ return ChestMenu.fourRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.three")) {
|
||||
+ player.sixRowEnderchestSlotCount = 27;
|
||||
+ return ChestMenu.threeRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.two")) {
|
||||
+ player.sixRowEnderchestSlotCount = 18;
|
||||
+ return ChestMenu.twoRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.one")) {
|
||||
+ player.sixRowEnderchestSlotCount = 9;
|
||||
+ return ChestMenu.oneRow(syncId, inventory, playerEnderChestContainer);
|
||||
+ }
|
||||
+ }
|
||||
+ player.sixRowEnderchestSlotCount = -1;
|
||||
+ return ChestMenu.sixRows(syncId, inventory, playerEnderChestContainer);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new EnderChestBlockEntity(pos, state);
|
||||
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index 0f808855f58281578c2758513787f0f7330c9291..9f6063089f0aa3a68d26ae7cfe39379123ab2f47 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -55,7 +55,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
this.maxStack = i;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
|
||||
+ case 6 -> 54;
|
||||
+ case 5 -> 45;
|
||||
+ case 4 -> 36;
|
||||
+ case 2 -> 18;
|
||||
+ case 1 -> 9;
|
||||
+ default -> 27;
|
||||
+ }, ItemStack.EMPTY);
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
@Override
|
||||
protected void onOpen(Level level, BlockPos pos, BlockState state) {
|
||||
@@ -107,7 +117,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
- return 27;
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ return switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
|
||||
+ case 6 -> 54;
|
||||
+ case 5 -> 45;
|
||||
+ case 4 -> 36;
|
||||
+ case 2 -> 18;
|
||||
+ case 1 -> 9;
|
||||
+ default -> 27;
|
||||
+ };
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,7 +146,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
|
||||
@Override
|
||||
protected AbstractContainerMenu createMenu(int id, Inventory player) {
|
||||
- return ChestMenu.threeRows(id, player, this);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ return switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(id, player, this);
|
||||
+ case 5 -> ChestMenu.fiveRows(id, player, this);
|
||||
+ case 4 -> ChestMenu.fourRows(id, player, this);
|
||||
+ case 2 -> ChestMenu.twoRows(id, player, this);
|
||||
+ case 1 -> ChestMenu.oneRow(id, player, this);
|
||||
+ default -> ChestMenu.threeRows(id, player, this);
|
||||
+ };
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,76 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sun, 12 May 2019 00:43:12 -0500
|
||||
Subject: [PATCH] Giants AI settings
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Giant.java b/net/minecraft/world/entity/monster/Giant.java
|
||||
index 13021800af7cc9263ef4f393f9cfbda5061a32ae..73da18c4b54e250c434fd75971ef0a8f7c8cf6a3 100644
|
||||
--- a/net/minecraft/world/entity/monster/Giant.java
|
||||
+++ b/net/minecraft/world/entity/monster/Giant.java
|
||||
@@ -30,8 +30,25 @@ public class Giant extends Monster {
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
- this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
||||
- this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
||||
+ // Purpur start - Giants AI settings
|
||||
+ if (level().purpurConfig.giantHaveAI) {
|
||||
+ this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this));
|
||||
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
||||
+ this.goalSelector.addGoal(7, new net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal(this, 1.0D));
|
||||
+ this.goalSelector.addGoal(8, new net.minecraft.world.entity.ai.goal.LookAtPlayerGoal(this, net.minecraft.world.entity.player.Player.class, 16.0F));
|
||||
+ this.goalSelector.addGoal(8, new net.minecraft.world.entity.ai.goal.RandomLookAroundGoal(this));
|
||||
+ this.goalSelector.addGoal(5, new net.minecraft.world.entity.ai.goal.MoveTowardsRestrictionGoal(this, 1.0D));
|
||||
+ if (level().purpurConfig.giantHaveHostileAI) {
|
||||
+ this.goalSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.0D, false));
|
||||
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
||||
+ this.targetSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class));
|
||||
+ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, net.minecraft.world.entity.player.Player.class, true));
|
||||
+ this.targetSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, net.minecraft.world.entity.npc.Villager.class, false));
|
||||
+ this.targetSelector.addGoal(4, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, net.minecraft.world.entity.animal.IronGolem.class, true));
|
||||
+ this.targetSelector.addGoal(5, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, net.minecraft.world.entity.animal.Turtle.class, true));
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Giants AI settings
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
@@ -49,8 +66,36 @@ public class Giant extends Monster {
|
||||
return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 100.0).add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.ATTACK_DAMAGE, 50.0);
|
||||
}
|
||||
|
||||
+ // Purpur - Giants AI settings
|
||||
+ @Override
|
||||
+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.SpawnGroupData entityData) {
|
||||
+ net.minecraft.world.entity.SpawnGroupData groupData = super.finalizeSpawn(world, difficulty, spawnReason, entityData);
|
||||
+ if (groupData == null) {
|
||||
+ populateDefaultEquipmentSlots(this.random, difficulty);
|
||||
+ populateDefaultEquipmentEnchantments(world, this.random, difficulty);
|
||||
+ }
|
||||
+ return groupData;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void populateDefaultEquipmentSlots(net.minecraft.util.RandomSource random, net.minecraft.world.DifficultyInstance difficulty) {
|
||||
+ super.populateDefaultEquipmentSlots(this.random, difficulty);
|
||||
+ // TODO make configurable
|
||||
+ if (random.nextFloat() < (level().getDifficulty() == net.minecraft.world.Difficulty.HARD ? 0.1F : 0.05F)) {
|
||||
+ this.setItemSlot(net.minecraft.world.entity.EquipmentSlot.MAINHAND, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.IRON_SWORD));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float getJumpPower() {
|
||||
+ // make giants jump as high as everything else relative to their size
|
||||
+ // 1.0 makes bottom of feet about as high as their waist when they jump
|
||||
+ return level().purpurConfig.giantJumpHeight;
|
||||
+ }
|
||||
+ // Purpur end - Giants AI settings
|
||||
+
|
||||
@Override
|
||||
public float getWalkTargetValue(BlockPos pos, LevelReader level) {
|
||||
- return level.getPathfindingCostFromLightLevels(pos);
|
||||
+ return super.getWalkTargetValue(pos, level); // Purpur - Giants AI settings - fix light requirements for natural spawns
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sun, 12 Apr 2020 13:19:34 -0500
|
||||
Subject: [PATCH] Chickens can retaliate
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/animal/Chicken.java b/net/minecraft/world/entity/animal/Chicken.java
|
||||
index 509163f409a5b8988a484aedb2f3ddf042d5eb13..d718f0ed362c49803260dceed64bd93e2b6744fc 100644
|
||||
--- a/net/minecraft/world/entity/animal/Chicken.java
|
||||
+++ b/net/minecraft/world/entity/animal/Chicken.java
|
||||
@@ -73,6 +73,11 @@ public class Chicken extends Animal {
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.chickenMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.chickenScale);
|
||||
+ // Purpur start - Chickens can retaliate
|
||||
+ if (level().purpurConfig.chickenRetaliate) {
|
||||
+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D);
|
||||
+ }
|
||||
+ // Purpur end - Chickens can retaliate
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
@@ -80,13 +85,21 @@ public class Chicken extends Animal {
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
- this.goalSelector.addGoal(1, new PanicGoal(this, 1.4));
|
||||
+ //this.goalSelector.addGoal(1, new PanicGoal(this, 1.4)); // Purpur - Chickens can retaliate - moved down
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, itemStack -> itemStack.is(ItemTags.CHICKEN_FOOD), false));
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
||||
+ // Purpur start - Chickens can retaliate
|
||||
+ if (level().purpurConfig.chickenRetaliate) {
|
||||
+ this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.0D, false));
|
||||
+ this.targetSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal(this));
|
||||
+ } else {
|
||||
+ this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D));
|
||||
+ }
|
||||
+ // Purpur end - Chickens can retaliate
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,7 +108,7 @@ public class Chicken extends Animal {
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
- return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 4.0).add(Attributes.MOVEMENT_SPEED, 0.25);
|
||||
+ return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 4.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur - Chickens can retaliate
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,152 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 29 Jun 2019 02:32:40 -0500
|
||||
Subject: [PATCH] Minecart settings and WASD controls
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index d77381237f8a7d1b2f280a5032f5e1c8f0ab8f94..9a88ca440fad04b5941cda125c6a39d24adf6d37 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1240,6 +1240,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
} else {
|
||||
// Purpur start - Add boat fall damage config
|
||||
if (damageSource.is(net.minecraft.tags.DamageTypeTags.IS_FALL)) {
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.AbstractMinecart && level().purpurConfig.minecartControllable && !level().purpurConfig.minecartControllableFallDamage) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.Boat && !level().purpurConfig.boatsDoFallDamage) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
index 9e15e7159cf98b3928110df9eae6de93793bf44e..6df4d736d94b9e49a3eb3d59a329e37127aa64cd 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
@@ -83,6 +83,10 @@ public abstract class AbstractMinecart extends VehicleEntity {
|
||||
private double flyingY = 0.95;
|
||||
private double flyingZ = 0.95;
|
||||
public Double maxSpeed;
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ public double storedMaxSpeed;
|
||||
+ public boolean isNewBehavior;
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -91,8 +95,13 @@ public abstract class AbstractMinecart extends VehicleEntity {
|
||||
this.blocksBuilding = true;
|
||||
if (useExperimentalMovement(level)) {
|
||||
this.behavior = new NewMinecartBehavior(this);
|
||||
+ this.isNewBehavior = true; // Purpur - Minecart settings and WASD controls
|
||||
} else {
|
||||
this.behavior = new OldMinecartBehavior(this);
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ this.isNewBehavior = false;
|
||||
+ maxSpeed = storedMaxSpeed = level.purpurConfig.minecartMaxSpeed;
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +267,14 @@ public abstract class AbstractMinecart extends VehicleEntity {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ if (!this.isNewBehavior) {
|
||||
+ if (storedMaxSpeed != level().purpurConfig.minecartMaxSpeed) {
|
||||
+ maxSpeed = storedMaxSpeed = level().purpurConfig.minecartMaxSpeed;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
+
|
||||
// CraftBukkit start
|
||||
double prevX = this.getX();
|
||||
double prevY = this.getY();
|
||||
@@ -394,15 +411,61 @@ public abstract class AbstractMinecart extends VehicleEntity {
|
||||
this.behavior.moveAlongTrack(level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ private Double lastSpeed;
|
||||
+
|
||||
+ public double getControllableSpeed() {
|
||||
+ BlockState blockState = level().getBlockState(this.blockPosition());
|
||||
+ if (!blockState.isSolid()) {
|
||||
+ blockState = level().getBlockState(this.blockPosition().relative(Direction.DOWN));
|
||||
+ }
|
||||
+ Double speed = level().purpurConfig.minecartControllableBlockSpeeds.get(blockState.getBlock());
|
||||
+ if (!blockState.isSolid()) {
|
||||
+ speed = lastSpeed;
|
||||
+ }
|
||||
+ if (speed == null) {
|
||||
+ speed = level().purpurConfig.minecartControllableBaseSpeed;
|
||||
+ }
|
||||
+ return lastSpeed = speed;
|
||||
+ }
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
+
|
||||
protected void comeOffTrack(ServerLevel level) {
|
||||
double maxSpeed = this.getMaxSpeed(level);
|
||||
Vec3 deltaMovement = this.getDeltaMovement();
|
||||
this.setDeltaMovement(Mth.clamp(deltaMovement.x, -maxSpeed, maxSpeed), deltaMovement.y, Mth.clamp(deltaMovement.z, -maxSpeed, maxSpeed));
|
||||
+
|
||||
+ // Purpur start - Minecart settings and WASD controls
|
||||
+ if (level().purpurConfig.minecartControllable && !isInWater() && !isInLava() && !passengers.isEmpty()) {
|
||||
+ Entity passenger = passengers.get(0);
|
||||
+ if (passenger instanceof net.minecraft.server.level.ServerPlayer player) {
|
||||
+ net.minecraft.world.entity.player.Input lastClientInput = player.getLastClientInput();
|
||||
+ float forward = (lastClientInput.forward() == lastClientInput.backward() ? 0.0F : lastClientInput.forward() ? 1.0F : -1.0F);
|
||||
+ if (lastClientInput.jump() && this.onGround) {
|
||||
+ setDeltaMovement(new Vec3(getDeltaMovement().x, level().purpurConfig.minecartControllableHopBoost, getDeltaMovement().z));
|
||||
+ }
|
||||
+ if (forward != 0.0F) {
|
||||
+ org.bukkit.util.Vector velocity = player.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(getControllableSpeed());
|
||||
+ if (forward < 0.0) {
|
||||
+ velocity.multiply(-0.5);
|
||||
+ }
|
||||
+ setDeltaMovement(new Vec3(velocity.getX(), getDeltaMovement().y, velocity.getZ()));
|
||||
+ }
|
||||
+ this.setYRot(passenger.getYRot() - 90);
|
||||
+ maxUpStep = level().purpurConfig.minecartControllableStepHeight;
|
||||
+ } else {
|
||||
+ maxUpStep = 0.0F;
|
||||
+ }
|
||||
+ } else {
|
||||
+ maxUpStep = 0.0F;
|
||||
+ }
|
||||
+ // Purpur end - Minecart settings and WASD controls
|
||||
if (this.onGround()) {
|
||||
// CraftBukkit start - replace magic numbers with our variables
|
||||
this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ));
|
||||
// CraftBukkit end
|
||||
}
|
||||
+ else if (level().purpurConfig.minecartControllable) setDeltaMovement(new Vec3(getDeltaMovement().x * derailedX, getDeltaMovement().y, getDeltaMovement().z * derailedZ)); // Purpur - Minecart settings and WASD controls
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
if (!this.onGround()) {
|
||||
diff --git a/net/minecraft/world/item/MinecartItem.java b/net/minecraft/world/item/MinecartItem.java
|
||||
index 620069daba04d48b57fc933328eda77f6ca9333e..0403b9b01994269d394820e8c8710ba1b9808bf0 100644
|
||||
--- a/net/minecraft/world/item/MinecartItem.java
|
||||
+++ b/net/minecraft/world/item/MinecartItem.java
|
||||
@@ -30,8 +30,9 @@ public class MinecartItem extends Item {
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
BlockState blockState = level.getBlockState(clickedPos);
|
||||
if (!blockState.is(BlockTags.RAILS)) {
|
||||
- return InteractionResult.FAIL;
|
||||
- } else {
|
||||
+ if (!level.purpurConfig.minecartPlaceAnywhere) return InteractionResult.FAIL; // Purpur - Minecart settings and WASD controls
|
||||
+ if (blockState.isSolid()) clickedPos = clickedPos.relative(context.getClickedFace());
|
||||
+ } // else { // Purpur - Minecart settings and WASD controls
|
||||
ItemStack itemInHand = context.getItemInHand();
|
||||
RailShape railShape = blockState.getBlock() instanceof BaseRailBlock
|
||||
? blockState.getValue(((BaseRailBlock)blockState.getBlock()).getShapeProperty())
|
||||
@@ -72,6 +73,6 @@ public class MinecartItem extends Item {
|
||||
itemInHand.shrink(1);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
- }
|
||||
+ // } // Purpur - Minecart settings and WASD controls
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Fri, 29 Nov 2019 22:10:12 -0600
|
||||
Subject: [PATCH] Villagers follow emerald blocks
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
||||
index 61ed4d687120fcbb7b91863e400f3657ebcde687..e773c426567964fc8269237d71c3434a5473985c 100644
|
||||
--- a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
||||
@@ -162,7 +162,7 @@ public class DefaultAttributes {
|
||||
.put(EntityType.VILLAGER, Villager.createAttributes().build())
|
||||
.put(EntityType.VINDICATOR, Vindicator.createAttributes().build())
|
||||
.put(EntityType.WARDEN, Warden.createAttributes().build())
|
||||
- .put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build())
|
||||
+ .put(EntityType.WANDERING_TRADER, net.minecraft.world.entity.npc.WanderingTrader.createAttributes().build()) // Purpur - Villagers follow emerald blocks
|
||||
.put(EntityType.WITCH, Witch.createAttributes().build())
|
||||
.put(EntityType.WITHER, WitherBoss.createAttributes().build())
|
||||
.put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build())
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/TemptGoal.java b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
index 438d6347778a94b4fe430320b268a2d67afa209a..f88f618d34fb343b31de3af1a875d6633703df71 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
@@ -58,7 +58,7 @@ public class TemptGoal extends Goal {
|
||||
}
|
||||
|
||||
private boolean shouldFollow(LivingEntity entity) {
|
||||
- return this.items.test(entity.getMainHandItem()) || this.items.test(entity.getOffhandItem());
|
||||
+ return (this.items.test(entity.getMainHandItem()) || this.items.test(entity.getOffhandItem())) && (!(this.mob instanceof net.minecraft.world.entity.npc.Villager villager) || !villager.isSleeping()); // Purpur - Villagers follow emerald blocks
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
index a71d16d968bb90fd7aca6f01a3dd56df4f9a7ce6..b4e79cac5611942240ce85120f7bbee329ae2fb8 100644
|
||||
--- a/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
+++ b/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
@@ -45,6 +45,8 @@ import org.bukkit.event.entity.VillagerAcquireTradeEvent;
|
||||
// CraftBukkit end
|
||||
|
||||
public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant {
|
||||
+ static final net.minecraft.world.item.crafting.Ingredient TEMPT_ITEMS = net.minecraft.world.item.crafting.Ingredient.of(net.minecraft.world.level.block.Blocks.EMERALD_BLOCK.asItem()); // Purpur - Villagers follow emerald blocks
|
||||
+
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public CraftMerchant getCraftMerchant() {
|
||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
||||
index c4ce3a2f03bb7665beb131892288d8e4f722a4b5..ff07cfe07200be23f17310522d737fca3251a580 100644
|
||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -265,6 +265,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
||||
+ if (level().purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, TEMPT_ITEMS, false)); // Purpur - Villagers follow emerald blocks
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
@@ -273,6 +274,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.villagerMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.villagerScale);
|
||||
+ this.getAttribute(Attributes.TEMPT_RANGE).setBaseValue(this.level().purpurConfig.villagerTemptRange); // Purpur - Villagers follow emerald blocks
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
@@ -341,7 +343,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5);
|
||||
+ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.TEMPT_RANGE, 10.0D); // Purpur - Villagers follow emerald blocks
|
||||
}
|
||||
|
||||
public boolean assignProfessionWhenSpawned() {
|
||||
diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
index 5d5fa6b4ad18b4213f5098e4d708f3301a6f59c6..4ba2921dd99f674344fe3371332c9b23365d3aa2 100644
|
||||
--- a/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
+++ b/net/minecraft/world/entity/npc/WanderingTrader.java
|
||||
@@ -97,9 +97,16 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
|
||||
@Override
|
||||
public void initAttributes() {
|
||||
this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.wanderingTraderMaxHealth);
|
||||
+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.TEMPT_RANGE).setBaseValue(this.level().purpurConfig.wanderingTraderTemptRange); // Purpur - Villagers follow emerald blocks
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Villagers follow emerald blocks
|
||||
+ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() {
|
||||
+ return Mob.createMobAttributes().add(net.minecraft.world.entity.ai.attributes.Attributes.TEMPT_RANGE, 10.0D);
|
||||
+ }
|
||||
+ // Purpur end - Villagers follow emerald blocks
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
@@ -134,6 +141,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 0.5));
|
||||
this.goalSelector.addGoal(1, new LookAtTradingPlayerGoal(this));
|
||||
this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0, 0.35));
|
||||
+ if (level().purpurConfig.wanderingTraderFollowEmeraldBlock) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, TEMPT_ITEMS, false)); // Purpur - Villagers follow emerald blocks
|
||||
this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35));
|
||||
this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35));
|
||||
this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F));
|
||||
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 27 Feb 2020 21:42:19 -0600
|
||||
Subject: [PATCH] Configurable void damage height and damage
|
||||
|
||||
temporarily migrate to paper's config
|
||||
drop patch on the next minecraft release
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 9afbfe9bf493e09ca1963e8956ab7573964479b4..d04c06fafd133f773f311e7c2708fa8b049da67c 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1222,6 +1222,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
// Purpur end - config for startup commands
|
||||
|
||||
+ // Purpur start - Configurable void damage height and damage
|
||||
+ if (org.purpurmc.purpur.configuration.transformation.VoidDamageHeightMigration.HAS_BEEN_REGISTERED) {
|
||||
+ try {
|
||||
+ org.purpurmc.purpur.PurpurConfig.config.save((java.io.File) this.options.valueOf("purpur-settings"));
|
||||
+ } catch (IOException ex) {
|
||||
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Could not save " + this.options.valueOf("purpur-settings"), ex);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Configurable void damage height and damage
|
||||
+
|
||||
while (this.running) {
|
||||
long l;
|
||||
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 315b5be292b5cd81c526e9190ea43cd25afb89d4..4f90ebcd86fba38dec313143e36614e992c7dbc7 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -209,6 +209,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
org.spigotmc.SpigotConfig.registerCommands();
|
||||
// Spigot end
|
||||
io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc.
|
||||
+ // Purpur start - Configurable void damage height and damage
|
||||
+ try {
|
||||
+ org.purpurmc.purpur.PurpurConfig.init((java.io.File) options.valueOf("purpur-settings"));
|
||||
+ } catch (Exception e) {
|
||||
+ DedicatedServer.LOGGER.error("Unable to load server configuration", e);
|
||||
+ return false;
|
||||
+ }
|
||||
+ org.purpurmc.purpur.PurpurConfig.registerCommands();
|
||||
+ // Purpur end - Configurable void damage height and damage
|
||||
// Paper start - initialize global and world-defaults configuration
|
||||
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 25 Jul 2019 18:07:37 -0500
|
||||
Subject: [PATCH] Implement elytra settings
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index d1f7da0f4adc4609247c349d7ccdb0e6bba9b8f8..6de5f527c018201d874e06a45c9509fa12125766 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3595,7 +3595,18 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (i1 % 2 == 0) {
|
||||
List<EquipmentSlot> list = EquipmentSlot.VALUES.stream().filter(slot -> canGlideUsing(this.getItemBySlot(slot), slot)).toList();
|
||||
EquipmentSlot equipmentSlot = Util.getRandom(list, this.random);
|
||||
- this.getItemBySlot(equipmentSlot).hurtAndBreak(1, this, equipmentSlot);
|
||||
+
|
||||
+ // Purpur start - Implement elytra settings
|
||||
+ int damage = level().purpurConfig.elytraDamagePerSecond;
|
||||
+ if (level().purpurConfig.elytraDamageMultiplyBySpeed > 0) {
|
||||
+ double speed = getDeltaMovement().lengthSqr();
|
||||
+ if (speed > level().purpurConfig.elytraDamageMultiplyBySpeed) {
|
||||
+ damage *= (int) speed;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.getItemBySlot(equipmentSlot).hurtAndBreak(damage, this, equipmentSlot);
|
||||
+ // Purpur end - Implement elytra settings
|
||||
}
|
||||
|
||||
this.gameEvent(GameEvent.ELYTRA_GLIDE);
|
||||
diff --git a/net/minecraft/world/item/FireworkRocketItem.java b/net/minecraft/world/item/FireworkRocketItem.java
|
||||
index 75a9bd205f32b77c5d242cb9fac0f571ce36045a..b03f182c62c699cc222e67c1ae6eadf99c45d48d 100644
|
||||
--- a/net/minecraft/world/item/FireworkRocketItem.java
|
||||
+++ b/net/minecraft/world/item/FireworkRocketItem.java
|
||||
@@ -66,6 +66,19 @@ public class FireworkRocketItem extends Item implements ProjectileItem {
|
||||
com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand));
|
||||
if (event.callEvent() && delayed.attemptSpawn()) {
|
||||
player.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below
|
||||
+
|
||||
+ // Purpur start - Implement elytra settings
|
||||
+ if (level.purpurConfig.elytraDamagePerFireworkBoost > 0) {
|
||||
+ List<net.minecraft.world.entity.EquipmentSlot> list = net.minecraft.world.entity.EquipmentSlot.VALUES.stream().filter((enumitemslot) -> net.minecraft.world.entity.LivingEntity.canGlideUsing(player.getItemBySlot(enumitemslot), enumitemslot)).toList();
|
||||
+ net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, player.random);
|
||||
+
|
||||
+ ItemStack glideItem = player.getItemBySlot(enumitemslot);
|
||||
+ if (player.canGlide()) {
|
||||
+ glideItem.hurtAndBreak(level.purpurConfig.elytraDamagePerFireworkBoost, player, enumitemslot);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Implement elytra settings
|
||||
+
|
||||
if (event.shouldConsume() && !player.hasInfiniteMaterials()) {
|
||||
itemInHand.shrink(1); // Moved up from below
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index c5426585f53a3139dc9d188a73e3a7ff4cb2e492..264b713e8b7c3d5f7d8e1facc90a60349f2cf414 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -733,6 +733,14 @@ public final class ItemStack implements DataComponentHolder {
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Purpur start - Implement elytra settings
|
||||
+ if (this.has(DataComponents.GLIDER)) {
|
||||
+ setDamageValue(this.getMaxDamage() - 1);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Purpur end - Implement elytra settings
|
||||
+
|
||||
this.shrink(1);
|
||||
onBreak.accept(item);
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/TridentItem.java b/net/minecraft/world/item/TridentItem.java
|
||||
index 07f8c7644a112bb1ba283d1eadd8661010e888a4..7ea7db834e7b627a1d7d37ca87cd43eb61408565 100644
|
||||
--- a/net/minecraft/world/item/TridentItem.java
|
||||
+++ b/net/minecraft/world/item/TridentItem.java
|
||||
@@ -133,6 +133,18 @@ public class TridentItem extends Item implements ProjectileItem {
|
||||
f1 *= tridentSpinAttackStrength / squareRoot;
|
||||
f2 *= tridentSpinAttackStrength / squareRoot;
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(player, stack, f, f1, f2); // CraftBukkit
|
||||
+
|
||||
+ // Purpur start - Implement elytra settings
|
||||
+ List<EquipmentSlot> list = EquipmentSlot.VALUES.stream().filter((enumitemslot) -> LivingEntity.canGlideUsing(entity.getItemBySlot(enumitemslot), enumitemslot)).toList();
|
||||
+ if (!list.isEmpty()) {
|
||||
+ EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, entity.random);
|
||||
+ ItemStack glideItem = entity.getItemBySlot(enumitemslot);
|
||||
+ if (glideItem.has(net.minecraft.core.component.DataComponents.GLIDER) && level.purpurConfig.elytraDamagePerTridentBoost > 0) {
|
||||
+ glideItem.hurtAndBreak(level.purpurConfig.elytraDamagePerTridentBoost, entity, enumitemslot);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Implement elytra settings
|
||||
+
|
||||
player.push(f, f1, f2);
|
||||
player.startAutoSpinAttack(20, 8.0F, stack);
|
||||
if (player.onGround()) {
|
||||
@@ -0,0 +1,177 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 26 Mar 2020 21:39:32 -0500
|
||||
Subject: [PATCH] Configurable jockey options
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Drowned.java b/net/minecraft/world/entity/monster/Drowned.java
|
||||
index 9c328f67260606d9252547848d5916cab4290e74..83fc978a94be4655e8c47ee634b8cd280d2a6fde 100644
|
||||
--- a/net/minecraft/world/entity/monster/Drowned.java
|
||||
+++ b/net/minecraft/world/entity/monster/Drowned.java
|
||||
@@ -105,6 +105,23 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Configurable jockey options
|
||||
+ @Override
|
||||
+ public boolean jockeyOnlyBaby() {
|
||||
+ return level().purpurConfig.drownedJockeyOnlyBaby;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double jockeyChance() {
|
||||
+ return level().purpurConfig.drownedJockeyChance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean jockeyTryExistingChickens() {
|
||||
+ return level().purpurConfig.drownedJockeyTryExistingChickens;
|
||||
+ }
|
||||
+ // Purpur end - Configurable jockey options
|
||||
+
|
||||
@Override
|
||||
protected void addBehaviourGoals() {
|
||||
this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0));
|
||||
diff --git a/net/minecraft/world/entity/monster/Husk.java b/net/minecraft/world/entity/monster/Husk.java
|
||||
index c2365ae1cf6f98e262f302a117c4647c383dfbb5..7a8951f93e65c6df145e30d44b9d928dd0c39189 100644
|
||||
--- a/net/minecraft/world/entity/monster/Husk.java
|
||||
+++ b/net/minecraft/world/entity/monster/Husk.java
|
||||
@@ -50,6 +50,23 @@ public class Husk extends Zombie {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Configurable jockey options
|
||||
+ @Override
|
||||
+ public boolean jockeyOnlyBaby() {
|
||||
+ return level().purpurConfig.huskJockeyOnlyBaby;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double jockeyChance() {
|
||||
+ return level().purpurConfig.huskJockeyChance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean jockeyTryExistingChickens() {
|
||||
+ return level().purpurConfig.huskJockeyTryExistingChickens;
|
||||
+ }
|
||||
+ // Purpur end - Configurable jockey options
|
||||
+
|
||||
public static boolean checkHuskSpawnRules(
|
||||
EntityType<Husk> entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random
|
||||
) {
|
||||
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 8886aa0da372223ecd4d1a17c60971e167ced886..63446c874e7153dcfb99133145c8b5311d7d86cd 100644
|
||||
--- a/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -125,6 +125,20 @@ public class Zombie extends Monster {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Configurable jockey options
|
||||
+ public boolean jockeyOnlyBaby() {
|
||||
+ return level().purpurConfig.zombieJockeyOnlyBaby;
|
||||
+ }
|
||||
+
|
||||
+ public double jockeyChance() {
|
||||
+ return level().purpurConfig.zombieJockeyChance;
|
||||
+ }
|
||||
+
|
||||
+ public boolean jockeyTryExistingChickens() {
|
||||
+ return level().purpurConfig.zombieJockeyTryExistingChickens;
|
||||
+ }
|
||||
+ // Purpur end - Configurable jockey options
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
@@ -556,19 +570,18 @@ public class Zombie extends Monster {
|
||||
}
|
||||
|
||||
if (spawnGroupData instanceof Zombie.ZombieGroupData zombieGroupData) {
|
||||
- if (zombieGroupData.isBaby) {
|
||||
- this.setBaby(true);
|
||||
+ if (!jockeyOnlyBaby() || zombieGroupData.isBaby) { // Purpur - Configurable jockey options
|
||||
+ this.setBaby(zombieGroupData.isBaby); // Purpur - Configurable jockey options
|
||||
if (zombieGroupData.canSpawnJockey) {
|
||||
- if (random.nextFloat() < 0.05) {
|
||||
- List<Chicken> entitiesOfClass = level.getEntitiesOfClass(
|
||||
+ if (random.nextFloat() < jockeyChance()) { // Purpur - Configurable jockey options
|
||||
+ List<Chicken> entitiesOfClass = jockeyTryExistingChickens() ? level.getEntitiesOfClass( // Purpur - Configurable jockey options
|
||||
Chicken.class, this.getBoundingBox().inflate(5.0, 3.0, 5.0), EntitySelector.ENTITY_NOT_BEING_RIDDEN
|
||||
- );
|
||||
+ ) : java.util.Collections.emptyList(); // Purpur - Configurable jockey options
|
||||
if (!entitiesOfClass.isEmpty()) {
|
||||
Chicken chicken = entitiesOfClass.get(0);
|
||||
chicken.setChickenJockey(true);
|
||||
this.startRiding(chicken);
|
||||
- }
|
||||
- } else if (random.nextFloat() < 0.05) {
|
||||
+ } else { // Purpur - Configurable jockey options
|
||||
Chicken chicken1 = EntityType.CHICKEN.create(this.level(), EntitySpawnReason.JOCKEY);
|
||||
if (chicken1 != null) {
|
||||
chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F);
|
||||
@@ -577,6 +590,7 @@ public class Zombie extends Monster {
|
||||
this.startRiding(chicken1);
|
||||
level.addFreshEntity(chicken1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit
|
||||
}
|
||||
+ } // Purpur - Configurable jockey options
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
index 578cfc33a493b5ebc2ed42733577129a8953a461..f1e9bf75c50f353bd377051be82a391f97d952fd 100644
|
||||
--- a/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
+++ b/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
@@ -107,6 +107,23 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Configurable jockey options
|
||||
+ @Override
|
||||
+ public boolean jockeyOnlyBaby() {
|
||||
+ return level().purpurConfig.zombieVillagerJockeyOnlyBaby;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double jockeyChance() {
|
||||
+ return level().purpurConfig.zombieVillagerJockeyChance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean jockeyTryExistingChickens() {
|
||||
+ return level().purpurConfig.zombieVillagerJockeyTryExistingChickens;
|
||||
+ }
|
||||
+ // Purpur end - Configurable jockey options
|
||||
+
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
index 1424954f5b4cf0fbe821425cd741b4b5c1bfed50..9603589e0501feee900cd21b04eb84b02bb45de2 100644
|
||||
--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
@@ -88,6 +88,23 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Configurable jockey options
|
||||
+ @Override
|
||||
+ public boolean jockeyOnlyBaby() {
|
||||
+ return level().purpurConfig.zombifiedPiglinJockeyOnlyBaby;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double jockeyChance() {
|
||||
+ return level().purpurConfig.zombifiedPiglinJockeyChance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean jockeyTryExistingChickens() {
|
||||
+ return level().purpurConfig.zombifiedPiglinJockeyTryExistingChickens;
|
||||
+ }
|
||||
+ // Purpur end - Configurable jockey options
|
||||
+
|
||||
@Override
|
||||
public void setPersistentAngerTarget(@Nullable UUID target) {
|
||||
this.persistentAngerTarget = target;
|
||||
@@ -0,0 +1,255 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 9 May 2019 18:26:06 -0500
|
||||
Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
index 67711964552a8e32d3590a64aff78e1db768b026..d58829c88b86358a0c06a982b302fc9a31c15853 100644
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
@@ -26,6 +26,12 @@ public class EndCrystal extends Entity {
|
||||
private static final EntityDataAccessor<Boolean> DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN);
|
||||
public int time;
|
||||
public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals
|
||||
+ // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+ private net.minecraft.world.entity.monster.Phantom targetPhantom;
|
||||
+ private int phantomBeamTicks = 0;
|
||||
+ private int phantomDamageCooldown = 0;
|
||||
+ private int idleCooldown = 0;
|
||||
+ // Purpur end - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
|
||||
public EndCrystal(EntityType<? extends EndCrystal> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -94,6 +100,49 @@ public class EndCrystal extends Entity {
|
||||
// Paper end - Fix invulnerable end crystals
|
||||
if (this.level().purpurConfig.endCrystalCramming > 0 && this.level().getEntitiesOfClass(EndCrystal.class, getBoundingBox()).size() > this.level().purpurConfig.endCrystalCramming) this.hurt(this.damageSources().cramming(), 6.0F); // Purpur - End Crystal Cramming
|
||||
|
||||
+ // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+ if (level().purpurConfig.phantomAttackedByCrystalRadius <= 0 || --idleCooldown > 0) {
|
||||
+ return; // on cooldown
|
||||
+ }
|
||||
+
|
||||
+ if (targetPhantom == null) {
|
||||
+ for (net.minecraft.world.entity.monster.Phantom phantom : level().getEntitiesOfClass(net.minecraft.world.entity.monster.Phantom.class, getBoundingBox().inflate(level().purpurConfig.phantomAttackedByCrystalRadius))) {
|
||||
+ if (phantom.hasLineOfSight(this)) {
|
||||
+ attackPhantom(phantom);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ setBeamTarget(new BlockPos(targetPhantom).offset(0, -2, 0));
|
||||
+ if (--phantomBeamTicks > 0 && targetPhantom.isAlive()) {
|
||||
+ phantomDamageCooldown--;
|
||||
+ if (targetPhantom.hasLineOfSight(this)) {
|
||||
+ if (phantomDamageCooldown <= 0) {
|
||||
+ phantomDamageCooldown = 20;
|
||||
+ targetPhantom.hurt(targetPhantom.damageSources().indirectMagic(this, this), level().purpurConfig.phantomAttackedByCrystalDamage);
|
||||
+ }
|
||||
+ } else {
|
||||
+ forgetPhantom(); // no longer in sight
|
||||
+ }
|
||||
+ } else {
|
||||
+ forgetPhantom(); // attacked long enough
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void attackPhantom(net.minecraft.world.entity.monster.Phantom phantom) {
|
||||
+ phantomDamageCooldown = 0;
|
||||
+ phantomBeamTicks = 60;
|
||||
+ targetPhantom = phantom;
|
||||
+ }
|
||||
+
|
||||
+ private void forgetPhantom() {
|
||||
+ targetPhantom = null;
|
||||
+ setBeamTarget(null);
|
||||
+ phantomBeamTicks = 0;
|
||||
+ phantomDamageCooldown = 0;
|
||||
+ idleCooldown = 60;
|
||||
+ // Purpur end - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
|
||||
index 08fc2dc0fecfa370c99e877d502149a8ea147e5f..aea7b608d88d243113f67665844841ac879c3f88 100644
|
||||
--- a/net/minecraft/world/entity/monster/Phantom.java
|
||||
+++ b/net/minecraft/world/entity/monster/Phantom.java
|
||||
@@ -47,6 +47,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
Vec3 moveTargetPoint = Vec3.ZERO;
|
||||
public BlockPos anchorPoint = BlockPos.ZERO;
|
||||
Phantom.AttackPhase attackPhase = Phantom.AttackPhase.CIRCLE;
|
||||
+ Vec3 crystalPosition; // Purpur - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
// Paper start
|
||||
@Nullable
|
||||
public java.util.UUID spawningEntity;
|
||||
@@ -118,6 +119,25 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
+ // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+ @Override
|
||||
+ protected void dropFromLootTable(ServerLevel world, DamageSource damageSource, boolean causedByPlayer) {
|
||||
+ boolean dropped = false;
|
||||
+ if (lastHurtByPlayer == null && damageSource.getEntity() instanceof net.minecraft.world.entity.boss.enderdragon.EndCrystal) {
|
||||
+ if (random.nextInt(5) < 1) {
|
||||
+ dropped = spawnAtLocation(world, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.PHANTOM_MEMBRANE)) != null;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!dropped) {
|
||||
+ super.dropFromLootTable(world, damageSource, causedByPlayer);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCirclingCrystal() {
|
||||
+ return crystalPosition != null;
|
||||
+ }
|
||||
+ // Purpur end - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+
|
||||
@Override
|
||||
public boolean isFlapping() {
|
||||
return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0;
|
||||
@@ -131,9 +151,15 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
- this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal());
|
||||
- this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal());
|
||||
- this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal());
|
||||
+ // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+ if (level().purpurConfig.phantomOrbitCrystalRadius > 0) {
|
||||
+ this.goalSelector.addGoal(1, new PhantomFindCrystalGoal(this));
|
||||
+ this.goalSelector.addGoal(2, new PhantomOrbitCrystalGoal(this));
|
||||
+ }
|
||||
+ this.goalSelector.addGoal(3, new Phantom.PhantomAttackStrategyGoal());
|
||||
+ this.goalSelector.addGoal(4, new Phantom.PhantomSweepAttackGoal());
|
||||
+ this.goalSelector.addGoal(5, new Phantom.PhantomCircleAroundAnchorGoal());
|
||||
+ // Purpur end - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal());
|
||||
}
|
||||
@@ -509,6 +535,124 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+ class PhantomFindCrystalGoal extends Goal {
|
||||
+ private final Phantom phantom;
|
||||
+ private net.minecraft.world.entity.boss.enderdragon.EndCrystal crystal;
|
||||
+ private Comparator<net.minecraft.world.entity.boss.enderdragon.EndCrystal> comparator;
|
||||
+
|
||||
+ PhantomFindCrystalGoal(Phantom phantom) {
|
||||
+ this.phantom = phantom;
|
||||
+ this.comparator = Comparator.comparingDouble(phantom::distanceToSqr);
|
||||
+ this.setFlags(EnumSet.of(Flag.LOOK));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canUse() {
|
||||
+ double range = maxTargetRange();
|
||||
+ List<net.minecraft.world.entity.boss.enderdragon.EndCrystal> crystals = level().getEntitiesOfClass(net.minecraft.world.entity.boss.enderdragon.EndCrystal.class, phantom.getBoundingBox().inflate(range));
|
||||
+ if (crystals.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ crystals.sort(comparator);
|
||||
+ crystal = crystals.get(0);
|
||||
+ if (phantom.distanceToSqr(crystal) > range * range) {
|
||||
+ crystal = null;
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canContinueToUse() {
|
||||
+ if (crystal == null || !crystal.isAlive()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ double range = maxTargetRange();
|
||||
+ return phantom.distanceToSqr(crystal) <= (range * range) * 2;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void start() {
|
||||
+ phantom.crystalPosition = new Vec3(crystal.getX(), crystal.getY() + (phantom.random.nextInt(10) + 10), crystal.getZ());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void stop() {
|
||||
+ crystal = null;
|
||||
+ phantom.crystalPosition = null;
|
||||
+ super.stop();
|
||||
+ }
|
||||
+
|
||||
+ private double maxTargetRange() {
|
||||
+ return phantom.level().purpurConfig.phantomOrbitCrystalRadius;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class PhantomOrbitCrystalGoal extends Goal {
|
||||
+ private final Phantom phantom;
|
||||
+ private float offset;
|
||||
+ private float radius;
|
||||
+ private float verticalChange;
|
||||
+ private float direction;
|
||||
+
|
||||
+ PhantomOrbitCrystalGoal(Phantom phantom) {
|
||||
+ this.phantom = phantom;
|
||||
+ this.setFlags(EnumSet.of(Flag.MOVE));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canUse() {
|
||||
+ return phantom.isCirclingCrystal();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void start() {
|
||||
+ this.radius = 5.0F + phantom.random.nextFloat() * 10.0F;
|
||||
+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F;
|
||||
+ this.direction = phantom.random.nextBoolean() ? 1.0F : -1.0F;
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void tick() {
|
||||
+ if (phantom.random.nextInt(350) == 0) {
|
||||
+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F;
|
||||
+ }
|
||||
+ if (phantom.random.nextInt(250) == 0) {
|
||||
+ ++this.radius;
|
||||
+ if (this.radius > 15.0F) {
|
||||
+ this.radius = 5.0F;
|
||||
+ this.direction = -this.direction;
|
||||
+ }
|
||||
+ }
|
||||
+ if (phantom.random.nextInt(450) == 0) {
|
||||
+ this.offset = phantom.random.nextFloat() * 2.0F * 3.1415927F;
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.distanceToSqr(phantom.getX(), phantom.getY(), phantom.getZ()) < 4.0D) {
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.y < phantom.getY() && !phantom.level().isEmptyBlock(new BlockPos(phantom).below(1))) {
|
||||
+ this.verticalChange = Math.max(1.0F, this.verticalChange);
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ if (phantom.moveTargetPoint.y > phantom.getY() && !phantom.level().isEmptyBlock(new BlockPos(phantom).above(1))) {
|
||||
+ this.verticalChange = Math.min(-1.0F, this.verticalChange);
|
||||
+ updateOffset();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void updateOffset() {
|
||||
+ this.offset += this.direction * 15.0F * 0.017453292F;
|
||||
+ phantom.moveTargetPoint = phantom.crystalPosition.add(
|
||||
+ this.radius * Mth.cos(this.offset),
|
||||
+ -4.0F + this.verticalChange,
|
||||
+ this.radius * Mth.sin(this.offset));
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Phantoms attracted to crystals and crystals shoot phantoms
|
||||
+
|
||||
class PhantomMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur - Ridables
|
||||
private float speed = 0.1F;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: draycia <lonelyyordle@gmail.com>
|
||||
Date: Sun, 12 Apr 2020 20:41:59 -0700
|
||||
Subject: [PATCH] Phantoms burn in light
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
|
||||
index aea7b608d88d243113f67665844841ac879c3f88..4cc1c8d8967b1e9ee5b0b1c50d887f3de3e8a882 100644
|
||||
--- a/net/minecraft/world/entity/monster/Phantom.java
|
||||
+++ b/net/minecraft/world/entity/monster/Phantom.java
|
||||
@@ -53,6 +53,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
public java.util.UUID spawningEntity;
|
||||
public boolean shouldBurnInDay = true;
|
||||
// Paper end
|
||||
+ private static final net.minecraft.world.item.crafting.Ingredient TORCH = net.minecraft.world.item.crafting.Ingredient.of(net.minecraft.world.item.Items.TORCH, net.minecraft.world.item.Items.SOUL_TORCH); // Purpur - Phantoms burn in light
|
||||
|
||||
public Phantom(EntityType<? extends Phantom> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -253,7 +254,11 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public void aiStep() {
|
||||
- if (this.isAlive() && this.shouldBurnInDay && this.isSunBurnTick()) { // Paper - shouldBurnInDay API
|
||||
+ // Purpur start - Phantoms burn in light
|
||||
+ boolean burnFromDaylight = this.shouldBurnInDay && this.isSunBurnTick() && this.level().purpurConfig.phantomBurnInDaylight;
|
||||
+ boolean burnFromLightSource = this.level().purpurConfig.phantomBurnInLight > 0 && this.level().getMaxLocalRawBrightness(blockPosition()) >= this.level().purpurConfig.phantomBurnInLight;
|
||||
+ if (this.isAlive() && (burnFromDaylight || burnFromLightSource)) { // Paper - shouldBurnInDay API
|
||||
+ // Purpur end - Phantoms burn in light
|
||||
if (getRider() == null || !this.isControllable()) // Purpur - Ridables
|
||||
this.igniteForSeconds(8.0F);
|
||||
}
|
||||
@@ -374,6 +379,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
List<Player> nearbyPlayers = serverLevel.getNearbyPlayers(
|
||||
this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0, 64.0, 16.0)
|
||||
);
|
||||
+ if (level().purpurConfig.phantomIgnorePlayersWithTorch) nearbyPlayers.removeIf(human -> TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND)) || TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.OFF_HAND))); // Purpur - Phantoms burn in light
|
||||
if (!nearbyPlayers.isEmpty()) {
|
||||
nearbyPlayers.sort(Comparator.<Player, Double>comparing(Entity::getY).reversed());
|
||||
|
||||
@@ -739,6 +745,12 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
return false;
|
||||
} else if (!target.isAlive()) {
|
||||
return false;
|
||||
+ // Purpur start - Phantoms burn in light
|
||||
+ } else if (level().purpurConfig.phantomBurnInLight > 0 && level().getLightEmission(new BlockPos(Phantom.this)) >= level().purpurConfig.phantomBurnInLight) {
|
||||
+ return false;
|
||||
+ } else if (level().purpurConfig.phantomIgnorePlayersWithTorch && (TORCH.test(target.getItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND)) || TORCH.test(target.getItemInHand(net.minecraft.world.InteractionHand.OFF_HAND)))) {
|
||||
+ return false;
|
||||
+ // Purpur end - Phantoms burn in light
|
||||
} else if (target instanceof Player player && (target.isSpectator() || player.isCreative())) {
|
||||
return false;
|
||||
} else if (!this.canUse()) {
|
||||
@@ -0,0 +1,600 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Sun, 15 Nov 2020 02:18:15 -0800
|
||||
Subject: [PATCH] Make entity breeding times configurable
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java
|
||||
index 4fb63e58eac5d67fcd31c3233dca1dae72b98bc4..dd8d315eba203db121e24e3402f2117fc0f3043f 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java
|
||||
@@ -118,8 +118,10 @@ public class VillagerMakeLove extends Behavior<Villager> {
|
||||
return Optional.empty();
|
||||
}
|
||||
// Move age setting down
|
||||
- parent.setAge(6000);
|
||||
- partner.setAge(6000);
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ parent.setAge(level.purpurConfig.villagerBreedingTicks);
|
||||
+ partner.setAge(level.purpurConfig.villagerBreedingTicks);
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
level.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING);
|
||||
// CraftBukkit end
|
||||
level.broadcastEntityEvent(breedOffspring, (byte)12);
|
||||
diff --git a/net/minecraft/world/entity/animal/Animal.java b/net/minecraft/world/entity/animal/Animal.java
|
||||
index 33c3752be451508343cad83766da7c3be1822d02..fa34e7f1c20dfd569b52a9c8e0a8d4d5e659ce20 100644
|
||||
--- a/net/minecraft/world/entity/animal/Animal.java
|
||||
+++ b/net/minecraft/world/entity/animal/Animal.java
|
||||
@@ -40,6 +40,7 @@ public abstract class Animal extends AgeableMob {
|
||||
@Nullable
|
||||
public UUID loveCause;
|
||||
public ItemStack breedItem; // CraftBukkit - Add breedItem variable
|
||||
+ public abstract int getPurpurBreedTime(); // Purpur - Make entity breeding times configurable
|
||||
|
||||
protected Animal(EntityType<? extends Animal> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -279,8 +280,10 @@ public abstract class Animal extends AgeableMob {
|
||||
player.awardStat(Stats.ANIMALS_BRED);
|
||||
CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby);
|
||||
} // Paper
|
||||
- this.setAge(6000);
|
||||
- animal.setAge(6000);
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ this.setAge(this.getPurpurBreedTime());
|
||||
+ animal.setAge(animal.getPurpurBreedTime());
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
this.resetLove();
|
||||
animal.resetLove();
|
||||
level.broadcastEntityEvent(this, (byte)18);
|
||||
diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java
|
||||
index 3cdfded14a2fb74e3f345e893e60364b6b810075..199bd7e9b053a2eac76987ceb5caebc088d1071d 100644
|
||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -480,6 +480,13 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.beeBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public int getRemainingPersistentAngerTime() {
|
||||
return this.entityData.get(DATA_REMAINING_ANGER_TIME);
|
||||
diff --git a/net/minecraft/world/entity/animal/Cat.java b/net/minecraft/world/entity/animal/Cat.java
|
||||
index 98ce277c5b27591e22daa3c85241be1b8689bfae..584568cef949cee24aa7850d2ff99d47cd089a6e 100644
|
||||
--- a/net/minecraft/world/entity/animal/Cat.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cat.java
|
||||
@@ -126,6 +126,13 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.catBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.temptGoal = new Cat.CatTemptGoal(this, 0.6, itemStack -> itemStack.is(ItemTags.CAT_FOOD), true);
|
||||
diff --git a/net/minecraft/world/entity/animal/Chicken.java b/net/minecraft/world/entity/animal/Chicken.java
|
||||
index d718f0ed362c49803260dceed64bd93e2b6744fc..39ad1729ef03fc35a6365ee215be214eccfd959a 100644
|
||||
--- a/net/minecraft/world/entity/animal/Chicken.java
|
||||
+++ b/net/minecraft/world/entity/animal/Chicken.java
|
||||
@@ -81,6 +81,13 @@ public class Chicken extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.chickenBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
diff --git a/net/minecraft/world/entity/animal/Cow.java b/net/minecraft/world/entity/animal/Cow.java
|
||||
index d2a4bfa5334f7361067e4adac36ba5a4a4fa6ad8..e4965300eb41512d03a0b111422c98627cf29a54 100644
|
||||
--- a/net/minecraft/world/entity/animal/Cow.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cow.java
|
||||
@@ -63,6 +63,13 @@ public class Cow extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.cowBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
diff --git a/net/minecraft/world/entity/animal/Fox.java b/net/minecraft/world/entity/animal/Fox.java
|
||||
index 8bf893837586ae2a9b4ef7564d242e16e4863b5d..1acf9b8c9e6a5915b3f095e83d3f209708947093 100644
|
||||
--- a/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -175,6 +175,13 @@ public class Fox extends Animal implements VariantHolder<Fox.Variant> {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.foxBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
@@ -969,8 +976,10 @@ public class Fox extends Animal implements VariantHolder<Fox.Variant> {
|
||||
CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer, this.animal, this.partner, fox);
|
||||
}
|
||||
|
||||
- this.animal.setAge(6000);
|
||||
- this.partner.setAge(6000);
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ this.animal.setAge(this.animal.getPurpurBreedTime());
|
||||
+ this.partner.setAge(this.partner.getPurpurBreedTime());
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
this.animal.resetLove();
|
||||
this.partner.resetLove();
|
||||
serverLevel.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason
|
||||
diff --git a/net/minecraft/world/entity/animal/MushroomCow.java b/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
index 990723c31aa1040a4e45b9857a18d86287ef91b4..a64b609bf5ce38a252bfa1bcff869f88e14389b5 100644
|
||||
--- a/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
@@ -79,6 +79,13 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.mooshroomBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public float getWalkTargetValue(BlockPos pos, LevelReader level) {
|
||||
return level.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : level.getPathfindingCostFromLightLevels(pos);
|
||||
diff --git a/net/minecraft/world/entity/animal/Ocelot.java b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
index 41c42ecbf6aa233bd82000a4bbba3b186cca6a9d..b06697fd64a8962133f0324b2c03b9e9b4f32086 100644
|
||||
--- a/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -87,6 +87,13 @@ public class Ocelot extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.ocelotBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public boolean isTrusting() {
|
||||
return this.entityData.get(DATA_TRUSTING);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/Panda.java b/net/minecraft/world/entity/animal/Panda.java
|
||||
index 5b07dff937c8873300eabecf1c510cf562fae4f3..450c7be36846bf4e95f84615fca893501415cdbc 100644
|
||||
--- a/net/minecraft/world/entity/animal/Panda.java
|
||||
+++ b/net/minecraft/world/entity/animal/Panda.java
|
||||
@@ -140,6 +140,13 @@ public class Panda extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.pandaBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected boolean canDispenserEquipIntoSlot(EquipmentSlot slot) {
|
||||
return slot == EquipmentSlot.MAINHAND && this.canPickUpLoot();
|
||||
diff --git a/net/minecraft/world/entity/animal/Parrot.java b/net/minecraft/world/entity/animal/Parrot.java
|
||||
index 87de937fd17c2e7e8916f8503b0334e7015bdb8f..9d7e142cc4b9ea32aad7ab17f3fc09a7a3a1d862 100644
|
||||
--- a/net/minecraft/world/entity/animal/Parrot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Parrot.java
|
||||
@@ -194,6 +194,13 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder<Parrot
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return 6000;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(
|
||||
diff --git a/net/minecraft/world/entity/animal/Pig.java b/net/minecraft/world/entity/animal/Pig.java
|
||||
index 7df848bd9c4cf98fbd431a8cae16a2df86ec5e2b..801365d71b5b733e2dce54211e08d26d7f45f4d9 100644
|
||||
--- a/net/minecraft/world/entity/animal/Pig.java
|
||||
+++ b/net/minecraft/world/entity/animal/Pig.java
|
||||
@@ -81,6 +81,13 @@ public class Pig extends Animal implements ItemSteerable, Saddleable {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.pigBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
diff --git a/net/minecraft/world/entity/animal/PolarBear.java b/net/minecraft/world/entity/animal/PolarBear.java
|
||||
index 913439a769a36521ba59d59cba4d6878d3186254..365ad366bd0077619b0f6b5d26ed41038da0397e 100644
|
||||
--- a/net/minecraft/world/entity/animal/PolarBear.java
|
||||
+++ b/net/minecraft/world/entity/animal/PolarBear.java
|
||||
@@ -124,6 +124,13 @@ public class PolarBear extends Animal implements NeutralMob {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.polarBearBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
|
||||
diff --git a/net/minecraft/world/entity/animal/Rabbit.java b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
index e71161ecc9d4ee3fe29fa3a27d11d63e1a28d1a0..bbdd06002b07699fffebdf6ed8148abdb69c24cc 100644
|
||||
--- a/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -145,6 +145,13 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.rabbitBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
diff --git a/net/minecraft/world/entity/animal/Sheep.java b/net/minecraft/world/entity/animal/Sheep.java
|
||||
index b66440f5cfbd714c6d2f5b7f66b4e755602b4521..882c799cb66a2acada33ff24f3adb7eb611f89c1 100644
|
||||
--- a/net/minecraft/world/entity/animal/Sheep.java
|
||||
+++ b/net/minecraft/world/entity/animal/Sheep.java
|
||||
@@ -106,6 +106,13 @@ public class Sheep extends Animal implements Shearable {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.sheepBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.eatBlockGoal = new EatBlockGoal(this);
|
||||
diff --git a/net/minecraft/world/entity/animal/Turtle.java b/net/minecraft/world/entity/animal/Turtle.java
|
||||
index 4f0fbbb2caeda6d1477d3297fd68f802e4f3a9ca..edbccb7ca27aa8a1917eb8b35b3ba8600c91111a 100644
|
||||
--- a/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -109,6 +109,13 @@ public class Turtle extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.turtleBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public void setHomePos(BlockPos homePos) {
|
||||
this.entityData.set(HOME_POS, homePos);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/Wolf.java b/net/minecraft/world/entity/animal/Wolf.java
|
||||
index afc12968313a408e8a71a20c2c0defde52605c4e..9d79946497cfc92ff11160b86d5064d86916af36 100644
|
||||
--- a/net/minecraft/world/entity/animal/Wolf.java
|
||||
+++ b/net/minecraft/world/entity/animal/Wolf.java
|
||||
@@ -210,6 +210,13 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder<Hol
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.wolfBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
index c10ebb66dec26b6ccc223e98effa0b9a68363626..90bcd8c79cccbcbe7ff3fd2534e0c3450b970bd4 100644
|
||||
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
@@ -105,6 +105,13 @@ public class Armadillo extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.armadilloBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
index f2f09a529e9db88784ff4299fdf3966046c736ab..07eee1f82331a2172aede02219a7eae8e82c7b59 100644
|
||||
--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
@@ -140,6 +140,13 @@ public class Axolotl extends Animal implements VariantHolder<Axolotl.Variant>, B
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.axolotlBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public float getWalkTargetValue(BlockPos pos, LevelReader level) {
|
||||
return 0.0F;
|
||||
diff --git a/net/minecraft/world/entity/animal/camel/Camel.java b/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
index 1d7e2358bac193af48dc4b7f5b0295e3bffa152b..1d7ae2a08968860636918e7c66b60139a9d761b4 100644
|
||||
--- a/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
+++ b/net/minecraft/world/entity/animal/camel/Camel.java
|
||||
@@ -90,6 +90,13 @@ public class Camel extends AbstractHorse {
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.camelBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
index 9a400c8bf2b54aa5fbcbe65b61670cac5fbebf05..c4ea9485294b7dec2582c638802f003ad70659b6 100644
|
||||
--- a/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
@@ -165,6 +165,12 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.frogBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
@Override
|
||||
protected Brain.Provider<Frog> brainProvider() {
|
||||
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
|
||||
diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
index 302208b566038a3a352ca867dd70a61887bac104..0a018dbfe3750cf91892d8cfb5c0eac18e83d587 100644
|
||||
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -128,6 +128,13 @@ public class Goat extends Animal {
|
||||
}
|
||||
// Purpur end - Ridables
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.goatBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected Brain.Provider<Goat> brainProvider() {
|
||||
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/Donkey.java b/net/minecraft/world/entity/animal/horse/Donkey.java
|
||||
index 223f1d109680e3643ab2c8343be22713e89755fd..b977597785df5665176ab2f330633ec61b7c9feb 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/Donkey.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/Donkey.java
|
||||
@@ -40,6 +40,13 @@ public class Donkey extends AbstractChestedHorse {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.donkeyBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return SoundEvents.DONKEY_AMBIENT;
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/Horse.java b/net/minecraft/world/entity/animal/horse/Horse.java
|
||||
index 8bd118e82da9e4d4153de0a3efaf6d69e3c4c540..0339ab08b3029a9ffc102c5b865e411aca2a863c 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/Horse.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/Horse.java
|
||||
@@ -67,6 +67,13 @@ public class Horse extends AbstractHorse implements VariantHolder<Variant> {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.horseBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void randomizeAttributes(RandomSource random) {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt));
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
index 58e726dd33f572a31b4910b9ff666c4252fb03a9..6efe52edb6909ed2b38210ce6a0334eddc55f261 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
@@ -141,6 +141,13 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.llamaBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public boolean isTraderLlama() {
|
||||
return false;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/Mule.java b/net/minecraft/world/entity/animal/horse/Mule.java
|
||||
index d0d6b511dbd4f992d11f06e7539b0c1034250660..20458799fdcfa16bdd1c22df74b414000b110f82 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/Mule.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/Mule.java
|
||||
@@ -39,6 +39,13 @@ public class Mule extends AbstractChestedHorse {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.muleBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return SoundEvents.MULE_AMBIENT;
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
||||
index 6cc64c7e2f50a311460cd5d7ffa9545e5d7e0b02..0ce71ab6a28a5fbff9d71793b855c116b31729fc 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
||||
@@ -63,6 +63,13 @@ public class SkeletonHorse extends AbstractHorse {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return 6000;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/TraderLlama.java b/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
||||
index 715cb8046e1fb9ac929d81709777bf4ae9323d46..870775ce8a1bd09d35bf85551e1af3a6edfefc0e 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
||||
@@ -68,6 +68,13 @@ public class TraderLlama extends Llama {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.traderLlamaBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public boolean isTraderLlama() {
|
||||
return true;
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/ZombieHorse.java b/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
||||
index 8da61e14f2470dfb191d9dfaf19c713584b8e9b8..cdff0fab8a256c1e06e280500a31d4a99659d1ee 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
||||
@@ -62,6 +62,13 @@ public class ZombieHorse extends AbstractHorse {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return 6000;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
index a5ff61a3697e2299c96288b6f8d7c6f2511d86d5..11a5da22149a61ca48bbb0a8ed10b71e91a5cc98 100644
|
||||
--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
+++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
@@ -113,6 +113,13 @@ public class Sniffer extends Animal {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.snifferBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java
|
||||
index be0dc92bf5ae3da1368a649e9c4e7ff5dbb1c67c..f36e94437b4e21961532ac9ab91767617f9c3c32 100644
|
||||
--- a/net/minecraft/world/entity/monster/Strider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Strider.java
|
||||
@@ -119,6 +119,13 @@ public class Strider extends Animal implements ItemSteerable, Saddleable {
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.striderBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
public static boolean checkStriderSpawnRules(
|
||||
EntityType<Strider> entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random
|
||||
) {
|
||||
diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
index 54924cd7c84cbcd22ffc0bd37fc24f24e73c18bc..266d1838e6602ef6322c15732f2693a865911f2e 100644
|
||||
--- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
@@ -122,6 +122,13 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
||||
this.timeInOverworld = timeInOverworld;
|
||||
}
|
||||
|
||||
+ // Purpur start - Make entity breeding times configurable
|
||||
+ @Override
|
||||
+ public int getPurpurBreedTime() {
|
||||
+ return this.level().purpurConfig.hoglinBreedingTicks;
|
||||
+ }
|
||||
+ // Purpur end - Make entity breeding times configurable
|
||||
+
|
||||
@Override
|
||||
public boolean canBeLeashed() {
|
||||
return true;
|
||||
@@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 17 Nov 2020 03:23:48 -0800
|
||||
Subject: [PATCH] Apply display names from item forms of entities to entities
|
||||
and vice versa
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index d368b1971b270c44efc849464a100832bc29a679..8c0ab32487c56e2caf42404184f86c9bcf5f8b41 100644
|
||||
--- a/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -564,6 +564,7 @@ public class ArmorStand extends LivingEntity {
|
||||
|
||||
private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(ServerLevel level, DamageSource damageSource) { // Paper
|
||||
ItemStack itemStack = new ItemStack(Items.ARMOR_STAND);
|
||||
+ if (level.purpurConfig.persistentDroppableEntityDisplayNames) // Purpur - Apply display names from item forms of entities to entities and vice versa
|
||||
itemStack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
|
||||
this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior
|
||||
return this.brokenByAnything(level, damageSource); // Paper
|
||||
diff --git a/net/minecraft/world/entity/decoration/ItemFrame.java b/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
index 65e1d7c5ac94b1cfb921fa009be59d3e5872f0b5..3ee1d8798db666ee8d83556047e40ff217cda732 100644
|
||||
--- a/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
+++ b/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
@@ -223,7 +223,11 @@ public class ItemFrame extends HangingEntity {
|
||||
this.removeFramedMap(item);
|
||||
} else {
|
||||
if (dropItem) {
|
||||
- this.spawnAtLocation(level, this.getFrameItemStack());
|
||||
+ // Purpur start - Apply display names from item forms of entities to entities and vice versa
|
||||
+ final ItemStack itemFrame = this.getFrameItemStack();
|
||||
+ if (!level.purpurConfig.persistentDroppableEntityDisplayNames) itemFrame.set(DataComponents.CUSTOM_NAME, null);
|
||||
+ this.spawnAtLocation(level, itemFrame);
|
||||
+ // Purpur end - Apply display names from item forms of entities to entities and vice versa
|
||||
}
|
||||
|
||||
if (!item.isEmpty()) {
|
||||
diff --git a/net/minecraft/world/entity/decoration/Painting.java b/net/minecraft/world/entity/decoration/Painting.java
|
||||
index 5b905a4d49c44b04d5795c2bf297f3c69d183d7c..b6429a2bbb6fc1e08610ab20e50f8f0414f0ad26 100644
|
||||
--- a/net/minecraft/world/entity/decoration/Painting.java
|
||||
+++ b/net/minecraft/world/entity/decoration/Painting.java
|
||||
@@ -162,7 +162,11 @@ public class Painting extends HangingEntity implements VariantHolder<Holder<Pain
|
||||
if (level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
|
||||
this.playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F);
|
||||
if (!(entity instanceof Player player && player.hasInfiniteMaterials())) {
|
||||
- this.spawnAtLocation(level, Items.PAINTING);
|
||||
+ // Purpur start - Apply display names from item forms of entities to entities and vice versa
|
||||
+ final ItemStack painting = new ItemStack(Items.PAINTING);
|
||||
+ if (!this.level().purpurConfig.persistentDroppableEntityDisplayNames) painting.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, null);
|
||||
+ this.spawnAtLocation(level, painting);
|
||||
+ // Purpur end - Apply display names from item forms of entities to entities and vice versa
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
index 4e724a12f13032075aeff7cf71b9ceabd5a7bd88..b1b312e45ed4514eaa6fb3941af64b641220c5bd 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
@@ -879,7 +879,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
|
||||
@Override
|
||||
public final ItemStack getPickResult() {
|
||||
- return new ItemStack(this.dropItem.get());
|
||||
+ // Purpur start - Apply display names from item forms of entities to entities and vice versa
|
||||
+ final ItemStack boat = new ItemStack(this.dropItem.get());
|
||||
+ if (!this.level().purpurConfig.persistentDroppableEntityDisplayNames) {
|
||||
+ boat.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, null);
|
||||
+ }
|
||||
+ return boat;
|
||||
+ // Purpur end - Apply display names from item forms of entities to entities and vice versa
|
||||
}
|
||||
|
||||
public static enum Status {
|
||||
diff --git a/net/minecraft/world/item/ArmorStandItem.java b/net/minecraft/world/item/ArmorStandItem.java
|
||||
index d82e6651999a2650ec8884c4c3d8de4133cb42a4..a26b9fe964c79da57aaa0f755a81934f51a79913 100644
|
||||
--- a/net/minecraft/world/item/ArmorStandItem.java
|
||||
+++ b/net/minecraft/world/item/ArmorStandItem.java
|
||||
@@ -51,6 +51,10 @@ public class ArmorStandItem extends Item {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Purpur start - Apply display names from item forms of entities to entities and vice versa
|
||||
+ if (!serverLevel.purpurConfig.persistentDroppableEntityDisplayNames) armorStand.setCustomName(null);
|
||||
+ if (serverLevel.purpurConfig.armorstandSetNameVisible && armorStand.getCustomName() != null) armorStand.setCustomNameVisible(true);
|
||||
+ // Purpur end - Apply display names from item forms of entities to entities and vice versa
|
||||
serverLevel.addFreshEntityWithPassengers(armorStand);
|
||||
level.playSound(
|
||||
null, armorStand.getX(), armorStand.getY(), armorStand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F
|
||||
diff --git a/net/minecraft/world/item/BoatItem.java b/net/minecraft/world/item/BoatItem.java
|
||||
index 13ce174e4f7e406f57a68ea0d3ef0ee3367f3f3b..ca86122e38688b29340cd8413ccf1746315e292a 100644
|
||||
--- a/net/minecraft/world/item/BoatItem.java
|
||||
+++ b/net/minecraft/world/item/BoatItem.java
|
||||
@@ -63,6 +63,7 @@ public class BoatItem extends Item {
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
boat.setYRot(player.getYRot());
|
||||
+ if (!level.purpurConfig.persistentDroppableEntityDisplayNames) boat.setCustomName(null); // Purpur - Apply display names from item forms of entities to entities and vice versa
|
||||
if (!level.noCollision(boat, boat.getBoundingBox())) {
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/item/HangingEntityItem.java b/net/minecraft/world/item/HangingEntityItem.java
|
||||
index 85980c7e5ad63398e0f0948fb0250f580251fe63..cd9e0398876567afc337db8f6ff0ebb0ee162383 100644
|
||||
--- a/net/minecraft/world/item/HangingEntityItem.java
|
||||
+++ b/net/minecraft/world/item/HangingEntityItem.java
|
||||
@@ -62,6 +62,7 @@ public class HangingEntityItem extends Item {
|
||||
CustomData customData = itemInHand.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
|
||||
if (!customData.isEmpty()) {
|
||||
EntityType.updateCustomEntityTag(level, player, hangingEntity, customData);
|
||||
+ if (!level.purpurConfig.persistentDroppableEntityDisplayNames) hangingEntity.setCustomName(null); // Purpur - Apply display names from item forms of entities to entities and vice versa
|
||||
}
|
||||
|
||||
if (hangingEntity.survives()) {
|
||||
@@ -0,0 +1,171 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Sat, 5 Dec 2020 01:20:16 -0800
|
||||
Subject: [PATCH] Option for Villager Clerics to farm Nether Wart
|
||||
|
||||
Adds an option so that Villagers with the Cleric profession are able to
|
||||
farm Nether Wart. Reimplemented based on a feature of the carpet-extra
|
||||
mod.
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
index 4106549bd4dec1cc47d8765be8f5d119fe33bf56..e98fac58b29f78cb63bd868811cca41e1644e9ac 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
@@ -32,6 +32,7 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
private long nextOkStartTime;
|
||||
private int timeWorkedSoFar;
|
||||
private final List<BlockPos> validFarmlandAroundVillager = Lists.newArrayList();
|
||||
+ private boolean clericWartFarmer = false; // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
|
||||
public HarvestFarmland() {
|
||||
super(
|
||||
@@ -50,9 +51,10 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) {
|
||||
if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
return false;
|
||||
- } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER) {
|
||||
+ } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER && !(level.purpurConfig.villagerClericsFarmWarts && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC)) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
return false;
|
||||
} else {
|
||||
+ if (!this.clericWartFarmer && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC) this.clericWartFarmer = true; // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
BlockPos.MutableBlockPos mutableBlockPos = owner.blockPosition().mutable();
|
||||
this.validFarmlandAroundVillager.clear();
|
||||
|
||||
@@ -83,6 +85,7 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
BlockState blockState = serverLevel.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
Block block1 = serverLevel.getBlockState(pos.below()).getBlock();
|
||||
+ if (this.clericWartFarmer) return block == net.minecraft.world.level.block.Blocks.NETHER_WART && blockState.getValue(net.minecraft.world.level.block.NetherWartBlock.AGE) == 3 || blockState.isAir() && block1 == net.minecraft.world.level.block.Blocks.SOUL_SAND; // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
return block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState) || blockState.isAir() && block1 instanceof FarmBlock;
|
||||
}
|
||||
|
||||
@@ -109,19 +112,19 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
BlockState blockState = level.getBlockState(this.aboveFarmlandPos);
|
||||
Block block = blockState.getBlock();
|
||||
Block block1 = level.getBlockState(this.aboveFarmlandPos.below()).getBlock();
|
||||
- if (block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState)) {
|
||||
+ if (block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState) && !this.clericWartFarmer || this.clericWartFarmer && block == net.minecraft.world.level.block.Blocks.NETHER_WART && blockState.getValue(net.minecraft.world.level.block.NetherWartBlock.AGE) == 3) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, blockState.getFluidState().createLegacyBlock())) { // CraftBukkit // Paper - fix wrong block state
|
||||
level.destroyBlock(this.aboveFarmlandPos, true, owner);
|
||||
} // CraftBukkit
|
||||
}
|
||||
|
||||
- if (blockState.isAir() && block1 instanceof FarmBlock && owner.hasFarmSeeds()) {
|
||||
+ if (blockState.isAir() && block1 instanceof FarmBlock && !this.clericWartFarmer || this.clericWartFarmer && block1 == net.minecraft.world.level.block.Blocks.SOUL_SAND && owner.hasFarmSeeds()) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
SimpleContainer inventory = owner.getInventory();
|
||||
|
||||
for (int i = 0; i < inventory.getContainerSize(); i++) {
|
||||
ItemStack item = inventory.getItem(i);
|
||||
boolean flag = false;
|
||||
- if (!item.isEmpty() && item.is(ItemTags.VILLAGER_PLANTABLE_SEEDS) && item.getItem() instanceof BlockItem blockItem) {
|
||||
+ if (!item.isEmpty() && (item.is(ItemTags.VILLAGER_PLANTABLE_SEEDS) || this.clericWartFarmer && item.getItem() == net.minecraft.world.item.Items.NETHER_WART) && item.getItem() instanceof BlockItem blockItem) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
BlockState blockState1 = blockItem.getBlock().defaultBlockState();
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, blockState1)) { // CraftBukkit
|
||||
level.setBlockAndUpdate(this.aboveFarmlandPos, blockState1);
|
||||
@@ -136,7 +139,7 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
this.aboveFarmlandPos.getX(),
|
||||
this.aboveFarmlandPos.getY(),
|
||||
this.aboveFarmlandPos.getZ(),
|
||||
- SoundEvents.CROP_PLANTED,
|
||||
+ this.clericWartFarmer ? SoundEvents.NETHER_WART_PLANTED : SoundEvents.CROP_PLANTED, // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
SoundSource.BLOCKS,
|
||||
1.0F,
|
||||
1.0F
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java b/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java
|
||||
index 243ac036f95794e7766aefb4630b635681ae5a5f..4d8523a43d60cd6b4fd5546ffb3a61417b2c475b 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/TradeWithVillager.java
|
||||
@@ -59,6 +59,12 @@ public class TradeWithVillager extends Behavior<Villager> {
|
||||
throwHalfStack(owner, ImmutableSet.of(Items.WHEAT), villager);
|
||||
}
|
||||
|
||||
+ // Purpur start - Option for Villager Clerics to farm Nether Wart
|
||||
+ if (level.purpurConfig.villagerClericsFarmWarts && level.purpurConfig.villagerClericFarmersThrowWarts && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC && owner.getInventory().countItem(Items.NETHER_WART) > Items.NETHER_WART.getDefaultMaxStackSize() / 2) {
|
||||
+ throwHalfStack(owner, ImmutableSet.of(Items.NETHER_WART), villager);
|
||||
+ }
|
||||
+ // Purpur end - Option for Villager Clerics to farm Nether Wart
|
||||
+
|
||||
if (!this.trades.isEmpty() && owner.getInventory().hasAnyOf(this.trades)) {
|
||||
throwHalfStack(owner, this.trades, villager);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
|
||||
index 84afd8646b05409c582f29d73f9fea4b09feb603..32779b121322688a4b14e460b1f902ef67770b32 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java
|
||||
@@ -74,8 +74,13 @@ public class VillagerGoalPackages {
|
||||
}
|
||||
|
||||
public static ImmutableList<Pair<Integer, ? extends BehaviorControl<? super Villager>>> getWorkPackage(VillagerProfession profession, float speedModifier) {
|
||||
+ // Purpur start - Option for Villager Clerics to farm Nether Wart
|
||||
+ return getWorkPackage(profession, speedModifier, false);
|
||||
+ }
|
||||
+ public static ImmutableList<Pair<Integer, ? extends BehaviorControl<? super Villager>>> getWorkPackage(VillagerProfession profession, float speedModifier, boolean clericsFarmWarts) {
|
||||
+ // Purpur end - Option for Villager Clerics to farm Nether Wart
|
||||
WorkAtPoi workAtPoi;
|
||||
- if (profession == VillagerProfession.FARMER) {
|
||||
+ if (profession == VillagerProfession.FARMER || (clericsFarmWarts && profession == VillagerProfession.CLERIC)) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
workAtPoi = new WorkAtComposter();
|
||||
} else {
|
||||
workAtPoi = new WorkAtPoi();
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
index 6b99afb4f237b5d6def98f3e03492975b795bc95..234e9d4aca14bc2a2e138918be1430516d710060 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
@@ -22,6 +22,13 @@ public class SecondaryPoiSensor extends Sensor<Villager> {
|
||||
|
||||
@Override
|
||||
protected void doTick(ServerLevel level, Villager entity) {
|
||||
+ // Purpur start - Option for Villager Clerics to farm Nether Wart - make sure clerics don't wander to soul sand when the option is off
|
||||
+ Brain<?> brain = entity.getBrain();
|
||||
+ if (!level.purpurConfig.villagerClericsFarmWarts && entity.getVillagerData().getProfession() == net.minecraft.world.entity.npc.VillagerProfession.CLERIC) {
|
||||
+ brain.eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Purpur end - Option for Villager Clerics to farm Nether Wart
|
||||
ResourceKey<Level> resourceKey = level.dimension();
|
||||
BlockPos blockPos = entity.blockPosition();
|
||||
List<GlobalPos> list = Lists.newArrayList();
|
||||
@@ -38,7 +45,7 @@ public class SecondaryPoiSensor extends Sensor<Villager> {
|
||||
}
|
||||
}
|
||||
|
||||
- Brain<?> brain = entity.getBrain();
|
||||
+ //Brain<?> brain = entity.getBrain(); // Purpur - Option for Villager Clerics to farm Nether Wart - moved up
|
||||
if (!list.isEmpty()) {
|
||||
brain.setMemory(MemoryModuleType.SECONDARY_JOB_SITE, list);
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
||||
index ff07cfe07200be23f17310522d737fca3251a580..017b54e0b8dec8996c90a3c6651867277dd516df 100644
|
||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -311,7 +311,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
villagerBrain.setSchedule(Schedule.VILLAGER_DEFAULT);
|
||||
villagerBrain.addActivityWithConditions(
|
||||
Activity.WORK,
|
||||
- VillagerGoalPackages.getWorkPackage(profession, 0.5F),
|
||||
+ VillagerGoalPackages.getWorkPackage(profession, 0.5F, this.level().purpurConfig.villagerClericsFarmWarts), // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))
|
||||
);
|
||||
}
|
||||
@@ -977,7 +977,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
}
|
||||
|
||||
public boolean hasFarmSeeds() {
|
||||
- return this.getInventory().hasAnyMatching(itemStack -> itemStack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS));
|
||||
+ return this.getInventory().hasAnyMatching(itemStack -> this.level().purpurConfig.villagerClericsFarmWarts && this.getVillagerData().getProfession() == VillagerProfession.CLERIC ? itemStack.is(Items.NETHER_WART) : itemStack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/npc/VillagerProfession.java b/net/minecraft/world/entity/npc/VillagerProfession.java
|
||||
index 1ec8ad124c76483d11057eb97fcfb9aebee0c301..f783d058a080408d572938d36ba031f33a08e9af 100644
|
||||
--- a/net/minecraft/world/entity/npc/VillagerProfession.java
|
||||
+++ b/net/minecraft/world/entity/npc/VillagerProfession.java
|
||||
@@ -31,7 +31,7 @@ public record VillagerProfession(
|
||||
public static final VillagerProfession ARMORER = register("armorer", PoiTypes.ARMORER, SoundEvents.VILLAGER_WORK_ARMORER);
|
||||
public static final VillagerProfession BUTCHER = register("butcher", PoiTypes.BUTCHER, SoundEvents.VILLAGER_WORK_BUTCHER);
|
||||
public static final VillagerProfession CARTOGRAPHER = register("cartographer", PoiTypes.CARTOGRAPHER, SoundEvents.VILLAGER_WORK_CARTOGRAPHER);
|
||||
- public static final VillagerProfession CLERIC = register("cleric", PoiTypes.CLERIC, SoundEvents.VILLAGER_WORK_CLERIC);
|
||||
+ public static final VillagerProfession CLERIC = register("cleric", PoiTypes.CLERIC, ImmutableSet.of(Items.NETHER_WART), ImmutableSet.of(Blocks.SOUL_SAND), SoundEvents.VILLAGER_WORK_CLERIC); // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
public static final VillagerProfession FARMER = register(
|
||||
"farmer",
|
||||
PoiTypes.FARMER,
|
||||
@@ -0,0 +1,360 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Encode42 <me@encode42.dev>
|
||||
Date: Tue, 5 Jan 2021 22:21:56 -0500
|
||||
Subject: [PATCH] Add mobGriefing bypass to everything affected
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 6de5f527c018201d874e06a45c9509fa12125766..2dc588e2d503c16ccd2589ce18abd2ecebbc8e74 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1818,7 +1818,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
boolean var6 = false;
|
||||
if (this.dead && entitySource instanceof WitherBoss) { // Paper
|
||||
- if (serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (serverLevel.purpurConfig.witherBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
BlockPos blockPos = this.blockPosition();
|
||||
BlockState blockState = Blocks.WITHER_ROSE.defaultBlockState();
|
||||
if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) {
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index c431f28c3f4f6cec946048f5752c364429af5ba1..d93584c6793818463e8883ffe399bf16b03263a9 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -648,7 +648,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
&& this.canPickUpLoot()
|
||||
&& this.isAlive()
|
||||
&& !this.dead
|
||||
- && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ && serverLevel.purpurConfig.entitiesPickUpLootBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
Vec3i pickupReach = this.getPickupReach();
|
||||
|
||||
for (ItemEntity itemEntity : this.level()
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
index e98fac58b29f78cb63bd868811cca41e1644e9ac..56d49bc71cb0cb0a08ff771991fd77ab774b4b59 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java
|
||||
@@ -49,7 +49,7 @@ public class HarvestFarmland extends Behavior<Villager> {
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) {
|
||||
- if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (!level.purpurConfig.villagerBypassMobGriefing == !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
return false;
|
||||
} else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER && !(level.purpurConfig.villagerClericsFarmWarts && owner.getVillagerData().getProfession() == VillagerProfession.CLERIC)) { // Purpur - Option for Villager Clerics to farm Nether Wart
|
||||
return false;
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
index e026e07ca86700c864a3dceda6817fb7b6cb11e9..f1dfe0bf047e7d331b2379a672ff7b8eae4c9c90 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
|
||||
@@ -30,7 +30,7 @@ public class BreakDoorGoal extends DoorInteractGoal {
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return super.canUse()
|
||||
- && getServerLevel(this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)
|
||||
+ && this.mob.level().purpurConfig.zombieBypassMobGriefing == !getServerLevel(this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) // Purpur - Add mobGriefing bypass to everything affected
|
||||
&& this.isValidDifficulty(this.mob.level().getDifficulty())
|
||||
&& !this.isOpen();
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
index e84893780b533b1ecb3675606b5c2daf7339b861..65eb4d8001b07cb3f7cda17565eea10a88a9c47c 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
|
||||
@@ -67,7 +67,7 @@ public class EatBlockGoal extends Goal {
|
||||
BlockPos blockPos = this.mob.blockPosition();
|
||||
final BlockState blockState = this.level.getBlockState(blockPos); // Paper - fix wrong block state
|
||||
if (IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).purpurConfig.sheepBypassMobGriefing == !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state // Purpur - Add mobGriefing bypass to everything affected
|
||||
this.level.destroyBlock(blockPos, false);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class EatBlockGoal extends Goal {
|
||||
} else {
|
||||
BlockPos blockPos1 = blockPos.below();
|
||||
if (this.level.getBlockState(blockPos1).is(Blocks.GRASS_BLOCK)) {
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockPos1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).purpurConfig.sheepBypassMobGriefing == !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state // Purpur - Add mobGriefing bypass to everything affected
|
||||
this.level.levelEvent(2001, blockPos1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState()));
|
||||
this.level.setBlock(blockPos1, Blocks.DIRT.defaultBlockState(), 2);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
index 579ca031d461ed4327fe4fb45c5289565322e64e..95fa516910a3834bbd4db6d11279e13a1f0dac41 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
@@ -35,7 +35,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
- if (!getServerLevel(this.removerMob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (!getServerLevel(this.removerMob).purpurConfig.zombieBypassMobGriefing == !getServerLevel(this.removerMob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
return false;
|
||||
} else if (this.nextStartTick > 0) {
|
||||
this.nextStartTick--;
|
||||
diff --git a/net/minecraft/world/entity/animal/Fox.java b/net/minecraft/world/entity/animal/Fox.java
|
||||
index 1acf9b8c9e6a5915b3f095e83d3f209708947093..3d94d5c9ecab0fe7332daf4cdac879385159eaa1 100644
|
||||
--- a/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -1038,7 +1038,7 @@ public class Fox extends Animal implements VariantHolder<Fox.Variant> {
|
||||
}
|
||||
|
||||
protected void onReachedTarget() {
|
||||
- if (getServerLevel(Fox.this.level()).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (getServerLevel(Fox.this.level()).purpurConfig.foxBypassMobGriefing ^ getServerLevel(Fox.this.level()).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
BlockState blockState = Fox.this.level().getBlockState(this.blockPos);
|
||||
if (blockState.is(Blocks.SWEET_BERRY_BUSH)) {
|
||||
this.pickSweetBerries(blockState);
|
||||
diff --git a/net/minecraft/world/entity/animal/Rabbit.java b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
index bbdd06002b07699fffebdf6ed8148abdb69c24cc..7379def14f3f700fb8a746dc89d89e249e93b7b9 100644
|
||||
--- a/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -620,7 +620,7 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
if (this.nextStartTick <= 0) {
|
||||
- if (!getServerLevel(this.rabbit).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (!getServerLevel(this.rabbit).purpurConfig.rabbitBypassMobGriefing == !getServerLevel(this.rabbit).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/animal/SnowGolem.java b/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
index d97a297db3bec0c86c6a82ef1c353015df2115f7..6ee73b798ab306f7c828c9f06ca5b1a96bd96139 100644
|
||||
--- a/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
@@ -136,7 +136,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
||||
this.hurtServer(serverLevel, this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING
|
||||
}
|
||||
|
||||
- if (!serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (!serverLevel.purpurConfig.snowGolemBypassMobGriefing == !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index ca900bb646e16c7b4342f23c3ffae786eab28145..724d259d4b793f2043e63dda9022bdfddc4dca38 100644
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -547,7 +547,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
BlockPos blockPos = new BlockPos(i, i1, i2);
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) {
|
||||
- if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) {
|
||||
+ if (level.purpurConfig.enderDragonBypassMobGriefing ^ level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
// CraftBukkit start - Add blocks to list rather than destroying them
|
||||
//flag1 = level.removeBlock(blockPos, false) || flag1;
|
||||
flag1 = true;
|
||||
diff --git a/net/minecraft/world/entity/boss/wither/WitherBoss.java b/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
index 60e666aa8afe14b519010b6d137a89e3d22f6c81..a325fa87e149e7f354ed4cf3dbb30a002c4ce32a 100644
|
||||
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -493,7 +493,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
||||
|
||||
if (this.destroyBlocksTick > 0) {
|
||||
this.destroyBlocksTick--;
|
||||
- if (this.destroyBlocksTick == 0 && level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (this.destroyBlocksTick == 0 && level.purpurConfig.witherBypassMobGriefing ^ level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
boolean flag = false;
|
||||
int alternativeTarget = Mth.floor(this.getBbWidth() / 2.0F + 1.0F);
|
||||
int floor = Mth.floor(this.getBbHeight());
|
||||
diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java
|
||||
index f8d6935439b4e672ed655b2a458451d4b1fa8ffd..7b74322aef3d7d45a322abccc71d9168b3c0911b 100644
|
||||
--- a/net/minecraft/world/entity/monster/EnderMan.java
|
||||
+++ b/net/minecraft/world/entity/monster/EnderMan.java
|
||||
@@ -516,7 +516,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
public boolean canUse() {
|
||||
if (!enderman.level().purpurConfig.endermanAllowGriefing) return false; // Purpur - Add enderman and creeper griefing controls
|
||||
return this.enderman.getCarriedBlock() != null
|
||||
- && getServerLevel(this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)
|
||||
+ && getServerLevel(this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) == !this.enderman.level().purpurConfig.endermanBypassMobGriefing // Purpur - Add mobGriefing bypass to everything affected
|
||||
&& this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0;
|
||||
}
|
||||
|
||||
@@ -666,7 +666,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
public boolean canUse() {
|
||||
if (!enderman.level().purpurConfig.endermanAllowGriefing) return false; // Purpur - Add enderman and creeper griefing controls
|
||||
return this.enderman.getCarriedBlock() == null
|
||||
- && getServerLevel(this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)
|
||||
+ && getServerLevel(this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) == !this.enderman.level().purpurConfig.endermanBypassMobGriefing // Purpur - Add mobGriefing bypass to everything affected
|
||||
&& this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Evoker.java b/net/minecraft/world/entity/monster/Evoker.java
|
||||
index d3d7e11a12af404d83e81888a9a633dfb93412ec..91574baf7ca095eae909e8e7225ad500bde15af2 100644
|
||||
--- a/net/minecraft/world/entity/monster/Evoker.java
|
||||
+++ b/net/minecraft/world/entity/monster/Evoker.java
|
||||
@@ -323,7 +323,7 @@ public class Evoker extends SpellcasterIllager {
|
||||
return false;
|
||||
} else {
|
||||
ServerLevel serverLevel = getServerLevel(Evoker.this.level());
|
||||
- if (!serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ if (!serverLevel.purpurConfig.evokerBypassMobGriefing == !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
return false;
|
||||
} else {
|
||||
List<Sheep> nearbyEntities = serverLevel.getNearbyEntities(
|
||||
diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java
|
||||
index 36ebfc1102a18e4050eb9a2441d75bafcf3784b8..3449628fb87fd760abd730d84699c3a09c6ec761 100644
|
||||
--- a/net/minecraft/world/entity/monster/Ravager.java
|
||||
+++ b/net/minecraft/world/entity/monster/Ravager.java
|
||||
@@ -175,7 +175,7 @@ public class Ravager extends Raider {
|
||||
|
||||
if (this.level() instanceof ServerLevel serverLevel
|
||||
&& this.horizontalCollision
|
||||
- && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
||||
+ && serverLevel.purpurConfig.ravagerBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
boolean flag = false;
|
||||
AABB aabb = this.getBoundingBox().inflate(0.2);
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Silverfish.java b/net/minecraft/world/entity/monster/Silverfish.java
|
||||
index d3befe91bc65bbc2bc0d8651b78e8c9576cd0f75..0d3b8b64a23a19d67a1a4a01faaf6649a59f54ad 100644
|
||||
--- a/net/minecraft/world/entity/monster/Silverfish.java
|
||||
+++ b/net/minecraft/world/entity/monster/Silverfish.java
|
||||
@@ -170,7 +170,7 @@ public class Silverfish extends Monster {
|
||||
return false;
|
||||
} else {
|
||||
RandomSource random = this.mob.getRandom();
|
||||
- if (getServerLevel(this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && random.nextInt(reducedTickDelay(10)) == 0) {
|
||||
+ if (getServerLevel(this.mob).purpurConfig.silverfishBypassMobGriefing ^ getServerLevel(this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && random.nextInt(reducedTickDelay(10)) == 0) { // Purpur - Add mobGriefing bypass to everything affected
|
||||
this.selectedDirection = Direction.getRandom(random);
|
||||
BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection);
|
||||
BlockState blockState = this.mob.level().getBlockState(blockPos);
|
||||
@@ -247,7 +247,7 @@ public class Silverfish extends Monster {
|
||||
Block block = blockState.getBlock();
|
||||
if (block instanceof InfestedBlock) {
|
||||
// CraftBukkit start
|
||||
- BlockState afterState = getServerLevel(level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? blockState.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(level.getBlockState(blockPos1)); // Paper - fix wrong block state
|
||||
+ BlockState afterState = getServerLevel(level).purpurConfig.silverfishBypassMobGriefing ^ getServerLevel(level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? blockState.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(level.getBlockState(blockPos1)); // Paper - fix wrong block state // Purpur - Add mobGriefing bypass to everything affected
|
||||
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockPos1, afterState)) { // Paper - fix wrong block state
|
||||
continue;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
index 897c57263ab7347987b289016a71d11f693bc8b2..d923a424e2b33b7d4e9e4ecdce8e0a8c825038de 100644
|
||||
--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
@@ -473,7 +473,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
||||
|
||||
@Override
|
||||
public boolean wantsToPickUp(ServerLevel level, ItemStack stack) {
|
||||
- return level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack);
|
||||
+ return level.purpurConfig.piglinBypassMobGriefing ^ level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); // Purpur - Add mobGriefing bypass to everything affected
|
||||
}
|
||||
|
||||
protected boolean canReplaceCurrentItem(ItemStack candidate) {
|
||||
diff --git a/net/minecraft/world/entity/projectile/LargeFireball.java b/net/minecraft/world/entity/projectile/LargeFireball.java
|
||||
index 4a752ace041228f095af7b1b4878a03c5ed2381f..3e8b5d042eddb817dee2504ff9aa263f6195b1c7 100644
|
||||
--- a/net/minecraft/world/entity/projectile/LargeFireball.java
|
||||
+++ b/net/minecraft/world/entity/projectile/LargeFireball.java
|
||||
@@ -18,20 +18,20 @@ public class LargeFireball extends Fireball {
|
||||
|
||||
public LargeFireball(EntityType<? extends LargeFireball> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
- this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit
|
||||
+ this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.purpurConfig.fireballsBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit // Purpur - Add mobGriefing bypass to everything affected
|
||||
}
|
||||
|
||||
public LargeFireball(Level level, LivingEntity owner, Vec3 movement, int explosionPower) {
|
||||
super(EntityType.FIREBALL, owner, movement, level);
|
||||
this.explosionPower = explosionPower;
|
||||
- this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit
|
||||
+ this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.purpurConfig.fireballsBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit // Purpur - Add mobGriefing bypass to everything affected
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHit(HitResult result) {
|
||||
super.onHit(result);
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
- boolean _boolean = serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
+ boolean _boolean = serverLevel.purpurConfig.fireballsBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur - Add mobGriefing bypass to everything affected
|
||||
// CraftBukkit start - fire ExplosionPrimeEvent
|
||||
org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
|
||||
this.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index ad0bb896d6ea669ce88bfe6490319e8ba7a29001..843f1396a6567672e5e8002d7e48fb18cf39d5de 100644
|
||||
--- a/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -454,7 +454,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
@Override
|
||||
public boolean mayInteract(ServerLevel level, BlockPos pos) {
|
||||
Entity owner = this.getOwner();
|
||||
- return owner instanceof Player ? owner.mayInteract(level, pos) : owner == null || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
+ return owner instanceof Player ? owner.mayInteract(level, pos) : owner == null || level.purpurConfig.projectilesBypassMobGriefing ^ level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur - Add mobGriefing bypass to everything affected
|
||||
}
|
||||
|
||||
public boolean mayBreak(ServerLevel level) {
|
||||
diff --git a/net/minecraft/world/entity/projectile/SmallFireball.java b/net/minecraft/world/entity/projectile/SmallFireball.java
|
||||
index 8c84cea43fc0e42a576004663670977eac99f1a6..808aa5dcb27c87b6ba5c1eee639486067447e370 100644
|
||||
--- a/net/minecraft/world/entity/projectile/SmallFireball.java
|
||||
+++ b/net/minecraft/world/entity/projectile/SmallFireball.java
|
||||
@@ -25,7 +25,7 @@ public class SmallFireball extends Fireball {
|
||||
super(EntityType.SMALL_FIREBALL, owner, movement, level);
|
||||
// CraftBukkit start
|
||||
if (this.getOwner() != null && this.getOwner() instanceof Mob) {
|
||||
- this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
+ this.isIncendiary = (level instanceof ServerLevel serverLevel) && serverLevel.purpurConfig.fireballsBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur - Add mobGriefing bypass to everything affected
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index 8270d76a753bfd26a4c8ef6610bee5c24ee59cfe..c06b589e669b055a26f662df60070d5908256220 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -399,7 +399,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
}
|
||||
|
||||
private boolean cannotPickUpBanner() {
|
||||
- if (!getServerLevel(this.mob).getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items
|
||||
+ if (!this.mob.level().purpurConfig.pillagerBypassMobGriefing == !getServerLevel(this.mob).getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur - Add mobGriefing bypass to everything affected
|
||||
if (!this.mob.hasActiveRaid()) {
|
||||
return true;
|
||||
} else if (this.mob.getCurrentRaid().isOver()) {
|
||||
diff --git a/net/minecraft/world/level/block/CropBlock.java b/net/minecraft/world/level/block/CropBlock.java
|
||||
index b43f16297ac4441d78d0dc1fadb555698b0c3f6d..27f0c5c886a3f8b14ef9a00e2aaaabf4bf09c7db 100644
|
||||
--- a/net/minecraft/world/level/block/CropBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CropBlock.java
|
||||
@@ -182,7 +182,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock {
|
||||
@Override
|
||||
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
|
||||
- if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.purpurConfig.ravagerGriefableBlocks.contains(serverLevel.getBlockState(pos).getBlock()) && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Purpur - Configurable ravager griefable blocks list
|
||||
+ if (level instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.purpurConfig.ravagerGriefableBlocks.contains(serverLevel.getBlockState(pos).getBlock()) && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !serverLevel.purpurConfig.ravagerBypassMobGriefing == !serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Purpur - Configurable ravager griefable blocks list // Purpur - Add mobGriefing bypass to everything affected
|
||||
serverLevel.destroyBlock(pos, true, entity);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/FarmBlock.java b/net/minecraft/world/level/block/FarmBlock.java
|
||||
index 6ab9a1188ce60e114ef35e393d9f2f46d490af83..9a7ca836e54cc3f58001c85f0079747f4d4941ad 100644
|
||||
--- a/net/minecraft/world/level/block/FarmBlock.java
|
||||
+++ b/net/minecraft/world/level/block/FarmBlock.java
|
||||
@@ -114,7 +114,7 @@ public class FarmBlock extends Block {
|
||||
if (level instanceof ServerLevel serverLevel
|
||||
&& (serverLevel.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= serverLevel.purpurConfig.farmlandTrampleHeight : level.random.nextFloat() < fallDistance - 0.5F) // // Purpur - Configurable farmland trample height
|
||||
&& entity instanceof LivingEntity
|
||||
- && (entity instanceof Player || serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))
|
||||
+ && (entity instanceof Player || serverLevel.purpurConfig.farmlandBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))
|
||||
&& entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) {
|
||||
// CraftBukkit start - Interact soil
|
||||
org.bukkit.event.Cancellable cancellable;
|
||||
diff --git a/net/minecraft/world/level/block/PowderSnowBlock.java b/net/minecraft/world/level/block/PowderSnowBlock.java
|
||||
index 9c0ded7ae7e3a520704033a866f80743ae85d772..4f3646961beb877520e257e11224c3045467d351 100644
|
||||
--- a/net/minecraft/world/level/block/PowderSnowBlock.java
|
||||
+++ b/net/minecraft/world/level/block/PowderSnowBlock.java
|
||||
@@ -84,7 +84,7 @@ public class PowderSnowBlock extends Block implements BucketPickup {
|
||||
// CraftBukkit - move down
|
||||
&& entity.mayInteract(serverLevel, pos)) {
|
||||
// CraftBukkit start
|
||||
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) {
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(serverLevel.purpurConfig.powderSnowBypassMobGriefing ^ serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/net/minecraft/world/level/block/TurtleEggBlock.java b/net/minecraft/world/level/block/TurtleEggBlock.java
|
||||
index c97d5bd7b4c1b6f8eccbe2d123292e913a285ef2..a3a093d95306baac22e5cf720f5b14f733b548d4 100644
|
||||
--- a/net/minecraft/world/level/block/TurtleEggBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TurtleEggBlock.java
|
||||
@@ -216,7 +216,7 @@ public class TurtleEggBlock extends Block {
|
||||
// Purpur end - Option to disable turtle egg trampling with feather falling
|
||||
if (entity instanceof Player) return true;
|
||||
|
||||
- return level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
+ return level.purpurConfig.turtleEggsBypassMobGriefing ^ level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur - Add mobGriefing bypass to everything affected
|
||||
// Purpur end - Add turtle egg block options
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Sat, 9 Jan 2021 15:26:04 +0100
|
||||
Subject: [PATCH] Add EntityTeleportHinderedEvent
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/EndGatewayBlock.java b/net/minecraft/world/level/block/EndGatewayBlock.java
|
||||
index 84a1bd5e40e635962d795506861447851e443eee..54abeb142e119edd1c1d1c263821b95b1f05c388 100644
|
||||
--- a/net/minecraft/world/level/block/EndGatewayBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EndGatewayBlock.java
|
||||
@@ -98,6 +98,13 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal {
|
||||
org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type
|
||||
if (!event.callEvent()) return;
|
||||
// Paper end - call EntityPortalEnterEvent
|
||||
+ // Purpur start - Add EntityTeleportHinderedEvent
|
||||
+ if (level.purpurConfig.imposeTeleportRestrictionsOnGateways && (entity.isVehicle() || entity.isPassenger())) {
|
||||
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_GATEWAY).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Add EntityTeleportHinderedEvent
|
||||
entity.setAsInsidePortal(this, pos);
|
||||
TheEndGatewayBlockEntity.triggerCooldown(level, pos, state, theEndGatewayBlockEntity);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
index 01cddd7001b4a7f99c1b1d147fac904d3064d733..7e60bcadd2d343e00fc554dba0b85c9191f7efb6 100644
|
||||
--- a/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
@@ -58,6 +58,13 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
|
||||
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
|
||||
if (entity.canUsePortal(false)) {
|
||||
+ // Purpur start - Add EntityTeleportHinderedEvent
|
||||
+ if (level.purpurConfig.imposeTeleportRestrictionsOnEndPortals && (entity.isVehicle() || entity.isPassenger())) {
|
||||
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Add EntityTeleportHinderedEvent
|
||||
// CraftBukkit start - Entity in portal
|
||||
org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type
|
||||
level.getCraftServer().getPluginManager().callEvent(event);
|
||||
diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
index 006444811c00a8820bddaf75950e794271efdd82..eb659209008209c0930770e5f9671a3d7a4abae6 100644
|
||||
--- a/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
+++ b/net/minecraft/world/level/block/NetherPortalBlock.java
|
||||
@@ -117,6 +117,13 @@ public class NetherPortalBlock extends Block implements Portal {
|
||||
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
|
||||
if (entity.canUsePortal(false)) {
|
||||
+ // Purpur start - Add EntityTeleportHinderedEvent
|
||||
+ if (level.purpurConfig.imposeTeleportRestrictionsOnNetherPortals && (entity.isVehicle() || entity.isPassenger())) {
|
||||
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.NETHER_PORTAL).callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Add EntityTeleportHinderedEvent
|
||||
// CraftBukkit start - Entity in portal
|
||||
org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type
|
||||
level.getCraftServer().getPluginManager().callEvent(event);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Kerllenevich <ben@omega24.dev>
|
||||
Date: Tue, 25 May 2021 16:31:09 -0400
|
||||
Subject: [PATCH] API for any mob to burn daylight
|
||||
|
||||
Co-authored by: Encode42 <me@encode42.dev>
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 62a38ecedbd579b32a8fd9cff5a433bfe635fc62..8473a7d9af9d83e97387ddf4cc50f6ad22730def 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -530,6 +530,24 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
// Purpur end - Add canSaveToDisk to Entity
|
||||
|
||||
+ // Purpur start - copied from Mob - API for any mob to burn daylight
|
||||
+ public boolean isSunBurnTick() {
|
||||
+ if (this.level().isDay() && !this.level().isClientSide) {
|
||||
+ float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue();
|
||||
+ BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
|
||||
+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow;
|
||||
+ if (lightLevelDependentMagicValue > 0.5F
|
||||
+ && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F
|
||||
+ && !flag
|
||||
+ && this.level().canSeeSky(blockPos)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Purpur end - copied from Mob - API for any mob to burn daylight
|
||||
+
|
||||
public Entity(EntityType<?> entityType, Level level) {
|
||||
this.type = entityType;
|
||||
this.level = level;
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 2dc588e2d503c16ccd2589ce18abd2ecebbc8e74..db5a2227009bc4d655fc781d5850221f36f2d112 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -301,6 +301,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
|
||||
public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
|
||||
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
|
||||
+ protected boolean shouldBurnInDay = false; public boolean shouldBurnInDay() { return this.shouldBurnInDay; } public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Purpur - API for any mob to burn daylight
|
||||
|
||||
@Override
|
||||
public float getBukkitYaw() {
|
||||
@@ -809,6 +810,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
});
|
||||
DataResult<Tag> dataResult = this.brain.serializeStart(NbtOps.INSTANCE);
|
||||
dataResult.resultOrPartial(LOGGER::error).ifPresent(brain -> compound.put("Brain", brain));
|
||||
+ compound.putBoolean("Purpur.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -892,6 +894,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (compound.contains("Brain", 10)) {
|
||||
this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compound.get("Brain")));
|
||||
}
|
||||
+
|
||||
+ // Purpur start - API for any mob to burn daylight
|
||||
+ if (compound.contains("Purpur.ShouldBurnInDay")) {
|
||||
+ this.shouldBurnInDay = compound.getBoolean("Purpur.ShouldBurnInDay");
|
||||
+ }
|
||||
+ // Purpur end - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -3574,6 +3582,32 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) {
|
||||
this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F);
|
||||
}
|
||||
+
|
||||
+ // Purpur start - copied from Zombie - API for any mob to burn daylight
|
||||
+ if (this.isAlive()) {
|
||||
+ boolean flag = this.shouldBurnInDay() && this.isSunBurnTick(); // Paper - shouldBurnInDay API // Purpur - use shouldBurnInDay() method to handle Phantoms properly - API for any mob to burn daylight
|
||||
+ if (flag) {
|
||||
+ ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
+ if (!itemBySlot.isEmpty()) {
|
||||
+ if (itemBySlot.isDamageableItem()) {
|
||||
+ Item item = itemBySlot.getItem();
|
||||
+ itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2));
|
||||
+ if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) {
|
||||
+ this.onEquippedItemBroken(item, EquipmentSlot.HEAD);
|
||||
+ this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ flag = false;
|
||||
+ }
|
||||
+
|
||||
+ if (flag) {
|
||||
+ if (getRider() == null || !this.isControllable()) // Purpur - ignore mobs which are uncontrollable or without rider - API for any mob to burn daylight
|
||||
+ this.igniteForSeconds(8.0F);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - copied from Zombie - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
public boolean isSensitiveToWater() {
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index d93584c6793818463e8883ffe399bf16b03263a9..70ee86993d381445855ac7e7290da384d6675987 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -1655,19 +1655,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
}
|
||||
|
||||
public boolean isSunBurnTick() {
|
||||
- if (this.level().isDay() && !this.level().isClientSide) {
|
||||
- float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue();
|
||||
- BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ());
|
||||
- boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow;
|
||||
- if (lightLevelDependentMagicValue > 0.5F
|
||||
- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F
|
||||
- && !flag
|
||||
- && this.level().canSeeSky(blockPos)) {
|
||||
- return true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ // Purpur - implemented in Entity - API for any mob to burn daylight
|
||||
+ return super.isSunBurnTick();
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/AbstractSkeleton.java b/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
index e186aee80b052b7fc4bfe02763010bfb2d55ea35..223739818e9ac6c9fe396b82bce53a3ab029610a 100644
|
||||
--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
+++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
@@ -64,11 +64,12 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
AbstractSkeleton.this.setAggressive(true);
|
||||
}
|
||||
};
|
||||
- private boolean shouldBurnInDay = true; // Paper - shouldBurnInDay API
|
||||
+ //private boolean shouldBurnInDay = true; // Paper - shouldBurnInDay API // Purpur - moved to LivingEntity; keep methods for ABI compatibility - API for any mob to burn daylight
|
||||
|
||||
protected AbstractSkeleton(EntityType<? extends AbstractSkeleton> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.reassessWeaponGoal();
|
||||
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,27 +111,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
|
||||
@Override
|
||||
public void aiStep() {
|
||||
- boolean isSunBurnTick = this.shouldBurnInDay && this.isSunBurnTick(); // Paper - shouldBurnInDay API
|
||||
- if (isSunBurnTick) {
|
||||
- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
- if (!itemBySlot.isEmpty()) {
|
||||
- if (itemBySlot.isDamageableItem()) {
|
||||
- Item item = itemBySlot.getItem();
|
||||
- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2));
|
||||
- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) {
|
||||
- this.onEquippedItemBroken(item, EquipmentSlot.HEAD);
|
||||
- this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- isSunBurnTick = false;
|
||||
- }
|
||||
-
|
||||
- if (isSunBurnTick) {
|
||||
- this.igniteForSeconds(8.0F);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
+ // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
@@ -243,7 +224,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
super.readAdditionalSaveData(compound);
|
||||
this.reassessWeaponGoal();
|
||||
// Paper start - shouldBurnInDay API
|
||||
- if (compound.contains("Paper.ShouldBurnInDay")) {
|
||||
+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
|
||||
}
|
||||
// Paper end - shouldBurnInDay API
|
||||
@@ -252,7 +233,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
@Override
|
||||
public void addAdditionalSaveData(final net.minecraft.nbt.CompoundTag nbt) {
|
||||
super.addAdditionalSaveData(nbt);
|
||||
- nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
|
||||
+ //nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
}
|
||||
// Paper end - shouldBurnInDay API
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Husk.java b/net/minecraft/world/entity/monster/Husk.java
|
||||
index 31eef2869945d9de565d627cac3fc1a5db380a2a..e618e716cb5ff3a3c5d284e985455694cc0edde0 100644
|
||||
--- a/net/minecraft/world/entity/monster/Husk.java
|
||||
+++ b/net/minecraft/world/entity/monster/Husk.java
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.world.level.ServerLevelAccessor;
|
||||
public class Husk extends Zombie {
|
||||
public Husk(EntityType<? extends Husk> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
+ this.setShouldBurnInDay(false); // Purpur - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
// Purpur start - Ridables
|
||||
@@ -82,7 +83,7 @@ public class Husk extends Zombie {
|
||||
|
||||
@Override
|
||||
public boolean isSunSensitive() {
|
||||
- return false;
|
||||
+ return this.shouldBurnInDay; // Purpur - moved to LivingEntity; keep methods for ABI compatibility - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
|
||||
index 32b7c34d3c68dcfa936b628b2d038524204129a3..0ee817699fffbb929011465029182cc56befc30c 100644
|
||||
--- a/net/minecraft/world/entity/monster/Phantom.java
|
||||
+++ b/net/minecraft/world/entity/monster/Phantom.java
|
||||
@@ -60,6 +60,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
this.xpReward = 5;
|
||||
this.moveControl = new Phantom.PhantomMoveControl(this);
|
||||
this.lookControl = new Phantom.PhantomLookControl(this);
|
||||
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
// Purpur start - Ridables
|
||||
@@ -146,6 +147,16 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
}
|
||||
// Purpur end - Toggle for water sensitive mob damage
|
||||
|
||||
+ //private boolean shouldBurnInDay = true; // Purpur - moved to LivingEntity; keep methods for ABI compatibility - API for any mob to burn daylight
|
||||
+ // Purpur start - API for any mob to burn daylight
|
||||
+ public boolean shouldBurnInDay() {
|
||||
+ boolean burnFromDaylight = this.shouldBurnInDay && this.level().purpurConfig.phantomBurnInDaylight;
|
||||
+ boolean burnFromLightSource = this.level().purpurConfig.phantomBurnInLight > 0 && this.level().getMaxLocalRawBrightness(blockPosition()) >= this.level().purpurConfig.phantomBurnInLight;
|
||||
+ return burnFromDaylight || burnFromLightSource;
|
||||
+ }
|
||||
+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; }
|
||||
+ // Purpur end - API for any mob to burn daylight
|
||||
+
|
||||
@Override
|
||||
public boolean isFlapping() {
|
||||
return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0;
|
||||
@@ -261,6 +272,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public void aiStep() {
|
||||
+ // Purpur - implemented in LivingEntity; moved down to shouldBurnInDay() - API for any mob to burn daylight
|
||||
// Purpur start - Phantoms burn in light
|
||||
boolean burnFromDaylight = this.shouldBurnInDay && this.isSunBurnTick() && this.level().purpurConfig.phantomBurnInDaylight;
|
||||
boolean burnFromLightSource = this.level().purpurConfig.phantomBurnInLight > 0 && this.level().getMaxLocalRawBrightness(blockPosition()) >= this.level().purpurConfig.phantomBurnInLight;
|
||||
@@ -299,7 +311,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
if (compound.hasUUID("Paper.SpawningEntity")) {
|
||||
this.spawningEntity = compound.getUUID("Paper.SpawningEntity");
|
||||
}
|
||||
- if (compound.contains("Paper.ShouldBurnInDay")) {
|
||||
+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
|
||||
}
|
||||
// Paper end
|
||||
@@ -316,7 +328,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
||||
if (this.spawningEntity != null) {
|
||||
compound.putUUID("Paper.SpawningEntity", this.spawningEntity);
|
||||
}
|
||||
- compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay);
|
||||
+ //compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
// Paper end
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
|
||||
index bb8c37c8348172947efe14d48ed9ae203409affa..b1da45df27f02395d793e7eafe576f5f92aa3a7b 100644
|
||||
--- a/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -89,11 +89,12 @@ public class Zombie extends Monster {
|
||||
private boolean canBreakDoors;
|
||||
private int inWaterTime;
|
||||
public int conversionTime;
|
||||
- private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
|
||||
+ //private boolean shouldBurnInDay = true; // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
|
||||
public Zombie(EntityType<? extends Zombie> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(level.paperConfig().entities.behavior.doorBreakingDifficulty.getOrDefault(entityType, level.paperConfig().entities.behavior.doorBreakingDifficulty.get(EntityType.ZOMBIE)))); // Paper - Configurable door breaking difficulty
|
||||
+ this.setShouldBurnInDay(true); // Purpur - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
public Zombie(Level level) {
|
||||
@@ -290,29 +291,7 @@ public class Zombie extends Monster {
|
||||
|
||||
@Override
|
||||
public void aiStep() {
|
||||
- if (this.isAlive()) {
|
||||
- boolean flag = this.isSunSensitive() && this.isSunBurnTick();
|
||||
- if (flag) {
|
||||
- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
- if (!itemBySlot.isEmpty()) {
|
||||
- if (itemBySlot.isDamageableItem()) {
|
||||
- Item item = itemBySlot.getItem();
|
||||
- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2));
|
||||
- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) {
|
||||
- this.onEquippedItemBroken(item, EquipmentSlot.HEAD);
|
||||
- this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- flag = false;
|
||||
- }
|
||||
-
|
||||
- if (flag) {
|
||||
- this.igniteForSeconds(8.0F);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
+ // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
super.aiStep();
|
||||
}
|
||||
|
||||
@@ -371,6 +350,7 @@ public class Zombie extends Monster {
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ public boolean shouldBurnInDay() { return this.isSunSensitive(); } // Purpur - for ABI compatibility - API for any mob to burn daylight
|
||||
public boolean isSunSensitive() {
|
||||
return this.shouldBurnInDay; // Paper - Add more Zombie API
|
||||
}
|
||||
@@ -509,7 +489,7 @@ public class Zombie extends Monster {
|
||||
compound.putBoolean("CanBreakDoors", this.canBreakDoors());
|
||||
compound.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1);
|
||||
compound.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1);
|
||||
- compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API
|
||||
+ //compound.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); // Paper - Add more Zombie API // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -522,7 +502,7 @@ public class Zombie extends Monster {
|
||||
this.startUnderWaterConversion(compound.getInt("DrownedConversionTime"));
|
||||
}
|
||||
// Paper start - Add more Zombie API
|
||||
- if (compound.contains("Paper.ShouldBurnInDay")) {
|
||||
+ if (false && compound.contains("Paper.ShouldBurnInDay")) { // Purpur - implemented in LivingEntity - API for any mob to burn daylight
|
||||
this.shouldBurnInDay = compound.getBoolean("Paper.ShouldBurnInDay");
|
||||
}
|
||||
// Paper end - Add more Zombie API
|
||||
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Mon, 30 Aug 2021 22:49:53 -0500
|
||||
Subject: [PATCH] Cows naturally aggressive to players chance
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/animal/Cow.java b/net/minecraft/world/entity/animal/Cow.java
|
||||
index a8c76fcbbaa4afd2d0bd568874995b91d8d67c03..b62c4449047da36d8b4d4b87d03c77906d12dc31 100644
|
||||
--- a/net/minecraft/world/entity/animal/Cow.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cow.java
|
||||
@@ -32,6 +32,8 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class Cow extends Animal {
|
||||
+ private boolean isNaturallyAggressiveToPlayers; // Purpur - Cows naturally aggressive to players chance
|
||||
+
|
||||
private static final EntityDimensions BABY_DIMENSIONS = EntityType.COW.getDimensions().scale(0.5F).withEyeHeight(0.665F);
|
||||
|
||||
public Cow(EntityType<? extends Cow> entityType, Level level) {
|
||||
@@ -60,6 +62,7 @@ public class Cow extends Animal {
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.cowScale);
|
||||
+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(this.level().purpurConfig.cowNaturallyAggressiveToPlayersDamage); // Purpur - Cows naturally aggressive to players chance
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
@@ -77,17 +80,27 @@ public class Cow extends Animal {
|
||||
}
|
||||
// Purpur end - Toggle for water sensitive mob damage
|
||||
|
||||
+ // Purpur start - Cows naturally aggressive to players chance
|
||||
+ @Override
|
||||
+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, net.minecraft.world.entity.SpawnGroupData entityData) {
|
||||
+ this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance;
|
||||
+ return super.finalizeSpawn(world, difficulty, spawnReason, entityData);
|
||||
+ }
|
||||
+ // Purpur end - Cows naturally aggressive to players chance
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
|
||||
+ this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - Cows naturally aggressive to players chance
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
||||
+ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Cows naturally aggressive to players chance
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +109,7 @@ public class Cow extends Animal {
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
- return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
|
||||
+ return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur - Cows naturally aggressive to players chance
|
||||
}
|
||||
|
||||
@Override
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: granny <granny@purpurmc.org>
|
||||
Date: Mon, 16 Oct 2023 21:54:47 -0700
|
||||
Subject: [PATCH] config for turning bundles into functional quivers
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index db5a2227009bc4d655fc781d5850221f36f2d112..c26846d3b92be4ed8ec40ce21128dfe912f19298 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -4456,6 +4456,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
public ItemStack getProjectile(ItemStack weaponStack) {
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ return getProjectile(weaponStack, false);
|
||||
+ }
|
||||
+ public ItemStack getProjectile(ItemStack weaponStack, boolean useBundleItemStack) {
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Monster.java b/net/minecraft/world/entity/monster/Monster.java
|
||||
index c1ebb74b0d4a8e2eb8880ccaf20f0f9bc1940094..4d0916c0ec6c199f9ef359a17cda0891448d07f6 100644
|
||||
--- a/net/minecraft/world/entity/monster/Monster.java
|
||||
+++ b/net/minecraft/world/entity/monster/Monster.java
|
||||
@@ -144,6 +144,12 @@ public abstract class Monster extends PathfinderMob implements Enemy {
|
||||
|
||||
@Override
|
||||
public ItemStack getProjectile(ItemStack shootable) {
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ return getProjectile(shootable, false);
|
||||
+ }
|
||||
+ @Override
|
||||
+ public ItemStack getProjectile(ItemStack shootable, boolean useBundleItemStack) {
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
if (shootable.getItem() instanceof ProjectileWeaponItem) {
|
||||
Predicate<ItemStack> supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles();
|
||||
ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles);
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 43657822f0660613078e9afa512000b5255a1537..2363ec5b718b50cb178f231e544b89c00af79796 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -2294,6 +2294,12 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public ItemStack getProjectile(ItemStack shootable) {
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ return getProjectile(shootable, false);
|
||||
+ }
|
||||
+ @Override
|
||||
+ public ItemStack getProjectile(ItemStack shootable, boolean useBundleItemStack) {
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
if (!(shootable.getItem() instanceof ProjectileWeaponItem)) {
|
||||
return ItemStack.EMPTY;
|
||||
} else {
|
||||
@@ -2306,6 +2312,39 @@ public abstract class Player extends LivingEntity {
|
||||
|
||||
for (int i = 0; i < this.inventory.getContainerSize(); i++) {
|
||||
ItemStack item = this.inventory.getItem(i);
|
||||
+
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ if ((this.level().purpurConfig.bowUseBundleAsQuiver || this.level().purpurConfig.crossbowUseBundleAsQuiver) && item.getItem() instanceof net.minecraft.world.item.BundleItem) {
|
||||
+ net.minecraft.world.item.component.BundleContents bundleContents = item.get(net.minecraft.core.component.DataComponents.BUNDLE_CONTENTS);
|
||||
+ if (bundleContents == null || bundleContents.isEmpty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Optional<ItemStack> first = bundleContents.itemCopyStream().filter(supportedHeldProjectiles).findFirst();
|
||||
+
|
||||
+ if (first.isEmpty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ItemStack itemStack = first.get();
|
||||
+ if (useBundleItemStack) {
|
||||
+ net.minecraft.world.item.component.BundleContents.Mutable mutable = new net.minecraft.world.item.component.BundleContents.Mutable(bundleContents);
|
||||
+ ItemStack itemStack2 = mutable.removeOne(itemStack);
|
||||
+ if (itemStack2 == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ itemStack2.shrink(1);
|
||||
+ if (itemStack2.getCount() != 0) {
|
||||
+ mutable.tryInsert(itemStack2);
|
||||
+ }
|
||||
+ item.set(net.minecraft.core.component.DataComponents.BUNDLE_CONTENTS, mutable.toImmutable());
|
||||
+ }
|
||||
+ itemStack.setCount(1);
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
+
|
||||
if (supportedHeldProjectiles.test(item)) {
|
||||
return item;
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/BowItem.java b/net/minecraft/world/item/BowItem.java
|
||||
index b3e003694ce0da357e91ab3ce2b1380f9ab0a32a..186bd391ed3738734ca2d8e82339af0158ae4875 100644
|
||||
--- a/net/minecraft/world/item/BowItem.java
|
||||
+++ b/net/minecraft/world/item/BowItem.java
|
||||
@@ -27,7 +27,7 @@ public class BowItem extends ProjectileWeaponItem {
|
||||
if (!(entity instanceof Player player)) {
|
||||
return false;
|
||||
} else {
|
||||
- ItemStack projectile = player.getProjectile(stack);
|
||||
+ ItemStack projectile = player.getProjectile(stack, true); // Purpur - config for turning bundles into functional quivers
|
||||
// Purpur start - Infinity bow settings
|
||||
if (level.purpurConfig.infinityWorksWithoutArrows && projectile.isEmpty() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY, stack) > 0) {
|
||||
projectile = new ItemStack(Items.ARROW);
|
||||
diff --git a/net/minecraft/world/item/BundleItem.java b/net/minecraft/world/item/BundleItem.java
|
||||
index 966029b761bcb31113b167831fe7f4f2dea4b17d..eda25cc71b4804d805b1a7f875f823b20efc754b 100644
|
||||
--- a/net/minecraft/world/item/BundleItem.java
|
||||
+++ b/net/minecraft/world/item/BundleItem.java
|
||||
@@ -131,7 +131,7 @@ public class BundleItem extends Item {
|
||||
}
|
||||
|
||||
private void dropContent(Level level, Player player, ItemStack stack) {
|
||||
- if (this.dropContent(stack, player)) {
|
||||
+ if (!(level.purpurConfig.bowUseBundleAsQuiver || level.purpurConfig.bowUseBundleAsQuiver) && this.dropContent(stack, player)) { // Purpur - config for turning bundles into functional quivers
|
||||
playDropContentsSound(level, player);
|
||||
player.awardStat(Stats.ITEM_USED.get(this));
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/CrossbowItem.java b/net/minecraft/world/item/CrossbowItem.java
|
||||
index 1131e984fd30e40c1b99054b5db9462ffe55b5f1..c9dbe63316cad0437f50fa3f7ffe345ec1906752 100644
|
||||
--- a/net/minecraft/world/item/CrossbowItem.java
|
||||
+++ b/net/minecraft/world/item/CrossbowItem.java
|
||||
@@ -72,7 +72,7 @@ public class CrossbowItem extends ProjectileWeaponItem {
|
||||
if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) {
|
||||
this.performShooting(level, player, hand, itemInHand, getShootingPower(chargedProjectiles), (float) level.purpurConfig.crossbowProjectileOffset, null); // Purpur - Projectile offset config
|
||||
return InteractionResult.CONSUME;
|
||||
- } else if (!player.getProjectile(itemInHand).isEmpty()) {
|
||||
+ } else if (!player.getProjectile(itemInHand).isEmpty()) { // Purpur - config for turning bundles into functional quivers
|
||||
this.startSoundPlayed = false;
|
||||
this.midLoadSoundPlayed = false;
|
||||
player.startUsingItem(hand);
|
||||
@@ -124,7 +124,7 @@ public class CrossbowItem extends ProjectileWeaponItem {
|
||||
return CrossbowItem.tryLoadProjectiles(shooter, crossbowStack, true);
|
||||
}
|
||||
private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbowStack, boolean consume) {
|
||||
- List<ItemStack> list = draw(crossbowStack, shooter.getProjectile(crossbowStack), shooter, consume);
|
||||
+ List<ItemStack> list = draw(crossbowStack, shooter.getProjectile(crossbowStack, true), shooter, consume); // Purpur - config for turning bundles into functional quivers
|
||||
// Paper end - Add EntityLoadCrossbowEvent
|
||||
if (!list.isEmpty()) {
|
||||
crossbowStack.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(list));
|
||||
diff --git a/net/minecraft/world/item/component/BundleContents.java b/net/minecraft/world/item/component/BundleContents.java
|
||||
index fca2dd0fb9ff4ff795a01de722fbb31dc02682fa..6fb9becef49bd4161c7829d240dd9e786f2226b5 100644
|
||||
--- a/net/minecraft/world/item/component/BundleContents.java
|
||||
+++ b/net/minecraft/world/item/component/BundleContents.java
|
||||
@@ -163,7 +163,12 @@ public final class BundleContents implements TooltipComponent {
|
||||
}
|
||||
|
||||
private int findStackIndex(ItemStack stack) {
|
||||
- if (!stack.isStackable()) {
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ return this.findStackIndex(stack, false);
|
||||
+ }
|
||||
+ private int findStackIndex(ItemStack stack, boolean skipStackableCheck) {
|
||||
+ if (!skipStackableCheck && !stack.isStackable()) {
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
return -1;
|
||||
} else {
|
||||
for (int i = 0; i < this.items.size(); i++) {
|
||||
@@ -223,11 +228,20 @@ public final class BundleContents implements TooltipComponent {
|
||||
|
||||
@Nullable
|
||||
public ItemStack removeOne() {
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ return this.removeOne(null);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ public ItemStack removeOne(ItemStack itemStack2) {
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
if (this.items.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
int i = this.selectedItem != -1 && this.selectedItem < this.items.size() ? this.selectedItem : 0;
|
||||
- ItemStack itemStack = this.items.remove(i).copy();
|
||||
+ // Purpur start - config for turning bundles into functional quivers
|
||||
+ int stackIndex = itemStack2 != null ? this.findStackIndex(itemStack2, true) : -1;
|
||||
+ ItemStack itemStack = this.items.remove(stackIndex == -1 ? i : stackIndex).copy();
|
||||
+ // Purpur end - config for turning bundles into functional quivers
|
||||
this.weight = this.weight.subtract(BundleContents.getWeight(itemStack).multiplyBy(Fraction.getFraction(itemStack.getCount(), 1)));
|
||||
this.toggleSelectedItem(-1);
|
||||
return itemStack;
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
@@ -141,6 +_,8 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (!player.level().purpurConfig.idleTimeoutTickNearbyEntities && player.isAfk()) continue; // Purpur - AFK API
|
||||
+
|
||||
final int worldHeight = world.getHeight();
|
||||
ActivationRange.maxBB = player.getBoundingBox().inflate(maxRange, worldHeight, maxRange);
|
||||
ActivationType.MISC.boundingBox = player.getBoundingBox().inflate(miscActivationRange, worldHeight, miscActivationRange);
|
||||
@@ -282,6 +_,7 @@
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkIfActive(final Entity entity) {
|
||||
+ if (entity.level().purpurConfig.squidImmuneToEAR && entity instanceof net.minecraft.world.entity.animal.Squid) return true; // Purpur - Squid EAR immunity
|
||||
// Never safe to skip fireworks or item gravity
|
||||
if (entity instanceof FireworkRocketEntity || (entity instanceof ItemEntity && (entity.tickCount + entity.getId()) % 4 == 0)) { // Needed for item gravity, see ItemEntity tick
|
||||
return true;
|
||||
@@ -0,0 +1,28 @@
|
||||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -30,6 +_,7 @@
|
||||
private boolean trackingStackTrace = true;
|
||||
private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0];
|
||||
private final SystemReport systemReport = new SystemReport();
|
||||
+ private List<String> extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER! REPORT TO PURPUR INSTEAD!", ""); // Purpur - Rebrand
|
||||
|
||||
public CrashReport(String title, Throwable exception) {
|
||||
io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception); // Paper
|
||||
@@ -130,7 +_,7 @@
|
||||
}
|
||||
|
||||
public String getFriendlyReport(ReportType type) {
|
||||
- return this.getFriendlyReport(type, List.of());
|
||||
+ return this.getFriendlyReport(type, extraInfo); // Purpur - Rebrand
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -161,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean saveToFile(Path path, ReportType type) {
|
||||
- return this.saveToFile(path, type, List.of());
|
||||
+ return this.saveToFile(path, type, extraInfo); // Purpur - Rebrand
|
||||
}
|
||||
|
||||
public SystemReport getSystemReport() {
|
||||
@@ -0,0 +1,53 @@
|
||||
--- a/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -455,6 +_,19 @@
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Purpur start - Gamemode extra permissions
|
||||
+ public boolean testPermission(int i, String bukkitPermission) {
|
||||
+ if (hasPermission(i, bukkitPermission)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ net.kyori.adventure.text.Component permissionMessage = getLevel().getServer().server.permissionMessage();
|
||||
+ if (!permissionMessage.equals(net.kyori.adventure.text.Component.empty())) {
|
||||
+ sendFailure(io.papermc.paper.adventure.PaperAdventure.asVanilla(permissionMessage.replaceText(net.kyori.adventure.text.TextReplacementConfig.builder().matchLiteral("<permission>").replacement(bukkitPermission).build())));
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Purpur end - Gamemode extra permissions
|
||||
+
|
||||
public Vec3 getPosition() {
|
||||
return this.worldPosition;
|
||||
}
|
||||
@@ -540,6 +_,30 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Purpur config files
|
||||
+ public void sendSuccess(@Nullable String message) {
|
||||
+ sendSuccess(message, false);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable String message, boolean broadcastToOps) {
|
||||
+ if (message == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ sendSuccess(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message), broadcastToOps);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ sendSuccess(message, false);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable net.kyori.adventure.text.Component message, boolean broadcastToOps) {
|
||||
+ if (message == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ sendSuccess(() -> io.papermc.paper.adventure.PaperAdventure.asVanilla(message), broadcastToOps);
|
||||
+ }
|
||||
+ // Purpur end - Purpur config files
|
||||
|
||||
public void sendSuccess(Supplier<Component> messageSupplier, boolean allowLogging) {
|
||||
boolean flag = this.source.acceptsSuccess() && !this.silent;
|
||||
@@ -0,0 +1,44 @@
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -216,8 +_,8 @@
|
||||
JfrCommand.register(this.dispatcher);
|
||||
}
|
||||
|
||||
- if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
- TestCommand.register(this.dispatcher);
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands || SharedConstants.IS_RUNNING_IN_IDE) { // Purpur - register minecraft debug commands
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands) TestCommand.register(this.dispatcher); // Purpur - register minecraft debug commands
|
||||
RaidCommand.register(this.dispatcher, context);
|
||||
DebugPathCommand.register(this.dispatcher);
|
||||
DebugMobSpawningCommand.register(this.dispatcher);
|
||||
@@ -245,6 +_,14 @@
|
||||
StopCommand.register(this.dispatcher);
|
||||
TransferCommand.register(this.dispatcher);
|
||||
WhitelistCommand.register(this.dispatcher);
|
||||
+ org.purpurmc.purpur.command.CreditsCommand.register(this.dispatcher); // Purpur - Add credits command
|
||||
+ org.purpurmc.purpur.command.DemoCommand.register(this.dispatcher); // Purpur - Add demo command
|
||||
+ org.purpurmc.purpur.command.PingCommand.register(this.dispatcher); // Purpur - Add ping command
|
||||
+ org.purpurmc.purpur.command.UptimeCommand.register(this.dispatcher); // Purpur - Add uptime command
|
||||
+ org.purpurmc.purpur.command.TPSBarCommand.register(this.dispatcher); // Purpur - Implement TPSBar
|
||||
+ org.purpurmc.purpur.command.CompassCommand.register(this.dispatcher); // Purpur - Add compass command
|
||||
+ org.purpurmc.purpur.command.RamBarCommand.register(this.dispatcher); // Purpur - Add rambar command
|
||||
+ org.purpurmc.purpur.command.RamCommand.register(this.dispatcher); // Purpur - Add ram command
|
||||
}
|
||||
|
||||
if (selection.includeIntegrated) {
|
||||
@@ -488,6 +_,7 @@
|
||||
private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<SharedSuggestionProvider> rootCommandNode) {
|
||||
// Paper end - Perf: Async command map building
|
||||
new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootCommandNode, true).callEvent(); // Paper - Brigadier API
|
||||
+ if (org.bukkit.event.player.PlayerCommandSendEvent.getHandlerList().getRegisteredListeners().length > 0) { // Purpur - Skip events if there's no listeners
|
||||
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);
|
||||
|
||||
@@ -498,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ } // Purpur - Skip events if there's no listeners
|
||||
|
||||
player.connection.send(new ClientboundCommandsPacket(rootCommandNode));
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
@@ -192,26 +_,27 @@
|
||||
this.checkPermissions(source);
|
||||
if (this.playerName != null) {
|
||||
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
|
||||
- return playerByName == null ? List.of() : List.of(playerByName);
|
||||
+ return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
|
||||
} else if (this.entityUUID != null) {
|
||||
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID);
|
||||
- return playerByName == null ? List.of() : List.of(playerByName);
|
||||
+ return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
|
||||
} else {
|
||||
Vec3 vec3 = this.position.apply(source.getPosition());
|
||||
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
|
||||
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
|
||||
if (this.currentEntity) {
|
||||
- return source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer) ? List.of(serverPlayer) : List.of();
|
||||
+ return source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer) && canSee(source, serverPlayer) ? List.of(serverPlayer) : List.of(); // Purpur - Hide hidden players from entity selector
|
||||
} else {
|
||||
int resultLimit = this.getResultLimit();
|
||||
List<ServerPlayer> players;
|
||||
if (this.isWorldLimited()) {
|
||||
players = source.getLevel().getPlayers(predicate, resultLimit);
|
||||
+ players.removeIf(entityplayer3 -> !canSee(source, entityplayer3)); // Purpur - Hide hidden players from entity selector
|
||||
} else {
|
||||
players = new ObjectArrayList<>();
|
||||
|
||||
for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) {
|
||||
- if (predicate.test(serverPlayer1)) {
|
||||
+ if (predicate.test(serverPlayer1) && canSee(source, serverPlayer1)) { // Purpur - Hide hidden players from entity selector
|
||||
players.add(serverPlayer1);
|
||||
if (players.size() >= resultLimit) {
|
||||
return players;
|
||||
@@ -270,4 +_,10 @@
|
||||
public static Component joinNames(List<? extends Entity> names) {
|
||||
return ComponentUtils.formatList(names, Entity::getDisplayName);
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Hide hidden players from entity selector
|
||||
+ private boolean canSee(CommandSourceStack sender, ServerPlayer target) {
|
||||
+ return !org.purpurmc.purpur.PurpurConfig.hideHiddenPlayersFromEntitySelector || !(sender.getEntity() instanceof ServerPlayer player) || player.getBukkitEntity().canSee(target.getBukkitEntity());
|
||||
+ }
|
||||
+ // Purpur end - Hide hidden players from entity selector
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/core/BlockPos.java
|
||||
+++ b/net/minecraft/core/BlockPos.java
|
||||
@@ -63,6 +_,12 @@
|
||||
public static final int MAX_HORIZONTAL_COORDINATE = 33554431;
|
||||
// Paper end - Optimize Bit Operations by inlining
|
||||
|
||||
+ // Purpur start - Ridables
|
||||
+ public BlockPos(net.minecraft.world.entity.Entity entity) {
|
||||
+ super(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
|
||||
+ }
|
||||
+ // Purpur end - Ridables
|
||||
+
|
||||
public BlockPos(int x, int y, int z) {
|
||||
super(x, y, z);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -892,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));
|
||||
+ // Purpur start - Dispensers place anvils option
|
||||
+ DispenserBlock.registerBehavior(Items.ANVIL, (new OptionalDispenseItemBehavior() {
|
||||
+ @Override
|
||||
+ public ItemStack execute(BlockSource dispenser, ItemStack stack) {
|
||||
+ net.minecraft.world.level.Level level = dispenser.level();
|
||||
+ if (!level.purpurConfig.dispenserPlaceAnvils) return super.execute(dispenser, stack);
|
||||
+ Direction facing = dispenser.blockEntity().getBlockState().getValue(DispenserBlock.FACING);
|
||||
+ BlockPos pos = dispenser.pos().relative(facing);
|
||||
+ BlockState state = level.getBlockState(pos);
|
||||
+ if (state.isAir()) {
|
||||
+ level.setBlockAndUpdate(pos, Blocks.ANVIL.defaultBlockState().setValue(net.minecraft.world.level.block.AnvilBlock.FACING, facing.getAxis() == Direction.Axis.Y ? Direction.NORTH : facing.getClockWise()));
|
||||
+ stack.shrink(1);
|
||||
+ }
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }));
|
||||
+ // Purpur end - Dispensers place anvils option
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
@@ -31,7 +_,7 @@
|
||||
return false;
|
||||
} else {
|
||||
LivingEntity livingEntity = entitiesOfClass.getFirst();
|
||||
- EquipmentSlot equipmentSlotForItem = livingEntity.getEquipmentSlotForItem(item);
|
||||
+ EquipmentSlot equipmentSlotForItem = blockSource.level().purpurConfig.dispenserApplyCursedArmor ? livingEntity.getEquipmentSlotForItem(item) : livingEntity.getEquipmentSlotForDispenserItem(item); if (equipmentSlotForItem == null) return false; // Purpur - Dispenser curse of binding protection
|
||||
ItemStack itemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
// CraftBukkit start
|
||||
net.minecraft.world.level.Level world = blockSource.level();
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/gametest/framework/GameTestHelper.java
|
||||
+++ b/net/minecraft/gametest/framework/GameTestHelper.java
|
||||
@@ -279,6 +_,8 @@
|
||||
return gameType.isCreative();
|
||||
}
|
||||
|
||||
+ public void setAfk(final boolean afk) {} // Purpur - AFK API
|
||||
+
|
||||
@Override
|
||||
public boolean isLocalPlayer() {
|
||||
return true;
|
||||
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -588,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
|
||||
+ private static int tickSecond; // Purpur - Max joins per second
|
||||
public void tick() {
|
||||
this.flushQueue();
|
||||
// Paper start - Buffer joins to world
|
||||
if (Connection.currTick != net.minecraft.server.MinecraftServer.currentTick) {
|
||||
Connection.currTick = net.minecraft.server.MinecraftServer.currentTick;
|
||||
+ // Purpur start - Max joins per second
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.maxJoinsPerSecond) {
|
||||
+ if (++Connection.tickSecond > 20) {
|
||||
+ Connection.tickSecond = 0;
|
||||
+ Connection.joinAttemptsThisTick = 0;
|
||||
+ }
|
||||
+ } else
|
||||
+ // Purpur end - Max joins per second
|
||||
Connection.joinAttemptsThisTick = 0;
|
||||
}
|
||||
// Paper end - Buffer joins to world
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/network/chat/SignedMessageChain.java
|
||||
+++ b/net/minecraft/network/chat/SignedMessageChain.java
|
||||
@@ -45,7 +_,7 @@
|
||||
SignedMessageLink signedMessageLink = SignedMessageChain.this.nextLink;
|
||||
if (signedMessageLink == 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 {
|
||||
@@ -0,0 +1,15 @@
|
||||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -108,6 +_,12 @@
|
||||
JvmProfiler.INSTANCE.start(Environment.SERVER);
|
||||
}
|
||||
|
||||
+ // Purpur start - Add toggle for enchant level clamping - load config files early
|
||||
+ org.bukkit.configuration.file.YamlConfiguration purpurConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("purpur-settings"));
|
||||
+ org.purpurmc.purpur.PurpurConfig.clampEnchantLevels = purpurConfiguration.getBoolean("settings.enchantment.clamp-levels", true);
|
||||
+ org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands = purpurConfiguration.getBoolean("settings.register-minecraft-debug-commands"); // Purpur - register minecraft debug commands
|
||||
+ // Purpur end - Add toggle for enchant level clamping - load config files early
|
||||
+
|
||||
io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper
|
||||
Bootstrap.bootStrap();
|
||||
Bootstrap.validate();
|
||||
@@ -0,0 +1,133 @@
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -284,6 +_,7 @@
|
||||
public joptsimple.OptionSet options;
|
||||
public org.bukkit.command.ConsoleCommandSender console;
|
||||
public static int currentTick; // Paper - improve tick loop
|
||||
+ public static final long startTimeMillis = System.currentTimeMillis(); // Purpur - Add uptime command
|
||||
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
||||
public int autosavePeriod;
|
||||
// Paper - don't store the vanilla dispatcher
|
||||
@@ -294,7 +_,7 @@
|
||||
public static final int TICK_TIME = 1000000000 / MinecraftServer.TPS;
|
||||
private static final int SAMPLE_INTERVAL = 20; // Paper - improve server tick loop
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
- public final double[] recentTps = new double[3];
|
||||
+ public final double[] recentTps = new double[4]; // Purpur - Add 5 second tps average in /tps
|
||||
// Spigot end
|
||||
public volatile boolean hasFullyShutdown; // Paper - Improved watchdog support
|
||||
public volatile boolean abnormalExit; // Paper - Improved watchdog support
|
||||
@@ -302,7 +_,9 @@
|
||||
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files
|
||||
public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
|
||||
private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping
|
||||
+ public boolean lagging = false; // Purpur - Lagging threshold
|
||||
public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation
|
||||
+ protected boolean upnp = false; // Purpur - UPnP Port Forwarding
|
||||
|
||||
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
||||
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
||||
@@ -1001,6 +_,15 @@
|
||||
|
||||
LOGGER.info("Stopping server");
|
||||
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
|
||||
+ // Purpur start - UPnP Port Forwarding
|
||||
+ if (upnp) {
|
||||
+ if (dev.omega24.upnp4j.UPnP4J.close(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
|
||||
+ LOGGER.info("[UPnP] Port {} closed", this.getPort());
|
||||
+ } else {
|
||||
+ LOGGER.error("[UPnP] Failed to close port {}", this.getPort());
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - UPnP Port Forwarding
|
||||
// CraftBukkit start
|
||||
if (this.server != null) {
|
||||
this.server.spark.disable(); // Paper - spark
|
||||
@@ -1093,6 +_,8 @@
|
||||
this.safeShutdown(waitForServer, false);
|
||||
}
|
||||
public void safeShutdown(boolean waitForServer, boolean isRestarting) {
|
||||
+ org.purpurmc.purpur.task.BossBarTask.stopAll(); // Purpur - Implement TPSBar
|
||||
+ org.purpurmc.purpur.task.BeehiveTask.instance().unregister(); // Purpur - Give bee counts in beehives to Purpur clients
|
||||
this.isRestarting = isRestarting;
|
||||
this.hasLoggedStop = true; // Paper - Debugging
|
||||
if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
|
||||
@@ -1112,6 +_,7 @@
|
||||
private static final long MAX_CATCHUP_BUFFER = TICK_TIME * TPS * 60L;
|
||||
private long lastTick = 0;
|
||||
private long catchupTime = 0;
|
||||
+ public final RollingAverage tps5s = new RollingAverage(5); // Purpur - Add 5 second tps average in /tps
|
||||
public final RollingAverage tps1 = new RollingAverage(60);
|
||||
public final RollingAverage tps5 = new RollingAverage(60 * 5);
|
||||
public final RollingAverage tps15 = new RollingAverage(60 * 15);
|
||||
@@ -1197,6 +_,16 @@
|
||||
}
|
||||
// Paper end - Add onboarding message for initial server start
|
||||
|
||||
+ // Purpur start - config for startup commands
|
||||
+ if (!Boolean.getBoolean("Purpur.IReallyDontWantStartupCommands") && !org.purpurmc.purpur.PurpurConfig.startupCommands.isEmpty()) {
|
||||
+ LOGGER.info("Purpur: Running startup commands specified in purpur.yml.");
|
||||
+ for (final String startupCommand : org.purpurmc.purpur.PurpurConfig.startupCommands) {
|
||||
+ LOGGER.info("Purpur: Running the following command: \"{}\"", startupCommand);
|
||||
+ ((net.minecraft.server.dedicated.DedicatedServer) this).handleConsoleInput(startupCommand, this.createCommandSourceStack());
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - config for startup commands
|
||||
+
|
||||
while (this.running) {
|
||||
long l;
|
||||
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
|
||||
@@ -1221,14 +_,19 @@
|
||||
if (++MinecraftServer.currentTick % MinecraftServer.SAMPLE_INTERVAL == 0) {
|
||||
final long diff = currentTime - tickSection;
|
||||
final java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP);
|
||||
+ tps5s.add(currentTps, diff); // Purpur - Add 5 second tps average in /tps
|
||||
tps1.add(currentTps, diff);
|
||||
tps5.add(currentTps, diff);
|
||||
tps15.add(currentTps, diff);
|
||||
|
||||
// Backwards compat with bad plugins
|
||||
- this.recentTps[0] = tps1.getAverage();
|
||||
- this.recentTps[1] = tps5.getAverage();
|
||||
- this.recentTps[2] = tps15.getAverage();
|
||||
+ // Purpur start - Add 5 second tps average in /tps
|
||||
+ this.recentTps[0] = tps5s.getAverage();
|
||||
+ this.recentTps[1] = tps1.getAverage();
|
||||
+ this.recentTps[2] = tps5.getAverage();
|
||||
+ this.recentTps[3] = tps15.getAverage();
|
||||
+ // Purpur end - Add 5 second tps average in /tps
|
||||
+ lagging = recentTps[0] < org.purpurmc.purpur.PurpurConfig.laggingThreshold; // Purpur - Lagging threshold
|
||||
tickSection = currentTime;
|
||||
}
|
||||
// Paper end - further improve server tick loop
|
||||
@@ -1260,6 +_,12 @@
|
||||
profilerFiller.popPush("nextTickWait");
|
||||
this.mayHaveDelayedTasks = true;
|
||||
this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + l, this.nextTickTimeNanos);
|
||||
+ // Purpur start - Configurable TPS Catchup
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.tpsCatchup /*|| !gg.pufferfish.pufferfish.PufferfishConfig.tpsCatchup*/) { // Purpur - Configurable TPS Catchup
|
||||
+ this.nextTickTimeNanos = currentTime + l;
|
||||
+ this.delayedTasksMaxNextTickTimeNanos = nextTickTimeNanos;
|
||||
+ }
|
||||
+ // Purpur end - Configurable TPS Catchup
|
||||
this.startMeasuringTaskExecutionTime();
|
||||
this.waitUntilNextTick();
|
||||
this.finishMeasuringTaskExecutionTime();
|
||||
@@ -1690,7 +_,7 @@
|
||||
long worldTime = level.getGameTime();
|
||||
final ClientboundSetTimePacket worldPacket = new ClientboundSetTimePacket(worldTime, dayTime, doDaylight);
|
||||
for (Player entityhuman : level.players()) {
|
||||
- if (!(entityhuman instanceof ServerPlayer) || (tickCount + entityhuman.getId()) % 20 != 0) {
|
||||
+ if (!(entityhuman instanceof ServerPlayer) || (!level.isForceTime() && (tickCount + entityhuman.getId()) % 20 != 0)) { // Purpur - Configurable daylight cycle
|
||||
continue;
|
||||
}
|
||||
ServerPlayer entityplayer = (ServerPlayer) entityhuman;
|
||||
@@ -1855,7 +_,7 @@
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
- return io.papermc.paper.ServerBuildInfo.buildInfo().brandName(); // Paper
|
||||
+ return org.purpurmc.purpur.PurpurConfig.serverModName; // Paper // Purpur - Configurable server mod name
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport systemReport) {
|
||||
@@ -0,0 +1,18 @@
|
||||
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -148,6 +_,7 @@
|
||||
AdvancementHolder advancementHolder = advancementManager.get(path);
|
||||
if (advancementHolder == null) {
|
||||
if (!path.getNamespace().equals(ResourceLocation.DEFAULT_NAMESPACE)) return; // CraftBukkit
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressIgnoredAdvancementWarnings) // Purpur - Logger settings (suppressing pointless logs)
|
||||
LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", path, this.playerSavePath);
|
||||
} else {
|
||||
this.startProgress(advancementHolder, progress);
|
||||
@@ -195,6 +_,7 @@
|
||||
advancement.value().display().ifPresent(displayInfo -> {
|
||||
// Paper start - Add Adventure message to PlayerAdvancementDoneEvent
|
||||
if (event.message() != null && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.advancementOnlyBroadcastToAffectedPlayer) this.player.sendMessage(message); else // Purpur - Configurable broadcast settings
|
||||
this.playerList.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false);
|
||||
// Paper end
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/server/commands/EnchantCommand.java
|
||||
+++ b/net/minecraft/server/commands/EnchantCommand.java
|
||||
@@ -70,7 +_,7 @@
|
||||
|
||||
private static int enchant(CommandSourceStack source, Collection<? extends Entity> targets, Holder<Enchantment> enchantment, int level) throws CommandSyntaxException {
|
||||
Enchantment enchantment1 = enchantment.value();
|
||||
- if (level > enchantment1.getMaxLevel()) {
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.allowUnsafeEnchantCommand && level > enchantment1.getMaxLevel()) { // Purpur - Config to allow unsafe enchants
|
||||
throw ERROR_LEVEL_TOO_HIGH.create(level, enchantment1.getMaxLevel());
|
||||
} else {
|
||||
int i = 0;
|
||||
@@ -81,7 +_,7 @@
|
||||
ItemStack mainHandItem = livingEntity.getMainHandItem();
|
||||
if (!mainHandItem.isEmpty()) {
|
||||
if (enchantment1.canEnchant(mainHandItem)
|
||||
- && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(mainHandItem).keySet(), enchantment)) {
|
||||
+ && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(mainHandItem).keySet(), enchantment) || (org.purpurmc.purpur.PurpurConfig.allowUnsafeEnchantCommand && !mainHandItem.hasEnchantment(enchantment))) { // Purpur - Config to allow unsafe enchants
|
||||
mainHandItem.enchant(enchantment, level);
|
||||
i++;
|
||||
} else if (targets.size() == 1) {
|
||||
@@ -0,0 +1,21 @@
|
||||
--- a/net/minecraft/server/commands/GameModeCommand.java
|
||||
+++ b/net/minecraft/server/commands/GameModeCommand.java
|
||||
@@ -51,6 +_,18 @@
|
||||
}
|
||||
|
||||
private static int setMode(CommandContext<CommandSourceStack> source, Collection<ServerPlayer> players, GameType gameType) {
|
||||
+ // Purpur start - Gamemode extra permissions
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.commandGamemodeRequiresPermission) {
|
||||
+ String gamemode = gameType.getName();
|
||||
+ CommandSourceStack sender = source.getSource();
|
||||
+ if (!sender.testPermission(2, "minecraft.command.gamemode." + gamemode)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (sender.getEntity() instanceof ServerPlayer player && (players.size() > 1 || !players.contains(player)) && !sender.testPermission(2, "minecraft.command.gamemode." + gamemode + ".other")) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Gamemode extra permissions
|
||||
int i = 0;
|
||||
|
||||
for (ServerPlayer serverPlayer : players) {
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -66,6 +_,7 @@
|
||||
i1 -= min;
|
||||
ItemStack itemStack1 = item.createItemStack(min, false);
|
||||
boolean flag = serverPlayer.getInventory().add(itemStack1);
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.disableGiveCommandDrops) continue; // Purpur - add config option for toggling give command dropping
|
||||
if (flag && itemStack1.isEmpty()) {
|
||||
ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event
|
||||
if (itemEntity != null) {
|
||||
@@ -0,0 +1,66 @@
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -106,6 +_,7 @@
|
||||
// CraftBukkit start
|
||||
if (!org.bukkit.craftbukkit.Main.useConsole) return;
|
||||
// Paper start - Use TerminalConsoleAppender
|
||||
+ if (DedicatedServer.this.gui == null || System.console() != null) // Purpur - GUI Improvements - has no GUI or has console (did not double-click)
|
||||
new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
|
||||
/*
|
||||
jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader;
|
||||
@@ -224,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
|
||||
+ /*// Purpur start - Purpur config files // Purpur - Configurable void damage height and damage
|
||||
+ try {
|
||||
+ org.purpurmc.purpur.PurpurConfig.init((java.io.File) options.valueOf("purpur-settings"));
|
||||
+ } catch (Exception e) {
|
||||
+ DedicatedServer.LOGGER.error("Unable to load server configuration", e);
|
||||
+ return false;
|
||||
+ }
|
||||
+ org.purpurmc.purpur.PurpurConfig.registerCommands();
|
||||
+ */// Purpur end - Purpur config files // Purpur - Configurable void damage height and damage
|
||||
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
|
||||
|
||||
this.setPvpAllowed(properties.pvp);
|
||||
@@ -271,6 +_,30 @@
|
||||
if (true) throw new IllegalStateException("Failed to bind to port", var10); // Paper - Propagate failed to bind to port error
|
||||
return false;
|
||||
}
|
||||
+ // Purpur start - UPnP Port Forwarding
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.useUPnP) {
|
||||
+ LOGGER.info("[UPnP] Attempting to start UPnP port forwarding service...");
|
||||
+ if (dev.omega24.upnp4j.UPnP4J.isUPnPAvailable()) {
|
||||
+ if (dev.omega24.upnp4j.UPnP4J.isOpen(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
|
||||
+ this.upnp = false;
|
||||
+ LOGGER.info("[UPnP] Port {} is already open", this.getPort());
|
||||
+ } else if (dev.omega24.upnp4j.UPnP4J.open(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
|
||||
+ this.upnp = true;
|
||||
+ LOGGER.info("[UPnP] Successfully opened port {}", this.getPort());
|
||||
+ } else {
|
||||
+ this.upnp = false;
|
||||
+ LOGGER.info("[UPnP] Failed to open port {}", this.getPort());
|
||||
+ }
|
||||
+
|
||||
+ if (upnp) {
|
||||
+ LOGGER.info("[UPnP] {}:{}", dev.omega24.upnp4j.UPnP4J.getExternalIP(), this.getPort());
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.upnp = false;
|
||||
+ LOGGER.error("[UPnP] Service is unavailable");
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - UPnP Port Forwarding
|
||||
|
||||
// CraftBukkit start
|
||||
// this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up
|
||||
@@ -350,6 +_,8 @@
|
||||
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
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
@@ -49,6 +_,7 @@
|
||||
public final boolean onlineMode = this.get("online-mode", true);
|
||||
public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false);
|
||||
public final String serverIp = this.get("server-ip", "");
|
||||
+ public final String serverName = this.get("server-name", "Unknown Server"); // Purpur - Bring back server name
|
||||
public final boolean pvp = this.get("pvp", true);
|
||||
public final boolean allowFlight = this.get("allow-flight", false);
|
||||
public final String motd = this.get("motd", "A Minecraft Server");
|
||||
@@ -0,0 +1,135 @@
|
||||
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -39,6 +_,11 @@
|
||||
private Thread logAppenderThread;
|
||||
private final Collection<Runnable> finalizers = Lists.newArrayList();
|
||||
final AtomicBoolean isClosing = new AtomicBoolean();
|
||||
+ // Purpur start - GUI Improvements
|
||||
+ private final CommandHistory history = new CommandHistory();
|
||||
+ private String currentCommand = "";
|
||||
+ private int historyIndex = 0;
|
||||
+ // Purpur end - GUI Improvements
|
||||
|
||||
public static MinecraftServerGui showFrameFor(final DedicatedServer server) {
|
||||
try {
|
||||
@@ -46,7 +_,7 @@
|
||||
} catch (Exception var3) {
|
||||
}
|
||||
|
||||
- final JFrame jFrame = new JFrame("Minecraft server");
|
||||
+ final JFrame jFrame = new JFrame("Purpur Minecraft server"); // Purpur - Improve GUI
|
||||
final MinecraftServerGui minecraftServerGui = new MinecraftServerGui(server);
|
||||
jFrame.setDefaultCloseOperation(2);
|
||||
jFrame.add(minecraftServerGui);
|
||||
@@ -54,7 +_,7 @@
|
||||
jFrame.setLocationRelativeTo(null);
|
||||
jFrame.setVisible(true);
|
||||
// Paper start - Improve ServerGUI
|
||||
- jFrame.setName("Minecraft server");
|
||||
+ jFrame.setName("Purpur Minecraft server"); // Purpur - Improve GUI
|
||||
try {
|
||||
jFrame.setIconImage(javax.imageio.ImageIO.read(java.util.Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
|
||||
} catch (java.io.IOException ignore) {
|
||||
@@ -64,7 +_,7 @@
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
if (!minecraftServerGui.isClosing.getAndSet(true)) {
|
||||
- jFrame.setTitle("Minecraft server - shutting down!");
|
||||
+ jFrame.setTitle("Purpur Minecraft server - shutting down!"); // Purpur - Improve GUI
|
||||
server.halt(true);
|
||||
minecraftServerGui.runFinalizers();
|
||||
}
|
||||
@@ -112,7 +_,7 @@
|
||||
|
||||
private JComponent buildChatPanel() {
|
||||
JPanel jPanel = new JPanel(new BorderLayout());
|
||||
- JTextArea jTextArea = new JTextArea();
|
||||
+ org.purpurmc.purpur.gui.JColorTextPane jTextArea = new org.purpurmc.purpur.gui.JColorTextPane(); // Purpur - GUI Improvements
|
||||
JScrollPane jScrollPane = new JScrollPane(jTextArea, 22, 30);
|
||||
jTextArea.setEditable(false);
|
||||
jTextArea.setFont(MONOSPACED);
|
||||
@@ -121,10 +_,43 @@
|
||||
String trimmed = jTextField.getText().trim();
|
||||
if (!trimmed.isEmpty()) {
|
||||
this.server.handleConsoleInput(trimmed, this.server.createCommandSourceStack());
|
||||
+ // Purpur start - GUI Improvements
|
||||
+ history.add(trimmed);
|
||||
+ historyIndex = -1;
|
||||
+ // Purpur end - GUI Improvements
|
||||
}
|
||||
|
||||
jTextField.setText("");
|
||||
});
|
||||
+ // Purpur start - GUI Improvements
|
||||
+ jTextField.getInputMap().put(javax.swing.KeyStroke.getKeyStroke("UP"), "up");
|
||||
+ jTextField.getInputMap().put(javax.swing.KeyStroke.getKeyStroke("DOWN"), "down");
|
||||
+ jTextField.getActionMap().put("up", new javax.swing.AbstractAction() {
|
||||
+ @Override
|
||||
+ public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
|
||||
+ if (historyIndex < 0) {
|
||||
+ currentCommand = jTextField.getText();
|
||||
+ }
|
||||
+ if (historyIndex < history.size() - 1) {
|
||||
+ jTextField.setText(history.get(++historyIndex));
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ jTextField.getActionMap().put("down", new javax.swing.AbstractAction() {
|
||||
+ @Override
|
||||
+ public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
|
||||
+ if (historyIndex >= 0) {
|
||||
+ if (historyIndex == 0) {
|
||||
+ --historyIndex;
|
||||
+ jTextField.setText(currentCommand);
|
||||
+ } else {
|
||||
+ --historyIndex;
|
||||
+ jTextField.setText(history.get(historyIndex));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ // Purpur end - GUI Improvements
|
||||
jTextArea.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent event) {
|
||||
@@ -159,7 +_,7 @@
|
||||
}
|
||||
|
||||
private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\e\\[[\\d;]*[^\\d;]"); // CraftBukkit // Paper
|
||||
- public void print(JTextArea textArea, JScrollPane scrollPane, String line) {
|
||||
+ public void print(org.purpurmc.purpur.gui.JColorTextPane textArea, JScrollPane scrollPane, String line) { // Purpur - GUI Improvements
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
SwingUtilities.invokeLater(() -> this.print(textArea, scrollPane, line));
|
||||
} else {
|
||||
@@ -170,16 +_,29 @@
|
||||
flag = verticalScrollBar.getValue() + verticalScrollBar.getSize().getHeight() + MONOSPACED.getSize() * 4 > verticalScrollBar.getMaximum();
|
||||
}
|
||||
|
||||
- try {
|
||||
+ /*try { // Purpur - GUI Improvements
|
||||
document.insertString(document.getLength(), MinecraftServerGui.ANSI.matcher(line).replaceAll(""), null); // CraftBukkit
|
||||
} catch (BadLocationException var8) {
|
||||
- }
|
||||
+ }*/ // Purpur - GUI Improvements
|
||||
+ textArea.append(line); // Purpur - GUI Improvements
|
||||
|
||||
if (flag) {
|
||||
verticalScrollBar.setValue(Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Purpur start - GUI Improvements
|
||||
+ public static class CommandHistory extends java.util.LinkedList<String> {
|
||||
+ @Override
|
||||
+ public boolean add(String command) {
|
||||
+ if (size() > 1000) {
|
||||
+ remove();
|
||||
+ }
|
||||
+ return super.offerFirst(command);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - GUI Improvements
|
||||
|
||||
// Paper start - Add onboarding message for initial server start
|
||||
private JComponent buildOnboardingPanel() {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/server/gui/StatsComponent.java
|
||||
+++ b/net/minecraft/server/gui/StatsComponent.java
|
||||
@@ -43,7 +_,7 @@
|
||||
}
|
||||
this.msgs[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)";
|
||||
this.msgs[1] = "Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms";
|
||||
- this.msgs[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg);
|
||||
+ this.msgs[2] = "TPS from last 5s, 1m, 5m, 15m: " + String.join(", ", tpsAvg); // Purpur - Add 5 second tps average in /tps
|
||||
// Paper end - Improve ServerGUI
|
||||
this.values[this.vp++ & 0xFF] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
|
||||
this.repaint();
|
||||
@@ -0,0 +1,172 @@
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -207,6 +_,8 @@
|
||||
private final StructureManager structureManager;
|
||||
private final StructureCheck structureCheck;
|
||||
private final boolean tickTime;
|
||||
+ private double preciseTime; // Purpur - Configurable daylight cycle
|
||||
+ private boolean forceTime; // Purpur - Configurable daylight cycle
|
||||
private final RandomSequences randomSequences;
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -595,7 +_,24 @@
|
||||
// CraftBukkit end
|
||||
this.tickTime = tickTime;
|
||||
this.server = server;
|
||||
- this.customSpawners = customSpawners;
|
||||
+ // Purpur start - Allow toggling special MobSpawners per world
|
||||
+ this.customSpawners = new ArrayList<>();
|
||||
+ if (purpurConfig.phantomSpawning) {
|
||||
+ this.customSpawners.add(new net.minecraft.world.level.levelgen.PhantomSpawner());
|
||||
+ }
|
||||
+ if (purpurConfig.patrolSpawning) {
|
||||
+ this.customSpawners.add(new net.minecraft.world.level.levelgen.PatrolSpawner());
|
||||
+ }
|
||||
+ if (purpurConfig.catSpawning) {
|
||||
+ this.customSpawners.add(new net.minecraft.world.entity.npc.CatSpawner());
|
||||
+ }
|
||||
+ if (purpurConfig.villageSiegeSpawning) {
|
||||
+ this.customSpawners.add(new net.minecraft.world.entity.ai.village.VillageSiege());
|
||||
+ }
|
||||
+ if (purpurConfig.villagerTraderSpawning) {
|
||||
+ this.customSpawners.add(new net.minecraft.world.entity.npc.WanderingTraderSpawner(serverLevelData));
|
||||
+ }
|
||||
+ // Purpur end - Allow toggling special MobSpawners per world
|
||||
this.serverLevelData = serverLevelData;
|
||||
ChunkGenerator chunkGenerator = levelStem.generator();
|
||||
// CraftBukkit start
|
||||
@@ -681,6 +_,7 @@
|
||||
this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler);
|
||||
// Paper end - rewrite chunk system
|
||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
+ this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@@ -727,7 +_,7 @@
|
||||
}
|
||||
|
||||
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
- if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) {
|
||||
+ if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) { // Purpur - Config for skipping night
|
||||
// Paper start - create time skip event - move up calculations
|
||||
final long newDayTime = this.levelData.getDayTime() + 24000L;
|
||||
org.bukkit.event.world.TimeSkipEvent event = new org.bukkit.event.world.TimeSkipEvent(
|
||||
@@ -846,6 +_,13 @@
|
||||
this.serverLevelData.getScheduledEvents().tick(this.server, l);
|
||||
Profiler.get().pop();
|
||||
if (this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
|
||||
+ // Purpur start - Configurable daylight cycle
|
||||
+ int incrementTicks = isDay() ? this.purpurConfig.daytimeTicks : this.purpurConfig.nighttimeTicks;
|
||||
+ if (incrementTicks != 12000) {
|
||||
+ this.preciseTime += 12000 / (double) incrementTicks;
|
||||
+ this.setDayTime(this.preciseTime);
|
||||
+ } else
|
||||
+ // Purpur end - Configurable daylight cycle
|
||||
this.setDayTime(this.levelData.getDayTime() + 1L);
|
||||
}
|
||||
}
|
||||
@@ -853,7 +_,21 @@
|
||||
|
||||
public void setDayTime(long time) {
|
||||
this.serverLevelData.setDayTime(time);
|
||||
- }
|
||||
+ // Purpur start - Configurable daylight cycle
|
||||
+ this.preciseTime = time;
|
||||
+ this.forceTime = false;
|
||||
+ }
|
||||
+ public void setDayTime(double i) {
|
||||
+ this.serverLevelData.setDayTime((long) i);
|
||||
+ this.forceTime = true;
|
||||
+ // Purpur end - Configurable daylight cycle
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - Configurable daylight cycle
|
||||
+ public boolean isForceTime() {
|
||||
+ return this.forceTime;
|
||||
+ }
|
||||
+ // Purpur end - Configurable daylight cycle
|
||||
|
||||
public void tickCustomSpawners(boolean spawnEnemies, boolean spawnFriendlies) {
|
||||
for (CustomSpawner customSpawner : this.customSpawners) {
|
||||
@@ -934,9 +_,18 @@
|
||||
&& this.random.nextDouble() < currentDifficultyAt.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01) // Paper - Configurable spawn chances for skeleton horses
|
||||
&& !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD);
|
||||
if (flag) {
|
||||
+ // Purpur start - Special mobs naturally spawn
|
||||
+ net.minecraft.world.entity.animal.horse.AbstractHorse entityhorseskeleton;
|
||||
+ if (purpurConfig.zombieHorseSpawnChance > 0D && random.nextDouble() <= purpurConfig.zombieHorseSpawnChance) {
|
||||
+ entityhorseskeleton = EntityType.ZOMBIE_HORSE.create(this, EntitySpawnReason.EVENT);
|
||||
+ } else {
|
||||
+ entityhorseskeleton = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
|
||||
+ if (entityhorseskeleton != null) ((SkeletonHorse) entityhorseskeleton).setTrap(true);
|
||||
+ }
|
||||
+ // Purpur end - Special mobs naturally spawn
|
||||
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
|
||||
if (skeletonHorse != null) {
|
||||
- skeletonHorse.setTrap(true);
|
||||
+ //skeletonHorse.setTrap(true); // Purpur - Special mobs naturally spawn - moved up
|
||||
skeletonHorse.setAge(0);
|
||||
skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
this.addFreshEntity(skeletonHorse, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit
|
||||
@@ -1009,7 +_,7 @@
|
||||
pointOfInterestType -> pointOfInterestType.is(PoiTypes.LIGHTNING_ROD),
|
||||
blockPos -> blockPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()) - 1,
|
||||
pos,
|
||||
- 128,
|
||||
+ org.purpurmc.purpur.PurpurConfig.lightningRodRange, // Purpur - Make lightning rod range configurable
|
||||
PoiManager.Occupancy.ANY
|
||||
);
|
||||
return optional.map(blockPos -> blockPos.above(1));
|
||||
@@ -1057,8 +_,26 @@
|
||||
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
Component component;
|
||||
if (this.sleepStatus.areEnoughSleeping(_int)) {
|
||||
+ // Purpur start - Customizable sleeping actionbar messages
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.sleepSkippingNight.isBlank()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.sleepSkippingNight.equalsIgnoreCase("default")) {
|
||||
+ component = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepSkippingNight));
|
||||
+ } else
|
||||
+ // Purpur end - Customizable sleeping actionbar messages
|
||||
component = Component.translatable("sleep.skipping_night");
|
||||
} else {
|
||||
+ // Purpur start - Customizable sleeping actionbar messages
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent.isBlank()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent.equalsIgnoreCase("default")) {
|
||||
+ component = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent,
|
||||
+ net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed("count", Integer.toString(this.sleepStatus.amountSleeping())),
|
||||
+ net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed("total", Integer.toString(this.sleepStatus.sleepersNeeded(_int)))));
|
||||
+ } else
|
||||
+ // Purpur end - Customizable sleeping actionbar messages
|
||||
component = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(_int));
|
||||
}
|
||||
|
||||
@@ -1191,6 +_,7 @@
|
||||
@VisibleForTesting
|
||||
public void resetWeatherCycle() {
|
||||
// CraftBukkit start
|
||||
+ if (this.purpurConfig.rainStopsAfterSleep) // Purpur - Option for if rain and thunder should stop on sleep
|
||||
this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents
|
||||
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
|
||||
// Not that everyone ever manages to get the whole server to sleep at the same time....
|
||||
@@ -1198,6 +_,7 @@
|
||||
this.serverLevelData.setRainTime(0);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ if (this.purpurConfig.thunderStopsAfterSleep) // Purpur - Option for if rain and thunder should stop on sleep
|
||||
this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents
|
||||
// CraftBukkit start
|
||||
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
|
||||
@@ -2676,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
|
||||
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
|
||||
+ if (!entity.level().purpurConfig.playerVoidTrading && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Purpur - Allow void trading
|
||||
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
|
||||
}
|
||||
// Paper end - Fix merchant inventory not closing on entity removal
|
||||
@@ -0,0 +1,276 @@
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -393,6 +_,10 @@
|
||||
public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
|
||||
public @Nullable String clientBrandName = null; // Paper - Brand support
|
||||
public org.bukkit.event.player.PlayerQuitEvent.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
|
||||
+ public boolean purpurClient = false; // Purpur - Purpur client support
|
||||
+ private boolean tpsBar = false; // Purpur - Implement TPSBar
|
||||
+ private boolean compassBar = false; // Purpur - Add compass command
|
||||
+ private boolean ramBar = false; // Purpur - Implement rambar commands
|
||||
|
||||
// Paper start - rewrite chunk system
|
||||
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
|
||||
@@ -561,6 +_,10 @@
|
||||
if (tag != null) {
|
||||
BlockPos.CODEC.parse(NbtOps.INSTANCE, tag).resultOrPartial(LOGGER::error).ifPresent(pos -> this.raidOmenPosition = pos);
|
||||
}
|
||||
+
|
||||
+ if (compound.contains("Purpur.TPSBar")) { this.tpsBar = compound.getBoolean("Purpur.TPSBar"); } // Purpur - Implement TPSBar
|
||||
+ if (compound.contains("Purpur.CompassBar")) { this.compassBar = compound.getBoolean("Purpur.CompassBar"); } // Purpur - Add compass command
|
||||
+ if (compound.contains("Purpur.RamBar")) { this.ramBar = compound.getBoolean("Purpur.RamBar"); } // Purpur - Implement rambar command
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -605,6 +_,9 @@
|
||||
}
|
||||
|
||||
this.saveEnderPearls(compound);
|
||||
+ compound.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur - Implement TPSBar
|
||||
+ compound.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur - Add compass command
|
||||
+ compound.putBoolean("Purpur.RamBar", this.ramBar); // Purpur - Add rambar command
|
||||
}
|
||||
|
||||
private void saveParentVehicle(CompoundTag tag) {
|
||||
@@ -1124,6 +_,7 @@
|
||||
)
|
||||
);
|
||||
Team team = this.getTeam();
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendSystemMessage(deathMessage); else // Purpur - Configurable broadcast settings
|
||||
if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) {
|
||||
this.server.getPlayerList().broadcastSystemMessage(deathMessage, false);
|
||||
} else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
|
||||
@@ -1217,6 +_,13 @@
|
||||
if (this.isInvulnerableTo(level, damageSource)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // Purpur start - Add boat fall damage config
|
||||
+ if (damageSource.is(net.minecraft.tags.DamageTypeTags.IS_FALL)) {
|
||||
+ if (getRootVehicle() instanceof net.minecraft.world.entity.vehicle.Boat && !level().purpurConfig.boatsDoFallDamage) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Add boat fall damage config
|
||||
Entity entity = damageSource.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))
|
||||
@@ -1446,6 +_,7 @@
|
||||
serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
|
||||
this.unsetRemoved();
|
||||
// CraftBukkit end
|
||||
+ this.portalPos = io.papermc.paper.util.MCUtil.toBlockPosition(exit); // Purpur - Fix stuck in portals
|
||||
this.setServerLevel(level);
|
||||
this.connection.internalTeleport(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); // CraftBukkit - use internal teleport without event
|
||||
this.connection.resetPosition();
|
||||
@@ -1564,7 +_,7 @@
|
||||
new AABB(vec3.x() - 8.0, vec3.y() - 5.0, vec3.z() - 8.0, vec3.x() + 8.0, vec3.y() + 5.0, vec3.z() + 8.0),
|
||||
monster -> monster.isPreventingPlayerRest(this.serverLevel(), this)
|
||||
);
|
||||
- if (!entitiesOfClass.isEmpty()) {
|
||||
+ if (!this.level().purpurConfig.playerSleepNearMonsters && !entitiesOfClass.isEmpty()) { // Purpur - Config to ignore nearby mobs when sleeping
|
||||
return Either.left(Player.BedSleepingProblem.NOT_SAFE);
|
||||
}
|
||||
}
|
||||
@@ -1601,7 +_,19 @@
|
||||
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
|
||||
});
|
||||
if (!this.serverLevel().canSleepThroughNights()) {
|
||||
- this.displayClientMessage(Component.translatable("sleep.not_possible"), true);
|
||||
+ // 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.displayClientMessage(clientMessage, true);
|
||||
+ }
|
||||
+ // Purpur end - Customizable sleeping actionbar messages
|
||||
}
|
||||
|
||||
((ServerLevel)this.level()).updateSleepingPlayerList();
|
||||
@@ -1709,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {
|
||||
+ if (level().purpurConfig.signAllowColors) this.connection.send(signEntity.getTranslatedUpdatePacket(textFilteringEnabled, isFrontText)); // Purpur - Signs allow color codes
|
||||
this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signEntity.getBlockPos()));
|
||||
this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText));
|
||||
}
|
||||
@@ -2014,6 +_,26 @@
|
||||
this.lastSentExp = -1; // CraftBukkit - Added to reset
|
||||
}
|
||||
|
||||
+ // Purpur start - Component related conveniences
|
||||
+ public void sendActionBarMessage(@Nullable String message) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ sendActionBarMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendActionBarMessage(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ if (message != null) {
|
||||
+ sendActionBarMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendActionBarMessage(@Nullable Component message) {
|
||||
+ if (message != null) {
|
||||
+ displayClientMessage(message, true);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Component related conveniences
|
||||
+
|
||||
@Override
|
||||
public void displayClientMessage(Component chatComponent, boolean actionBar) {
|
||||
this.sendSystemMessage(chatComponent, actionBar);
|
||||
@@ -2235,6 +_,20 @@
|
||||
);
|
||||
}
|
||||
|
||||
+ // Purpur start - Component related conveniences
|
||||
+ public void sendMiniMessage(@Nullable String message) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendMessage(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ if (message != null) {
|
||||
+ this.sendSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message));
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Component related conveniences
|
||||
+
|
||||
public void sendSystemMessage(Component mesage) {
|
||||
this.sendSystemMessage(mesage, false);
|
||||
}
|
||||
@@ -2373,7 +_,67 @@
|
||||
|
||||
public void resetLastActionTime() {
|
||||
this.lastActionTime = Util.getMillis();
|
||||
- }
|
||||
+ this.setAfk(false); // Purpur - AFK API
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - AFK API
|
||||
+ private boolean isAfk = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public void setAfk(boolean afk) {
|
||||
+ if (this.isAfk == afk) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ String msg = afk ? org.purpurmc.purpur.PurpurConfig.afkBroadcastAway : org.purpurmc.purpur.PurpurConfig.afkBroadcastBack;
|
||||
+
|
||||
+ org.purpurmc.purpur.event.PlayerAFKEvent event = new org.purpurmc.purpur.event.PlayerAFKEvent(this.getBukkitEntity(), afk, this.level().purpurConfig.idleTimeoutKick, msg, !org.bukkit.Bukkit.isPrimaryThread());
|
||||
+ if (!event.callEvent() || event.shouldKick()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.isAfk = afk;
|
||||
+
|
||||
+ if (!afk) {
|
||||
+ resetLastActionTime();
|
||||
+ }
|
||||
+
|
||||
+ msg = event.getBroadcastMsg();
|
||||
+ if (msg != null && !msg.isEmpty()) {
|
||||
+ String playerName = this.getGameProfile().getName();
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.afkBroadcastUseDisplayName) {
|
||||
+ net.kyori.adventure.text.Component playerDisplayNameComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getBukkitEntity().getDisplayName());
|
||||
+ playerName = net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(playerDisplayNameComponent);
|
||||
+ }
|
||||
+ server.getPlayerList().broadcastMiniMessage(String.format(msg, playerName), false);
|
||||
+ }
|
||||
+
|
||||
+ if (this.level().purpurConfig.idleTimeoutUpdateTabList) {
|
||||
+ String scoreboardName = getScoreboardName();
|
||||
+ String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName());
|
||||
+ String[] split = playerListName.split(scoreboardName);
|
||||
+ String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, "");
|
||||
+ String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, "");
|
||||
+ if (afk) {
|
||||
+ getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true);
|
||||
+ } else {
|
||||
+ getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix, true);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ((ServerLevel) this.level()).updateSleepingPlayerList();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isAfk() {
|
||||
+ return this.isAfk;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canBeCollidedWith() {
|
||||
+ return !this.isAfk() && super.canBeCollidedWith();
|
||||
+ }
|
||||
+ // Purpur end - AFK API
|
||||
|
||||
public ServerStatsCounter getStats() {
|
||||
return this.stats;
|
||||
@@ -3078,4 +_,56 @@
|
||||
return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity();
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Purpur start - Add option to teleport to spawn if outside world border
|
||||
+ public void teleport(org.bukkit.Location to) {
|
||||
+ this.ejectPassengers();
|
||||
+ this.stopRiding(true);
|
||||
+
|
||||
+ if (this.isSleeping()) {
|
||||
+ this.stopSleepInBed(true, false);
|
||||
+ }
|
||||
+
|
||||
+ if (this.containerMenu != this.inventoryMenu) {
|
||||
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT);
|
||||
+ }
|
||||
+
|
||||
+ ServerLevel toLevel = ((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle();
|
||||
+ if (this.level() == toLevel) {
|
||||
+ this.connection.teleport(to);
|
||||
+ } else {
|
||||
+ this.server.getPlayerList().respawn(this, true, RemovalReason.KILLED, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.DEATH, to);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Add option to teleport to spawn if outside world border
|
||||
+
|
||||
+ // Purpur start - Implement TPSBar
|
||||
+ public boolean tpsBar() {
|
||||
+ return this.tpsBar;
|
||||
+ }
|
||||
+
|
||||
+ public void tpsBar(boolean tpsBar) {
|
||||
+ this.tpsBar = tpsBar;
|
||||
+ }
|
||||
+ // Purpur end - Implement TPSBar
|
||||
+
|
||||
+ // Purpur start - Add compass command
|
||||
+ public boolean compassBar() {
|
||||
+ return this.compassBar;
|
||||
+ }
|
||||
+
|
||||
+ public void compassBar(boolean compassBar) {
|
||||
+ this.compassBar = compassBar;
|
||||
+ }
|
||||
+ // Purpur end - Add compass command
|
||||
+
|
||||
+ // Purpur start - Add rambar command
|
||||
+ public boolean ramBar() {
|
||||
+ return this.ramBar;
|
||||
+ }
|
||||
+
|
||||
+ public void ramBar(boolean ramBar) {
|
||||
+ this.ramBar = ramBar;
|
||||
+ }
|
||||
+ // Purpur end - Add rambar command
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -351,6 +_,7 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+ if (this.player.level().purpurConfig.slabHalfBreak && this.player.isShiftKeyDown() && blockState.getBlock() instanceof net.minecraft.world.level.block.SlabBlock && ((net.minecraft.world.level.block.SlabBlock) blockState.getBlock()).halfBreak(blockState, pos, this.player)) return true; // Purpur - Break individual slabs when sneaking
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -464,6 +_,7 @@
|
||||
public InteractionHand interactHand;
|
||||
public ItemStack interactItemStack;
|
||||
public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) {
|
||||
+ if (shiftClickMended(stack)) return InteractionResult.SUCCESS; // Purpur - Shift right click to use exp for mending
|
||||
BlockPos blockPos = hitResult.getBlockPos();
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
boolean cancelledBlock = false;
|
||||
@@ -506,7 +_,7 @@
|
||||
boolean flag = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty();
|
||||
boolean flag1 = player.isSecondaryUseActive() && flag;
|
||||
ItemStack itemStack = stack.copy();
|
||||
- if (!flag1) {
|
||||
+ if (!flag1 || (player.level().purpurConfig.composterBulkProcess && blockState.is(net.minecraft.world.level.block.Blocks.COMPOSTER))) { // Purpur - Sneak to bulk process composter
|
||||
InteractionResult interactionResult = blockState.useItemOn(player.getItemInHand(hand), level, player, hand, hitResult);
|
||||
if (interactionResult.consumesAction()) {
|
||||
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockPos, itemStack);
|
||||
@@ -552,4 +_,18 @@
|
||||
public void setLevel(ServerLevel serverLevel) {
|
||||
this.level = serverLevel;
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Shift right click to use exp for mending
|
||||
+ public boolean shiftClickMended(ItemStack itemstack) {
|
||||
+ if (this.player.level().purpurConfig.shiftRightClickRepairsMendingPoints > 0 && this.player.isShiftKeyDown() && this.player.getBukkitEntity().hasPermission("purpur.mending_shift_click")) {
|
||||
+ int points = Math.min(this.player.totalExperience, this.player.level().purpurConfig.shiftRightClickRepairsMendingPoints);
|
||||
+ if (points > 0 && itemstack.isDamaged() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.MENDING, itemstack) > 0) {
|
||||
+ this.player.giveExperiencePoints(-points);
|
||||
+ this.player.level().addFreshEntity(new net.minecraft.world.entity.ExperienceOrb(this.player.level(), this.player.getX(), this.player.getY(), this.player.getZ(), points, org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN, this.player, this.player));
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Purpur end - Shift right click to use exp for mending
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -312,6 +_,7 @@
|
||||
return true;
|
||||
} else {
|
||||
// Paper start - Buffer OOB setBlock calls
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressSetBlockFarChunk) // Purpur - Logger settings (suppressing pointless logs)
|
||||
if (!hasSetFarWarned) {
|
||||
Util.logAndPauseIfInIde(
|
||||
"Detected setBlock in a far chunk ["
|
||||
@@ -0,0 +1,72 @@
|
||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -41,6 +_,7 @@
|
||||
private long keepAliveChallenge;
|
||||
private long closedListenerTime;
|
||||
private boolean closed = false;
|
||||
+ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur - Alternative Keepalive Handling
|
||||
private int latency;
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
// CraftBukkit start
|
||||
@@ -51,6 +_,7 @@
|
||||
public final java.util.Map<java.util.UUID, net.kyori.adventure.resource.ResourcePackCallback> packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
|
||||
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
protected static final net.minecraft.resources.ResourceLocation MINECRAFT_BRAND = net.minecraft.resources.ResourceLocation.withDefaultNamespace("brand"); // Paper - Brand support
|
||||
+ protected static final net.minecraft.resources.ResourceLocation PURPUR_CLIENT = net.minecraft.resources.ResourceLocation.fromNamespaceAndPath("purpur", "client"); // Purpur - Purpur client support
|
||||
|
||||
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie, net.minecraft.server.level.ServerPlayer player) { // CraftBukkit
|
||||
this.server = server;
|
||||
@@ -118,6 +_,16 @@
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||
+ // Purpur start - Alternative Keepalive Handling
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) {
|
||||
+ if (this.keepAlivePending && !keepAlives.isEmpty() && keepAlives.contains(packet.getId())) {
|
||||
+ int ping = (int) (Util.getMillis() - packet.getId());
|
||||
+ this.latency = (this.latency * 3 + ping) / 4;
|
||||
+ this.keepAlivePending = false;
|
||||
+ keepAlives.clear(); // we got a valid response, lets roll with it and forget the rest
|
||||
+ }
|
||||
+ } else
|
||||
+ // Purpur end - Alternative Keepalive Handling
|
||||
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||
int i = (int)(Util.getMillis() - this.keepAliveTime);
|
||||
this.latency = (this.latency * 3 + i) / 4;
|
||||
@@ -159,6 +_,13 @@
|
||||
ServerGamePacketListenerImpl.LOGGER.error("Couldn't register custom payload", ex);
|
||||
this.disconnect(Component.literal("Invalid payload REGISTER!"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
||||
}
|
||||
+ // Purpur start - Purpur client support
|
||||
+ } else if (identifier.equals(PURPUR_CLIENT)) {
|
||||
+ try {
|
||||
+ player.purpurClient = true;
|
||||
+ } catch (Exception ignore) {
|
||||
+ }
|
||||
+ // Purpur end - Purpur client support
|
||||
} else if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER)) {
|
||||
try {
|
||||
String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
@@ -238,6 +_,22 @@
|
||||
// Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||
// This should effectively place the keepalive handling back to "as it was" before 1.12.2
|
||||
final long elapsedTime = millis - this.keepAliveTime;
|
||||
+
|
||||
+ // Purpur start - Alternative Keepalive Handling
|
||||
+ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) {
|
||||
+ if (elapsedTime >= 1000L) { // 1 second
|
||||
+ if (this.keepAlivePending && !this.processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) {
|
||||
+ this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
|
||||
+ } else if (this.checkIfClosed(millis)) {
|
||||
+ this.keepAlivePending = true;
|
||||
+ this.keepAliveTime = millis; // hijack this field for 1 second intervals
|
||||
+ this.keepAlives.add(millis); // currentTime is ID
|
||||
+ this.send(new ClientboundKeepAlivePacket(millis));
|
||||
+ }
|
||||
+ }
|
||||
+ } else
|
||||
+ // Purpur end - Alternative Keepalive Handling
|
||||
+
|
||||
if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
|
||||
if (this.keepAlivePending) {
|
||||
if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
@@ -0,0 +1,224 @@
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -326,6 +_,20 @@
|
||||
this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat
|
||||
}
|
||||
|
||||
+ // Purpur start - AFK API
|
||||
+ private final com.google.common.cache.LoadingCache<org.bukkit.craftbukkit.entity.CraftPlayer, Boolean> kickPermissionCache = com.google.common.cache.CacheBuilder.newBuilder()
|
||||
+ .maximumSize(1000)
|
||||
+ .expireAfterWrite(1, java.util.concurrent.TimeUnit.MINUTES)
|
||||
+ .build(
|
||||
+ new com.google.common.cache.CacheLoader<>() {
|
||||
+ @Override
|
||||
+ public Boolean load(org.bukkit.craftbukkit.entity.CraftPlayer player) {
|
||||
+ return player.hasPermission("purpur.bypassIdleKick");
|
||||
+ }
|
||||
+ }
|
||||
+ );
|
||||
+ // Purpur end - AFK API
|
||||
+
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.ackBlockChangesUpTo > -1) {
|
||||
@@ -384,6 +_,12 @@
|
||||
if (this.player.getLastActionTime() > 0L
|
||||
&& this.server.getPlayerIdleTimeout() > 0
|
||||
&& Util.getMillis() - this.player.getLastActionTime() > this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits
|
||||
+ // Purpur start - AFK API
|
||||
+ this.player.setAfk(true);
|
||||
+ if (!this.player.level().purpurConfig.idleTimeoutKick || (!Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK")) && kickPermissionCache.getUnchecked(this.player.getBukkitEntity()))) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Purpur end - AFK API
|
||||
this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
|
||||
}
|
||||
@@ -629,6 +_,8 @@
|
||||
this.lastYaw = to.getYaw();
|
||||
this.lastPitch = to.getPitch();
|
||||
|
||||
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur - AFK API
|
||||
+
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
@@ -709,6 +_,7 @@
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
if (packet.getId() == this.awaitingTeleport) {
|
||||
if (this.awaitingPositionFromClient == null) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn("Disconnected on accept teleport packet. Was not expecting position data from client at this time"); // Purpur - Add more logger output for invalid movement kicks
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
|
||||
return;
|
||||
}
|
||||
@@ -1176,6 +_,10 @@
|
||||
final int maxBookPageSize = pageMax.intValue();
|
||||
final double multiplier = Math.clamp(io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier, 0.3D, 1D);
|
||||
long byteAllowed = maxBookPageSize;
|
||||
+ // Purpur start - PlayerBookTooLargeEvent
|
||||
+ int slot = packet.slot();
|
||||
+ ItemStack itemstack = Inventory.isHotbarSlot(slot) || slot == Inventory.SLOT_OFFHAND ? this.player.getInventory().getItem(slot) : ItemStack.EMPTY;
|
||||
+ // Purpur end - PlayerBookTooLargeEvent
|
||||
for (final String page : pageList) {
|
||||
final int byteLength = page.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;
|
||||
byteTotal += byteLength;
|
||||
@@ -1200,7 +_,8 @@
|
||||
}
|
||||
|
||||
if (byteTotal > byteAllowed) {
|
||||
- ServerGamePacketListenerImpl.LOGGER.warn("{} tried to send a book too large. Book size: {} - Allowed: {} - Pages: {}", this.player.getScoreboardName(), byteTotal, byteAllowed, pageList.size());
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to send too large of a book. Book size: {} - Allowed: {} - Pages: {}", this.player.getScoreboardName(), byteTotal, byteAllowed, pageList.size());
|
||||
+ org.purpurmc.purpur.event.player.PlayerBookTooLargeEvent event = new org.purpurmc.purpur.event.player.PlayerBookTooLargeEvent(player.getBukkitEntity(), itemstack.asBukkitCopy()); if (event.shouldKickPlayer()) // Purpur - PlayerBookTooLargeEvent
|
||||
this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -1219,31 +_,45 @@
|
||||
Optional<String> optional = packet.title();
|
||||
optional.ifPresent(list::add);
|
||||
list.addAll(packet.pages());
|
||||
+ // Purpur start - Allow color codes in books
|
||||
+ boolean hasEditPerm = getCraftPlayer().hasPermission("purpur.book.color.edit");
|
||||
+ boolean hasSignPerm = hasEditPerm || getCraftPlayer().hasPermission("purpur.book.color.sign");
|
||||
+ // Purpur end - Allow color codes in books
|
||||
Consumer<List<FilteredText>> consumer = optional.isPresent()
|
||||
- ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot)
|
||||
- : texts -> this.updateBookContents(texts, slot);
|
||||
+ ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot, hasSignPerm) // Purpur - Allow color codes in books
|
||||
+ : texts -> this.updateBookContents(texts, slot, hasEditPerm); // Purpur - Allow color codes in books
|
||||
this.filterTextPacket(list).thenAcceptAsync(consumer, this.server);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBookContents(List<FilteredText> pages, int index) {
|
||||
+ // Purpur start - Allow color codes in books
|
||||
+ updateBookContents(pages, index, false);
|
||||
+ }
|
||||
+ private void updateBookContents(List<FilteredText> pages, int index, boolean hasPerm) {
|
||||
+ // Purpur end - Allow color codes in books
|
||||
// CraftBukkit start
|
||||
ItemStack handItem = this.player.getInventory().getItem(index);
|
||||
ItemStack item = handItem.copy();
|
||||
// CraftBukkit end
|
||||
if (item.has(DataComponents.WRITABLE_BOOK_CONTENT)) {
|
||||
- List<Filterable<String>> list = pages.stream().map(this::filterableFromOutgoing).toList();
|
||||
+ List<Filterable<String>> list = pages.stream().map(filteredText -> filterableFromOutgoing(filteredText).map(s -> color(s, hasPerm))).toList(); // Purpur - Allow color codes in books
|
||||
item.set(DataComponents.WRITABLE_BOOK_CONTENT, new WritableBookContent(list));
|
||||
this.player.getInventory().setItem(index, CraftEventFactory.handleEditBookEvent(this.player, index, handItem, item)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent)
|
||||
}
|
||||
}
|
||||
|
||||
private void signBook(FilteredText title, List<FilteredText> pages, int index) {
|
||||
+ // Purpur start - Allow color codes in books
|
||||
+ signBook(title, pages, index, false);
|
||||
+ }
|
||||
+ private void signBook(FilteredText title, List<FilteredText> pages, int index, boolean hasPerm) {
|
||||
+ // Purpur end - Allow color codes in books
|
||||
ItemStack item = this.player.getInventory().getItem(index);
|
||||
if (item.has(DataComponents.WRITABLE_BOOK_CONTENT)) {
|
||||
ItemStack itemStack = item.transmuteCopy(Items.WRITTEN_BOOK);
|
||||
itemStack.remove(DataComponents.WRITABLE_BOOK_CONTENT);
|
||||
- List<Filterable<Component>> list = pages.stream().map(filteredText -> this.filterableFromOutgoing(filteredText).<Component>map(Component::literal)).toList();
|
||||
+ List<Filterable<Component>> list = pages.stream().map((filteredText) -> this.filterableFromOutgoing(filteredText).map(s -> hexColor(s, hasPerm))).toList(); // Purpur - Allow color codes in books
|
||||
itemStack.set(
|
||||
DataComponents.WRITTEN_BOOK_CONTENT,
|
||||
new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getName().getString(), 0, list, true)
|
||||
@@ -1257,6 +_,16 @@
|
||||
return this.player.isTextFilteringEnabled() ? Filterable.passThrough(filteredText.filteredOrEmpty()) : Filterable.from(filteredText);
|
||||
}
|
||||
|
||||
+ // Purpur start - Allow color codes in books
|
||||
+ private Component hexColor(String str, boolean hasPerm) {
|
||||
+ return hasPerm ? PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().deserialize(str)) : Component.literal(str);
|
||||
+ }
|
||||
+
|
||||
+ private String color(String str, boolean hasPerm) {
|
||||
+ return hasPerm ? org.bukkit.ChatColor.color(str, false) : str;
|
||||
+ }
|
||||
+ // Purpur end - Allow color codes in books
|
||||
+
|
||||
@Override
|
||||
public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
@@ -1292,7 +_,15 @@
|
||||
@Override
|
||||
public void handleMovePlayer(ServerboundMovePlayerPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
|
||||
- if (containsInvalidValues(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0), packet.getYRot(0.0F), packet.getXRot(0.0F))) {
|
||||
+ // Purpur start - Add more logger output for invalid movement kicks
|
||||
+ boolean invalidX = Double.isNaN(packet.getX(0.0));
|
||||
+ boolean invalidY = Double.isNaN(packet.getY(0.0));
|
||||
+ boolean invalidZ = Double.isNaN(packet.getZ(0.0));
|
||||
+ boolean invalidYaw = !Floats.isFinite(packet.getYRot(0.0F));
|
||||
+ boolean invalidPitch = !Floats.isFinite(packet.getXRot(0.0F));
|
||||
+ if (invalidX || invalidY || invalidZ || invalidYaw || invalidPitch) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(String.format("Disconnected on move player packet. Invalid data: x=%b, y=%b, z=%b, yaw=%b, pitch=%b", invalidX, invalidY, invalidZ, invalidYaw, invalidPitch));
|
||||
+ // Purpur end - Add more logger output for invalid movement kicks
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
|
||||
} else {
|
||||
ServerLevel serverLevel = this.player.serverLevel();
|
||||
@@ -1467,7 +_,7 @@
|
||||
movedWrongly = true;
|
||||
if (event.getLogWarning())
|
||||
// Paper end
|
||||
- LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
|
||||
+ LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), verticalDelta); // Purpur - AFK API
|
||||
} // Paper
|
||||
}
|
||||
|
||||
@@ -1533,6 +_,8 @@
|
||||
this.lastYaw = to.getYaw();
|
||||
this.lastPitch = to.getPitch();
|
||||
|
||||
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur - AFK API
|
||||
+
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
@@ -1589,6 +_,13 @@
|
||||
this.player.tryResetCurrentImpulseContext();
|
||||
}
|
||||
|
||||
+ // Purpur start - Dont run with scissors!
|
||||
+ if (this.player.serverLevel().purpurConfig.dontRunWithScissors && this.player.isSprinting() && !(this.player.serverLevel().purpurConfig.ignoreScissorsInWater && this.player.isInWater()) && !(this.player.serverLevel().purpurConfig.ignoreScissorsInLava && this.player.isInLava()) && (isScissors(this.player.getItemInHand(InteractionHand.MAIN_HAND)) || isScissors(this.player.getItemInHand(InteractionHand.OFF_HAND))) && (int) (Math.random() * 10) == 0) {
|
||||
+ this.player.hurtServer(this.player.serverLevel(), this.player.damageSources().scissors(), (float) this.player.serverLevel().purpurConfig.scissorsRunningDamage);
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.dontRunWithScissors.isBlank()) this.player.sendActionBarMessage(org.purpurmc.purpur.PurpurConfig.dontRunWithScissors);
|
||||
+ }
|
||||
+ // Purpur end - Dont run with scissors!
|
||||
+
|
||||
this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z);
|
||||
this.lastGoodX = this.player.getX();
|
||||
this.lastGoodY = this.player.getY();
|
||||
@@ -1637,6 +_,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start - Dont run with scissors!
|
||||
+ public boolean isScissors(ItemStack stack) {
|
||||
+ if (!stack.is(Items.SHEARS)) return false;
|
||||
+
|
||||
+ ResourceLocation itemModelReference = stack.get(net.minecraft.core.component.DataComponents.ITEM_MODEL);
|
||||
+ if (itemModelReference != null && itemModelReference.equals(this.player.serverLevel().purpurConfig.dontRunWithScissorsItemModelReference)) return true;
|
||||
+
|
||||
+ return stack.getOrDefault(DataComponents.CUSTOM_MODEL_DATA, net.minecraft.world.item.component.CustomModelData.EMPTY).equals(net.minecraft.world.item.component.CustomModelData.EMPTY);
|
||||
+ }
|
||||
+ // Purpur end - Dont run with scissors!
|
||||
+
|
||||
// Paper start - optimise out extra getCubes
|
||||
private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
|
||||
final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
||||
@@ -2001,6 +_,7 @@
|
||||
|
||||
boolean cancelled;
|
||||
if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) {
|
||||
+ if (this.player.gameMode.shiftClickMended(itemInHand)) return; // Purpur - Shift right click to use exp for mending
|
||||
org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemInHand, hand);
|
||||
cancelled = event.useItemInHand() == Event.Result.DENY;
|
||||
} else {
|
||||
@@ -2741,6 +_,7 @@
|
||||
|
||||
AABB boundingBox = target.getBoundingBox();
|
||||
if (this.player.canInteractWithEntity(boundingBox, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(3.0))) { // Paper - configurable lenience value for interact range
|
||||
+ if (target instanceof net.minecraft.world.entity.Mob mob) mob.ticksSinceLastInteraction = 0; // Purpur - Entity lifespan
|
||||
packet.dispatch(
|
||||
new ServerboundInteractPacket.Handler() {
|
||||
private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction entityInteraction, PlayerInteractEntityEvent event) { // CraftBukkit
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -307,7 +_,7 @@
|
||||
ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!");
|
||||
ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(string1)); // Spigot
|
||||
} else {
|
||||
- ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.unverified_username"));
|
||||
+ 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", string1);
|
||||
}
|
||||
} catch (AuthenticationUnavailableException var4) {
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
@@ -37,6 +_,7 @@
|
||||
} else {
|
||||
this.hasRequestedStatus = true;
|
||||
// this.connection.send(new ClientboundStatusResponsePacket(this.status)); // Paper
|
||||
+ if (net.minecraft.server.MinecraftServer.getServer().getStatus().version().isEmpty()) return; // Purpur - Fix 'outdated server' showing in ping before server fully boots - do not respond to pings before we know the protocol version
|
||||
com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(net.minecraft.server.MinecraftServer.getServer(), this.connection); // Paper - handle status request
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -396,6 +_,7 @@
|
||||
scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
|
||||
}
|
||||
// Paper end - Configurable player collision
|
||||
+ org.purpurmc.purpur.task.BossBarTask.addToAll(player); // Purpur - Implement TPSBar
|
||||
PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
|
||||
// Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
|
||||
if (player.isDeadOrDying()) {
|
||||
@@ -501,6 +_,7 @@
|
||||
}
|
||||
public net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
|
||||
// Paper end - Fix kick event leave message not being sent
|
||||
+ org.purpurmc.purpur.task.BossBarTask.removeFromAll(player.getBukkitEntity()); // Purpur - Implement TPSBar
|
||||
ServerLevel serverLevel = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
// CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
|
||||
@@ -665,7 +_,7 @@
|
||||
// return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)
|
||||
// ? Component.translatable("multiplayer.disconnect.server_full")
|
||||
// : null;
|
||||
- if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)) {
|
||||
+ if (this.players.size() >= this.maxPlayers && !(player.hasPermission("purpur.joinfullserver") || this.canBypassPlayerLimit(gameProfile))) { // Purpur - Allow player join full server by permission
|
||||
event.disallow(org.bukkit.event.player.PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
|
||||
}
|
||||
}
|
||||
@@ -919,6 +_,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start - Component related conveniences
|
||||
+ public void broadcastMiniMessage(@Nullable String message, boolean overlay) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ this.broadcastMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message), overlay);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void broadcastMessage(@Nullable net.kyori.adventure.text.Component message, boolean overlay) {
|
||||
+ if (message != null) {
|
||||
+ this.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), overlay);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Component related conveniences
|
||||
+
|
||||
public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
if (serverPlayer.level().dimension() == dimension) {
|
||||
@@ -1002,6 +_,7 @@
|
||||
} else {
|
||||
b = (byte)(24 + permLevel);
|
||||
}
|
||||
+ if (b < 28 && player.getBukkitEntity().hasPermission("purpur.debug.f3n")) b = 28; // Purpur - Add permission for F3+N debug
|
||||
|
||||
player.connection.send(new ClientboundEntityEventPacket(player, b));
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/server/players/SleepStatus.java
|
||||
+++ b/net/minecraft/server/players/SleepStatus.java
|
||||
@@ -15,7 +_,7 @@
|
||||
|
||||
public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List<ServerPlayer> sleepingPlayers) {
|
||||
// CraftBukkit start
|
||||
- int i = (int) sleepingPlayers.stream().filter(player -> player.isSleepingLongEnough() || player.fauxSleeping).count();
|
||||
+ int i = (int) sleepingPlayers.stream().filter(player -> player.isSleepingLongEnough() || player.fauxSleeping || (player.level().purpurConfig.idleTimeoutCountAsSleeping && player.isAfk())).count(); // Purpur - AFK API
|
||||
boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough);
|
||||
return anyDeepSleep && i >= this.sleepersNeeded(requiredSleepPercentage);
|
||||
// CraftBukkit end
|
||||
@@ -43,7 +_,7 @@
|
||||
for (ServerPlayer serverPlayer : players) {
|
||||
if (!serverPlayer.isSpectator()) {
|
||||
this.activePlayers++;
|
||||
- if (serverPlayer.isSleeping() || serverPlayer.fauxSleeping) { // CraftBukkit
|
||||
+ if (serverPlayer.isSleeping() || serverPlayer.fauxSleeping || (serverPlayer.level().purpurConfig.idleTimeoutCountAsSleeping && serverPlayer.isAfk())) { // CraftBukkit // Purpur - AFK API
|
||||
this.sleepingPlayers++;
|
||||
}
|
||||
// CraftBukkit start
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/stats/ServerRecipeBook.java
|
||||
+++ b/net/minecraft/stats/ServerRecipeBook.java
|
||||
@@ -138,6 +_,7 @@
|
||||
try {
|
||||
ResourceKey<Recipe<?>> resourceKey = ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(string));
|
||||
if (!isRecognized.test(resourceKey)) {
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressUnrecognizedRecipeErrors) // Purpur - Logger settings (suppressing pointless logs)
|
||||
LOGGER.error("Tried to load unrecognized recipe: {} removed now.", resourceKey);
|
||||
} else {
|
||||
output.accept(resourceKey);
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/util/StringUtil.java
|
||||
+++ b/net/minecraft/util/StringUtil.java
|
||||
@@ -87,6 +_,7 @@
|
||||
|
||||
// Paper start - Username validation
|
||||
public static boolean isReasonablePlayerName(final String name) {
|
||||
+ if (true) return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(name).matches(); // Purpur - Configurable valid characters for usernames
|
||||
if (name.isEmpty() || name.length() > 16) {
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/world/damagesource/CombatRules.java
|
||||
+++ b/net/minecraft/world/damagesource/CombatRules.java
|
||||
@@ -15,7 +_,7 @@
|
||||
|
||||
public static float getDamageAfterAbsorb(LivingEntity entity, float damage, DamageSource damageSource, float armorValue, float armorToughness) {
|
||||
float f = 2.0F + armorToughness / 4.0F;
|
||||
- float f1 = Mth.clamp(armorValue - damage / f, armorValue * 0.2F, 20.0F);
|
||||
+ float f1 = Mth.clamp(armorValue - damage / f, armorValue * 0.2F, org.purpurmc.purpur.PurpurConfig.limitArmor ? 20F : Float.MAX_VALUE); // Purpur - Add attribute clamping and armor limit config
|
||||
float f2 = f1 / 25.0F;
|
||||
ItemStack weaponItem = damageSource.getWeaponItem();
|
||||
float f3;
|
||||
@@ -30,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static float getDamageAfterMagicAbsorb(float damage, float enchantModifiers) {
|
||||
- float f = Mth.clamp(enchantModifiers, 0.0F, 20.0F);
|
||||
+ float f = Mth.clamp(enchantModifiers, 0.0F, org.purpurmc.purpur.PurpurConfig.limitArmor ? 20F : Float.MAX_VALUE); // Purpur - Add attribute clamping and armor limit config
|
||||
return damage * (1.0F - f / 25.0F);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
--- a/net/minecraft/world/damagesource/CombatTracker.java
|
||||
+++ b/net/minecraft/world/damagesource/CombatTracker.java
|
||||
@@ -54,7 +_,7 @@
|
||||
|
||||
private Component getMessageForAssistedFall(Entity entity, Component entityDisplayName, String hasWeaponTranslationKey, String noWeaponTranslationKey) {
|
||||
ItemStack itemStack = entity instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY;
|
||||
- return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME)
|
||||
+ return !itemStack.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemStack.has(DataComponents.CUSTOM_NAME)) // Purpur - always show item in player death messages
|
||||
? Component.translatable(hasWeaponTranslationKey, this.mob.getDisplayName(), entityDisplayName, itemStack.getDisplayName())
|
||||
: Component.translatable(noWeaponTranslationKey, this.mob.getDisplayName(), entityDisplayName);
|
||||
}
|
||||
@@ -98,6 +_,15 @@
|
||||
Component component = ComponentUtils.wrapInSquareBrackets(Component.translatable(string + ".link")).withStyle(INTENTIONAL_GAME_DESIGN_STYLE);
|
||||
return Component.translatable(string + ".message", this.mob.getDisplayName(), component);
|
||||
} else {
|
||||
+ // Purpur start - Dont run with scissors!
|
||||
+ if (damageSource.isScissors()) {
|
||||
+ return damageSource.getLocalizedDeathMessage(org.purpurmc.purpur.PurpurConfig.deathMsgRunWithScissors, this.mob);
|
||||
+ // Purpur start - Stonecutter damage
|
||||
+ } else if (damageSource.isStonecutter()) {
|
||||
+ return damageSource.getLocalizedDeathMessage(org.purpurmc.purpur.PurpurConfig.deathMsgStonecutter, this.mob);
|
||||
+ // Purpur end - Stonecutter damage
|
||||
+ }
|
||||
+ // Purpur end - Dont run with scissors!
|
||||
return damageSource.getLocalizedDeathMessage(this.mob);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
--- a/net/minecraft/world/damagesource/DamageSource.java
|
||||
+++ b/net/minecraft/world/damagesource/DamageSource.java
|
||||
@@ -28,6 +_,8 @@
|
||||
private boolean sweep = false;
|
||||
private boolean melting = false;
|
||||
private boolean poison = false;
|
||||
+ private boolean scissors = false; // Purpur - Dont run with scissors!
|
||||
+ private boolean stonecutter = false; // Purpur - Stonecutter damage
|
||||
@Nullable
|
||||
private Entity customEventDamager = null; // This field is a helper for when causing entity damage is not set by vanilla // Paper - fix DamageSource API
|
||||
|
||||
@@ -58,6 +_,27 @@
|
||||
return this.poison;
|
||||
}
|
||||
|
||||
+ // Purpur start - Dont run with scissors!
|
||||
+ public DamageSource scissors() {
|
||||
+ this.scissors = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isScissors() {
|
||||
+ return this.scissors;
|
||||
+ }
|
||||
+ // Purpur end - Dont run with scissors!
|
||||
+ // Purpur start - - Stonecutter damage
|
||||
+ public DamageSource stonecutter() {
|
||||
+ this.stonecutter = true;
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isStonecutter() {
|
||||
+ return this.stonecutter;
|
||||
+ }
|
||||
+ // Purpur end - Stonecutter damage
|
||||
+
|
||||
// Paper start - fix DamageSource API
|
||||
@Nullable
|
||||
public Entity getCustomEventDamager() {
|
||||
@@ -118,6 +_,8 @@
|
||||
damageSource.sweep = this.isSweep();
|
||||
damageSource.poison = this.isPoison();
|
||||
damageSource.melting = this.isMelting();
|
||||
+ damageSource.scissors = this.isScissors(); // Purpur - Dont run with scissors!
|
||||
+ damageSource.stonecutter = this.isStonecutter(); // Purpur - Stonecutter damage
|
||||
return damageSource;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -184,11 +_,20 @@
|
||||
} else {
|
||||
Component component = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName();
|
||||
ItemStack itemStack = this.causingEntity instanceof LivingEntity livingEntity1 ? livingEntity1.getMainHandItem() : ItemStack.EMPTY;
|
||||
- return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME)
|
||||
+ return !itemStack.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemStack.has(DataComponents.CUSTOM_NAME)) // Purpur - always show item in player death messages
|
||||
? Component.translatable(string + ".item", livingEntity.getDisplayName(), component, itemStack.getDisplayName())
|
||||
: Component.translatable(string, livingEntity.getDisplayName(), component);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Component related conveniences
|
||||
+ public Component getLocalizedDeathMessage(String str, LivingEntity entity) {
|
||||
+ net.kyori.adventure.text.Component name = io.papermc.paper.adventure.PaperAdventure.asAdventure(entity.getDisplayName());
|
||||
+ net.kyori.adventure.text.minimessage.tag.resolver.TagResolver template = net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("player", name);
|
||||
+ net.kyori.adventure.text.Component component = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(str, template);
|
||||
+ return io.papermc.paper.adventure.PaperAdventure.asVanilla(component);
|
||||
+ }
|
||||
+ // Purpur end - Component related conveniences
|
||||
|
||||
public String getMsgId() {
|
||||
return this.type().msgId();
|
||||
@@ -0,0 +1,36 @@
|
||||
--- a/net/minecraft/world/damagesource/DamageSources.java
|
||||
+++ b/net/minecraft/world/damagesource/DamageSources.java
|
||||
@@ -45,11 +_,15 @@
|
||||
// CraftBukkit start
|
||||
private final DamageSource melting;
|
||||
private final DamageSource poison;
|
||||
+ private final DamageSource scissors; // Purpur - Dont run with scissors!
|
||||
+ private final DamageSource stonecutter; // Purpur - Stonecutter damage
|
||||
|
||||
public DamageSources(RegistryAccess registry) {
|
||||
this.damageTypes = registry.lookupOrThrow(Registries.DAMAGE_TYPE);
|
||||
this.melting = this.source(DamageTypes.ON_FIRE).melting();
|
||||
this.poison = this.source(DamageTypes.MAGIC).poison();
|
||||
+ this.scissors = this.source(DamageTypes.MAGIC).scissors(); // Purpur - Dont run with scissors!
|
||||
+ this.stonecutter = this.source(DamageTypes.MAGIC).stonecutter(); // Purpur - Stonecutter damage
|
||||
// CraftBukkit end
|
||||
this.inFire = this.source(DamageTypes.IN_FIRE);
|
||||
this.campfire = this.source(DamageTypes.CAMPFIRE);
|
||||
@@ -100,6 +_,17 @@
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Purpur start - Dont run with scissors!
|
||||
+ public DamageSource scissors() {
|
||||
+ return this.scissors;
|
||||
+ }
|
||||
+ // Purpur end - Dont run with scissors!
|
||||
+
|
||||
+ // Purpur start - Stonecutter damage
|
||||
+ public DamageSource stonecutter() {
|
||||
+ return this.stonecutter;
|
||||
+ }
|
||||
+ // Purpur end - Stonecutter damage
|
||||
public DamageSource inFire() {
|
||||
return this.inFire;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/effect/HungerMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/HungerMobEffect.java
|
||||
@@ -12,7 +_,7 @@
|
||||
@Override
|
||||
public boolean applyEffectTick(ServerLevel level, LivingEntity entity, int amplifier) {
|
||||
if (entity instanceof Player player) {
|
||||
- player.causeFoodExhaustion(0.005F * (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent
|
||||
+ player.causeFoodExhaustion(entity.level().purpurConfig.humanHungerExhaustionAmount * (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent // Purpur - Config MobEffect by world
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/world/effect/PoisonMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/PoisonMobEffect.java
|
||||
@@ -12,8 +_,8 @@
|
||||
|
||||
@Override
|
||||
public boolean applyEffectTick(ServerLevel level, LivingEntity entity, int amplifier) {
|
||||
- if (entity.getHealth() > 1.0F) {
|
||||
- entity.hurtServer(level, entity.damageSources().poison(), 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON
|
||||
+ if (entity.getHealth() > entity.level().purpurConfig.entityMinimalHealthPoison) { // Purpur
|
||||
+ entity.hurtServer(level, entity.damageSources().poison(), entity.level().purpurConfig.entityPoisonDegenerationAmount); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON // Purpur - Config MobEffect by world
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/effect/RegenerationMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/RegenerationMobEffect.java
|
||||
@@ -11,7 +_,7 @@
|
||||
@Override
|
||||
public boolean applyEffectTick(ServerLevel level, LivingEntity entity, int amplifier) {
|
||||
if (entity.getHealth() < entity.getMaxHealth()) {
|
||||
- entity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit
|
||||
+ entity.heal(entity.level().purpurConfig.entityHealthRegenAmount, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit // Purpur - Config MobEffect by world
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/effect/SaturationMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/SaturationMobEffect.java
|
||||
@@ -16,7 +_,8 @@
|
||||
int oldFoodLevel = player.getFoodData().foodLevel;
|
||||
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, amplifier + 1 + oldFoodLevel);
|
||||
if (!event.isCancelled()) {
|
||||
- player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F);
|
||||
+ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur - Burp delay
|
||||
+ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, entity.level().purpurConfig.humanSaturationRegenAmount); // Purpur - Config MobEffect by world
|
||||
}
|
||||
|
||||
((org.bukkit.craftbukkit.entity.CraftPlayer) player.getBukkitEntity()).sendHealthUpdate();
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/effect/WitherMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/WitherMobEffect.java
|
||||
@@ -12,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean applyEffectTick(ServerLevel level, LivingEntity entity, int amplifier) {
|
||||
- entity.hurtServer(level, entity.damageSources().wither(), 1.0F);
|
||||
+ entity.hurtServer(level, entity.damageSources().wither(), entity.level().purpurConfig.entityWitherDegenerationAmount); // Purpur - Config MobEffect by world
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -136,7 +_,7 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
|
||||
-
|
||||
+ public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes
|
||||
// CraftBukkit start
|
||||
private static final int CURRENT_LEVEL = 2;
|
||||
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation
|
||||
@@ -253,9 +_,10 @@
|
||||
public double xOld;
|
||||
public double yOld;
|
||||
public double zOld;
|
||||
+ public float maxUpStep; // Purpur - Add option to set armorstand step height
|
||||
public boolean noPhysics;
|
||||
private boolean wasOnFire;
|
||||
- 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 int tickCount;
|
||||
private int remainingFireTicks = -this.getFireImmuneTicks();
|
||||
public boolean wasTouchingWater;
|
||||
@@ -289,8 +_,8 @@
|
||||
public PortalProcessor portalProcess;
|
||||
public int portalCooldown;
|
||||
private boolean invulnerable;
|
||||
- protected UUID uuid = Mth.createInsecureUUID(this.random);
|
||||
- protected String stringUUID = this.uuid.toString();
|
||||
+ protected UUID uuid; // Purpur - Add toggle for RNG manipulation
|
||||
+ protected String stringUUID; // Purpur - Add toggle for RNG manipulation
|
||||
private boolean hasGlowingTag;
|
||||
private final Set<String> tags = new io.papermc.paper.util.SizeLimitedSet<>(new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(), MAX_ENTITY_TAG_COUNT); // Paper - fully limit tag size - replace set impl
|
||||
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
|
||||
@@ -342,6 +_,7 @@
|
||||
public long activatedTick = Integer.MIN_VALUE;
|
||||
public boolean isTemporarilyActive;
|
||||
public long activatedImmunityTick = Integer.MIN_VALUE;
|
||||
+ public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API
|
||||
|
||||
public void inactiveTick() {
|
||||
}
|
||||
@@ -522,10 +_,21 @@
|
||||
}
|
||||
// Paper end - optimise entity tracker
|
||||
|
||||
+ // Purpur start - Add canSaveToDisk to Entity
|
||||
+ public boolean canSaveToDisk() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Purpur end - Add canSaveToDisk to Entity
|
||||
+
|
||||
public Entity(EntityType<?> entityType, Level level) {
|
||||
this.type = entityType;
|
||||
this.level = level;
|
||||
this.dimensions = entityType.getDimensions();
|
||||
+ // Purpur start - Add toggle for RNG manipulation
|
||||
+ this.random = level == null || level.purpurConfig.entitySharedRandom ? SHARED_RANDOM : RandomSource.create();
|
||||
+ this.uuid = Mth.createInsecureUUID(this.random);
|
||||
+ this.stringUUID = this.uuid.toString();
|
||||
+ // Purpur end - Add toggle for RNG manipulation
|
||||
this.position = Vec3.ZERO;
|
||||
this.blockPosition = BlockPos.ZERO;
|
||||
this.chunkPosition = ChunkPos.ZERO;
|
||||
@@ -904,6 +_,7 @@
|
||||
&& this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
|
||||
&& (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
|
||||
// Paper end - Configurable nether ceiling damage
|
||||
+ if (this.level.purpurConfig.teleportOnNetherCeilingDamage && this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this instanceof ServerPlayer player) player.teleport(io.papermc.paper.util.MCUtil.toLocation(this.level, this.level.getSharedSpawnPos())); else // Purpur - Add option to teleport to spawn on nether ceiling damage
|
||||
this.onBelowWorld();
|
||||
}
|
||||
}
|
||||
@@ -1826,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean fireImmune() {
|
||||
- return this.getType().fireImmune();
|
||||
+ return this.immuneToFire != null ? immuneToFire : this.getType().fireImmune(); // Purpur - add fire immune API
|
||||
}
|
||||
|
||||
public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) {
|
||||
@@ -1895,7 +_,7 @@
|
||||
return this.isInWater() || flag;
|
||||
}
|
||||
|
||||
- public void updateInWaterStateAndDoWaterCurrentPushing() {
|
||||
+ public void updateInWaterStateAndDoWaterCurrentPushing() { // Purpur - Movement options for armor stands - package-private -> public - TODO: use AT file
|
||||
if (this.getVehicle() instanceof AbstractBoat abstractBoat && !abstractBoat.isUnderWater()) {
|
||||
this.wasTouchingWater = false;
|
||||
} else if (this.updateFluidHeightAndDoFluidPushing(FluidTags.WATER, 0.014)) {
|
||||
@@ -2521,6 +_,13 @@
|
||||
compound.putBoolean("Paper.FreezeLock", true);
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start - Fire immune API
|
||||
+ if (immuneToFire != null) {
|
||||
+ compound.putBoolean("Purpur.FireImmune", immuneToFire);
|
||||
+ }
|
||||
+ // Purpur end - Fire immune API
|
||||
+
|
||||
return compound;
|
||||
} catch (Throwable var9) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT");
|
||||
@@ -2670,6 +_,13 @@
|
||||
freezeLocked = compound.getBoolean("Paper.FreezeLock");
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start - Fire immune API
|
||||
+ if (compound.contains("Purpur.FireImmune")) {
|
||||
+ immuneToFire = compound.getBoolean("Purpur.FireImmune");
|
||||
+ }
|
||||
+ // Purpur end - Fire immune API
|
||||
+
|
||||
} catch (Throwable var17) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded");
|
||||
@@ -2916,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.AbstractVillager) return InteractionResult.CONSUME; // Purpur - Allow leashing villagers
|
||||
// CraftBukkit start - fire PlayerUnleashEntityEvent
|
||||
// Paper start - Expand EntityUnleashEvent
|
||||
org.bukkit.event.player.PlayerUnleashEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials());
|
||||
@@ -3241,15 +_,18 @@
|
||||
return Vec3.directionFromRotation(this.getRotationVector());
|
||||
}
|
||||
|
||||
+ public BlockPos portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals
|
||||
public void setAsInsidePortal(Portal portal, BlockPos pos) {
|
||||
if (this.isOnPortalCooldown()) {
|
||||
+ if (!(level().purpurConfig.playerFixStuckPortal && this instanceof Player && !pos.equals(this.portalPos))) // Purpur - Fix stuck in portals
|
||||
this.setPortalCooldown();
|
||||
- } else {
|
||||
+ } else if (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer) { // Purpur - Entities can use portals
|
||||
if (this.portalProcess == null || !this.portalProcess.isSamePortal(portal)) {
|
||||
this.portalProcess = new PortalProcessor(portal, pos.immutable());
|
||||
} else if (!this.portalProcess.isInsidePortalThisTick()) {
|
||||
this.portalProcess.updateEntryPosition(pos.immutable());
|
||||
this.portalProcess.setAsInsidePortalThisTick(true);
|
||||
+ this.portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3454,7 +_,7 @@
|
||||
}
|
||||
|
||||
public int getMaxAirSupply() {
|
||||
- return this.maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
|
||||
+ return this.level == null? this.maxAirTicks : this.level().purpurConfig.drowningAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() // Purpur - Drowning Settings
|
||||
}
|
||||
|
||||
public int getAirSupply() {
|
||||
@@ -3949,7 +_,7 @@
|
||||
// CraftBukkit end
|
||||
|
||||
public boolean canUsePortal(boolean allowPassengers) {
|
||||
- return (allowPassengers || !this.isPassenger()) && this.isAlive();
|
||||
+ return (allowPassengers || !this.isPassenger()) && this.isAlive() && (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer); // Purpur - Entities can use portals
|
||||
}
|
||||
|
||||
public boolean canTeleport(Level fromLevel, Level toLevel) {
|
||||
@@ -4481,6 +_,12 @@
|
||||
return Mth.lerp(partialTick, this.yRotO, this.yRot);
|
||||
}
|
||||
|
||||
+ // Purpur start - Stop squids floating on top of water
|
||||
+ public AABB getAxisForFluidCheck() {
|
||||
+ return this.getBoundingBox().deflate(0.001D);
|
||||
+ }
|
||||
+ // Purpur end - Stop squids floating on top of water
|
||||
+
|
||||
// Paper start - optimise collisions
|
||||
public boolean updateFluidHeightAndDoFluidPushing(final TagKey<Fluid> fluid, final double flowScale) {
|
||||
if (this.touchingUnloadedChunk()) {
|
||||
@@ -4879,7 +_,7 @@
|
||||
}
|
||||
|
||||
public float maxUpStep() {
|
||||
- return 0.0F;
|
||||
+ return maxUpStep; // Purpur - Add option to set armorstand step height
|
||||
}
|
||||
|
||||
public void onExplosionHit(@Nullable Entity entity) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/EntitySelector.java
|
||||
+++ b/net/minecraft/world/entity/EntitySelector.java
|
||||
@@ -28,6 +_,8 @@
|
||||
return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks;
|
||||
};
|
||||
// Paper end - Ability to control player's insomnia and phantoms
|
||||
+ public static Predicate<Player> notAfk = (player) -> !player.isAfk(); // Purpur - AFK API
|
||||
+
|
||||
// Paper start - Affects Spawning API
|
||||
public static final Predicate<Entity> PLAYER_AFFECTS_SPAWNING = (entity) -> {
|
||||
return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning;
|
||||
@@ -0,0 +1,52 @@
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -1083,6 +_,16 @@
|
||||
return register(vanillaEntityId(key), builder);
|
||||
}
|
||||
|
||||
+ // Purpur start - PlayerSetSpawnerTypeWithEggEvent
|
||||
+ public static EntityType<?> getFromBukkitType(org.bukkit.entity.EntityType bukkitType) {
|
||||
+ return getFromKey(ResourceLocation.parse(bukkitType.getKey().toString()));
|
||||
+ }
|
||||
+
|
||||
+ public static EntityType<?> getFromKey(ResourceLocation location) {
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getValue(location);
|
||||
+ }
|
||||
+ // Purpur end - PlayerSetSpawnerTypeWithEggEvent
|
||||
+
|
||||
public static ResourceLocation getKey(EntityType<?> entityType) {
|
||||
return BuiltInRegistries.ENTITY_TYPE.getKey(entityType);
|
||||
}
|
||||
@@ -1312,6 +_,16 @@
|
||||
return this.category;
|
||||
}
|
||||
|
||||
+ // Purpur start - PlayerSetSpawnerTypeWithEggEvent
|
||||
+ public String getName() {
|
||||
+ return BuiltInRegistries.ENTITY_TYPE.getKey(this).getPath();
|
||||
+ }
|
||||
+
|
||||
+ public String getTranslatedName() {
|
||||
+ return getDescription().getString();
|
||||
+ }
|
||||
+ // Purpur end - PlayerSetSpawnerTypeWithEggEvent
|
||||
+
|
||||
public String getDescriptionId() {
|
||||
return this.descriptionId;
|
||||
}
|
||||
@@ -1370,7 +_,14 @@
|
||||
entity.load(tag);
|
||||
},
|
||||
// Paper end - Don't fire sync event during generation
|
||||
- () -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id"))
|
||||
+ // Purpur start - log skipped entity's position
|
||||
+ () -> {LOGGER.warn("Skipping Entity with id {}", tag.getString("id"));
|
||||
+ try {
|
||||
+ ListTag pos = tag.getList("Pos", 6);
|
||||
+ EntityType.LOGGER.warn("Location: {} {},{},{}", level.getWorld().getName(), pos.getDouble(0), pos.getDouble(1), pos.getDouble(2));
|
||||
+ } catch (Throwable ignore) {}
|
||||
+ }
|
||||
+ // Purpur end - log skipped entity's position
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -323,7 +_,7 @@
|
||||
public void playerTouch(Player entity) {
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
|
||||
- entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
|
||||
+ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, this.level().purpurConfig.playerExpPickupDelay, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay
|
||||
entity.take(this, 1);
|
||||
int i = this.repairPlayerItems(serverPlayer, this.value);
|
||||
if (i > 0) {
|
||||
@@ -339,7 +_,7 @@
|
||||
}
|
||||
|
||||
private int repairPlayerItems(ServerPlayer player, int value) {
|
||||
- Optional<EnchantedItemInUse> randomItemWith = EnchantmentHelper.getRandomItemWith(
|
||||
+ Optional<EnchantedItemInUse> randomItemWith = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith( // Purpur - Add option to mend the most damaged equipment first
|
||||
EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged
|
||||
);
|
||||
if (randomItemWith.isPresent()) {
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/net/minecraft/world/entity/GlowSquid.java
|
||||
+++ b/net/minecraft/world/entity/GlowSquid.java
|
||||
@@ -25,6 +_,13 @@
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Flying squids! Oh my!
|
||||
+ @Override
|
||||
+ public boolean canFly() {
|
||||
+ return this.level().purpurConfig.glowSquidsCanFly;
|
||||
+ }
|
||||
+ // Purpur end - Flying squids! Oh my!
|
||||
+
|
||||
@Override
|
||||
protected ParticleOptions getInkParticle() {
|
||||
return ParticleTypes.GLOW_SQUID_INK;
|
||||
@@ -0,0 +1,177 @@
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -459,6 +_,12 @@
|
||||
if (d < 0.0) {
|
||||
double damagePerBlock = this.level().getWorldBorder().getDamagePerBlock();
|
||||
if (damagePerBlock > 0.0) {
|
||||
+ // Purpur start - Add option to teleport to spawn if outside world border
|
||||
+ if (this.level().purpurConfig.teleportIfOutsideBorder && this instanceof ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.teleport(io.papermc.paper.util.MCUtil.toLocation(this.level(), this.level().getSharedSpawnPos()));
|
||||
+ return;
|
||||
+ }
|
||||
+ // Purpur end - Add option to teleport to spawn if outside world border
|
||||
this.hurtServer(serverLevel1, this.damageSources().outOfBorder(), Math.max(1, Mth.floor(-d * damagePerBlock)));
|
||||
}
|
||||
}
|
||||
@@ -472,7 +_,7 @@
|
||||
&& (!flag || !((Player)this).getAbilities().invulnerable);
|
||||
if (flag1) {
|
||||
this.setAirSupply(this.decreaseAirSupply(this.getAirSupply()));
|
||||
- if (this.getAirSupply() == -20) {
|
||||
+ if (this.getAirSupply() == -this.level().purpurConfig.drowningDamageInterval) { // Purpur - Drowning Settings
|
||||
this.setAirSupply(0);
|
||||
Vec3 deltaMovement = this.getDeltaMovement();
|
||||
|
||||
@@ -492,7 +_,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
- this.hurt(this.damageSources().drown(), 2.0F);
|
||||
+ this.hurt(this.damageSources().drown(), (float) this.level().purpurConfig.damageFromDrowning); // Purpur - Drowning Settings
|
||||
}
|
||||
} else if (this.getAirSupply() < this.getMaxAirSupply()) {
|
||||
this.setAirSupply(this.increaseAirSupply(this.getAirSupply()));
|
||||
@@ -1009,14 +_,32 @@
|
||||
if (lookingEntity != null) {
|
||||
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
EntityType<?> type = lookingEntity.getType();
|
||||
- if (type == EntityType.SKELETON && itemBySlot.is(Items.SKELETON_SKULL)
|
||||
- || type == EntityType.ZOMBIE && itemBySlot.is(Items.ZOMBIE_HEAD)
|
||||
- || type == EntityType.PIGLIN && itemBySlot.is(Items.PIGLIN_HEAD)
|
||||
- || type == EntityType.PIGLIN_BRUTE && itemBySlot.is(Items.PIGLIN_HEAD)
|
||||
- || type == EntityType.CREEPER && itemBySlot.is(Items.CREEPER_HEAD)) {
|
||||
- d *= 0.5;
|
||||
- }
|
||||
- }
|
||||
+ // Purpur start - Mob head visibility percent
|
||||
+ if (type == EntityType.SKELETON && itemBySlot.is(Items.SKELETON_SKULL)) {
|
||||
+ d *= lookingEntity.level().purpurConfig.skeletonHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if (type == EntityType.ZOMBIE && itemBySlot.is(Items.ZOMBIE_HEAD)) {
|
||||
+ d *= lookingEntity.level().purpurConfig.zombieHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if ((type == EntityType.PIGLIN || type == EntityType.PIGLIN_BRUTE) && itemBySlot.is(Items.PIGLIN_HEAD)) {
|
||||
+ d *= lookingEntity.level().purpurConfig.piglinHeadVisibilityPercent;
|
||||
+ }
|
||||
+ else if (type == EntityType.CREEPER && itemBySlot.is(Items.CREEPER_HEAD)) {
|
||||
+ d *= lookingEntity.level().purpurConfig.creeperHeadVisibilityPercent;
|
||||
+ }
|
||||
+ // Purpur end - Mob head visibility percent
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - Configurable mob blindness
|
||||
+ if (lookingEntity instanceof LivingEntity entityliving) {
|
||||
+ if (entityliving.hasEffect(MobEffects.BLINDNESS)) {
|
||||
+ int amplifier = entityliving.getEffect(MobEffects.BLINDNESS).getAmplifier();
|
||||
+ for (int i = 0; i < amplifier; i++) {
|
||||
+ d *= this.level().purpurConfig.mobsBlindnessMultiplier;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Configurable mob blindness
|
||||
|
||||
return d;
|
||||
}
|
||||
@@ -1063,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;
|
||||
@@ -1372,6 +_,24 @@
|
||||
this.stopSleeping();
|
||||
}
|
||||
|
||||
+ // Purpur start - One Punch Man!
|
||||
+ if (damageSource.getEntity() instanceof net.minecraft.world.entity.player.Player player && damageSource.getEntity().level().purpurConfig.creativeOnePunch && !damageSource.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!
|
||||
+ amount = 9999F;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - One Punch Man!
|
||||
+
|
||||
this.noActionTime = 0;
|
||||
if (amount < 0.0F) {
|
||||
amount = 0.0F;
|
||||
@@ -1536,11 +_,11 @@
|
||||
protected Player resolvePlayerResponsibleForDamage(DamageSource damageSource) {
|
||||
Entity entity = damageSource.getEntity();
|
||||
if (entity instanceof Player player) {
|
||||
- this.lastHurtByPlayerTime = 100;
|
||||
+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur - Config for mob last hurt by player time
|
||||
this.lastHurtByPlayer = player;
|
||||
return player;
|
||||
} else if (entity instanceof Wolf wolf && wolf.isTame()) {
|
||||
- this.lastHurtByPlayerTime = 100;
|
||||
+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur - Config for mob last hurt by player time
|
||||
if (wolf.getOwner() instanceof Player player1) {
|
||||
this.lastHurtByPlayer = player1;
|
||||
} else {
|
||||
@@ -1594,6 +_,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // 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().items) {
|
||||
+ if (item.getItem() == Items.TOTEM_OF_UNDYING) {
|
||||
+ itemInHand = item;
|
||||
+ itemStack = item.copy();
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Totems work in inventory
|
||||
+
|
||||
final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null;
|
||||
final EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot);
|
||||
event.setCancelled(itemStack == null);
|
||||
@@ -1790,6 +_,7 @@
|
||||
boolean flag = this.lastHurtByPlayerTime > 0;
|
||||
this.dropEquipment(level); // CraftBukkit - from below
|
||||
if (this.shouldDropLoot() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
+ if (!(damageSource.is(net.minecraft.world.damagesource.DamageTypes.CRAMMING) && level().purpurConfig.disableDropsOnCrammingDeath)) { // Purpur - Disable loot drops on death by cramming
|
||||
this.dropFromLootTable(level, damageSource, flag);
|
||||
// Paper start
|
||||
final boolean prev = this.clearEquipmentSlots;
|
||||
@@ -1798,6 +_,7 @@
|
||||
// Paper end
|
||||
this.dropCustomDeathLoot(level, damageSource, flag);
|
||||
this.clearEquipmentSlots = prev; // Paper
|
||||
+ } // Purpur - Disable loot drops on death by cramming
|
||||
}
|
||||
|
||||
// CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment
|
||||
@@ -2989,6 +_,7 @@
|
||||
float f = (float)(d * 10.0 - 3.0);
|
||||
if (f > 0.0F) {
|
||||
this.playSound(this.getFallDamageSound((int)f), 1.0F, 1.0F);
|
||||
+ if (level().purpurConfig.elytraKineticDamage) // Purpur - Toggle for kinetic damage
|
||||
this.hurt(this.damageSources().flyIntoWall(), f);
|
||||
}
|
||||
}
|
||||
@@ -4398,6 +_,12 @@
|
||||
? slot == EquipmentSlot.MAINHAND && this.canUseSlot(EquipmentSlot.MAINHAND)
|
||||
: slot == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.getType());
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Dispenser curse of binding protection
|
||||
+ public @Nullable EquipmentSlot getEquipmentSlotForDispenserItem(ItemStack itemstack) {
|
||||
+ return EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BINDING_CURSE, itemstack) > 0 ? null : this.getEquipmentSlotForItem(itemstack);
|
||||
+ }
|
||||
+ // Purpur end - Dispenser curse of binding protection
|
||||
|
||||
private static SlotAccess createEquipmentSlotAccess(LivingEntity entity, EquipmentSlot slot) {
|
||||
return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND
|
||||
@@ -0,0 +1,84 @@
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -145,6 +_,7 @@
|
||||
private BlockPos restrictCenter = BlockPos.ZERO;
|
||||
private float restrictRadius = -1.0F;
|
||||
public boolean aware = true; // CraftBukkit
|
||||
+ public int ticksSinceLastInteraction; // Purpur - Entity lifespan
|
||||
|
||||
protected Mob(EntityType<? extends Mob> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -294,6 +_,7 @@
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
+ if (target instanceof net.minecraft.server.level.ServerPlayer) this.ticksSinceLastInteraction = 0; // Purpur - Entity lifespan
|
||||
this.target = target;
|
||||
return true;
|
||||
// CraftBukkit end
|
||||
@@ -337,7 +_,27 @@
|
||||
}
|
||||
|
||||
profilerFiller.pop();
|
||||
- }
|
||||
+ incrementTicksSinceLastInteraction(); // Purpur - Entity lifespan
|
||||
+ }
|
||||
+
|
||||
+ // Purpur start - Entity lifespan
|
||||
+ private void incrementTicksSinceLastInteraction() {
|
||||
+ ++this.ticksSinceLastInteraction;
|
||||
+ if (getRider() != null) {
|
||||
+ this.ticksSinceLastInteraction = 0;
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.level().purpurConfig.entityLifeSpan <= 0) {
|
||||
+ return; // feature disabled
|
||||
+ }
|
||||
+ if (!this.removeWhenFarAway(0) || isPersistenceRequired() || requiresCustomPersistence() || hasCustomName()) {
|
||||
+ return; // mob persistent
|
||||
+ }
|
||||
+ if (this.ticksSinceLastInteraction > this.level().purpurConfig.entityLifeSpan) {
|
||||
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Entity lifespan
|
||||
|
||||
@Override
|
||||
protected void playHurtSound(DamageSource source) {
|
||||
@@ -486,6 +_,7 @@
|
||||
compound.putBoolean("NoAI", this.isNoAi());
|
||||
}
|
||||
compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
|
||||
+ compound.putInt("Purpur.ticksSinceLastInteraction", this.ticksSinceLastInteraction); // Purpur - Entity lifespan
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -568,6 +_,11 @@
|
||||
this.aware = compound.getBoolean("Bukkit.Aware");
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Purpur start - Entity lifespan
|
||||
+ if (compound.contains("Purpur.ticksSinceLastInteraction")) {
|
||||
+ this.ticksSinceLastInteraction = compound.getInt("Purpur.ticksSinceLastInteraction");
|
||||
+ }
|
||||
+ // Purpur end - Entity lifespan
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1280,7 +_,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
- this.setLeftHanded(random.nextFloat() < 0.05F);
|
||||
+ this.setLeftHanded(random.nextFloat() < level.getLevel().purpurConfig.entityLeftHandedChance); // Purpur - Changeable Mob Left Handed Chance
|
||||
return spawnGroupData;
|
||||
}
|
||||
|
||||
@@ -1619,6 +_,7 @@
|
||||
this.playAttackSound();
|
||||
}
|
||||
|
||||
+ if (target instanceof net.minecraft.server.level.ServerPlayer) this.ticksSinceLastInteraction = 0; // Purpur - Entity lifespan
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
|
||||
@@ -29,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public double sanitizeValue(double value) {
|
||||
+ if (!org.purpurmc.purpur.PurpurConfig.clampAttributes) return Double.isNaN(value) ? this.minValue : value; // Purpur - Add attribute clamping and armor limit config
|
||||
return Double.isNaN(value) ? this.minValue : Mth.clamp(value, this.minValue, this.maxValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
@@ -86,7 +_,7 @@
|
||||
};
|
||||
// Paper start - optimise POI access
|
||||
final java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
|
||||
- io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, acquirablePois, predicate1, mob.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes);
|
||||
+ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, acquirablePois, predicate1, mob.blockPosition(), level.purpurConfig.villagerAcquirePoiSearchRadius, level.purpurConfig.villagerAcquirePoiSearchRadius*level.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); // Purpur - Configurable villager search radius
|
||||
final Set<Pair<Holder<PoiType>, BlockPos>> set = new java.util.HashSet<>(poiposes.size());
|
||||
for (final Pair<Holder<PoiType>, BlockPos> poiPose : poiposes) {
|
||||
if (predicate.test(level, poiPose.getSecond())) {
|
||||
@@ -0,0 +1,29 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
|
||||
@@ -55,7 +_,7 @@
|
||||
Node nextNode = path.getNextNode();
|
||||
BlockPos blockPos = previousNode.asBlockPos();
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
- if (blockState.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock)) {
|
||||
+ if (blockState.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock)&& !DoorBlock.requiresRedstone(entity.level(), blockState, blockPos)) { // Purpur - Option to make doors require redstone
|
||||
DoorBlock doorBlock = (DoorBlock)blockState.getBlock();
|
||||
if (!doorBlock.isOpen(blockState)) {
|
||||
// CraftBukkit start - entities opening doors
|
||||
@@ -72,7 +_,7 @@
|
||||
|
||||
BlockPos blockPos1 = nextNode.asBlockPos();
|
||||
BlockState blockState1 = level.getBlockState(blockPos1);
|
||||
- if (blockState1.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock)) {
|
||||
+ if (blockState1.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock) && !DoorBlock.requiresRedstone(entity.level(), blockState1, blockPos1)) { // Purpur - Option to make doors require redstone
|
||||
DoorBlock doorBlock1 = (DoorBlock)blockState1.getBlock();
|
||||
if (!doorBlock1.isOpen(blockState1)) {
|
||||
// CraftBukkit start - entities opening doors
|
||||
@@ -118,7 +_,7 @@
|
||||
iterator.remove();
|
||||
} else {
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
- if (!blockState.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock)) {
|
||||
+ if (!blockState.is(BlockTags.MOB_INTERACTABLE_DOORS, state -> state.getBlock() instanceof DoorBlock) || DoorBlock.requiresRedstone(entity.level(), blockState, blockPos)) { // Purpur - Option to make doors require redstone
|
||||
iterator.remove();
|
||||
} else {
|
||||
DoorBlock doorBlock = (DoorBlock)blockState.getBlock();
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
|
||||
@@ -46,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canStillUse(ServerLevel level, Villager entity, long gameTime) {
|
||||
+ if (!entity.level().purpurConfig.villagerDisplayTradeItem) return false; // Purpur - Option for villager display trade item
|
||||
return this.checkExtraStartConditions(level, entity)
|
||||
&& this.lookTime > 0
|
||||
&& entity.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).isPresent();
|
||||
@@ -0,0 +1,18 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java
|
||||
@@ -22,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
+ if (!this.llama.level().purpurConfig.llamaJoinCaravans || !this.llama.shouldJoinCaravan) return false; // Purpur - Llama API // Purpur - Config to disable Llama caravans
|
||||
if (!this.llama.isLeashed() && !this.llama.inCaravan()) {
|
||||
List<Entity> entities = this.llama.level().getEntities(this.llama, this.llama.getBoundingBox().inflate(9.0, 4.0, 9.0), entity1 -> {
|
||||
EntityType<?> type = entity1.getType();
|
||||
@@ -71,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
+ if (!this.llama.shouldJoinCaravan) return false; // Purpur - Llama API
|
||||
if (this.llama.inCaravan() && this.llama.getCaravanHead().isAlive() && this.firstIsLeashed(this.llama, 0)) {
|
||||
double d = this.llama.distanceToSqr(this.llama.getCaravanHead());
|
||||
if (d > 676.0) {
|
||||
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java
|
||||
@@ -116,9 +_,9 @@
|
||||
}
|
||||
|
||||
this.mob.lookAt(target, 30.0F, 30.0F);
|
||||
- } else {
|
||||
+ } //else { // Purpur - MC-121706 - Fix mobs not looking up and down when strafing
|
||||
this.mob.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||
- }
|
||||
+ //} // Purpur - MC-121706 - Fix mobs not looking up and down when strafing
|
||||
|
||||
if (this.mob.isUsingItem()) {
|
||||
if (!hasLineOfSight && this.seeTime < -60) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java
|
||||
@@ -58,7 +_,7 @@
|
||||
if (firstPassenger instanceof Player player) {
|
||||
int temper = this.horse.getTemper();
|
||||
int maxTemper = this.horse.getMaxTemper();
|
||||
- if (maxTemper > 0 && this.horse.getRandom().nextInt(maxTemper) < temper && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this.horse, ((org.bukkit.craftbukkit.entity.CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent
|
||||
+ if (this.horse.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials() || maxTemper > 0 && this.horse.getRandom().nextInt(maxTemper) < temper && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this.horse, ((org.bukkit.craftbukkit.entity.CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent // Purpur - Config to always tame in Creative
|
||||
this.horse.tameWithName(player);
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
--- a/net/minecraft/world/entity/ai/goal/SwellGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/SwellGoal.java
|
||||
@@ -55,6 +_,14 @@
|
||||
this.creeper.setSwellDir(-1);
|
||||
} else {
|
||||
this.creeper.setSwellDir(1);
|
||||
+ // Purpur start - option to allow creeper to encircle target when fusing
|
||||
+ if (this.creeper.level().purpurConfig.creeperEncircleTarget) {
|
||||
+ net.minecraft.world.phys.Vec3 relative = this.creeper.position().subtract(this.target.position());
|
||||
+ relative = relative.yRot((float) Math.PI / 3).normalize().multiply(2, 2, 2);
|
||||
+ net.minecraft.world.phys.Vec3 destination = this.target.position().add(relative);
|
||||
+ this.creeper.getNavigation().moveTo(destination.x, destination.y, destination.z, 1);
|
||||
+ }
|
||||
+ // Purpur end - option to allow creeper to encircle target when fusing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
|
||||
@@ -56,7 +_,7 @@
|
||||
// Paper start - optimise POI access
|
||||
java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
|
||||
// don't ask me why it's unbounded. ask mojang.
|
||||
- io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes);
|
||||
+ io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), level.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); // Purpur - Configurable villager search radius
|
||||
Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes));
|
||||
// Paper end - optimise POI access
|
||||
if (path != null && path.canReach()) {
|
||||
@@ -0,0 +1,13 @@
|
||||
--- a/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
+++ b/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
|
||||
@@ -64,6 +_,10 @@
|
||||
return false;
|
||||
} else 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 (entity == null) {
|
||||
if (this.isCombat && (!target.canBeSeenAsEnemy() || level.getDifficulty() == Difficulty.PEACEFUL)) {
|
||||
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/world/entity/ambient/Bat.java
|
||||
+++ b/net/minecraft/world/entity/ambient/Bat.java
|
||||
@@ -231,7 +_,7 @@
|
||||
} else {
|
||||
int maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos);
|
||||
int i = 4;
|
||||
- if (isHalloween()) {
|
||||
+ if (Bat.isHalloweenSeason(level.getMinecraftWorld())) { // Purpur - Halloween options and optimizations
|
||||
i = 7;
|
||||
} else if (randomSource.nextBoolean()) {
|
||||
return false;
|
||||
@@ -243,6 +_,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Pufferfish start - only check for spooky season once an hour
|
||||
+ //private static boolean isSpookySeason = false;
|
||||
+ //private static final int ONE_HOUR = 20 * 60 * 60;
|
||||
+ //private static int lastSpookyCheck = -ONE_HOUR;
|
||||
+ public static boolean isHalloweenSeason(Level level) { return level.purpurConfig.forceHalloweenSeason || isHalloween(); } // Purpur - Halloween options and optimizations
|
||||
private static boolean isHalloween() {
|
||||
LocalDate localDate = LocalDate.now();
|
||||
int i = localDate.get(ChronoField.DAY_OF_MONTH);
|
||||
@@ -0,0 +1,34 @@
|
||||
--- a/net/minecraft/world/entity/animal/Animal.java
|
||||
+++ b/net/minecraft/world/entity/animal/Animal.java
|
||||
@@ -142,7 +_,7 @@
|
||||
ItemStack itemInHand = player.getItemInHand(hand);
|
||||
if (this.isFood(itemInHand)) {
|
||||
int age = this.getAge();
|
||||
- if (!this.level().isClientSide && age == 0 && this.canFallInLove()) {
|
||||
+ if (!this.level().isClientSide && age == 0 && this.canFallInLove() && (this.level().purpurConfig.animalBreedingCooldownSeconds <= 0 || !this.level().hasBreedingCooldown(player.getUUID(), this.getClass()))) { // Purpur - Add adjustable breeding cooldown to config
|
||||
final ItemStack breedCopy = itemInHand.copy(); // Paper - Fix EntityBreedEvent copying
|
||||
this.usePlayerItem(player, hand, itemInHand);
|
||||
this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
||||
@@ -239,10 +_,20 @@
|
||||
public void spawnChildFromBreeding(ServerLevel level, Animal mate) {
|
||||
AgeableMob breedOffspring = this.getBreedOffspring(level, mate);
|
||||
if (breedOffspring != null) {
|
||||
- breedOffspring.setBaby(true);
|
||||
- breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
|
||||
+ //breedOffspring.setBaby(true); // Purpur - Add adjustable breeding cooldown to config - moved down
|
||||
+ //breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); // Purpur - Add adjustable breeding cooldown to config - moved down
|
||||
// CraftBukkit start - call EntityBreedEvent
|
||||
ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(mate.getLoveCause())).orElse(null);
|
||||
+ // Purpur start - Add adjustable breeding cooldown to config
|
||||
+ if (breeder != null && level.purpurConfig.animalBreedingCooldownSeconds > 0) {
|
||||
+ if (level.hasBreedingCooldown(breeder.getUUID(), this.getClass())) {
|
||||
+ return;
|
||||
+ }
|
||||
+ level.addBreedingCooldown(breeder.getUUID(), this.getClass());
|
||||
+ }
|
||||
+ breedOffspring.setBaby(true);
|
||||
+ breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
|
||||
+ // Purpur end - Add adjustable breeding cooldown to config
|
||||
int experience = this.getRandom().nextInt(7) + 1;
|
||||
org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(breedOffspring, this, mate, breeder, this.breedItem, experience);
|
||||
if (entityBreedEvent.isCancelled()) {
|
||||
@@ -0,0 +1,43 @@
|
||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -365,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static boolean isNightOrRaining(Level level) {
|
||||
- return level.dimensionType().hasSkyLight() && (level.isNight() || level.isRaining());
|
||||
+ return level.dimensionType().hasSkyLight() && (level.isNight() && !level.purpurConfig.beeCanWorkAtNight || level.isRaining() && !level.purpurConfig.beeCanWorkInRain); // Purpur - Bee can work when raining or at night
|
||||
}
|
||||
|
||||
public void setStayOutOfHiveCountdown(int stayOutOfHiveCountdown) {
|
||||
@@ -398,6 +_,7 @@
|
||||
this.hurtServer(level, this.damageSources().drown(), 1.0F);
|
||||
}
|
||||
|
||||
+ if (hasStung && !this.level().purpurConfig.beeDiesAfterSting) setHasStung(false); else // Purpur - Stop bees from dying after stinging
|
||||
if (hasStung) {
|
||||
this.timeSinceSting++;
|
||||
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
|
||||
@@ -1136,6 +_,7 @@
|
||||
Bee.this.savedFlowerPos = optional.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);
|
||||
+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - Bee API
|
||||
return true;
|
||||
} else {
|
||||
Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
|
||||
@@ -1182,6 +_,7 @@
|
||||
this.pollinating = false;
|
||||
Bee.this.navigation.stop();
|
||||
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
|
||||
+ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos), Bee.this.hasNectar()).callEvent(); // Purpur - Bee API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1228,6 +_,7 @@
|
||||
this.setWantedPos();
|
||||
}
|
||||
|
||||
+ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - Bee API
|
||||
this.successfulPollinatingTicks++;
|
||||
if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
|
||||
this.lastSoundPlayedTick = this.successfulPollinatingTicks;
|
||||
@@ -0,0 +1,26 @@
|
||||
--- a/net/minecraft/world/entity/animal/Cat.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cat.java
|
||||
@@ -332,6 +_,14 @@
|
||||
return this.isTame() && otherAnimal instanceof Cat cat && cat.isTame() && super.canMate(otherAnimal);
|
||||
}
|
||||
|
||||
+ // Purpur start - Configurable default collar color
|
||||
+ @Override
|
||||
+ public void tame(Player player) {
|
||||
+ setCollarColor(level().purpurConfig.catDefaultCollarColor);
|
||||
+ super.tame(player);
|
||||
+ }
|
||||
+ // Purpur end - Configurable default collar color
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(
|
||||
@@ -438,7 +_,7 @@
|
||||
}
|
||||
|
||||
private void tryToTame(Player player) {
|
||||
- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
|
||||
+ if (this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials() || this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit // Purpur - Config to always tame in Creative
|
||||
this.tame(player);
|
||||
this.setOrderedToSit(true);
|
||||
this.level().broadcastEntityEvent(this, (byte)7);
|
||||
@@ -0,0 +1,90 @@
|
||||
--- a/net/minecraft/world/entity/animal/Cow.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cow.java
|
||||
@@ -43,7 +_,7 @@
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> itemStack.is(ItemTags.COW_FOOD), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
@@ -99,6 +_,10 @@
|
||||
ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
|
||||
player.setItemInHand(hand, itemStack);
|
||||
return InteractionResult.SUCCESS;
|
||||
+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom
|
||||
+ } else if (level().purpurConfig.cowFeedMushrooms > 0 && this.getType() != EntityType.MOOSHROOM && isMushroom(itemInHand)) {
|
||||
+ return this.feedMushroom(player, itemInHand);
|
||||
+ // Purpur end - Cows eat mushrooms
|
||||
} else {
|
||||
return super.mobInteract(player, hand);
|
||||
}
|
||||
@@ -114,4 +_,67 @@
|
||||
public EntityDimensions getDefaultDimensions(Pose pose) {
|
||||
return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose);
|
||||
}
|
||||
+
|
||||
+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom
|
||||
+ private int redMushroomsFed = 0;
|
||||
+ private int brownMushroomsFed = 0;
|
||||
+
|
||||
+ private boolean isMushroom(ItemStack stack) {
|
||||
+ return stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem() || stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem();
|
||||
+ }
|
||||
+
|
||||
+ private int incrementFeedCount(ItemStack stack) {
|
||||
+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) {
|
||||
+ return ++redMushroomsFed;
|
||||
+ } else {
|
||||
+ return ++brownMushroomsFed;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private InteractionResult feedMushroom(Player player, ItemStack stack) {
|
||||
+ level().broadcastEntityEvent(this, (byte) 18); // hearts
|
||||
+ playSound(SoundEvents.COW_MILK, 1.0F, 1.0F);
|
||||
+ if (incrementFeedCount(stack) < level().purpurConfig.cowFeedMushrooms) {
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ stack.shrink(1);
|
||||
+ }
|
||||
+ return InteractionResult.CONSUME; // require 5 mushrooms to transform (prevents mushroom duping)
|
||||
+ }
|
||||
+ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level(), EntitySpawnReason.CONVERSION);
|
||||
+ if (mooshroom == null) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem()) {
|
||||
+ mooshroom.setVariant(MushroomCow.Variant.BROWN);
|
||||
+ } else {
|
||||
+ mooshroom.setVariant(MushroomCow.Variant.RED);
|
||||
+ }
|
||||
+ mooshroom.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
|
||||
+ mooshroom.setHealth(this.getHealth());
|
||||
+ mooshroom.setAge(getAge());
|
||||
+ mooshroom.copyPosition(this);
|
||||
+ mooshroom.setYBodyRot(this.yBodyRot);
|
||||
+ mooshroom.setYHeadRot(this.getYHeadRot());
|
||||
+ mooshroom.yRotO = this.yRotO;
|
||||
+ mooshroom.xRotO = this.xRotO;
|
||||
+ if (this.hasCustomName()) {
|
||||
+ mooshroom.setCustomName(this.getCustomName());
|
||||
+ }
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ this.level().addFreshEntity(mooshroom);
|
||||
+ this.remove(RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ stack.shrink(1);
|
||||
+ }
|
||||
+ for (int i = 0; i < 15; ++i) {
|
||||
+ ((ServerLevel) level()).sendParticlesSource(((ServerLevel) level()).players(), null, net.minecraft.core.particles.ParticleTypes.HAPPY_VILLAGER,
|
||||
+ false, true,
|
||||
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 2), getZ() + random.nextFloat(), 1,
|
||||
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0);
|
||||
+ }
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // Purpur end - Cows eat mushrooms
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
--- a/net/minecraft/world/entity/animal/Dolphin.java
|
||||
+++ b/net/minecraft/world/entity/animal/Dolphin.java
|
||||
@@ -71,6 +_,7 @@
|
||||
private static final int TOTAL_MOISTNESS_LEVEL = 2400;
|
||||
public static final Predicate<ItemEntity> ALLOWED_ITEMS = itemEntity -> !itemEntity.hasPickUpDelay() && itemEntity.isAlive() && itemEntity.isInWater();
|
||||
public static final float BABY_SCALE = 0.65F;
|
||||
+ private boolean isNaturallyAggressiveToPlayers; // Purpur - Dolphins naturally aggressive to players chance
|
||||
|
||||
public Dolphin(EntityType<? extends Dolphin> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -87,6 +_,7 @@
|
||||
this.setAirSupply(this.getMaxAirSupply());
|
||||
this.setXRot(0.0F);
|
||||
SpawnGroupData spawnGroupData1 = Objects.requireNonNullElseGet(spawnGroupData, () -> new AgeableMob.AgeableMobGroupData(0.1F));
|
||||
+ this.isNaturallyAggressiveToPlayers = level.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance; // Purpur - Dolphins naturally aggressive to players chance
|
||||
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData1);
|
||||
}
|
||||
|
||||
@@ -169,17 +_,19 @@
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new BreathAirGoal(this));
|
||||
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
|
||||
+ this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - Dolphins naturally aggressive to players chance
|
||||
this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this));
|
||||
this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0));
|
||||
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0, 10));
|
||||
this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
|
||||
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(5, new DolphinJumpGoal(this, 10));
|
||||
- this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2F, true));
|
||||
+ //this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2F, true)); // Purpur - moved up - Dolphins naturally aggressive to players chance
|
||||
this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal());
|
||||
this.goalSelector.addGoal(8, new FollowBoatGoal(this));
|
||||
this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0, 1.0));
|
||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Guardian.class).setAlertOthers());
|
||||
+ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Dolphins naturally aggressive to players chance
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
@@ -412,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
+ if (this.dolphin.level().purpurConfig.dolphinDisableTreasureSearching) return false; // Purpur - Add option to disable dolphin treasure searching
|
||||
return this.dolphin.gotFish() && this.dolphin.getAirSupply() >= 100;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
--- a/net/minecraft/world/entity/animal/Fox.java
|
||||
+++ b/net/minecraft/world/entity/animal/Fox.java
|
||||
@@ -335,6 +_,11 @@
|
||||
}
|
||||
|
||||
private void setTargetGoals() {
|
||||
+ // Purpur start - Tulips change fox type - do not add duplicate goals
|
||||
+ this.targetSelector.removeGoal(this.landTargetGoal);
|
||||
+ this.targetSelector.removeGoal(this.turtleEggTargetGoal);
|
||||
+ this.targetSelector.removeGoal(this.fishTargetGoal);
|
||||
+ // Purpur end - Tulips change fox type
|
||||
if (this.getVariant() == Fox.Variant.RED) {
|
||||
this.targetSelector.addGoal(4, this.landTargetGoal);
|
||||
this.targetSelector.addGoal(4, this.turtleEggTargetGoal);
|
||||
@@ -364,6 +_,7 @@
|
||||
@Override
|
||||
public void setVariant(Fox.Variant variant) {
|
||||
this.entityData.set(DATA_TYPE_ID, variant.getId());
|
||||
+ this.setTargetGoals(); // Purpur - Tulips change fox type - fix API bug not updating pathfinders on type change
|
||||
}
|
||||
|
||||
List<UUID> getTrustedUUIDs() {
|
||||
@@ -684,6 +_,29 @@
|
||||
return slot == EquipmentSlot.MAINHAND;
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start - Tulips change fox type
|
||||
+ @Override
|
||||
+ public net.minecraft.world.InteractionResult mobInteract(Player player, net.minecraft.world.InteractionHand hand) {
|
||||
+ if (level().purpurConfig.foxTypeChangesWithTulips) {
|
||||
+ ItemStack itemstack = player.getItemInHand(hand);
|
||||
+ if (getVariant() == Variant.RED && itemstack.getItem() == Items.WHITE_TULIP) {
|
||||
+ setVariant(Variant.SNOW);
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ itemstack.shrink(1);
|
||||
+ }
|
||||
+ return net.minecraft.world.InteractionResult.SUCCESS;
|
||||
+ } else if (getVariant() == Variant.SNOW && itemstack.getItem() == Items.ORANGE_TULIP) {
|
||||
+ setVariant(Variant.RED);
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ itemstack.shrink(1);
|
||||
+ }
|
||||
+ return net.minecraft.world.InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+ return super.mobInteract(player, hand);
|
||||
+ }
|
||||
+ // Purpur end - Tulips change fox type
|
||||
|
||||
@Override
|
||||
// Paper start - Cancellable death event
|
||||
@@ -0,0 +1,53 @@
|
||||
--- a/net/minecraft/world/entity/animal/IronGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/IronGolem.java
|
||||
@@ -56,13 +_,26 @@
|
||||
private int remainingPersistentAngerTime;
|
||||
@Nullable
|
||||
private UUID persistentAngerTarget;
|
||||
+ @Nullable private UUID summoner; // Purpur - Summoner API
|
||||
|
||||
public IronGolem(EntityType<? extends IronGolem> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Summoner API
|
||||
+ @Nullable
|
||||
+ public UUID getSummoner() {
|
||||
+ return summoner;
|
||||
+ }
|
||||
+
|
||||
+ public void setSummoner(@Nullable UUID summoner) {
|
||||
+ this.summoner = summoner;
|
||||
+ }
|
||||
+ // Purpur end - Summoner API
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
+ if (this.level().purpurConfig.ironGolemPoppyCalm) this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.ReceiveFlower(this)); // Purpur - Iron golem calm anger options
|
||||
this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true));
|
||||
this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32.0F));
|
||||
this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6, false));
|
||||
@@ -140,6 +_,7 @@
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putBoolean("PlayerCreated", this.isPlayerCreated());
|
||||
+ if (getSummoner() != null) compound.putUUID("Purpur.Summoner", getSummoner()); // Purpur - Summoner API
|
||||
this.addPersistentAngerSaveData(compound);
|
||||
}
|
||||
|
||||
@@ -147,6 +_,7 @@
|
||||
public void readAdditionalSaveData(CompoundTag compound) {
|
||||
super.readAdditionalSaveData(compound);
|
||||
this.setPlayerCreated(compound.getBoolean("PlayerCreated"));
|
||||
+ if (compound.contains("Purpur.Summoner")) setSummoner(compound.getUUID("Purpur.Summoner")); // Purpur - Summoner API
|
||||
this.readPersistentAngerSaveData(this.level(), compound);
|
||||
}
|
||||
|
||||
@@ -266,6 +_,7 @@
|
||||
float f = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
|
||||
this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, f);
|
||||
itemInHand.consume(1, player);
|
||||
+ if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - Iron golem calm anger options
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
|
||||
@@ -192,6 +_,13 @@
|
||||
level.playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, soundSource, 1.0F, 1.0F);
|
||||
this.convertTo(EntityType.COW, ConversionParams.single(this, false, false), mob -> {
|
||||
level.sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
|
||||
+ // Purpur start - Fix cow rotation when shearing mooshroom
|
||||
+ mob.copyPosition(this);
|
||||
+ mob.yBodyRot = this.yBodyRot;
|
||||
+ mob.setYHeadRot(this.getYHeadRot());
|
||||
+ mob.yRotO = this.yRotO;
|
||||
+ mob.xRotO = this.xRotO;
|
||||
+ // Purpur end - Fix cow rotation when shearing mooshroom
|
||||
// Paper start - custom shear drops; moved drop generation to separate method
|
||||
drops.forEach(drop -> {
|
||||
this.spawnAtLocation(level, new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), drop));
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -232,7 +_,7 @@
|
||||
public boolean checkSpawnObstruction(LevelReader level) {
|
||||
if (level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox())) {
|
||||
BlockPos blockPos = this.blockPosition();
|
||||
- if (blockPos.getY() < level.getSeaLevel()) {
|
||||
+ if (!level().purpurConfig.ocelotSpawnUnderSeaLevel && blockPos.getY() < level.getSeaLevel()) { // Purpur - Option Ocelot Spawn Under Sea Level
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
--- a/net/minecraft/world/entity/animal/Parrot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Parrot.java
|
||||
@@ -152,6 +_,7 @@
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25));
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
+ if (this.level().purpurConfig.parrotBreedable) this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D)); // Purpur - Breedable parrots
|
||||
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.0, 5.0F, 1.0F));
|
||||
@@ -257,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
- if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
|
||||
+ if (this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials() || (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled())) { // CraftBukkit // Purpur - Config to always tame in Creative
|
||||
this.tame(player);
|
||||
this.level().broadcastEntityEvent(this, (byte)7);
|
||||
} else {
|
||||
@@ -265,6 +_,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (this.level().purpurConfig.parrotBreedable) return super.mobInteract(player, hand); // Purpur - Breedable parrots
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!itemInHand.is(ItemTags.PARROT_POISONOUS_FOOD)) {
|
||||
if (!this.isFlying() && this.isTame() && this.isOwnedBy(player)) {
|
||||
@@ -289,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean isFood(ItemStack stack) {
|
||||
- return false;
|
||||
+ return this.level().purpurConfig.parrotBreedable && stack.is(ItemTags.PARROT_FOOD); // Purpur - Breedable parrots
|
||||
}
|
||||
|
||||
public static boolean checkParrotSpawnRules(
|
||||
@@ -304,13 +_,13 @@
|
||||
|
||||
@Override
|
||||
public boolean canMate(Animal otherAnimal) {
|
||||
- return false;
|
||||
+ return super.canMate(otherAnimal); // Purpur - Breedable parrots
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
|
||||
- return null;
|
||||
+ return level.purpurConfig.parrotBreedable ? EntityType.PARROT.create(level, EntitySpawnReason.BREEDING) : null; // Purpur - Breedable parrots
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -0,0 +1,22 @@
|
||||
--- a/net/minecraft/world/entity/animal/Pig.java
|
||||
+++ b/net/minecraft/world/entity/animal/Pig.java
|
||||
@@ -132,6 +_,19 @@
|
||||
@Override
|
||||
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
||||
boolean isFood = this.isFood(player.getItemInHand(hand));
|
||||
+ // Purpur start - Pigs give saddle back
|
||||
+ if (level().purpurConfig.pigGiveSaddleBack && player.isSecondaryUseActive() && !isFood && isSaddled() && !isVehicle()) {
|
||||
+ this.steering.setSaddle(false);
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ ItemStack saddle = new ItemStack(Items.SADDLE);
|
||||
+ if (!player.getInventory().add(saddle)) {
|
||||
+ player.drop(saddle, false);
|
||||
+ }
|
||||
+ }
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // Purpur end - Pigs give saddle back
|
||||
+
|
||||
if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) {
|
||||
if (!this.level().isClientSide) {
|
||||
player.startRiding(this);
|
||||
@@ -0,0 +1,54 @@
|
||||
--- a/net/minecraft/world/entity/animal/PolarBear.java
|
||||
+++ b/net/minecraft/world/entity/animal/PolarBear.java
|
||||
@@ -64,6 +_,29 @@
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Breedable Polar Bears
|
||||
+ public boolean canMate(Animal other) {
|
||||
+ if (other == this) {
|
||||
+ return false;
|
||||
+ } else if (this.isStanding()) {
|
||||
+ return false;
|
||||
+ } else if (this.getTarget() != null) {
|
||||
+ return false;
|
||||
+ } else if (!(other instanceof PolarBear)) {
|
||||
+ return false;
|
||||
+ } else {
|
||||
+ PolarBear bear = (PolarBear) other;
|
||||
+ if (bear.isStanding()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (bear.getTarget() != null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return this.isInLove() && bear.isInLove();
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Breedable Polar Bears
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
|
||||
@@ -72,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public boolean isFood(ItemStack stack) {
|
||||
- return false;
|
||||
+ return level().purpurConfig.polarBearBreedableItem != null && stack.getItem() == level().purpurConfig.polarBearBreedableItem; // Purpur - Breedable Polar Bears
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,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, mob -> mob.isBaby() ? DamageTypeTags.PANIC_CAUSES : DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
||||
+ // Purpur start - Breedable Polar Bears
|
||||
+ if (level().purpurConfig.polarBearBreedableItem != null) {
|
||||
+ this.goalSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D));
|
||||
+ this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, net.minecraft.world.item.crafting.Ingredient.of(level().purpurConfig.polarBearBreedableItem), false));
|
||||
+ }
|
||||
+ // Purpur end - Breedable Polar Bears
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
@@ -0,0 +1,26 @@
|
||||
--- a/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -376,10 +_,23 @@
|
||||
}
|
||||
|
||||
this.setVariant(randomRabbitVariant);
|
||||
+
|
||||
+ // Purpur start - Special mobs naturally spawn
|
||||
+ if (randomRabbitVariant != Variant.EVIL && level.getLevel().purpurConfig.rabbitNaturalToast > 0D && random.nextDouble() <= level.getLevel().purpurConfig.rabbitNaturalToast) {
|
||||
+ setCustomName(Component.translatable("Toast"));
|
||||
+ }
|
||||
+ // Purpur end - Special mobs naturally spawn
|
||||
+
|
||||
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||
}
|
||||
|
||||
private static Rabbit.Variant getRandomRabbitVariant(LevelAccessor level, BlockPos pos) {
|
||||
+ // Purpur start - Special mobs naturally spawn
|
||||
+ Level world = level.getMinecraftWorld();
|
||||
+ if (world.purpurConfig.rabbitNaturalKiller > 0D && world.getRandom().nextDouble() <= world.purpurConfig.rabbitNaturalKiller) {
|
||||
+ return Rabbit.Variant.EVIL;
|
||||
+ }
|
||||
+ // Purpur end - Special mobs naturally spawn
|
||||
Holder<Biome> biome = level.getBiome(pos);
|
||||
int randomInt = level.getRandom().nextInt(100);
|
||||
if (biome.is(BiomeTags.SPAWNS_WHITE_RABBITS)) {
|
||||
@@ -0,0 +1,63 @@
|
||||
--- a/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
|
||||
@@ -44,15 +_,27 @@
|
||||
public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob {
|
||||
private static final EntityDataAccessor<Byte> DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE);
|
||||
private static final byte PUMPKIN_FLAG = 16;
|
||||
+ @Nullable private java.util.UUID summoner; // Purpur - Summoner API
|
||||
|
||||
public SnowGolem(EntityType<? extends SnowGolem> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
+ // Purpur start - Summoner API
|
||||
+ @Nullable
|
||||
+ public java.util.UUID getSummoner() {
|
||||
+ return summoner;
|
||||
+ }
|
||||
+
|
||||
+ public void setSummoner(@Nullable java.util.UUID summoner) {
|
||||
+ this.summoner = summoner;
|
||||
+ }
|
||||
+ // Purpur end - Summoner API
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
- this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25, 20, 10.0F));
|
||||
- this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0, 1.0000001E-5F));
|
||||
+ this.goalSelector.addGoal(1, new RangedAttackGoal(this, level().purpurConfig.snowGolemAttackDistance, level().purpurConfig.snowGolemSnowBallMin, level().purpurConfig.snowGolemSnowBallMax, level().purpurConfig.snowGolemSnowBallModifier)); // Purpur - Snow Golem rate of fire config
|
||||
+ this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F));
|
||||
this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
|
||||
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entity, level) -> entity instanceof Enemy));
|
||||
@@ -72,6 +_,7 @@
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putBoolean("Pumpkin", this.hasPumpkin());
|
||||
+ if (getSummoner() != null) compound.putUUID("Purpur.Summoner", getSummoner()); // Purpur - Summoner API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,6 +_,7 @@
|
||||
if (compound.contains("Pumpkin")) {
|
||||
this.setPumpkin(compound.getBoolean("Pumpkin"));
|
||||
}
|
||||
+ if (compound.contains("Purpur.Summoner")) setSummoner(compound.getUUID("Purpur.Summoner")); // Purpur - Summoner API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,6 +_,14 @@
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
+ // Purpur start - Snowman drop and put back pumpkin
|
||||
+ } else if (level().purpurConfig.snowGolemPutPumpkinBack && !hasPumpkin() && itemInHand.getItem() == Blocks.CARVED_PUMPKIN.asItem()) {
|
||||
+ setPumpkin(true);
|
||||
+ if (!player.getAbilities().instabuild) {
|
||||
+ itemInHand.shrink(1);
|
||||
+ }
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ // Purpur end - Snowman drop and put back pumpkin
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
--- a/net/minecraft/world/entity/animal/Squid.java
|
||||
+++ b/net/minecraft/world/entity/animal/Squid.java
|
||||
@@ -46,10 +_,29 @@
|
||||
|
||||
public Squid(EntityType<? extends Squid> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
- //this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random
|
||||
+ if (!level.purpurConfig.entitySharedRandom) this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random // Purpur - Add toggle for RNG manipulation
|
||||
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
|
||||
}
|
||||
|
||||
+ // Purpur start - Stop squids floating on top of water
|
||||
+ @Override
|
||||
+ public net.minecraft.world.phys.AABB getAxisForFluidCheck() {
|
||||
+ // Stops squids from floating just over the water
|
||||
+ return super.getAxisForFluidCheck().offsetY(level().purpurConfig.squidOffsetWaterCheck);
|
||||
+ }
|
||||
+ // Purpur end - Stop squids floating on top of water
|
||||
+
|
||||
+ // Purpur start - Flying squids! Oh my!
|
||||
+ public boolean canFly() {
|
||||
+ return this.level().purpurConfig.squidsCanFly;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isInWater() {
|
||||
+ return this.wasTouchingWater || canFly();
|
||||
+ }
|
||||
+ // Purpur end - Flying squids! Oh my!
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this));
|
||||
@@ -127,6 +_,7 @@
|
||||
}
|
||||
|
||||
if (this.isInWaterOrBubble()) {
|
||||
+ if (canFly()) setNoGravity(!wasTouchingWater); // Purpur - Flying squids! Oh my!
|
||||
if (this.tentacleMovement < (float) Math.PI) {
|
||||
float f = this.tentacleMovement / (float) Math.PI;
|
||||
this.tentacleAngle = Mth.sin(f * f * (float) Math.PI) * (float) Math.PI * 0.25F;
|
||||
@@ -310,7 +_,7 @@
|
||||
int noActionTime = this.squid.getNoActionTime();
|
||||
if (noActionTime > 100) {
|
||||
this.squid.movementVector = Vec3.ZERO;
|
||||
- } else if (this.squid.getRandom().nextInt(reducedTickDelay(50)) == 0 || !this.squid.wasTouchingWater || !this.squid.hasMovementVector()) {
|
||||
+ } else if (this.squid.getRandom().nextInt(reducedTickDelay(50)) == 0 || !this.squid.isInWater() || !this.squid.hasMovementVector()) { // Purpur - Flying squids! Oh my!
|
||||
float f = this.squid.getRandom().nextFloat() * (float) (Math.PI * 2);
|
||||
this.squid.movementVector = new Vec3(Mth.cos(f) * 0.2F, -0.1F + this.squid.getRandom().nextFloat() * 0.2F, Mth.sin(f) * 0.2F);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
+++ b/net/minecraft/world/entity/animal/WaterAnimal.java
|
||||
@@ -74,8 +_,7 @@
|
||||
seaLevel = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(seaLevel);
|
||||
i = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(i);
|
||||
// Paper end - Make water animal spawn height configurable
|
||||
- return pos.getY() >= i
|
||||
- && pos.getY() <= seaLevel
|
||||
+ return ((spawnReason == EntitySpawnReason.SPAWNER && level.getMinecraftWorld().purpurConfig.spawnerFixMC238526) || (pos.getY() >= i && pos.getY() <= seaLevel)) // Purpur - MC-238526 - Fix spawner not spawning water animals correctly
|
||||
&& level.getFluidState(pos.below()).is(FluidTags.WATER)
|
||||
&& level.getBlockState(pos.above()).is(Blocks.WATER);
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
--- a/net/minecraft/world/entity/animal/Wolf.java
|
||||
+++ b/net/minecraft/world/entity/animal/Wolf.java
|
||||
@@ -94,6 +_,37 @@
|
||||
EntityType<?> type = entity.getType();
|
||||
return type == EntityType.SHEEP || type == EntityType.RABBIT || type == EntityType.FOX;
|
||||
};
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ private boolean isRabid = false;
|
||||
+ private static final TargetingConditions.Selector RABID_PREDICATE = (entity, ignored) -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof net.minecraft.world.entity.Mob;
|
||||
+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR);
|
||||
+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE);
|
||||
+ private static final class AvoidRabidWolfGoal extends AvoidEntityGoal<Wolf> {
|
||||
+ private final Wolf wolf;
|
||||
+
|
||||
+ public AvoidRabidWolfGoal(Wolf wolf, float distance, double minSpeed, double maxSpeed) {
|
||||
+ super(wolf, Wolf.class, distance, minSpeed, maxSpeed);
|
||||
+ this.wolf = wolf;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean canUse() {
|
||||
+ return super.canUse() && !this.wolf.isRabid() && this.toAvoid != null && this.toAvoid.isRabid(); // wolves which are not rabid run away from rabid wolves
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void start() {
|
||||
+ this.wolf.setTarget(null);
|
||||
+ super.start();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void tick() {
|
||||
+ this.wolf.setTarget(null);
|
||||
+ super.tick();
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
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;
|
||||
@@ -115,12 +_,47 @@
|
||||
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
|
||||
}
|
||||
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ public boolean isRabid() {
|
||||
+ return this.isRabid;
|
||||
+ }
|
||||
+
|
||||
+ public void setRabid(boolean isRabid) {
|
||||
+ this.isRabid = isRabid;
|
||||
+ updatePathfinders(true);
|
||||
+ }
|
||||
+
|
||||
+ public void updatePathfinders(boolean modifyEffects) {
|
||||
+ this.targetSelector.removeGoal(PATHFINDER_VANILLA);
|
||||
+ this.targetSelector.removeGoal(PATHFINDER_RABID);
|
||||
+ if (this.isRabid) {
|
||||
+ setOwnerUUID(null);
|
||||
+ setTame(false, true);
|
||||
+ this.targetSelector.addGoal(5, PATHFINDER_RABID);
|
||||
+ if (modifyEffects) this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.CONFUSION, 1200));
|
||||
+ } else {
|
||||
+ this.targetSelector.addGoal(5, PATHFINDER_VANILLA);
|
||||
+ this.stopBeingAngry();
|
||||
+ if (modifyEffects) this.removeEffect(net.minecraft.world.effect.MobEffects.CONFUSION);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
+
|
||||
+ // Purpur start - Configurable default collar color
|
||||
+ @Override
|
||||
+ public void tame(Player player) {
|
||||
+ setCollarColor(level().purpurConfig.wolfDefaultCollarColor);
|
||||
+ super.tame(player);
|
||||
+ }
|
||||
+ // Purpur end - Configurable default collar color
|
||||
+
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5, DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
||||
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
||||
this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5, 1.5));
|
||||
+ this.goalSelector.addGoal(3, new AvoidRabidWolfGoal(this, 24.0F, 1.5D, 1.5D)); // Purpur - Configurable chance for wolves to spawn rabid
|
||||
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));
|
||||
@@ -133,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));
|
||||
- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR));
|
||||
+ // this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); // Purpur - Configurable chance for wolves to spawn rabid - moved to updatePathfinders()
|
||||
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));
|
||||
@@ -182,6 +_,7 @@
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putByte("CollarColor", (byte)this.getCollarColor().getId());
|
||||
+ compound.putBoolean("Purpur.IsRabid", this.isRabid); // Purpur - Configurable chance for wolves to spawn rabid
|
||||
this.getVariant().unwrapKey().ifPresent(resourceKey -> compound.putString("variant", resourceKey.location().toString()));
|
||||
this.addPersistentAngerSaveData(compound);
|
||||
}
|
||||
@@ -196,6 +_,10 @@
|
||||
if (compound.contains("CollarColor", 99)) {
|
||||
this.setCollarColor(DyeColor.byId(compound.getInt("CollarColor")));
|
||||
}
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ this.isRabid = compound.getBoolean("Purpur.IsRabid");
|
||||
+ this.updatePathfinders(false);
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
|
||||
this.readPersistentAngerSaveData(this.level(), compound);
|
||||
}
|
||||
@@ -215,6 +_,10 @@
|
||||
}
|
||||
|
||||
this.setVariant(holder);
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ this.isRabid = level.getLevel().purpurConfig.wolfNaturalRabid > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.wolfNaturalRabid;
|
||||
+ this.updatePathfinders(false);
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
|
||||
}
|
||||
|
||||
@@ -263,6 +_,11 @@
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (this.isAlive()) {
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ if (this.age % 300 == 0 && this.isRabid()) {
|
||||
+ this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.CONFUSION, 400));
|
||||
+ }
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
this.interestedAngleO = this.interestedAngle;
|
||||
if (this.isInterested()) {
|
||||
this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F;
|
||||
@@ -481,13 +_,27 @@
|
||||
itemInHand.consume(1, player);
|
||||
this.tryToTame(player);
|
||||
return InteractionResult.SUCCESS_SERVER;
|
||||
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
||||
+ } else if (this.level().purpurConfig.wolfMilkCuresRabies && itemInHand.getItem() == Items.MILK_BUCKET && this.isRabid()) {
|
||||
+ if (!player.isCreative()) {
|
||||
+ player.setItemInHand(hand, new ItemStack(Items.BUCKET));
|
||||
+ }
|
||||
+ this.setRabid(false);
|
||||
+ for (int i = 0; i < 10; ++i) {
|
||||
+ ((ServerLevel) level()).sendParticlesSource(((ServerLevel) level()).players(), null, ParticleTypes.HAPPY_VILLAGER,
|
||||
+ false, true,
|
||||
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 1.5), getZ() + random.nextFloat(), 1,
|
||||
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0);
|
||||
+ }
|
||||
+ return InteractionResult.SUCCESS_SERVER;
|
||||
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
||||
}
|
||||
|
||||
return super.mobInteract(player, hand);
|
||||
}
|
||||
|
||||
private void tryToTame(Player player) {
|
||||
- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check.
|
||||
+ if (this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials() || this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check. // Purpur - Config to always tame in Creative
|
||||
this.tame(player);
|
||||
this.navigation.stop();
|
||||
this.setTarget(null);
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -392,6 +_,7 @@
|
||||
|
||||
// Paper start - Goat ram API
|
||||
public void ram(net.minecraft.world.entity.LivingEntity entity) {
|
||||
+ if(!new org.purpurmc.purpur.event.entity.GoatRamEntityEvent((org.bukkit.entity.Goat) getBukkitEntity(), entity.getBukkitLivingEntity()).callEvent()) return; // Purpur - Added goat ram event
|
||||
Brain<Goat> brain = this.getBrain();
|
||||
brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position());
|
||||
brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user